Boards with fixed U-Boot load and entry addresses do not need an image container for RAM boot. Allow raw downloads when SPL_RAW_IMAGE_SUPPORT is enabled, using the board's existing address configuration and the completed download length.
Keep recognized FIT and legacy images on their respective validation paths, so an invalid container cannot fall back to raw execution. Reject raw downloads when SPL FIT signature verification is enabled to prevent bypassing that verification with an unsigned image. Signed-off-by: Carlo Caione <[email protected]> --- common/spl/spl_ram.c | 28 ++++++++++++++++++++++++--- doc/android/fastboot.rst | 9 ++++++--- drivers/fastboot/Kconfig | 2 +- test/image/spl_fastboot.c | 48 ++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 75 insertions(+), 12 deletions(-) diff --git a/common/spl/spl_ram.c b/common/spl/spl_ram.c index 43d9bc95516..463f5e48929 100644 --- a/common/spl/spl_ram.c +++ b/common/spl/spl_ram.c @@ -49,21 +49,43 @@ int spl_ram_load_fit(struct spl_image_info *spl_image, void *fit, size_t size) return spl_load_simple_fit(spl_image, &load, 0, fit); } +static int spl_ram_load_raw(struct spl_image_info *spl_image, void *buf, + size_t size) +{ + if (CONFIG_IS_ENABLED(FIT_SIGNATURE)) + return -EPERM; + if (!IS_ENABLED(CONFIG_SPL_RAW_IMAGE_SUPPORT)) + return -ENOEXEC; + if (!size || size == SIZE_MAX) + return -EINVAL; + if (size > CONFIG_SYS_BOOTM_LEN) + return -EFBIG; + + spl_set_header_raw_uboot(spl_image); + if (size > ULONG_MAX - spl_image->load_addr) + return -EOVERFLOW; + spl_image->size = size; + memmove(map_sysmem(spl_image->load_addr, size), buf, size); + return 0; +} + int spl_ram_load(struct spl_image_info *spl_image, void *buf, size_t size) { struct legacy_img_hdr *header = buf; struct spl_ram_image image = { .data = buf, .size = size }; struct spl_load_info load; - /* Require a complete magic word to identify a headered image. */ + /* A buffer too short for a magic word can only be a raw image. */ if (size < sizeof(header->ih_magic)) - return -EINVAL; + return spl_ram_load_raw(spl_image, buf, size); /* FIT images can contain multiple payloads with separate load addresses. */ if (image_get_magic(header) == FDT_MAGIC) return spl_ram_load_fit(spl_image, buf, size); + + /* Only unknown magic selects raw; recognized formats keep their errors. */ if (image_get_magic(header) != IH_MAGIC) - return -ENOEXEC; + return spl_ram_load_raw(spl_image, buf, size); /* Legacy images need a complete header and an uncompressed payload. */ if (CONFIG_IS_ENABLED(FIT_SIGNATURE)) diff --git a/doc/android/fastboot.rst b/doc/android/fastboot.rst index 73241e717b8..73b7825d726 100644 --- a/doc/android/fastboot.rst +++ b/doc/android/fastboot.rst @@ -157,9 +157,12 @@ FIT verification uses the board's existing SPL configuration. ``CONFIG_SPL_LEGACY_IMAGE_FORMAT`` also permits uncompressed legacy U-Boot images, using their header's load address and entry point. Legacy CRC checks follow ``CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK``. -With ``CONFIG_SPL_FIT_SIGNATURE``, legacy downloads are rejected to prevent -bypassing FIT verification. -Raw U-Boot binaries are not supported. +``CONFIG_SPL_RAW_IMAGE_SUPPORT`` permits a raw ``u-boot.bin``. SPL uses its +configured or binman-provided load address and entry point, and loads exactly +the downloaded bytes. The image must match that address and firmware handoff +contract; raw images carry no size, checksum or signature of their own. +With ``CONFIG_SPL_FIT_SIGNATURE``, legacy and raw downloads are rejected to +prevent bypassing FIT verification. The loader accepts these images directly or inside the Android v0 wrapper added by the standard fastboot client; separate ramdisk and second-stage diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig index f57b959f0ea..d83f0e371a8 100644 --- a/drivers/fastboot/Kconfig +++ b/drivers/fastboot/Kconfig @@ -71,7 +71,7 @@ config SPL_FASTBOOT_BOOT bool "Boot images downloaded with fastboot in SPL" depends on ARM || MIPS || RISCV || SANDBOX depends on SPL_FASTBOOT && SPL_FRAMEWORK - depends on SPL_LOAD_FIT || SPL_LEGACY_IMAGE_FORMAT + depends on SPL_LOAD_FIT || SPL_LEGACY_IMAGE_FORMAT || SPL_RAW_IMAGE_SUPPORT depends on !SPL_LOAD_FIT_FULL && !SPL_USB_SDP_SUPPORT help Enable fastboot boot to load a downloaded image through the SPL diff --git a/test/image/spl_fastboot.c b/test/image/spl_fastboot.c index 1263416ba8d..b519ac8911f 100644 --- a/test/image/spl_fastboot.c +++ b/test/image/spl_fastboot.c @@ -124,10 +124,13 @@ static int check_images(struct unit_test_state *uts, void *image, size_t size, NULL, NULL)); ut_assertok(check_download(uts, image, size - 1, NULL, NULL)); - magic = fdt_magic(image); - fdt_set_magic(image, 0); - ut_assertok(check_download(uts, image, size, NULL, NULL)); - fdt_set_magic(image, magic); + if (!IS_ENABLED(CONFIG_SPL_RAW_IMAGE_SUPPORT) || + CONFIG_IS_ENABLED(FIT_SIGNATURE)) { + magic = fdt_magic(image); + fdt_set_magic(image, 0); + ut_assertok(check_download(uts, image, size, NULL, NULL)); + fdt_set_magic(image, magic); + } /* The Android envelope is independent of the payload format. */ if (type != FIT_INTERNAL) @@ -139,7 +142,7 @@ static int check_images(struct unit_test_state *uts, void *image, size_t size, ut_assertok(check_download(uts, wrapped, wrapped_size, info, data)); ut_assertok(check_download(uts, wrapped, sizeof(*hdr) - 100, NULL, NULL)); ut_assertok(check_download(uts, wrapped, wrapped_size - 1, NULL, NULL)); - /* Android padding must not make a truncated FIT payload look complete. */ + /* Android padding must not make a truncated payload look complete. */ hdr->kernel_size = cpu_to_le32(size - 1); ut_assertok(check_download(uts, wrapped, wrapped_size, NULL, NULL)); hdr->kernel_size = cpu_to_le32(size); @@ -190,3 +193,38 @@ out: SPL_IMG_TEST(spl_test_fastboot, FIT_INTERNAL, 0); SPL_IMG_TEST(spl_test_fastboot, FIT_EXTERNAL, 0); SPL_IMG_TEST(spl_test_fastboot, LEGACY, 0); + +static int spl_test_fastboot_raw(struct unit_test_state *uts) +{ + u8 image[31], buffer[sizeof(image)], *dest; + struct spl_image_info expected = {}, loaded = {}; + int ret; + + if (!IS_ENABLED(CONFIG_SPL_RAW_IMAGE_SUPPORT)) + return -EAGAIN; + generate_data(image, sizeof(image), __func__); + spl_set_header_raw_uboot(&expected); + dest = map_sysmem(expected.load_addr, sizeof(image) + 1); + dest[sizeof(image)] = 0xa5; + fastboot_init(buffer, sizeof(buffer)); + ut_assertok(download_image(uts, image, sizeof(image))); + ut_assertok(run_fastboot_command(uts, "boot", FASTBOOT_COMMAND_BOOT, "OKAY")); + fastboot_boot(); + ret = spl_fastboot_load(&loaded); + fastboot_init(NULL, 0); + ut_asserteq(0xa5, dest[sizeof(image)]); + if (CONFIG_IS_ENABLED(FIT_SIGNATURE)) { + ut_asserteq(-EPERM, ret); + ut_asserteq(0, loaded.size); + return 0; + } + ut_assertok(ret); + ut_asserteq(expected.load_addr, loaded.load_addr); + ut_asserteq(expected.entry_point, loaded.entry_point); + ut_asserteq(expected.os, loaded.os); + ut_asserteq(sizeof(image), loaded.size); + ut_asserteq_mem(image, dest, sizeof(image)); + return 0; +} + +SPL_TEST(spl_test_fastboot_raw, 0); -- 2.56.0
