Boot Raspberry Pi 4 from net

Booting the Raspberry Pi from the network (aka PXE boot) allows you to use this small computer without the microSD memory card or the external flash drive connected to the USB port. In the internet you can find information how to boot the Raspberry Pi with PXE boot and NFS. In this article you will find information how to boot the Raspberry Pi with PXE boot and without NFS.

Prepare bootloader

Use Raspbian or other ready system which can be installed on the microSD memory card and update the bootloader in the Raspberry Pi by the following commands:

rpi-eeprom-config /lib/firmware/raspberrypi/bootloader/stable/pieeprom-2020-09-03.bin > boot.conf

Add/modify BOOT_ORDER, set it to BOOT_ORDER=0xf21

rpi-eeprom-config --out new-eeprom.bin --config boot.conf /lib/firmware/raspberrypi/bootloader/stable/pieeprom-2020-09-03.bin
rpi-eeprom-update -d -f new-eeprom.bin

Preparing DHCP server with booting from network

In this case I used isc-dhcp-server. Add the following lines into the range section of your DHCP server:

option tftp-server-name "192.168.1.1"; # option 66
option vendor-class-identifier "PXEClient"; # option 60
option vendor-encapsulated-options "Raspberry Pi Boot"; # option 43

Restart/reload you DHCP server.

Building the bare kernel and busybox with cross compiling

First, make sure that all dependencies needed for cross compiling are installed such as git, bc, bison, flex, libssl-dev, make, libc6-dev, libncurses5-dev, crossbuild-essential-arm64.

Build busybox:

git clone --depth=1 --branch=1_33_0 https://git.busybox.net/busybox
cd busybox
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- defconfig
# with static link
sed -i "s#^\# CONFIG_STATIC .*#CONFIG_STATIC=y#" .config
LDFLAGS="--static" make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j4

Build Linux kernel:

git clone --depth=1 https://github.com/raspberrypi/linux
cd linux
KERNEL=kernel8
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image modules dtbs -j4

Preparing initramfs and testing

Create initramfs:

cd busybox
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- install CONFIG_PREFIX=../ramfs
cd ../linux
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- INSTALL_MOD_PATH=../ramfs modules_install
cd ../ramfs
 find . | cpio --create --format='newc' | gzip > /srv/tftp/initrd
cd ..

Copy kernel and device trees:

cp linux/arch/arm64/boot/Image /srv/tftp/vmlinuz
cp linux/arch/arm64/boot/dts/broadcom/*.dtb /srv/tftp/

Create /srv/tftp/cmdline.txt file with the following content:

console=serial0,115200 console=tty rootfstype=ramfs root=/dev/ram rw rootwait elevator=deadline

Create /srv/tftp/config.txt file with the following content:

disable_overscan=1
kernel=vmlinuz
initramfs initrd
arm_64bit=1

Downlod bootloader files:

cd /srv/tftp
wget -q https://github.com/raspberrypi/firmware/raw/master/boot/{fixup,fixup4}.dat
wget -q https://github.com/raspberrypi/firmware/raw/master/boot/{start,start4}.elf

Testing

If everything is ready, connect the Raspberry Pi to the computer ethernet port, connect the USB-C cable with power, connect the Raspberry Pi with the external screen and watch the boot process:

Sources

  • https://brennan.io/2019/12/04/rpi4b-netboot/
  • https://balau82.wordpress.com/2010/03/27/busybox-for-arm-on-qemu/
  • https://wiki.beyondlogic.org/index.php?title=Cross_Compiling_BusyBox_for_ARM
  • https://www.raspberrypi.org/documentation/linux/kernel/building.md