Eryn Wells

Booting a Raspberry Pi Over TFTP

Raspberry Pi OS Development

In order to do this, I modified the EEPROM bootloader bootloader according to the instructions in the Raspberry Pi documentation. That page is also on GitHub which might be a more stable location. On Raspbian on the Raspberry Pi:

1fw=/lib/firmware/raspberrypi/bootloader/stable/pieeprom-2020-09-03.bin
2rpi-eeprom-config $fw > ~/bootconf.txt
3vi ~/bootconf.txt
4rpi-eeprom-config --out ~/pieeprom-new.bin --config ~/bootconf.txt $fw
5sudo rpi-eeprom-update -d -f ~/pieeprom-new.bin
6sudo reboot

My updated bootconf.txt is:

 1[all]
 2BOOT_UART=1
 3WAKE_ON_GPIO=0
 4POWER_OFF_ON_HALT=0
 5DHCP_TIMEOUT=45000
 6DHCP_REQ_TIMEOUT=4000
 7TFTP_FILE_TIMEOUT=30000
 8ENABLE_SELF_UPDATE=1
 9DISABLE_HDMI=0
10BOOT_ORDER=0xf412

I enabled UART debugging, and set the boot order to be: network 0x2, SD card 0x1, USB mass storage 0x4, and finally reboot 0xf. These steps need to be repeated if the bootloader is updated via apt.

I enabled the TFTP server on my Mac:

1sudo launchctl load -F /System/Library/LaunchDaemons/tftp.plist
2sudo launchctl enable System/com.apple.tftpd
3sudo launchctl start com.apple.tftpd

I’m not sure if the enable command is actually necessary. This doesn’t actually start the tftpd daemon. Instead, macOS starts the daemon on demand when it notices an incoming tftp request on the network. Don’t be alarmed!

The tftp server looks for files to serve out of /private/tftpboot, and those things need to be world rwx, i.e. 777. By default (this is configurable) the Raspberry Pi queries for a directory named by its serial number.

1mkdir /private/tftpboot/$raspberry_pi_serial
2chmod 777 /private/tftpboot
3chmod -R 777 /private/tftpboot/*

Raspberry Pi looks for files of various names in that directory, one in particular by the name of start.elf.

Next, I had to update my Ubiquiti router’s DHCP server configuration (on the command line) to pass a tftp-server parameter in the DHCP payload. This step may be optional because you can also set TFTP_IP in the bootconf.txt above to specify the IP directly. On my router:

1configure
2set service dhcp-server shared-network-name LAN subnet $lan_cidr_subnet tftp-server-name $ip_of_mac
3commit
4save
5exit

I also gave my Mac a static IP, and renewed the DHCP lease so it took the new IP to make the whole process a little more smooth. Now, it appears the Raspberry Pi will attempt a TFTP boot, and I see queries in the logs on my Mac.

Further Reading