valettearnaud
Netboot a raspberry 2 B with U-boot
When developing a low-level OS for the rpi, constantly swapping SD cards between the Pi and your machine quickly becomes a hassle. Every small change means physically removing the SD card, writing new files, reinserting it, and rebooting–wasting precious time.
A network boot setup eliminates this friction by allowing the Pi to fetch and boot your
latest program&|kernel directly from a TFTP server. Unfortunately the units made before
rpi 3 B aren't capable of doing so.
In this article U-boot is used as a mean to extend rpi2b on this specific feature, making
iterative OS development much smoother.
Files needed:
<your_board>.dtbbootcode.binstart.elffixup.dat
The latest boot files are in the Raspberry Pi firmware repository:
git clone --depth=1 https://github.com/raspberrypi/firmware.git
bootcode.bin:firmware/boot/bootcode.binstart.elf:firmware/boot/start.elffixup.dat:firmware/boot/fixup.datDTB files:firmware/boot/*.dtb
Copy them to your SD card’s boot partition.
Files to create
All these files should be present on your boot partition:
u-boot.bin
Do replace arm-none-eabi- with your cross-compiler of choice, given you're not
already on arm.
git clone git://git.denx.de/u-boot.git cd u-boot make ARCH=arm CROSS_COMPILE=arm-none-eabi- rpi_2_defconfig make ARCH=arm CROSS_COMPILE=arm-none-eabi-
This will generate u-boot.bin, do store it in the boot partition of your SD
card.
config.txt
Do replace the device_tree value with your board .dtb file.
The raspberry pi 2 B uses a broadcom 2836, but is is possible the adequate
.dtb file isn't called bcm2836.
Note that without some of these options, the rpi cannot use the eth, which
is necessary for us.
kernel=u-boot.bin enable_uart=1 hdmi_force_hotplug=1 hdmi_safe=1 hdmi_drive=2 device_tree=bcm2836-rpi-2-b.dtb boot_delay=1 dtoverlay=dwc2
boot.scr
That's the file u-boot uses as a bootscript. You can generate one based
on a boot.txt file you will write as needed.
Here we set tftp up to netboot any binary <your_program> at the instruction
located at 0x8000. This binary should be accessible from your tftp host,
reachable at the provided serverip/tftpserverip.
Here you can find more informations about what command you can use to boot,
bootm, bootz anything.
I use go because I set up my kernel _start section at a specific offset,
and I want to precisely execute this very precise instruction.
setenv company arva printenv company setenv ipaddr 192.168.1.101 setenv serverip 192.168.1.56 setenv tftpserverip 192.168.1.56 saveenv tftpboot 0x8000 <your_program> go 0x8000
Your file should end with a carriage return!
Then:
<path_to_u-boot_repo>/tools/mkimage -T script -d boot.txt boot.scr
TFTP server
On your host machine, set up a TFTP service: Arch documentation.
Here, we used /srv/tftp/ as a root folder to serve. This is where
<your_program> is located.
Launch
Once this is done, you can :
- Plug your raspberry pi unit to an ethernet cable
- (optional) plug it to HDMI to contemplate the u-boot splash screen
- Power it on
The unit should directly find the boot.scr bootflow and your kernel/program
should be launched: you don't have to modify anything on that SD card anymore and
can do continuous development without having to touch the unit.
Rebooting the unit will reload the kernel from tftp, you even can directly copy
your kernel on build to /srv/tftp/ in your Makefile for example.
... kernel7.img: $(BUILD_DIR)/kernel.elf mkdir -p $(IMG_DIR) $(ARMGNU)-objcopy -O binary $< $(IMG_DIR)/kernel7.img cp $(IMG_DIR)/kernel7.img /srv/tftp/kernel7.img ...