Skip to main content

Network Boot OpenBMC u-boot

·3 mins
The steps I took may may vary depending on the used System on Chip (SoC) or SPI/Memory configuration.

Why Network Booting my BSP? #

If you are an (Open)BMC developer, you have probably struggled to test your firmware image. Messed up something in our BSP? Then you’d need to rebuild your image and flash it on the SPI/eMMC via SoCFlash, phosphor-ipmi-flash, an external SPI flasher, or some tooling specific to your SoC. This can be painful, slow, and cost-intensive if you manage to break the SPI, especially if you have to rebuild your image often.

Testing in QEMU is not always an option, particularly for hardware platforms or features that aren’t available in QEMU yet.

With network booting, you can test your BSP changes quickly without flashing it every time. Theoretically, you could also use this option to network boot OpenBMC itself, but this will be covered in another blog article.

I Want It! #

Cool. The implementation is fairly simple, but you need to have some knowledge about your SoC (and your BMC stack).

In this post, I’ll use the following configuration:

  • MT: Lenovo HyperScale HR630X
  • SoC: ASPEED AST2500-A2
  • RAM: 512MB
  • SPI: MX25L256
  • OpenBMC commit: 3b3525f

We need to differentiate the testing between u-boot and phosphor.

u-boot Chainloading #

If you want to test a new u-boot version without flashing, you need to modify the entry point of your new u-boot image.

Why? Because u-boot will compile the entry address into the binary. Even if you go to the address where you’ve loaded your new u-boot, the new one will instruct the CPU to jump to 0x0 by default (or whatever is configured).

To achieve that u-boot uses a different address (in our case the memory), we need to set the CONFIG_SYS_TEXT_BASE config variable in our u-boot config. I’ll use 0x83000000 for that (0x80000000 is the start address of the memory for my system).

It’s up to you if you want to have a modular config that can be activated on-demand in your build/<system>/conf/local.conf or if you want to have a static config. I’ll go with the modular way.

Since I want to do this on multiple Lenovo machines, I’ll add the config in my meta layer under recipes-bsp/u-boot/files.

meta-lenovo/meta-common/recipes-bsp/u-boot/files/memory-load.cfg
CONFIG_SYS_TEXT_BASE=0x83000000

The decision for 0x83000000 as address instead of 0x8 is because “I only want to make sure that it doesn’t get overwritten”.

To include it in u-boot-aspeed-sdk when I need it, we need to add a bbappend file in meta-lenovo/meta-common/recipes-bsp/u-boot called u-boot-aspeed-sdk_%.bbappend. Please note that if you have a Nuvoton-based SoC, Raspberry Pi, or QEMU x86, then you may need to use a different append target.

meta-lenovo/meta-common/recipes-bsp/u-boot/u-boot-aspeed-sdk_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"

UBOOT_NETWORK_BOOT ?= "0"

SRC_URI:append = "${@oe.utils.conditional('UBOOT_NETWORK_BOOT', '1', ' file://memory-load.cfg', '', d)}"

And now, you only need to add UBOOT_NETWORK_BOOT="1" in your local.conf and build the phosphor image.

Once done, upload the u-boot blob on a TFTP server.

The chainloading of the u-boot image in u-boot is fairly simple (ast_eth1 is the dedicated NIC. The name might be eth1 if you have u-boot 2019 already flashed):

u-boot commands to start new u-boot
setenv ethact ast_eth1
dhcp
tftp 0x83000000 tftp-server-v4:u-boot.bin
md 0x83000000 # make sure content is there
go 0x83000000

If you have a DHCPv4 server that sends the TFTP option (code 66), then it is possible that u-boot will automatically try to boot the provided filename. However, this can be an issue if your new binary does not start at 0x8 (or wherever your memory is located).