You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Raspberry PI 4's boot loader require a little bit extra work. Here's some of the investigation notes I've done so far. https://github.com/jacobweinstock/dhcp/blob/proxydhcp-handler/option/rpi.go
On top of this, we'll need to provide RPI's with some non-Tinkerbell standard files (i.e. not ipxe.efi, undionly.pxe, or snp.efi)to initially netboot.
I’ve been working on an interesting solution to this problem using tools from the smee project. I load an EDK2 FDT binary firmware file via the armstub command-line option, enabling the boot sequence to load a second-stage bootloader—similar to EFI firmware on non-SBCs.
By leveraging TFTP and some smee project hacks, I found it’s possible to fully support Redfish with a single Docker image for a Raspberry Pi cluster. The TFTP server retrieves the MAC address from the DHCP process, bypasses default serial boot options, and injects EFI variables into the FDT file for customized boot configurations.
The only aspect not directly relevant to this project is power management. I’m using Unifi PoE and wrote custom Go libraries to handle IPAM for the BMC.
I have a significant amount of code to share if this sounds useful. Many components are compatible with smee, so let me know if you’d like to explore further!
Hey, lots of progress! Most of which can be easily ported into Tinkerbell if there's interest.
For a variety of reasons, I'm using Metal3 with OpenStack Ironic for my CAPI infra provider now, but have kept the components segmented so other infra projects can benefit.
The code provides an interface for manipulating EDK2 builds, as well as go generate commands that store the firmware in the project to be embedded as a byte array.
I'm piecing all the moving parts into a project tentatively named metal-boot that currently has the option of supervising OpenStack Ironic and proxying the Unix socket over a common API. My main focus was to remove the Kubernetes-in-Kubernetes requirement of Cluster API since provisioning the initial cluster is a completely separate operational process and a potential bottleneck if catastrophe occurs in the resulting CAPI management cluster. Essentially we're saying, "All you need to set up an enterprise Kubernetes solution is a pre-existing one!"
Since Ironic was built to work with any number of OpenStack configs as well as standalone, it's very flexible, but has many shortcomings. The work from Equinix looks very promising as a future-proof, scalable, modernized replacement for Ironic, so I'm happy to contribute if there are any components I'm working on that would fit nicely into the ecosystem.
What I've Achieved So Far
Redfish Interoperability over TCP Boot
Every EFI variable in EDK2 can be predicted with varying levels of difficulty. This gives us access to configure the network interface for the Broadcom chips, set up iSCSI initiators, swap between ACPI/Device Tree, and most importantly, customize the boot order, including options for one-time boot options (i.e., HTTP boot to a specific ISO next boot).
For working boot entries I had to reverse engineer the method that EDK2 uses to insert MAC addresses into optional data, but afterwards, custom network boot entries can be loaded dynamically.
The following example extracts a MAC address from existing EFI variables, but requires that the firmware is writable from the Raspberry Pi.
The referenced file contains many usage examples of the firmware manager including network configuration, firmware updates and version management, etc. Most of this behavior is functional, but needs additional work to make it work across different RPi boards.
How I'm Using the Firmware Manager
I found that I only need a single feature from the firmware manager after building out all of the above functionality.
reader, err:=h.firmware.GetFirmwareReader(mac)
iferr!=nil {
h.Log.Error(err, "failed to get firmware reader")
returnerr
}
_, err=rf.ReadFrom(reader)
This code loads the default firmware unless we need to network boot. If we need to network boot, we inject the PXE boot override into the firmware by MAC. Since EDK2 always loads storage EFI options first, this method works without fail. It's also surprisingly fast seeing as it injects variables into the firmware volume.
There is no one-size-fits-all regarding UEFI booting for raspberry pi hardware. RPI4 works great and RPI5 is a nightmare. After carefully reviewing Home Assistant OS, I found that the correct path forward seems to be to play nicely with the design specification - working with the board's strengths.
RPI device trees are difficult to implement in U-Boot and EDK2. I've had some success booting all RPI boards from a single firmware build, but this changes when switching EEPROM versions.
So my strategy now is to just have the built in Net boot as the first option. I set zero restarts and 4 second timeout. If the proxy DHCP request is never found, we boot to NVME, USB etc.
If the BOOTP result is returned, the board jumps straight into HookOS.
I'm happy to report that Raspberry PI 4b and 5 network booting are now natively supported by Tinkerbell and CaptainOS. tinkerbell/captain#67, tinkerbell/tinkerbell#805, and a couple other PRs made this possible. These are not yet in a tagged release so the latest from main will need to be used. Official docs are forthcoming (tinkerbell/tinkerbell#958).
Activity
jacobweinstock commentedon Jan 26, 2023
Raspberry PI 4's boot loader require a little bit extra work. Here's some of the investigation notes I've done so far. https://github.com/jacobweinstock/dhcp/blob/proxydhcp-handler/option/rpi.go
On top of this, we'll need to provide RPI's with some non-Tinkerbell standard files (i.e. not ipxe.efi, undionly.pxe, or snp.efi)to initially netboot.
hc2p commentedon Mar 16, 2023
Hi,
were you able to get further with this?
I'm trying to netboot a Raspberry 3B+ and just stumbled upon the missing Vendor-Option 43.
appkins commentedon Mar 3, 2025
I’ve been working on an interesting solution to this problem using tools from the smee project. I load an EDK2 FDT binary firmware file via the armstub command-line option, enabling the boot sequence to load a second-stage bootloader—similar to EFI firmware on non-SBCs.
By leveraging TFTP and some smee project hacks, I found it’s possible to fully support Redfish with a single Docker image for a Raspberry Pi cluster. The TFTP server retrieves the MAC address from the DHCP process, bypasses default serial boot options, and injects EFI variables into the FDT file for customized boot configurations.
The only aspect not directly relevant to this project is power management. I’m using Unifi PoE and wrote custom Go libraries to handle IPAM for the BMC.
I have a significant amount of code to share if this sounds useful. Many components are compatible with smee, so let me know if you’d like to explore further!
pedroalvesbatista commentedon Sep 4, 2025
Hey @appkins, how is this going ? Any progress ?
Would be good to try out.
appkins commentedon Sep 13, 2025
Hey, lots of progress! Most of which can be easily ported into Tinkerbell if there's interest.
For a variety of reasons, I'm using Metal3 with OpenStack Ironic for my CAPI infra provider now, but have kept the components segmented so other infra projects can benefit.
I added all the EDK2 EFI manipulation code into its own repo: https://github.com/metal3-community/uefi-firmware-manager.
The code provides an interface for manipulating EDK2 builds, as well as go generate commands that store the firmware in the project to be embedded as a byte array.
I'm piecing all the moving parts into a project tentatively named
metal-bootthat currently has the option of supervising OpenStack Ironic and proxying the Unix socket over a common API. My main focus was to remove the Kubernetes-in-Kubernetes requirement of Cluster API since provisioning the initial cluster is a completely separate operational process and a potential bottleneck if catastrophe occurs in the resulting CAPI management cluster. Essentially we're saying, "All you need to set up an enterprise Kubernetes solution is a pre-existing one!"Since Ironic was built to work with any number of OpenStack configs as well as standalone, it's very flexible, but has many shortcomings. The work from Equinix looks very promising as a future-proof, scalable, modernized replacement for Ironic, so I'm happy to contribute if there are any components I'm working on that would fit nicely into the ecosystem.
What I've Achieved So Far
Redfish Interoperability over TCP Boot
Every EFI variable in EDK2 can be predicted with varying levels of difficulty. This gives us access to configure the network interface for the Broadcom chips, set up iSCSI initiators, swap between ACPI/Device Tree, and most importantly, customize the boot order, including options for one-time boot options (i.e., HTTP boot to a specific ISO next boot).
For working boot entries I had to reverse engineer the method that EDK2 uses to insert MAC addresses into optional data, but afterwards, custom network boot entries can be loaded dynamically.
The following example extracts a MAC address from existing EFI variables, but requires that the firmware is writable from the Raspberry Pi.
metal3-community/metal-boot/api/redfish/server.go
The referenced file contains many usage examples of the firmware manager including network configuration, firmware updates and version management, etc. Most of this behavior is functional, but needs additional work to make it work across different RPi boards.
How I'm Using the Firmware Manager
I found that I only need a single feature from the firmware manager after building out all of the above functionality.
metal3-community/metal-boot/internal/tftp/tftp.go
This code loads the default firmware unless we need to network boot. If we need to network boot, we inject the PXE boot override into the firmware by MAC. Since EDK2 always loads storage EFI options first, this method works without fail. It's also surprisingly fast seeing as it injects variables into the firmware volume.
appkins commentedon Feb 11, 2026
My latest on this effort:
There is no one-size-fits-all regarding UEFI booting for raspberry pi hardware. RPI4 works great and RPI5 is a nightmare. After carefully reviewing Home Assistant OS, I found that the correct path forward seems to be to play nicely with the design specification - working with the board's strengths.
RPI device trees are difficult to implement in U-Boot and EDK2. I've had some success booting all RPI boards from a single firmware build, but this changes when switching EEPROM versions.
So my strategy now is to just have the built in Net boot as the first option. I set zero restarts and 4 second timeout. If the proxy DHCP request is never found, we boot to NVME, USB etc.
If the BOOTP result is returned, the board jumps straight into HookOS.
jacobweinstock commentedon Aug 31, 2026
I'm happy to report that Raspberry PI 4b and 5 network booting are now natively supported by Tinkerbell and CaptainOS. tinkerbell/captain#67, tinkerbell/tinkerbell#805, and a couple other PRs made this possible. These are not yet in a tagged release so the latest from main will need to be used. Official docs are forthcoming (tinkerbell/tinkerbell#958).