[BBB] usb boot using BOOTP and TFTP - solution

This forum is for supported devices using an ARMv7 Texas Instruments (TI) SoC.

[BBB] usb boot using BOOTP and TFTP - solution

Postby Zeno » Thu Apr 01, 2021 4:38 pm

Hello all,
recently I've been playing with booting BBB via USB to ease and automate flashing process. Through the fiddling, I found some peculiar things that are worth mentioning. First of all, through the net, there are some scattered informations regarding this procedure, from which I relied mostly on these two:
BBBlfs will probably work on its own as it incorporates bootp and tftp in itself, but I was looking for more general mechanism and simply digged in... :) Therefore I only used precompiled binary blobs from BBBlfs github page.

So lets recapitulate the boot process:
1) Eject external SD if any, hold S2 on BBB and connect your PC and P4 port on BBB via mini-USB cable
2) Internal AM335x ROM bootloader boots and exposes RNDIS network interface and asks for DHCP/BOOTP configuration
3) DHCP server on your PC then assigns IP to ROM bootloader and as a part of the same DHCP/BOOTP reply, sends name of U-boot SPL (secondary program loader) binary that it should boot, this is then requested and transferred via TFTP from your PC.
4) Once transferred, SPL boots in the same manner and again requests for DHCP/BOOTP, this time our server has to send other filename as part of its reply, that is u-boot booloader binary filename.
5) U-boot transfers, boots and here comes last booting step, TFTP is again in work, but your DHCP is not responsible anymore. U-boot simply asks for specific binary on its own using specific server IP (configured in U-boot at compile time), this binary is now flattened image tree (FIT) that includes kernel + DTB + ramdisk.
6) Uploaded kernel starts and exposes onboard eMMC as USB mass storage that simply attaches as SCSI disk to your PC, now you can simply "dd" your image to/from BBB eMMC.

As my system, I am using regular archlinux on my desktop PC, the most peculiar thing was setting up DHCP/BOOTP and TFTP servers. On the first try, I experimented with systemd-networkd to set up DHCP server of its own to send BOOTP options along. But I failed no manner what I tried, so the only thing I made systemd-networkd for me was to bring up the RNDIS interface and assign IP to it. Then I chose regular dhcp server for which some examples were available, configured subnets and to send corresponding binary filenames in DHCP/BOOTP responses, strange enough this failed too. Digged in tcpdump and in both previous cases, after DHCP/BOOTP responses there was no TFTP request for binary blob name which was sent, as if there was something wrong/incompatible (maybe because BOOTP is an older subset of DHCP and does not support dynamic addresses?). This helplessness led me to try dnsmasq - surprisingly this way worked quite easily! Also have to mention that at first I tried to use xinetd with tftpd as TFTP server, but tftpd accepts only absolute filenames, this proved critical in step 5, where U-boot asks for relative file named "itb" (which is hardcoded and wont change without recompilation of u-boot). As dnsmasq has its own tftp implementation which is sufficient and supports relative file names, my problem reduced only to configuring dnsmasq correctly, lets look on the results:

1) systemd-networkd profile:
Code: Select all

I have to comment here, that interface naming scheme in systemd-networkd causes a bit of head-ache. In the process, RNDIS restarts several times (between each boot stage), mac addresses of BBB change too and interface names on PC side too. For example MAC 88:c2:55:84:1f:ab and "enp2s0f0u13" for AM335x ROM, MAC 92:af:b8:15:db:77 and "enp2s0f0u13c2" for U-boot SPL and FIT. Sure, you can change interface name via udev rule like this:
Code: Select all
UBSYSTEM=="net" ACTION=="add", DEVPATH=="/devices/pci*/*XX.X/*/usb1/*", NAME="usb0"

but it is not necessary and you would have to use same USB port on your PC all the time. Good thing is, that systemd-networkd profile could contain wildcards and dnsmasq could be configured to listen on specific interfaces (or all except for...). Also local IP is a must for last U-boot stage when loading FIT image via TFTP.

2) dnsmasq config important options:
Code: Select all
#Enable only DHCP and TFTP
#Listen only on RNDIS interfaces (my case)
#Set range of dhcp addresses ( should be your PC address)
#switch between binary blobs in each stage based on vendor class string
dhcp-vendorclass=set:am335x,AM335x ROM
dhcp-vendorclass=set:ubootspl,AM335x U-Boot SPL
#fork, send spl for AM335x ROM, uboot for SPL
# Enable dnsmasq's built-in TFTP server
#Set tftp root to directory where your binary blobs are located

