Building OpenSBI and Uboot

HI all,
I have a maybe kiddy question. I’m still newbie in bootchain.
I want to slightly change OpenSBI from vendor image for some reasons, so I need to rebuild it.
Additionally it seems it will be useful to know how to build and install UBoot too.

I’ve tried to find some info about how to make it step by step (at least and generally).
I’ve found something but still have some questions. Maybe because I still have puzzles but don’t have a full picture in my mind.

So, I’ve found some pipeline to build SiFive HiFive Premier P550 firmware Makefile to create SiFive HiFive Premier P550 firmware · GitHub
It generate and provided files like:

./opensbi/build/platform/eswin/eic770x/firmware/fw_payload.bin
./opensbi/build/platform/eswin/eic770x/firmware/fw_dynamic.bin
./opensbi/build/platform/eswin/eic770x/firmware/fw_jump.bin

./u-boot/build_eswin/u-boot.bin

./hifive-premier-p550-tools/second_boot_fw/second_boot_fw.bin
./hifive-premier-p550-tools/ddr-fw/ddr_fw.bin
./hifive-premier-p550-tools/bootloader_ddr5_secboot.bin

The first question.
As you can see in

and

the script use specific versions.

How to know which commit U-Boot, OpenSBI, Esbd-77serial-nsign, meta-sifive I should use to build correct build?

The second question
it generate ./hifive-premier-p550-tools/bootloader_ddr5_secboot.bin
As understand it contain a new OpenSBI and UBoot.

