Add SPL_BLOBLIST_PASS_REGS to pass the bloblist to the next phase in registers, with the register conventions of the Firmware Handoff spec. SPL works out the register values once, right after finishing the bloblist, and keeps them in struct spl_image_info. The default jump_to_image() starts the next phase with them. Without the option, or if there is no bloblist to pass, the next phase is started without arguments as before.
U-Boot proper already looks for a bloblist in its boot registers, but SPL never puts one there, so the only way to hand the SPL bloblist on is a fixed address in memory that every phase has to agree on. Memory at a fixed address can also still hold a bloblist from an earlier boot, for example after a warm reset. Passing it in registers ties it to the current boot. Architectures and boards that provide their own jump_to_image() are not changed, but can use the same register values. Signed-off-by: David Lechner <[email protected]> --- common/Kconfig | 13 +++++++++++++ common/spl/spl.c | 21 ++++++++++++++++++++- include/spl.h | 3 +++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/common/Kconfig b/common/Kconfig index 92bf31f038b..4180755525d 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -1234,6 +1234,19 @@ config SPL_BLOBLIST_ALLOC endchoice +config SPL_BLOBLIST_PASS_REGS + bool "Pass the bloblist to the next phase in registers" + depends on ARM + help + Pass the bloblist to the next phase, normally U-Boot proper, in + registers with the register conventions of the Firmware Handoff + specification. The next phase then finds the bloblist without relying + on a fixed address in memory. + + SPL works out the register values in struct spl_image_info. The + default jump_to_image() uses them, other implementations need to do + the same. + endif # SPL_BLOBLIST if TPL_BLOBLIST diff --git a/common/spl/spl.c b/common/spl/spl.c index 6c9a1a1cbcc..6d81984428c 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -401,12 +401,23 @@ int spl_load(struct spl_image_info *spl_image, __weak void __noreturn jump_to_image(struct spl_image_info *spl_image) { + typedef void __noreturn (*image_entry_args_t)(ulong, ulong, ulong, ulong); typedef void __noreturn (*image_entry_noargs_t)(void); + debug("image entry point: 0x%lx\n", spl_image->entry_point); + + if (CONFIG_IS_ENABLED(BLOBLIST_PASS_REGS) && + spl_image->bloblist_args_valid) { + const ulong *args = spl_image->bloblist_args; + image_entry_args_t image_entry_args = + (image_entry_args_t)spl_image->entry_point; + + image_entry_args(args[0], args[1], args[2], args[3]); + } + image_entry_noargs_t image_entry = (image_entry_noargs_t)spl_image->entry_point; - debug("image entry point: 0x%lx\n", spl_image->entry_point); image_entry(); } @@ -846,6 +857,14 @@ void board_init_r(gd_t *dummy1, ulong dummy2) printf("Warning: Failed to finish bloblist (ret=%d)\n", ret); } + if (CONFIG_IS_ENABLED(BLOBLIST_PASS_REGS)) { + ret = xferlist_to_boot_arg(spl_image.bloblist_args); + if (ret) + printf("Warning: Failed to pass bloblist (ret=%d)\n", + ret); + else + spl_image.bloblist_args_valid = true; + } spl_board_prepare_for_boot(); diff --git a/include/spl.h b/include/spl.h index 390d18fd9d5..2b8a2f02835 100644 --- a/include/spl.h +++ b/include/spl.h @@ -298,6 +298,9 @@ struct spl_image_info { ulong fdt_size; u32 flags; void *arg; + /* Register values to pass a bloblist to the next phase, if valid */ + ulong bloblist_args[4]; + bool bloblist_args_valid; #ifdef CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK ulong dcrc_data; ulong dcrc_length; -- 2.53.0
