[PATCH 0/7] firmware: add FW_DYNAMIC_APPEND firmware type
Zong Li
zong.li at sifive.com
Mon Jul 6 20:39:47 PDT 2026
This series adds a fourth OpenSBI firmware type, FW_DYNAMIC_APPEND, next to
the existing FW_DYNAMIC, FW_JUMP and FW_PAYLOAD.
Motivation
==========
FW_DYNAMIC requires the previous booting stage to build a struct
fw_dynamic_info in memory and pass its address in a2. Some booting stages
cannot easily allocate and pass such a structure, but they can load the
OpenSBI image and patch a few words at a known location before jumping to
it. FW_DYNAMIC_APPEND targets exactly that case: the struct fw_dynamic_info
is appended into the OpenSBI binary and patched in place by the previous
stage. For example, the previous boot stage runs on a dedicated hart.
Therefore, it cannot set up CSRs of another hart that runs OpenSBI.
This scenario will occurs in server systems with secure boot.
Key design points
=================
- The appended struct fw_dynamic_info is placed immediately before .bss.
.bss is NOBITS and is dropped by 'objcopy -O binary', so a structure
after it would not be part of the flat .bin. Placing it before .bss
makes it the last PROGBITS content, i.e. it sits at the tail of the
.bin and can be located from the image size. The previous booting
tage can therefore find the structure at:
load_address + binary_file_size - sizeof(struct fw_dynamic_info)
- struct fw_dynamic_info gains a new 'boot_dtb' field (info version 3)
to carry the DTB address. Existing offsets are unchanged.
- The previous booting stage patches every field at runtime. The
reservation is a KEEP() PROGBITS section, so the zero-initialised
bytes still land at the tail of the .bin.
- On the cold-boot path (guarded by FW_DYNAMIC_APPEND), fw_base.S calls
fw_dynamic_append_boot_args() in fw_dynamic_append.S. The helper sets
a0 = mhartid, a2 = &appended struct, and a1 = boot_dtb, and clears the
reserved a3/a4 that fw_platform_init consumes. Only a0-a4 are handled
here, the remaining GPRs are already cleared by the existing _reset_regs
later on the cold path. The boot_dtb load is gated on info version 3, so
an older layout leaves a1 = 0 instead of reading past the struct.
Backward compatibility
======================
All changes for the existing three firmware types are compiled out: the
fw_base.S fixup and the .fw_dynamic_info output section are under
#ifdef FW_DYNAMIC_APPEND, which is defined only by fw_dynamic_append.S and
fw_dynamic_append.elf.ldS. FW_DYNAMIC, FW_JUMP and FW_PAYLOAD binaries are
byte-for-byte unchanged.
Build
=====
make PLATFORM=<platform_subdir> FW_DYNAMIC_APPEND=y
On the generic platform FW_DYNAMIC_APPEND=y is set in
platform/generic/objects.mk, so it is built by default.
Zong Li (7):
firmware: fw_dynamic: add boot_dtb field to struct fw_dynamic_info
firmware: fw_base.ldS: add .fw_dynamic_info output section before .bss
firmware: add fw_dynamic_append firmware type
firmware: fw_base.S: call fw_dynamic_append_boot_args on cold boot
firmware: build and enable the FW_DYNAMIC_APPEND firmware type
docs: firmware: document the FW_DYNAMIC_APPEND firmware type
docs: firmware: list FW_DYNAMIC_APPEND in fw.md
docs/firmware/fw.md | 19 ++++-
docs/firmware/fw_dynamic_append.md | 110 +++++++++++++++++++++++++++++
firmware/external_deps.mk | 1 +
firmware/fw_base.S | 11 +++
firmware/fw_base.ldS | 24 +++++++
firmware/fw_dynamic_append.S | 106 +++++++++++++++++++++++++++
firmware/fw_dynamic_append.elf.ldS | 24 +++++++
firmware/objects.mk | 2 +
include/sbi/fw_dynamic.h | 17 ++++-
platform/generic/objects.mk | 1 +
platform/template/objects.mk | 9 +++
11 files changed, 322 insertions(+), 2 deletions(-)
create mode 100644 docs/firmware/fw_dynamic_append.md
create mode 100644 firmware/fw_dynamic_append.S
create mode 100644 firmware/fw_dynamic_append.elf.ldS
--
2.43.7
More information about the opensbi
mailing list