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

Reply via email to