Does it, in generally, the same like standard bootloader_P550.bin (for example from this https://github.com/eswincomputing/hifive-premier-p550-ubuntu/releases/download/2025.10.30/bootloader_P550.bin)
Can I burn generated hifive-premier-p550-tools/bootloader_ddr5_secboot.bin to my board like this

ext4load usb 0 0x90000000 bootloader_ddr5_secboot.bin
es_burn write 0x90000000 flash

Will this update OpenSBI and Uboot?

And after that will the installed OS from p550-ubuntu-24.04-preinstalled-server-riscv64_20251210_1925_39.img.zst still work or I need to adapt the OS to a new bootloader (bootloader_ddr5_secboot.bin) somehow?

Sorry for such many words.

Clarify a few things:

The bootchain is a basically a tarball in ESWIN’s format that can be read by the ROM of the chip. It describes different stage images, such as secondary init second_boot_fw, DDR init ddr_fw.bin, and the actual bootloader fw_payload.bin (opensbi+u-boot). What actually happened is the small 32-bit SCPU core starts first on power-on and runs ROM, then it parses from the bootchain in SPI flash and invokes secondary init + DDR init. Finally it copies bootloader (opensbi+u-boot) to DRAM, and kick start the 64-bit MCPU cores. This kind of bootchain is packaged by Esbd-77serial-nsign. second/ddr_fw are all closed source blobs from ESWIN, but bootloader we can change it.

If you go the meta-sifive route, then there’s no need to care about the versioning of different components. They are already specified by the manifest files. Just check-out this branch GitHub - sifiveinc/meta-sifive at rel/meta-sifive/hifive-premier-p550 and it’ll describe all the git commits of all repos + any private patches applied on top of it.

If you decide to do everything manually, then mimic what meta-sifive does is a good start. For me, I do everything manually for bootchain, and what I learned:

For u-boot/OS compatibility, no need to worry so much. Ubuntu carries it’s own device-tree for kernel, and kernel/grub speaks EFI protocol to u-boot, so it’s properly interfaced.

And yes, you can es_burn the new bootchain to the board. Just make sure you know how to recover the board before attempting. Following the board recover procedure is a good exercise.

BTW, you can use the discord channel from Works with RISC-V to chat on eic770x/p550: Discord

1 Like

Hi, Bo,
Thanks a lot for deep explanation. Your answers are great, as usual.

It seems that in generally all clear and it looks like I mostly used the right way but after your explanation I will try to correct it. I mean will use your uboot and other feature mentioned by you.

Only one thing makes me worry.
I’ve looked to meta-sifive and found that meta-sifive has additional patches (0001-0007) for opensbi and an insignificant patch for uboot (you already has it in your config).

I guess that these patches made for vanilla opensbi (GitHub - riscv-software-src/opensbi: RISC-V Open Source Supervisor Binary Interface).

But I use ESWIN openSBI for my build process.

Do I need to apply meta-sifive (provided by sifiveinc) additional patches for my ESWIN openSBI (provided by eswin)?
Wouldn’t that lead to chaos in openSBI? Because ESWIN openSBI already has some features from meta-sifive patches and some features that doesn’t have meta-sifive and vanilla openSBI.

If you are using ESWIN’s opensbi repo, then no need for meta-sifive’s opensbi patches. Those patches are only meant for vanilla opensbi, and only applicable on top of this commit: meta-sifive/recipes-bsp/opensbi/opensbi-sifive-hf-prem_1.6.bb at 098ca1765fdebdad5d09d62be9731bca73280274 · sifiveinc/meta-sifive · GitHub

I have success with the following opensbi branch + u-boot branch from ESWIN (no other patches needed on top):

For u-boot, use make hifive_premier_p550_defconfig. For opensbi, my build parameters are as follows:

make CROSS_COMPILE=riscv64-unknown-linux-gnu- \
  PLATFORM=eswin/eic770x \
  PLATFORM_RISCV_ABI=lp64 \
  PLATFORM_RISCV_ISA=rv64imafdc_zicsr_zifencei  \
  FW_TEXT_START=0x80000000 \
  FW_PAYLOAD_OFFSET=0x200000 \
  FW_PAYLOAD_FDT_ADDR=0xf8000000 \
  FW_PAYLOAD_PATH=u-boot-nodtb.bin \
  FW_FDT_PATH=u-boot.dtb \
  BUILD_INFO=y \
  CHIPLET=BR2_CHIPLET_1 \
  CHIPLET_DIE_AVAILABLE=BR2_CHIPLET_1_DIE0_AVAILABLE \
  MEM_MODE=BR2_MEMMODE_FLAT \
  PLATFORM_CLUSTER_X_CORE=BR2_CLUSTER_4_CORE \
  ENABLE_VPU_SDK=0 \
  ENABLE_ECC=0

Great, thanks a lot

Great, it works well.
Thanks a lot.

I have one more question.
If someone could shed some light on this, I’d appreciate it

I want to load opensbi part from tftp. I can make
ext4load usb 0 0x90000000 bootloader_ddr5_secboot.bin

But if I can change OpenSBI on the fly (without burning it to a SPI flash) it will be more flexible.

I’ve found that I can compile fw_dynamic or fw_jump (opensbi+u-boot parts).
Can I load fw_dynamic or fw_jump from tftp in Uboot shell?

If yes, can I install for example OpenSBI 1.2 (that contain a ddr training and etc) and load fw_dynamic or fw_jump from (for example) OpenSBI 1.3 from tftp in Uboot shell?
Or Do I have to use all the parts of OpenSBI from the same version?

You are really hacking deep! Basically you can’t change OpenSBI on the fly when the 64-bit cores (MCPU) has already started opensbi/u-boot, so no, you can’t do it in u-boot. However, good news is that you can do it with UART boot. See my instructions here:

I used it to be able to iterate quickly. That’s how I managed to code up the support for EIC7700 in upstream OpenSBI. It allows me to boot a new OpenSBI/u-boot build without flash in 1 minute, which is pretty fast actually.

1 Like

Ho ho, great approach, it looks awesome.

I’ve already could see something like this but decided to put close looking at this on the back burner.
It seems now it’s a high time to deep dive to this too.

Thanks a lot for your instructions. It really helpful.

Will try it and return with feedback.

Great
It works
I’ve added only fw_payload.bin instead of stub spin-mcpu.bin

git diff uart/config.txt
diff --git a/board/bootchain/uart/config.txt b/board/bootchain/uart/config.txt
index 6d6a225..21d0a20 100644
--- a/board/bootchain/uart/config.txt
+++ b/board/bootchain/uart/config.txt
@@ -2,7 +2,7 @@
  bootchain_link_addr=3000c000
  out=bootchain.ihex
  {
- in=../archive/second_boot_fw-20240802.bin
+ in=../archive/my/second_boot_fw.bin
  sign_link_addr=30008000
  image_link_addr=30008000
  boot_flags=SCPU
@@ -35,7 +35,7 @@
  dl_irq_ofs=00000000
  }
  {
- in=../archive/ddr_fw-1.3.xzloader.bin
+ in=../archive/my/ddr_fw.bin
  sign_link_addr=59000000
  image_link_addr=59000000
  boot_flags=SCPU
@@ -68,7 +68,7 @@
  dl_irq_ofs=00000000
  }
  {
- in=../archive/spin-mcpu.bin
+ in=../archive/my/fw_payload.bin
  sign_link_addr=80000000
  image_link_addr=80000000
  boot_flags=MCPU
@@ -100,3 +100,4 @@
  dl_irq_num=00000000
  dl_irq_ofs=00000000
 }
+

Only one thing that I’ve would ask
Now it take too much time. I can see that you somehow compress *.bin

git clone --recurse-submodules https://github.com/ganboing/xz-loader.git
cd xz-loader/

I’ve added

all: test.elf fw_payload.bin fw_payload-rv64.bin

but have some issue

make

cc -Ixz-embedded/linux/include/linux -Iconfig -std=gnu11 -fno-strict-aliasing -ffunction-sections -fdata-sections -fsanitize=address -fPIE -Wall -Os -Wl,--gc-sections -o test.elf test.c string.c printf.c decompress.c payload.S xz-embedded/linux/lib/xz/xz_crc32.c xz-embedded/linux/lib/xz/xz_dec_stream.c xz-embedded/linux/lib/xz/xz_dec_bcj.c xz-embedded/linux/lib/xz/xz_dec_lzma2.c
test.c:7:13: error: 'PAYLOAD_SIZE' undeclared here (not in a function)
    7 | uint8_t buf[PAYLOAD_SIZE];
      |             ^~~~~~~~~~~~
payload.S:7:10: error: #error "PAYLOAD_XZ must be defined"
    7 |         #error "PAYLOAD_XZ must be defined"
      |          ^~~~~
make: *** [Makefile:62: test.elf] Error 1

Sorry for kiddy question.

There’s no need to replace the spin-mcpu.bin with the actual bootloader. The purpose of it is to hold the MCPU (P550) cores at the first instruction, and ready for openocd to upload the actual bootloader and start debugging. Refer to the sections below: EIC770x-Docs/board/bootchain/UART-Boot.md at main · ganboing/EIC770x-Docs · GitHub and EIC770x-Docs/board/bootchain/UART-Boot.md at main · ganboing/EIC770x-Docs · GitHub

1 Like