Basically this is all you need to have in your /etc/dnsmasq.conf. One more important thing to mention, dnsmasq must be run with "--bootp-dynamic" parameter, otherwise you must allocate IP based on MAC in your dnsmasq.conf like this:
Code: Select all

also "--leasefile-ro" parameter is probably essential because --bootp-dynamic causes leases to last/stay forever. Also you should not bind interfaces as they go up and down trough the process (dnsmasq wont start if they are down).

3) Last thing I should comment is relative to binary blobs from BBBlfs:
Download these three files in your tftp root directory (based on dnsmasq config, /XXX/tftpboot). Binary blob "fit" must be renamed to "itb". You can see in this patch (in CONFIG_BOOTCOMMAND changes)
that U-boot tries to TFPT blob named itb, also you can see that its IP is hardcoded to and it expects TFTP server on, hence systemd-networkd profile address.

4) Summary:
- Configure systemd network profile to set up RNDIS interface properly with IP, no DHCP (reload daemons, restart).
- Download binary blobs into designated TFTP root folder and rename "fit" to "itb".
- Configure dnsmasq as BOOTP/TFTP server according to provided config and start with "dnsmasq --bootp-dynamic --leasefile-ro"
- Hold S2 on BBB and plug into USB, after ~30s block device of exposed internal eMMC attaches to your PC.
- Clone/flash using for example:
Code: Select all
dd if=/dev/sdX | gzip -c  > ./image.img.gz
gunzip -c ./image.img.gz | dd of=/dev/sdX

Hope this helps and have a nice day.
Posts: 14
Joined: Wed May 03, 2017 5:00 pm

Re: [BBB] usb boot using BOOTP and TFTP - solution

Postby Zeno » Thu Jun 24, 2021 2:22 pm

Hello all,
I just found out a bit of problems facing usb boot with BBB industrial from seedstudios (the one with red PCB) while using the aforementioned process. This BBB has some new revision of eMMC card and that binary blob (FIT) used from BBBlfs complains about it and is not able to create block device to expose it via rndis g_mass_storage. Well, it is not unexpected as the images from BBBlfs are 7 years old. So I used a little trick to create new FIT from up-to-date archlinuxarm installation. Need to mention that both SPL and Uboot in the first two boot stages are okay and still work. All steps are carried on BGB running on archlinuxarm (from SDcard or flashed).
Well, the process to build new ramdisk binary blob is as follows:
1) use some existing BBB, modify /etc/mkinitcpio.conf MODULES array so that it contains g_mass_storage, like this
Code: Select all

2) then use
Code: Select all
mkinitcpio -p linux-am33x
on your BBB to rebuild initramfs, then your initramfs will contain g_mass_storage module, that is what we needed the most

3) create some folder, enter it and then
Code: Select all
zcat /boot/initramfs-linux.img | cpio -idmv
to decompress this image to your folder

4) modify init script (in the root of your folder) so that it contains this:
Code: Select all


. /init_functions


. /config

run_hookfunctions 'run_earlyhook' 'early hook' $EARLYHOOKS
run_hookfunctions 'run_hook' 'hook' $HOOKS

#attach mmcblk manually
/bin/mknod /dev/mmcblk1 b 179 0

#expose device via rndis g_mass_storage
modprobe g_mass_storage file=/dev/mmcblk1 iSerialNumber=42 iManufacturer=Circuitco  iProduct=BeagleBone-Black


its just a minimized version with unnecessary stuff deleted, only extended by mmcblk1 node creation and g_mass_storage module load, save it.

5) still in the same directory, repack initramfs using the following
Code: Select all
find . | cpio -H newc -o > ./initramfs.cpio

Code: Select all
cat initramfs.cpio | gzip > ramdisk.cpio.gz

6) create and enter some other directory, copy ramdisk.cpio.gz (from step 5), /boot/dtbs/am335x-boneblack.dtb and /boot/zImage into this directory
7) download maker.its from BBBlfs
Code: Select all
wget -O maker.its https://raw.githubusercontent.com/ungureanuvladvictor/BBBlfs/master/tools/maker.its

8) make sure uboot-tools are installed and execute
Code: Select all
mkimage -f maker.its itb
this generates new FIT for you
9) place this itb in dnsmasq tftp boot directory (replace the old one) and you are ready to go!

If you do not want to bother with this process, I pasted the final generated blob here: https://paste.c-net.org/GreeneVenue
One last sidelight is, that via modification of maker.its and selected device tree, you should be able to create image for any other am335x based platform.
Have a nice day.
Posts: 14
Joined: Wed May 03, 2017 5:00 pm

Return to Texas Instruments (TI)

Who is online

Users browsing this forum: No registered users and 2 guests