For a sandbox implementation, where code size is no object, it makes sense
to use the full bootstd drivers to load images.
For real boards, running from SRAM, this adds quite a bit of overhead.
Add a way to load the next phase using just the underlying storage
driver, to reduce code size. For now, only MMC is supported.
Change the log_debug() to show the load address and size in a more
neutral way, rather than suggesting that the load has already happened.
Series-to: u-boot
Series-cc: trini
Series-version: 2
Series-changes: 2
- Split up the first patch into 5 separate patches, to highlight code size
Cover-letter:
vbe: Series part F
This includes various patches towards implementing the VBE abrec
bootmeth in U-Boot. It mostly focuses on introducing a relocating
SPL-loader so that VBE can run in the limited amount of SRAM available
on many devices.
Another minor new feature is support in VBE for specifying the image
phase when loading from a FIT. This allows a single FIT to include
images for several boot phases, thus simplifying image-creation.
One lingering niggle in this series is that it has a different code path
for sandbox, since it does not support the relocating jump. It should be
possible to resolve this with additional work, but I have not attempted
this so far.
For v2, I have split the first patch into 5 pieces, to make it easier to
see the code-size impact, plus added a few tweaks to reduce code size.
Again, only MMC is supported so far.
Looking ahead, series G will have some more plumbing and H some rk3399
pieces. That should be enough to complete these feature.
Here is a run in my lab, with the VBE ABrec bootmeth. You can see that
VPL runs before memory is set up. SPL sets up memory and can be upgraded
in the field reliably.
$ ub-int vbe
Building U-Boot in sourcedir for rk3399-generic
Bootstrapping U-Boot from dir /tmp/b/rk3399-generic
Writing U-Boot using method rockchip
U-Boot TPL 2025.01-rc3-00345-gdfbdbf1eb56c-dirty (Jan 08 2025 - 10:47:58)
Trying to boot from vbe_abrec
load: Firefly-RK3399 Board
Using 'config-3' configuration
Trying 'image-vpl' firmware subimage
Using 'config-3' configuration
Trying 'fdt-3' fdt subimage
U-Boot VPL 2025.01-rc3-00345-gdfbdbf1eb56c-dirty (Jan 08 2025 - 10:47:58)
Trying to boot from vbe_abrec
load: Firefly-RK3399 Board
Starting with empty state
VBE: Firmware pick A at 800000
Using 'config-3' configuration
Trying 'spl' firmware subimage
Using 'config-3' configuration
Trying 'fdt-3' fdt subimage
Channel 0: DDR3, 800MHz
BW=32 Col=10 Bk=8 CS0 Row=15 CS1 Row=15 CS=2 Die BW=16 Size=2048MB
Channel 1: DDR3, 800MHz
BW=32 Col=10 Bk=8 CS0 Row=15 CS1 Row=15 CS=2 Die BW=16 Size=2048MB
256B stride
U-Boot SPL 2025.01-rc3-00345-gdfbdbf1eb56c-dirty (Jan 08 2025 - 10:47:58 -0700)
Trying to boot from vbe_abrec
load: Firefly-RK3399 Board
VBE: Firmware pick A at 900000
load_simple_fit: Skip load 'atf-5': image size is 0!
Relocating bloblist ff8eff00 to 100000: done
ns16550_serial serial@ff1a0000: pinctrl_select_state_full: uclass_get_device_by_phandle_id: err=-19
U-Boot 2025.01-rc3-00345-gdfbdbf1eb56c-dirty (Jan 08 2025 - 10:47:58 -0700)
SoC: Rockchip rk3399
Reset cause: POR
Model: Firefly-RK3399 Board
DRAM: 4 GiB (effective 3.9 GiB)
Core: 314 devices, 33 uclasses, devicetree: separate
MMC: mmc@fe310000: 3, mmc@fe320000: 1, mmc@fe330000: 0
Loading Environment from SPIFlash... Invalid bus 0 (err=-19)
*** Warning - spi_flash_probe_bus_cs() failed, using default environment
In: serial,usbkbd
Out: serial,vidconsole
Err: serial,vidconsole
Model: Firefly-RK3399 Board
Net: PMIC: RK808
eth0: ethernet@fe300000
starting USB...
Bus usb@fe380000: USB EHCI 1.00
Bus usb@fe3a0000: USB OHCI 1.0
Bus usb@fe3c0000: USB EHCI 1.00
Bus usb@fe3e0000: USB OHCI 1.0
Bus usb@fe900000: Register 2000140 NbrPorts 2
Starting the controller
USB XHCI 1.10
scanning bus usb@fe380000 for devices... 1 USB Device(s) found
scanning bus usb@fe3a0000 for devices... 1 USB Device(s) found
scanning bus usb@fe3c0000 for devices... 2 USB Device(s) found
scanning bus usb@fe3e0000 for devices... 1 USB Device(s) found
scanning bus usb@fe900000 for devices... 1 USB Device(s) found
scanning usb for storage devices... 0 Storage Device(s) found
Hit any key to stop autoboot: 0
END
Signed-off-by: Simon Glass <sjg@chromium.org>
VBE needs to load different images from a FIT depending on the xPL phase
in use. The IH_PHASE value is used to select the image to load.
Add the required logic to handle this. For compatibility with the
SPL-loader driver, fill out a struct spl_image_info with the details
needed to boot the next phase.
This is good enough for VBE-simple but ABrec will need the full set of
bootstd features. So add a USE_BOOTMETH define to control this.
Signed-off-by: Simon Glass <sjg@chromium.org>
Add FDT support so that this can be copied down in memory after loading
and made available to the new image.
Signed-off-by: Simon Glass <sjg@chromium.org>
This is fairly easy to use. The SPL loader sets up some fields in the
spl_image_info struct and calls spl_reloc_prepare(). When SPL is ready
to do the jump it must call spl_reloc_jump() instead of jump_to_image().
Add this logic.
Signed-off-by: Simon Glass <sjg@chromium.org>
When one xPL phase wants to jump to the next, the next phase must be
loaded into its required address. This means that the TEXT_BASE for the
two phases must be different and there cannot be any memory overlap
between the code used by the two phases. It also can mean that phases
need to be moved around to accommodate any size growth.
Having two xPL phases in SRAM at the same time can be tricky if SRAM
is limited, which it often is. It would be better if the second phase
could be loaded somewhere else, then decompressed into place over the
top of the first phase.
Introduce a relocating jump for xPL to support this. This selects a
suitable place to load the (typically compressed) next phase, copies
some decompression code out of the first phase, then jumps to this code
to decompress and start the next phase.
This feature makes it much easier to support Verified Boot for Embedded
(VBE) on RK3399 boards, which have 192KB of SRAM.
Signed-off-by: Simon Glass <sjg@chromium.org>
This function will be used by the relocating jumper too, so add a
typedef to the header file to avoid mismatches.
Signed-off-by: Simon Glass <sjg@chromium.org>
In many cases the FIT includes a devicetree. Add support for loading
this into a suitable place in memory.
Signed-off-by: Simon Glass <sjg@chromium.org>
In some cases only the 'loadable' property is present in the FIT.
Handle this by loading the first such image.
Signed-off-by: Simon Glass <sjg@chromium.org>
There is no guarantee that an FIT image starts on a block boundary. When
it doesn't, the image starts part-way through the first block.
Add logic to detect this and copy the image down into place.
Signed-off-by: Simon Glass <sjg@chromium.org>
At present the VBE implementation is limited to sandbox only. Adjust the
call to fit_image_load() to remove this limitation.
Signed-off-by: Simon Glass <sjg@chromium.org>
It is convenient to use TEXT_BASE as a place to hold the FIT header, but
this does not work in VPL, since SDRAM is not inited yet.
Allocate the memory instead. Ensure the size is aligned to the media
block-size so that it can be read in directly. Improve the
error-checking for blk_read() and add some more debugging.
Keep the existing TEXT_BASE mechanism in sandbox to avoid an
'Exec format error' when trying to run the image.
Signed-off-by: Simon Glass <sjg@chromium.org>
Loading a FIT is useful for other VBE methods, such as ABrec. Create a
new function to handling reading it.
Series-changes: 2
- Reword commit subject
- Move common code to the end of the file
Signed-off-by: Simon Glass <sjg@chromium.org>
All VBE methods read non-volatile data, so move this function into a
common file.
Series-changes: 2
- Split patch into several pieces
Signed-off-by: Simon Glass <sjg@chromium.org>
All VBE methods read a version string, so move this function into a
common file.
Series-changes: 2
- Split patch into several pieces
- Reduce inclusion of headers to only those necessary
Signed-off-by: Simon Glass <sjg@chromium.org>
VBE is currently quite careful with function arguments because it is
used in VPL which cannot be updated after manufacture. Bugs can cause
security holes.
Unfortunately this adds to code size.
In several cases we are reading values from a devicetree which is part
of U-Boot (or at least VPL) and so known to be good. Also, in several
places, getting bad values does not matter.
So change a few checks to assert() to reduce code size.
Series-changes: 2
- Add new patch to convert some checks to assertions
Signed-off-by: Simon Glass <sjg@chromium.org>
Pass the private data instead of the device, to help the compiler
optimise better. This saves 16 bytes of code on pinecube (rk3288)
Signed-off-by: Simon Glass <sjg@chromium.org>
Pass a struct udevice instead of the descriptor structure, since this is
the native argument for blk_read()
Series-changes: 2
- Split patch into several pieces
Signed-off-by: Simon Glass <sjg@chromium.org>
Move a few things into a new, common header file so that vbe-simple can
share code with the upcoming abrec.
Put struct simple_nvdata in it and rename it.
Series-changes: 2
- Split patch into several pieces
Signed-off-by: Simon Glass <sjg@chromium.org>
We should not be using the old blk_d...() interface, is only there to
aid migration to driver model.
Move to blk_read() instead.
Changes in v2:
- Split patch into several pieces
Signed-off-by: Simon Glass <sjg@chromium.org>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.