[PATCH 00/26] test: spl: Test some load methods

This series adds some tests for various SPL load methods, with the intent of helping debug v6 of [1]. With that in mind, notable omissions include NAND and ROMAPI, which both lack sandbox implementations, and OS_BOOT, which I have deferred due to its complexity. Semihosting is also omitted, but I think we can test that with qemu.
In order to test all of these methods, we must first generate suitable images, possibly on filesystems. While other tests have historically generated these images using external tools (e.g. mkimage, mkfs, etc.), I have chosen to generate them on the fly. This is for a few reasons:
- By removing external dependencies on pytest to create certain files, the tests become self-contained. This makes them easier to iterate on and debug. - By generating tests at runtime, we can dynamically vary the content. This helps detect test failures, as even if tests are loaded to the same location, the expected content will be different. - We are not testing the image parsers themselves (e.g. spl_load_simple_fit or fs_read) but rather the load methods (e.g. spl_mmc_load_image). It is unnecessary to exercise full functionality or generate 100% correct images. - By reducing functionality to only what is necessary, the complexity of various formats can often be greatly reduced.
This series depends on [2-3], which are small fixes identified through this patch set. The organization of patches in this series is as follows:
- General fixes for bugs which are unlikely to be triggered outside of this series - Changes to IMX8 container images to facilitate testing - General prep. work, particularly regarding linker issues - The tests themselves
Mostly-passing CI at [4]; I have since fixed the typo/missing cast.
[1] https://lore.kernel.org/all/20230731224304.111081-1-sean.anderson@seco.com/ [2] https://lore.kernel.org/all/20230930204246.515254-1-seanga2@gmail.com/ [3] https://lore.kernel.org/all/20231008014748.1987840-1-seanga2@gmail.com/ [4] https://source.denx.de/u-boot/custodians/u-boot-clk/-/pipelines/18091
Sean Anderson (26): spl: legacy: Fix referencing _image_binary_end spl: nor: Don't allocate header on stack spl: fit: Fix entry point for SPL_LOAD_FIT_FULL arm: imx: Fix i.MX8 container load address arm: imx: Add newlines after error messages arm: imx: Add function to validate i.MX8 containers arm: imx: Check header before calling spl_load_imx_container Move i.MX8 container image loading support to common/spl spl: Allow enabling SPL_OF_REAL and SPL_OF_PLATDATA at the same time lib: acpi: Fix linking SPL when ACPIGEN is enabled fs: ext4: Fix building ext4 in SPL if write is enabled fs: Compile in sandbox filesystem in SPL if it is enabled net: Fix compiling SPL when fastboot is enabled net: bootp: Move port numbers to header net: bootp: Fall back to BOOTP from DHCP when unit testing spl: Don't cache devices when UNIT_TEST is enabled spl: Use map_sysmem where appropriate test: spl: Split tests up and use some configs test: spl: Fix spl_test_load not failing if fname doesn't exist test: spl: Add functions to create images test: spl: Add functions to create filesystems test: spl: Add a test for spl_blk_load_image test: spl: Add a test for the MMC load method test: spl: Add a test for the NET load method test: spl: Add a test for the NOR load method test: spl: Add a test for the SPI load method
.azure-pipelines.yml | 4 + .gitlab-ci.yml | 7 + MAINTAINERS | 2 + arch/arm/include/asm/mach-imx/ahab.h | 2 +- arch/arm/mach-imx/Kconfig | 13 - arch/arm/mach-imx/Makefile | 2 +- arch/arm/mach-imx/cmd_dek.c | 4 +- arch/arm/mach-imx/ele_ahab.c | 4 +- arch/arm/mach-imx/image-container.c | 4 +- arch/arm/mach-imx/imx8/ahab.c | 4 +- arch/arm/mach-imx/spl_imx_romapi.c | 8 +- arch/sandbox/cpu/spl.c | 3 + arch/sandbox/cpu/start.c | 9 +- arch/sandbox/cpu/u-boot-spl.lds | 2 + arch/sandbox/include/asm/spl.h | 3 + common/spl/Kconfig | 15 + common/spl/Makefile | 1 + common/spl/spl.c | 4 +- common/spl/spl_blk_fs.c | 6 +- common/spl/spl_ext.c | 4 +- common/spl/spl_fat.c | 13 +- common/spl/spl_fit.c | 40 +- .../spl/spl_imx_container.c | 12 +- common/spl/spl_legacy.c | 8 +- common/spl/spl_mmc.c | 11 +- common/spl/spl_nand.c | 4 +- common/spl/spl_net.c | 10 +- common/spl/spl_nor.c | 18 +- common/spl/spl_spi.c | 18 +- configs/deneb_defconfig | 2 + configs/giedi_defconfig | 2 + configs/imx8qm_mek_defconfig | 2 + configs/imx8qxp_mek_defconfig | 2 + configs/sandbox_noinst_defconfig | 31 +- configs/sandbox_spl_defconfig | 8 + configs/sandbox_vpl_defconfig | 1 + drivers/core/Makefile | 1 + drivers/core/root.c | 2 +- drivers/i2c/Makefile | 2 +- drivers/i2c/i2c-emul-uclass.c | 2 +- drivers/serial/sandbox.c | 2 +- drivers/sysreset/sysreset_sandbox.c | 2 +- drivers/usb/gadget/f_sdp.c | 4 +- dts/Kconfig | 8 +- fs/Makefile | 1 + include/configs/sandbox.h | 3 + include/ext4fs.h | 1 + include/ext_common.h | 14 + .../image.h => include/imx_container.h | 9 + include/spl.h | 14 + include/test/spl.h | 155 ++++ lib/Kconfig | 6 + lib/Makefile | 1 + net/Makefile | 4 +- net/bootp.c | 9 +- net/bootp.h | 3 + net/net.c | 4 +- test/Kconfig | 1 + test/Makefile | 5 +- test/image/Kconfig | 50 ++ test/image/Makefile | 7 +- test/image/spl_load.c | 693 ++++++++++++++++-- test/image/spl_load_fs.c | 423 +++++++++++ test/image/spl_load_net.c | 252 +++++++ test/image/spl_load_nor.c | 39 + test/image/spl_load_os.c | 76 ++ test/image/spl_load_spi.c | 41 ++ test/py/tests/test_spl.py | 10 + test/test-main.c | 2 +- 69 files changed, 1966 insertions(+), 163 deletions(-) rename arch/arm/mach-imx/parse-container.c => common/spl/spl_imx_container.c (92%) rename arch/arm/include/asm/mach-imx/image.h => include/imx_container.h (82%) create mode 100644 include/test/spl.h create mode 100644 test/image/Kconfig create mode 100644 test/image/spl_load_fs.c create mode 100644 test/image/spl_load_net.c create mode 100644 test/image/spl_load_nor.c create mode 100644 test/image/spl_load_os.c create mode 100644 test/image/spl_load_spi.c

On non-arm architectures, _image_binary_end is defined as a ulong and not a char[]. Dereference it when accessing it, which is correct for both.
Fixes: 1b8a1be1a1f ("spl: spl_legacy: Fix spl_end address") Signed-off-by: Sean Anderson seanga2@gmail.com ---
common/spl/spl_legacy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/common/spl/spl_legacy.c b/common/spl/spl_legacy.c index 095443c63d8..e9564e5c2a5 100644 --- a/common/spl/spl_legacy.c +++ b/common/spl/spl_legacy.c @@ -19,7 +19,7 @@ static void spl_parse_legacy_validate(uintptr_t start, uintptr_t size) { uintptr_t spl_start = (uintptr_t)_start; - uintptr_t spl_end = (uintptr_t)_image_binary_end; + uintptr_t spl_end = (uintptr_t)&_image_binary_end; uintptr_t end = start + size;
if ((start >= spl_start && start < spl_end) ||

On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
On non-arm architectures, _image_binary_end is defined as a ulong and not a char[]. Dereference it when accessing it, which is correct for both.
Is 'dereference' the right word?
Fixes: 1b8a1be1a1f ("spl: spl_legacy: Fix spl_end address") Signed-off-by: Sean Anderson seanga2@gmail.com
common/spl/spl_legacy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org
diff --git a/common/spl/spl_legacy.c b/common/spl/spl_legacy.c index 095443c63d8..e9564e5c2a5 100644 --- a/common/spl/spl_legacy.c +++ b/common/spl/spl_legacy.c @@ -19,7 +19,7 @@ static void spl_parse_legacy_validate(uintptr_t start, uintptr_t size) { uintptr_t spl_start = (uintptr_t)_start;
uintptr_t spl_end = (uintptr_t)_image_binary_end;
uintptr_t spl_end = (uintptr_t)&_image_binary_end; uintptr_t end = start + size; if ((start >= spl_start && start < spl_end) ||
-- 2.37.1

On 10/11/23 23:41, Simon Glass wrote:
On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
On non-arm architectures, _image_binary_end is defined as a ulong and not a char[]. Dereference it when accessing it, which is correct for both.
Is 'dereference' the right word?
Yeah...
"Take the address of it when accessing it"?
--Sean
Fixes: 1b8a1be1a1f ("spl: spl_legacy: Fix spl_end address") Signed-off-by: Sean Anderson seanga2@gmail.com
common/spl/spl_legacy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org
diff --git a/common/spl/spl_legacy.c b/common/spl/spl_legacy.c index 095443c63d8..e9564e5c2a5 100644 --- a/common/spl/spl_legacy.c +++ b/common/spl/spl_legacy.c @@ -19,7 +19,7 @@ static void spl_parse_legacy_validate(uintptr_t start, uintptr_t size) { uintptr_t spl_start = (uintptr_t)_start;
uintptr_t spl_end = (uintptr_t)_image_binary_end;
uintptr_t spl_end = (uintptr_t)&_image_binary_end; uintptr_t end = start + size; if ((start >= spl_start && start < spl_end) ||
-- 2.37.1

Hi Sean,
On Wed, 11 Oct 2023 at 21:30, Sean Anderson seanga2@gmail.com wrote:
On 10/11/23 23:41, Simon Glass wrote:
On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
On non-arm architectures, _image_binary_end is defined as a ulong and not a char[]. Dereference it when accessing it, which is correct for both.
Is 'dereference' the right word?
Yeah...
"Take the address of it when accessing it"?
That seems better.
Regards, Simon
--Sean
Fixes: 1b8a1be1a1f ("spl: spl_legacy: Fix spl_end address") Signed-off-by: Sean Anderson seanga2@gmail.com
common/spl/spl_legacy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org
diff --git a/common/spl/spl_legacy.c b/common/spl/spl_legacy.c index 095443c63d8..e9564e5c2a5 100644 --- a/common/spl/spl_legacy.c +++ b/common/spl/spl_legacy.c @@ -19,7 +19,7 @@ static void spl_parse_legacy_validate(uintptr_t start, uintptr_t size) { uintptr_t spl_start = (uintptr_t)_start;
uintptr_t spl_end = (uintptr_t)_image_binary_end;
uintptr_t spl_end = (uintptr_t)&_image_binary_end; uintptr_t end = start + size; if ((start >= spl_start && start < spl_end) ||
-- 2.37.1

spl_image_info.name contains a reference to legacy_img_hdr. If we allocate the latter on the stack, it will be clobbered after we return. This was addressed for NAND back in 06377c5a1fc ("spl: spl_legacy: Fix NAND boot on OMAP3 BeagleBoard"), but that commit didn't fix NOR.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
common/spl/spl_nor.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/common/spl/spl_nor.c b/common/spl/spl_nor.c index 79d4f1d7aa8..c141a9ae629 100644 --- a/common/spl/spl_nor.c +++ b/common/spl/spl_nor.c @@ -26,7 +26,7 @@ unsigned long __weak spl_nor_get_uboot_base(void) static int spl_nor_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) { - __maybe_unused const struct legacy_img_hdr *header; + struct legacy_img_hdr *header; __maybe_unused struct spl_load_info load;
/* @@ -41,7 +41,7 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, * Load Linux from its location in NOR flash to its defined * location in SDRAM */ - header = (const struct legacy_img_hdr *)CONFIG_SYS_OS_BASE; + header = (void *)CONFIG_SYS_OS_BASE; #ifdef CONFIG_SPL_LOAD_FIT if (image_get_magic(header) == FDT_MAGIC) { int ret; @@ -91,8 +91,8 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, * Load real U-Boot from its location in NOR flash to its * defined location in SDRAM */ -#ifdef CONFIG_SPL_LOAD_FIT header = (const struct legacy_img_hdr *)spl_nor_get_uboot_base(); +#ifdef CONFIG_SPL_LOAD_FIT if (image_get_magic(header) == FDT_MAGIC) { debug("Found FIT format U-Boot\n"); load.bl_len = 1; @@ -111,14 +111,11 @@ static int spl_nor_load_image(struct spl_image_info *spl_image,
/* Legacy image handling */ if (IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_FORMAT)) { - struct legacy_img_hdr hdr; - load.bl_len = 1; load.read = spl_nor_load_read; - spl_nor_load_read(&load, spl_nor_get_uboot_base(), sizeof(hdr), &hdr); return spl_load_legacy_img(spl_image, bootdev, &load, spl_nor_get_uboot_base(), - &hdr); + header); }
return -EINVAL;

On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
spl_image_info.name contains a reference to legacy_img_hdr. If we allocate the latter on the stack, it will be clobbered after we return. This was addressed for NAND back in 06377c5a1fc ("spl: spl_legacy: Fix NAND boot on OMAP3 BeagleBoard"), but that commit didn't fix NOR.
Signed-off-by: Sean Anderson seanga2@gmail.com
common/spl/spl_nor.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

On Thu, Oct 12, 2023 at 5:45 AM Simon Glass sjg@chromium.org wrote:
On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
spl_image_info.name contains a reference to legacy_img_hdr. If we allocate the latter on the stack, it will be clobbered after we return. This was addressed for NAND back in 06377c5a1fc ("spl: spl_legacy: Fix NAND boot on OMAP3 BeagleBoard"), but that commit didn't fix NOR.
Signed-off-by: Sean Anderson seanga2@gmail.com
common/spl/spl_nor.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
Reviewed-by: Michael Trimarchi michael@amarulasolutions.com

The entry point is not always the same as the load address. Use the value of the entrypoint property if it exists and is nonzero (following the example of spl_load_simple_fit).
Fixes: 8a9dc16e4d0 ("spl: Add full fitImage support") Signed-off-by: Sean Anderson seanga2@gmail.com ---
common/spl/spl_fit.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index ce6b8aa370a..e3cdf8e5c05 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -884,8 +884,10 @@ int spl_load_fit_image(struct spl_image_info *spl_image, return ret;
spl_image->size = fw_len; - spl_image->entry_point = fw_data; spl_image->load_addr = fw_data; + if (fit_image_get_entry(header, ret, &spl_image->entry_point) || + !spl_image->entry_point) + spl_image->entry_point = fw_data; if (fit_image_get_os(header, ret, &spl_image->os)) spl_image->os = IH_OS_INVALID; spl_image->name = genimg_get_os_name(spl_image->os);

On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
The entry point is not always the same as the load address. Use the value of the entrypoint property if it exists and is nonzero (following the example of spl_load_simple_fit).
Fixes: 8a9dc16e4d0 ("spl: Add full fitImage support") Signed-off-by: Sean Anderson seanga2@gmail.com
common/spl/spl_fit.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org
The check for 0 makes me uneasy, but I can't imagine it being valid in practice.
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index ce6b8aa370a..e3cdf8e5c05 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -884,8 +884,10 @@ int spl_load_fit_image(struct spl_image_info *spl_image, return ret;
spl_image->size = fw_len;
spl_image->entry_point = fw_data; spl_image->load_addr = fw_data;
if (fit_image_get_entry(header, ret, &spl_image->entry_point) ||
!spl_image->entry_point)
spl_image->entry_point = fw_data; if (fit_image_get_os(header, ret, &spl_image->os)) spl_image->os = IH_OS_INVALID; spl_image->name = genimg_get_os_name(spl_image->os);
-- 2.37.1

On 10/11/23 23:41, Simon Glass wrote:
On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
The entry point is not always the same as the load address. Use the value of the entrypoint property if it exists and is nonzero (following the example of spl_load_simple_fit).
Fixes: 8a9dc16e4d0 ("spl: Add full fitImage support") Signed-off-by: Sean Anderson seanga2@gmail.com
common/spl/spl_fit.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org
The check for 0 makes me uneasy, but I can't imagine it being valid in practice.
This is mostly to match spl_load_simple_fit:
/* * If a platform does not provide CONFIG_SYS_UBOOT_START, U-Boot's * Makefile will set it to 0 and it will end up as the entry point * here. What it actually means is: use the load address. */
SYS_UBOOT_START doesn't seem to be set very often and defaults to TEXT_BASE. That appears to be undefined on
efi-x86_app64 efi-x86_app32 xtfpga 3c120 10m50
but none of these platforms define SPL_LOAD_FIT. So maybe this is moot?
--Sean
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index ce6b8aa370a..e3cdf8e5c05 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -884,8 +884,10 @@ int spl_load_fit_image(struct spl_image_info *spl_image, return ret;
spl_image->size = fw_len;
spl_image->entry_point = fw_data; spl_image->load_addr = fw_data;
if (fit_image_get_entry(header, ret, &spl_image->entry_point) ||
!spl_image->entry_point)
spl_image->entry_point = fw_data; if (fit_image_get_os(header, ret, &spl_image->os)) spl_image->os = IH_OS_INVALID; spl_image->name = genimg_get_os_name(spl_image->os);
-- 2.37.1

On Thu, Oct 12, 2023 at 12:28:22AM -0400, Sean Anderson wrote:
On 10/11/23 23:41, Simon Glass wrote:
On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
The entry point is not always the same as the load address. Use the value of the entrypoint property if it exists and is nonzero (following the example of spl_load_simple_fit).
Fixes: 8a9dc16e4d0 ("spl: Add full fitImage support") Signed-off-by: Sean Anderson seanga2@gmail.com
common/spl/spl_fit.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org
The check for 0 makes me uneasy, but I can't imagine it being valid in practice.
This is mostly to match spl_load_simple_fit:
/* * If a platform does not provide CONFIG_SYS_UBOOT_START, U-Boot's * Makefile will set it to 0 and it will end up as the entry point * here. What it actually means is: use the load address. */
SYS_UBOOT_START doesn't seem to be set very often and defaults to TEXT_BASE. That appears to be undefined on
efi-x86_app64 efi-x86_app32 xtfpga 3c120 10m50
but none of these platforms define SPL_LOAD_FIT. So maybe this is moot?
Moot for the last 3 there yes. Not sure about the U-Boot as EFI app builds.

Hi,
On Wed, 11 Oct 2023 at 21:28, Sean Anderson seanga2@gmail.com wrote:
On 10/11/23 23:41, Simon Glass wrote:
On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
The entry point is not always the same as the load address. Use the value of the entrypoint property if it exists and is nonzero (following the example of spl_load_simple_fit).
Fixes: 8a9dc16e4d0 ("spl: Add full fitImage support") Signed-off-by: Sean Anderson seanga2@gmail.com
common/spl/spl_fit.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org
The check for 0 makes me uneasy, but I can't imagine it being valid in practice.
This is mostly to match spl_load_simple_fit:
/* * If a platform does not provide CONFIG_SYS_UBOOT_START, U-Boot's * Makefile will set it to 0 and it will end up as the entry point * here. What it actually means is: use the load address. */
SYS_UBOOT_START doesn't seem to be set very often and defaults to TEXT_BASE. That appears to be undefined on
efi-x86_app64 efi-x86_app32 xtfpga 3c120 10m50
but none of these platforms define SPL_LOAD_FIT. So maybe this is moot?
Yes, it should be fine.
Regards, Simon
--Sean
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index ce6b8aa370a..e3cdf8e5c05 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -884,8 +884,10 @@ int spl_load_fit_image(struct spl_image_info *spl_image, return ret;
spl_image->size = fw_len;
spl_image->entry_point = fw_data; spl_image->load_addr = fw_data;
if (fit_image_get_entry(header, ret, &spl_image->entry_point) ||
!spl_image->entry_point)
spl_image->entry_point = fw_data; if (fit_image_get_os(header, ret, &spl_image->os)) spl_image->os = IH_OS_INVALID; spl_image->name = genimg_get_os_name(spl_image->os);
-- 2.37.1

We should load images to their destination, not their entry point.
Fixes: 7b86cd4274e ("imx8: support parsing i.MX8 Container file") Signed-off-by: Sean Anderson seanga2@gmail.com ---
arch/arm/mach-imx/parse-container.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/mach-imx/parse-container.c b/arch/arm/mach-imx/parse-container.c index e2a9e2b2732..d7275a58c17 100644 --- a/arch/arm/mach-imx/parse-container.c +++ b/arch/arm/mach-imx/parse-container.c @@ -45,7 +45,7 @@ static struct boot_img_t *read_auth_image(struct spl_image_info *spl_image, debug("%s: container: %p sector: %lu sectors: %u\n", __func__, container, sector, sectors); if (info->read(info, sector, sectors, - (void *)images[image_index].entry) != sectors) { + (void *)images[image_index].dst) != sectors) { printf("%s wrong\n", __func__); return NULL; }

These error messages are missing newlines. Add them.
Fixes: 6e81ca220e0 ("imx: parse-container: Use malloc for container processing") Signed-off-by: Sean Anderson seanga2@gmail.com ---
arch/arm/mach-imx/parse-container.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-imx/parse-container.c b/arch/arm/mach-imx/parse-container.c index d7275a58c17..c5df78d1c58 100644 --- a/arch/arm/mach-imx/parse-container.c +++ b/arch/arm/mach-imx/parse-container.c @@ -85,13 +85,13 @@ static int read_auth_container(struct spl_image_info *spl_image, }
if (container->tag != 0x87 && container->version != 0x0) { - printf("Wrong container header"); + printf("Wrong container header\n"); ret = -ENOENT; goto end; }
if (!container->num_images) { - printf("Wrong container, no image found"); + printf("Wrong container, no image found\n"); ret = -ENOENT; goto end; }

On 10/12/23 03:56, Sean Anderson wrote:
These error messages are missing newlines. Add them.
Fixes: 6e81ca220e0 ("imx: parse-container: Use malloc for container processing") Signed-off-by: Sean Anderson seanga2@gmail.com
arch/arm/mach-imx/parse-container.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-imx/parse-container.c b/arch/arm/mach-imx/parse-container.c index d7275a58c17..c5df78d1c58 100644 --- a/arch/arm/mach-imx/parse-container.c +++ b/arch/arm/mach-imx/parse-container.c @@ -85,13 +85,13 @@ static int read_auth_container(struct spl_image_info *spl_image, }
if (container->tag != 0x87 && container->version != 0x0) {
printf("Wrong container header");
printf("Wrong container header\n");
Please, use log_err() and add
#define LOG_CATEGORY LOGC_ARCH
to the top of the file.
Best regards
Heinrich
ret = -ENOENT; goto end;
}
if (!container->num_images) {
printf("Wrong container, no image found");
ret = -ENOENT; goto end; }printf("Wrong container, no image found\n");

Add a function to abstract the common task of validating i.MX8 container image headers.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
arch/arm/include/asm/mach-imx/image.h | 9 +++++++++ arch/arm/mach-imx/ele_ahab.c | 2 +- arch/arm/mach-imx/image-container.c | 2 +- arch/arm/mach-imx/imx8/ahab.c | 2 +- arch/arm/mach-imx/parse-container.c | 2 +- arch/arm/mach-imx/spl_imx_romapi.c | 3 ++- 6 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/arch/arm/include/asm/mach-imx/image.h b/arch/arm/include/asm/mach-imx/image.h index ee67ca96f4c..54cd684e35d 100644 --- a/arch/arm/include/asm/mach-imx/image.h +++ b/arch/arm/include/asm/mach-imx/image.h @@ -18,6 +18,9 @@ #define CONTAINER_HDR_QSPI_OFFSET SZ_4K #define CONTAINER_HDR_NAND_OFFSET SZ_128M
+#define CONTAINER_HDR_TAG 0x87 +#define CONTAINER_HDR_VERSION 0 + struct container_hdr { u8 version; u8 length_lsb; @@ -66,4 +69,10 @@ struct generate_key_blob_hdr { } __packed;
int get_container_size(ulong addr, u16 *header_length); + +static inline bool valid_container_hdr(struct container_hdr *container) +{ + return container->tag == CONTAINER_HDR_TAG && + container->version == CONTAINER_HDR_VERSION; +} #endif diff --git a/arch/arm/mach-imx/ele_ahab.c b/arch/arm/mach-imx/ele_ahab.c index 785b0d6ec3c..6a1ad198f89 100644 --- a/arch/arm/mach-imx/ele_ahab.c +++ b/arch/arm/mach-imx/ele_ahab.c @@ -343,7 +343,7 @@ int authenticate_os_container(ulong addr) }
phdr = (struct container_hdr *)addr; - if (phdr->tag != 0x87 || phdr->version != 0x0) { + if (!valid_container_hdr(phdr)) { printf("Error: Wrong container header\n"); return -EFAULT; } diff --git a/arch/arm/mach-imx/image-container.c b/arch/arm/mach-imx/image-container.c index 5f188ab32d1..eff9e0c4597 100644 --- a/arch/arm/mach-imx/image-container.c +++ b/arch/arm/mach-imx/image-container.c @@ -50,7 +50,7 @@ int get_container_size(ulong addr, u16 *header_length) u32 max_offset = 0, img_end;
phdr = (struct container_hdr *)addr; - if (phdr->tag != 0x87 || phdr->version != 0x0) { + if (!valid_container_hdr(phdr)) { debug("Wrong container header\n"); return -EFAULT; } diff --git a/arch/arm/mach-imx/imx8/ahab.c b/arch/arm/mach-imx/imx8/ahab.c index b58b14ca9b4..44ea63584aa 100644 --- a/arch/arm/mach-imx/imx8/ahab.c +++ b/arch/arm/mach-imx/imx8/ahab.c @@ -146,7 +146,7 @@ int authenticate_os_container(ulong addr) }
phdr = (struct container_hdr *)addr; - if (phdr->tag != 0x87 && phdr->version != 0x0) { + if (!valid_container_hdr(phdr)) { printf("Error: Wrong container header\n"); return -EFAULT; } diff --git a/arch/arm/mach-imx/parse-container.c b/arch/arm/mach-imx/parse-container.c index c5df78d1c58..0a3d41f411e 100644 --- a/arch/arm/mach-imx/parse-container.c +++ b/arch/arm/mach-imx/parse-container.c @@ -84,7 +84,7 @@ static int read_auth_container(struct spl_image_info *spl_image, goto end; }
- if (container->tag != 0x87 && container->version != 0x0) { + if (!valid_container_hdr(container)) { printf("Wrong container header\n"); ret = -ENOENT; goto end; diff --git a/arch/arm/mach-imx/spl_imx_romapi.c b/arch/arm/mach-imx/spl_imx_romapi.c index 4af41699678..b51061b987b 100644 --- a/arch/arm/mach-imx/spl_imx_romapi.c +++ b/arch/arm/mach-imx/spl_imx_romapi.c @@ -184,7 +184,8 @@ static u8 *search_container_header(u8 *p, int size)
for (i = 0; i < size; i += 4) { hdr = p + i; - if (*(hdr + 3) == 0x87 && *hdr == 0 && (*(hdr + 1) != 0 || *(hdr + 2) != 0)) + if (valid_container_hdr((void *)hdr) && + (*(hdr + 1) != 0 || *(hdr + 2) != 0)) return p + i; }

Make sure we have an IMX header before calling spl_load_imx_container, since if we don't it will fail with -ENOENT. This allows us to fall back to legacy/raw images if they are also enabled.
To avoid too much bloat, Legacy/Raw images are disabled for the four configs which only boot from raw MMC.
Future work could include merging imx_container.h with imx8image.h, since they appear to define mostly the same structures.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
MAINTAINERS | 1 + arch/arm/include/asm/mach-imx/ahab.h | 2 +- arch/arm/mach-imx/cmd_dek.c | 4 ++-- arch/arm/mach-imx/ele_ahab.c | 2 +- arch/arm/mach-imx/image-container.c | 2 +- arch/arm/mach-imx/imx8/ahab.c | 2 +- arch/arm/mach-imx/parse-container.c | 2 +- arch/arm/mach-imx/spl_imx_romapi.c | 5 +++-- common/spl/spl_mmc.c | 4 +++- common/spl/spl_nand.c | 4 +++- common/spl/spl_nor.c | 4 +++- common/spl/spl_spi.c | 4 +++- configs/deneb_defconfig | 2 ++ configs/giedi_defconfig | 2 ++ configs/imx8qm_mek_defconfig | 2 ++ configs/imx8qxp_mek_defconfig | 2 ++ drivers/usb/gadget/f_sdp.c | 4 +++- .../include/asm/mach-imx/image.h => include/imx_container.h | 0 18 files changed, 34 insertions(+), 14 deletions(-) rename arch/arm/include/asm/mach-imx/image.h => include/imx_container.h (100%)
diff --git a/MAINTAINERS b/MAINTAINERS index 7d5d05320c0..35209e73af5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -300,6 +300,7 @@ F: arch/arm/include/asm/mach-imx/ F: board/freescale/*mx*/ F: board/freescale/common/ F: drivers/serial/serial_mxc.c +F: include/imx_container.h
ARM HISILICON M: Peter Griffin peter.griffin@linaro.org diff --git a/arch/arm/include/asm/mach-imx/ahab.h b/arch/arm/include/asm/mach-imx/ahab.h index 4222e3db278..4884f056251 100644 --- a/arch/arm/include/asm/mach-imx/ahab.h +++ b/arch/arm/include/asm/mach-imx/ahab.h @@ -6,7 +6,7 @@ #ifndef __IMX_AHAB_H__ #define __IMX_AHAB_H__
-#include <asm/mach-imx/image.h> +#include <imx_container.h>
int ahab_auth_cntr_hdr(struct container_hdr *container, u16 length); int ahab_auth_release(void); diff --git a/arch/arm/mach-imx/cmd_dek.c b/arch/arm/mach-imx/cmd_dek.c index 6fa5b41fcd3..2f389dbe8df 100644 --- a/arch/arm/mach-imx/cmd_dek.c +++ b/arch/arm/mach-imx/cmd_dek.c @@ -18,12 +18,12 @@ #include <mapmem.h> #include <tee.h> #ifdef CONFIG_IMX_SECO_DEK_ENCAP +#include <imx_container.h> #include <firmware/imx/sci/sci.h> -#include <asm/mach-imx/image.h> #endif #ifdef CONFIG_IMX_ELE_DEK_ENCAP +#include <imx_container.h> #include <asm/mach-imx/ele_api.h> -#include <asm/mach-imx/image.h> #endif
#include <cpu_func.h> diff --git a/arch/arm/mach-imx/ele_ahab.c b/arch/arm/mach-imx/ele_ahab.c index 6a1ad198f89..295c055ad0a 100644 --- a/arch/arm/mach-imx/ele_ahab.c +++ b/arch/arm/mach-imx/ele_ahab.c @@ -6,12 +6,12 @@ #include <common.h> #include <command.h> #include <errno.h> +#include <imx_container.h> #include <asm/io.h> #include <asm/mach-imx/ele_api.h> #include <asm/mach-imx/sys_proto.h> #include <asm/arch-imx/cpu.h> #include <asm/arch/sys_proto.h> -#include <asm/mach-imx/image.h> #include <console.h> #include <cpu_func.h> #include <asm/global_data.h> diff --git a/arch/arm/mach-imx/image-container.c b/arch/arm/mach-imx/image-container.c index eff9e0c4597..ebc8021d7cc 100644 --- a/arch/arm/mach-imx/image-container.c +++ b/arch/arm/mach-imx/image-container.c @@ -5,6 +5,7 @@
#include <common.h> #include <errno.h> +#include <imx_container.h> #include <log.h> #include <malloc.h> #include <asm/io.h> @@ -12,7 +13,6 @@ #include <spi_flash.h> #include <spl.h> #include <nand.h> -#include <asm/mach-imx/image.h> #include <asm/arch/sys_proto.h> #include <asm/mach-imx/boot_mode.h>
diff --git a/arch/arm/mach-imx/imx8/ahab.c b/arch/arm/mach-imx/imx8/ahab.c index 44ea63584aa..994becccefd 100644 --- a/arch/arm/mach-imx/imx8/ahab.c +++ b/arch/arm/mach-imx/imx8/ahab.c @@ -6,6 +6,7 @@ #include <common.h> #include <command.h> #include <errno.h> +#include <imx_container.h> #include <log.h> #include <asm/global_data.h> #include <asm/io.h> @@ -13,7 +14,6 @@ #include <asm/mach-imx/sys_proto.h> #include <asm/arch-imx/cpu.h> #include <asm/arch/sys_proto.h> -#include <asm/mach-imx/image.h> #include <console.h> #include <cpu_func.h> #include "u-boot/sha256.h" diff --git a/arch/arm/mach-imx/parse-container.c b/arch/arm/mach-imx/parse-container.c index 0a3d41f411e..126ab7c57a1 100644 --- a/arch/arm/mach-imx/parse-container.c +++ b/arch/arm/mach-imx/parse-container.c @@ -6,9 +6,9 @@ #include <common.h> #include <stdlib.h> #include <errno.h> +#include <imx_container.h> #include <log.h> #include <spl.h> -#include <asm/mach-imx/image.h> #ifdef CONFIG_AHAB_BOOT #include <asm/mach-imx/ahab.h> #endif diff --git a/arch/arm/mach-imx/spl_imx_romapi.c b/arch/arm/mach-imx/spl_imx_romapi.c index b51061b987b..8816566b364 100644 --- a/arch/arm/mach-imx/spl_imx_romapi.c +++ b/arch/arm/mach-imx/spl_imx_romapi.c @@ -6,11 +6,11 @@ #include <common.h> #include <errno.h> #include <image.h> +#include <imx_container.h> #include <log.h> #include <asm/global_data.h> #include <linux/libfdt.h> #include <spl.h> -#include <asm/mach-imx/image.h> #include <asm/arch/sys_proto.h>
DECLARE_GLOBAL_DATA_PTR; @@ -111,7 +111,8 @@ static int spl_romapi_load_image_seekable(struct spl_image_info *spl_image, load.read = spl_romapi_read_seekable; load.priv = &pagesize; return spl_load_simple_fit(spl_image, &load, offset / pagesize, header); - } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && + valid_container_hdr((void *)header)) { struct spl_load_info load;
memset(&load, 0, sizeof(load)); diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 02ad32a23e0..67c7ae34a58 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -16,6 +16,7 @@ #include <errno.h> #include <mmc.h> #include <image.h> +#include <imx_container.h>
static int mmc_load_legacy(struct spl_image_info *spl_image, struct spl_boot_device *bootdev, @@ -108,7 +109,8 @@ int mmc_load_image_raw_sector(struct spl_image_info *spl_image, load.bl_len = mmc->read_bl_len; load.read = h_spl_load_read; ret = spl_load_simple_fit(spl_image, &load, sector, header); - } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && + valid_container_hdr((void *)header)) { struct spl_load_info load;
load.dev = mmc; diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c index 6cc34004f49..07916bedbb9 100644 --- a/common/spl/spl_nand.c +++ b/common/spl/spl_nand.c @@ -7,6 +7,7 @@ #include <config.h> #include <fdt_support.h> #include <image.h> +#include <imx_container.h> #include <log.h> #include <spl.h> #include <asm/io.h> @@ -99,7 +100,8 @@ static int spl_nand_load_element(struct spl_image_info *spl_image, load.bl_len = bl_len; load.read = spl_nand_fit_read; return spl_load_simple_fit(spl_image, &load, offset / bl_len, header); - } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && + valid_container_hdr((void *)header)) { struct spl_load_info load;
load.dev = NULL; diff --git a/common/spl/spl_nor.c b/common/spl/spl_nor.c index c141a9ae629..dd447982071 100644 --- a/common/spl/spl_nor.c +++ b/common/spl/spl_nor.c @@ -5,6 +5,7 @@
#include <common.h> #include <image.h> +#include <imx_container.h> #include <log.h> #include <spl.h>
@@ -102,7 +103,8 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, (void *)header); } #endif - if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && + valid_container_hdr((void *)header)) { load.bl_len = 1; load.read = spl_nor_load_read; return spl_load_imx_container(spl_image, &load, diff --git a/common/spl/spl_spi.c b/common/spl/spl_spi.c index d69069a75bf..1427c9478c0 100644 --- a/common/spl/spl_spi.c +++ b/common/spl/spl_spi.c @@ -10,6 +10,7 @@
#include <common.h> #include <image.h> +#include <imx_container.h> #include <log.h> #include <spi.h> #include <spi_flash.h> @@ -153,7 +154,8 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, err = spl_load_simple_fit(spl_image, &load, payload_offs, header); - } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && + valid_container_hdr((void *)header)) { struct spl_load_info load;
load.dev = flash; diff --git a/configs/deneb_defconfig b/configs/deneb_defconfig index 82869e4e0f9..ee2478aa0bb 100644 --- a/configs/deneb_defconfig +++ b/configs/deneb_defconfig @@ -44,6 +44,8 @@ CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x128000 CONFIG_SPL_BSS_MAX_SIZE=0x1000 CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +# CONFIG_SPL_LEGACY_IMAGE_FORMAT is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set CONFIG_SPL_SYS_MALLOC=y diff --git a/configs/giedi_defconfig b/configs/giedi_defconfig index b56b736c436..5e403c90c8c 100644 --- a/configs/giedi_defconfig +++ b/configs/giedi_defconfig @@ -44,6 +44,8 @@ CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x128000 CONFIG_SPL_BSS_MAX_SIZE=0x1000 CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +# CONFIG_SPL_LEGACY_IMAGE_FORMAT is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set CONFIG_SPL_SYS_MALLOC=y diff --git a/configs/imx8qm_mek_defconfig b/configs/imx8qm_mek_defconfig index b9083b0453f..4c5206306ee 100644 --- a/configs/imx8qm_mek_defconfig +++ b/configs/imx8qm_mek_defconfig @@ -38,6 +38,8 @@ CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x128000 CONFIG_SPL_BSS_MAX_SIZE=0x1000 CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +# CONFIG_SPL_LEGACY_IMAGE_FORMAT is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set CONFIG_SPL_SYS_MALLOC=y diff --git a/configs/imx8qxp_mek_defconfig b/configs/imx8qxp_mek_defconfig index f516b0b5557..f312d3945fb 100644 --- a/configs/imx8qxp_mek_defconfig +++ b/configs/imx8qxp_mek_defconfig @@ -38,6 +38,8 @@ CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x128000 CONFIG_SPL_BSS_MAX_SIZE=0x1000 CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +# CONFIG_SPL_LEGACY_IMAGE_FORMAT is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set CONFIG_SPL_SYS_MALLOC=y diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c index 2b3a9c5fd4c..ee9384fb37e 100644 --- a/drivers/usb/gadget/f_sdp.c +++ b/drivers/usb/gadget/f_sdp.c @@ -34,6 +34,7 @@ #include <spl.h> #include <image.h> #include <imximage.h> +#include <imx_container.h> #include <watchdog.h>
#define HID_REPORT_ID_MASK 0x000000ff @@ -852,7 +853,8 @@ static int sdp_handle_in_ep(struct spl_image_info *spl_image, return SDP_EXIT; } #endif - if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && + valid_container_hdr((void *)header)) { struct spl_load_info load;
load.dev = header; diff --git a/arch/arm/include/asm/mach-imx/image.h b/include/imx_container.h similarity index 100% rename from arch/arm/include/asm/mach-imx/image.h rename to include/imx_container.h

On 10/12/23 03:56, Sean Anderson wrote:
Make sure we have an IMX header before calling spl_load_imx_container, since if we don't it will fail with -ENOENT. This allows us to fall back to legacy/raw images if they are also enabled.
Looking at CONFIG_AHAB_BOOT (related to secure boot) we must be sure that we don't introduce any unsolicited fallback on existing configurations.
Best regards
Heinrich
To avoid too much bloat, Legacy/Raw images are disabled for the four configs which only boot from raw MMC.
Future work could include merging imx_container.h with imx8image.h, since they appear to define mostly the same structures.
Signed-off-by: Sean Anderson seanga2@gmail.com
MAINTAINERS | 1 + arch/arm/include/asm/mach-imx/ahab.h | 2 +- arch/arm/mach-imx/cmd_dek.c | 4 ++-- arch/arm/mach-imx/ele_ahab.c | 2 +- arch/arm/mach-imx/image-container.c | 2 +- arch/arm/mach-imx/imx8/ahab.c | 2 +- arch/arm/mach-imx/parse-container.c | 2 +- arch/arm/mach-imx/spl_imx_romapi.c | 5 +++-- common/spl/spl_mmc.c | 4 +++- common/spl/spl_nand.c | 4 +++- common/spl/spl_nor.c | 4 +++- common/spl/spl_spi.c | 4 +++- configs/deneb_defconfig | 2 ++ configs/giedi_defconfig | 2 ++ configs/imx8qm_mek_defconfig | 2 ++ configs/imx8qxp_mek_defconfig | 2 ++ drivers/usb/gadget/f_sdp.c | 4 +++- .../include/asm/mach-imx/image.h => include/imx_container.h | 0 18 files changed, 34 insertions(+), 14 deletions(-) rename arch/arm/include/asm/mach-imx/image.h => include/imx_container.h (100%)
diff --git a/MAINTAINERS b/MAINTAINERS index 7d5d05320c0..35209e73af5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -300,6 +300,7 @@ F: arch/arm/include/asm/mach-imx/ F: board/freescale/*mx*/ F: board/freescale/common/ F: drivers/serial/serial_mxc.c +F: include/imx_container.h
ARM HISILICON M: Peter Griffin peter.griffin@linaro.org diff --git a/arch/arm/include/asm/mach-imx/ahab.h b/arch/arm/include/asm/mach-imx/ahab.h index 4222e3db278..4884f056251 100644 --- a/arch/arm/include/asm/mach-imx/ahab.h +++ b/arch/arm/include/asm/mach-imx/ahab.h @@ -6,7 +6,7 @@ #ifndef __IMX_AHAB_H__ #define __IMX_AHAB_H__
-#include <asm/mach-imx/image.h> +#include <imx_container.h>
int ahab_auth_cntr_hdr(struct container_hdr *container, u16 length); int ahab_auth_release(void); diff --git a/arch/arm/mach-imx/cmd_dek.c b/arch/arm/mach-imx/cmd_dek.c index 6fa5b41fcd3..2f389dbe8df 100644 --- a/arch/arm/mach-imx/cmd_dek.c +++ b/arch/arm/mach-imx/cmd_dek.c @@ -18,12 +18,12 @@ #include <mapmem.h> #include <tee.h> #ifdef CONFIG_IMX_SECO_DEK_ENCAP +#include <imx_container.h> #include <firmware/imx/sci/sci.h> -#include <asm/mach-imx/image.h> #endif #ifdef CONFIG_IMX_ELE_DEK_ENCAP +#include <imx_container.h> #include <asm/mach-imx/ele_api.h> -#include <asm/mach-imx/image.h> #endif
#include <cpu_func.h> diff --git a/arch/arm/mach-imx/ele_ahab.c b/arch/arm/mach-imx/ele_ahab.c index 6a1ad198f89..295c055ad0a 100644 --- a/arch/arm/mach-imx/ele_ahab.c +++ b/arch/arm/mach-imx/ele_ahab.c @@ -6,12 +6,12 @@ #include <common.h> #include <command.h> #include <errno.h> +#include <imx_container.h> #include <asm/io.h> #include <asm/mach-imx/ele_api.h> #include <asm/mach-imx/sys_proto.h> #include <asm/arch-imx/cpu.h> #include <asm/arch/sys_proto.h> -#include <asm/mach-imx/image.h> #include <console.h> #include <cpu_func.h> #include <asm/global_data.h> diff --git a/arch/arm/mach-imx/image-container.c b/arch/arm/mach-imx/image-container.c index eff9e0c4597..ebc8021d7cc 100644 --- a/arch/arm/mach-imx/image-container.c +++ b/arch/arm/mach-imx/image-container.c @@ -5,6 +5,7 @@
#include <common.h> #include <errno.h> +#include <imx_container.h> #include <log.h> #include <malloc.h> #include <asm/io.h> @@ -12,7 +13,6 @@ #include <spi_flash.h> #include <spl.h> #include <nand.h> -#include <asm/mach-imx/image.h> #include <asm/arch/sys_proto.h> #include <asm/mach-imx/boot_mode.h>
diff --git a/arch/arm/mach-imx/imx8/ahab.c b/arch/arm/mach-imx/imx8/ahab.c index 44ea63584aa..994becccefd 100644 --- a/arch/arm/mach-imx/imx8/ahab.c +++ b/arch/arm/mach-imx/imx8/ahab.c @@ -6,6 +6,7 @@ #include <common.h> #include <command.h> #include <errno.h> +#include <imx_container.h> #include <log.h> #include <asm/global_data.h> #include <asm/io.h> @@ -13,7 +14,6 @@ #include <asm/mach-imx/sys_proto.h> #include <asm/arch-imx/cpu.h> #include <asm/arch/sys_proto.h> -#include <asm/mach-imx/image.h> #include <console.h> #include <cpu_func.h> #include "u-boot/sha256.h" diff --git a/arch/arm/mach-imx/parse-container.c b/arch/arm/mach-imx/parse-container.c index 0a3d41f411e..126ab7c57a1 100644 --- a/arch/arm/mach-imx/parse-container.c +++ b/arch/arm/mach-imx/parse-container.c @@ -6,9 +6,9 @@ #include <common.h> #include <stdlib.h> #include <errno.h> +#include <imx_container.h> #include <log.h> #include <spl.h> -#include <asm/mach-imx/image.h> #ifdef CONFIG_AHAB_BOOT #include <asm/mach-imx/ahab.h> #endif diff --git a/arch/arm/mach-imx/spl_imx_romapi.c b/arch/arm/mach-imx/spl_imx_romapi.c index b51061b987b..8816566b364 100644 --- a/arch/arm/mach-imx/spl_imx_romapi.c +++ b/arch/arm/mach-imx/spl_imx_romapi.c @@ -6,11 +6,11 @@ #include <common.h> #include <errno.h> #include <image.h> +#include <imx_container.h> #include <log.h> #include <asm/global_data.h> #include <linux/libfdt.h> #include <spl.h> -#include <asm/mach-imx/image.h> #include <asm/arch/sys_proto.h>
DECLARE_GLOBAL_DATA_PTR; @@ -111,7 +111,8 @@ static int spl_romapi_load_image_seekable(struct spl_image_info *spl_image, load.read = spl_romapi_read_seekable; load.priv = &pagesize; return spl_load_simple_fit(spl_image, &load, offset / pagesize, header);
- } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) {
} else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) &&
valid_container_hdr((void *)header)) {
struct spl_load_info load;
memset(&load, 0, sizeof(load));
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 02ad32a23e0..67c7ae34a58 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -16,6 +16,7 @@ #include <errno.h> #include <mmc.h> #include <image.h> +#include <imx_container.h>
static int mmc_load_legacy(struct spl_image_info *spl_image, struct spl_boot_device *bootdev, @@ -108,7 +109,8 @@ int mmc_load_image_raw_sector(struct spl_image_info *spl_image, load.bl_len = mmc->read_bl_len; load.read = h_spl_load_read; ret = spl_load_simple_fit(spl_image, &load, sector, header);
- } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) {
} else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) &&
valid_container_hdr((void *)header)) {
struct spl_load_info load;
load.dev = mmc;
diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c index 6cc34004f49..07916bedbb9 100644 --- a/common/spl/spl_nand.c +++ b/common/spl/spl_nand.c @@ -7,6 +7,7 @@ #include <config.h> #include <fdt_support.h> #include <image.h> +#include <imx_container.h> #include <log.h> #include <spl.h> #include <asm/io.h> @@ -99,7 +100,8 @@ static int spl_nand_load_element(struct spl_image_info *spl_image, load.bl_len = bl_len; load.read = spl_nand_fit_read; return spl_load_simple_fit(spl_image, &load, offset / bl_len, header);
- } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) {
} else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) &&
valid_container_hdr((void *)header)) {
struct spl_load_info load;
load.dev = NULL;
diff --git a/common/spl/spl_nor.c b/common/spl/spl_nor.c index c141a9ae629..dd447982071 100644 --- a/common/spl/spl_nor.c +++ b/common/spl/spl_nor.c @@ -5,6 +5,7 @@
#include <common.h> #include <image.h> +#include <imx_container.h> #include <log.h> #include <spl.h>
@@ -102,7 +103,8 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, (void *)header); } #endif
- if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) {
- if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) &&
load.bl_len = 1; load.read = spl_nor_load_read; return spl_load_imx_container(spl_image, &load,valid_container_hdr((void *)header)) {
diff --git a/common/spl/spl_spi.c b/common/spl/spl_spi.c index d69069a75bf..1427c9478c0 100644 --- a/common/spl/spl_spi.c +++ b/common/spl/spl_spi.c @@ -10,6 +10,7 @@
#include <common.h> #include <image.h> +#include <imx_container.h> #include <log.h> #include <spi.h> #include <spi_flash.h> @@ -153,7 +154,8 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, err = spl_load_simple_fit(spl_image, &load, payload_offs, header);
} else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) {
} else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) &&
valid_container_hdr((void *)header)) { struct spl_load_info load; load.dev = flash;
diff --git a/configs/deneb_defconfig b/configs/deneb_defconfig index 82869e4e0f9..ee2478aa0bb 100644 --- a/configs/deneb_defconfig +++ b/configs/deneb_defconfig @@ -44,6 +44,8 @@ CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x128000 CONFIG_SPL_BSS_MAX_SIZE=0x1000 CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +# CONFIG_SPL_LEGACY_IMAGE_FORMAT is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set CONFIG_SPL_SYS_MALLOC=y diff --git a/configs/giedi_defconfig b/configs/giedi_defconfig index b56b736c436..5e403c90c8c 100644 --- a/configs/giedi_defconfig +++ b/configs/giedi_defconfig @@ -44,6 +44,8 @@ CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x128000 CONFIG_SPL_BSS_MAX_SIZE=0x1000 CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +# CONFIG_SPL_LEGACY_IMAGE_FORMAT is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set CONFIG_SPL_SYS_MALLOC=y diff --git a/configs/imx8qm_mek_defconfig b/configs/imx8qm_mek_defconfig index b9083b0453f..4c5206306ee 100644 --- a/configs/imx8qm_mek_defconfig +++ b/configs/imx8qm_mek_defconfig @@ -38,6 +38,8 @@ CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x128000 CONFIG_SPL_BSS_MAX_SIZE=0x1000 CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +# CONFIG_SPL_LEGACY_IMAGE_FORMAT is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set CONFIG_SPL_SYS_MALLOC=y diff --git a/configs/imx8qxp_mek_defconfig b/configs/imx8qxp_mek_defconfig index f516b0b5557..f312d3945fb 100644 --- a/configs/imx8qxp_mek_defconfig +++ b/configs/imx8qxp_mek_defconfig @@ -38,6 +38,8 @@ CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x128000 CONFIG_SPL_BSS_MAX_SIZE=0x1000 CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +# CONFIG_SPL_LEGACY_IMAGE_FORMAT is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set CONFIG_SPL_SYS_MALLOC=y diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c index 2b3a9c5fd4c..ee9384fb37e 100644 --- a/drivers/usb/gadget/f_sdp.c +++ b/drivers/usb/gadget/f_sdp.c @@ -34,6 +34,7 @@ #include <spl.h> #include <image.h> #include <imximage.h> +#include <imx_container.h> #include <watchdog.h>
#define HID_REPORT_ID_MASK 0x000000ff @@ -852,7 +853,8 @@ static int sdp_handle_in_ep(struct spl_image_info *spl_image, return SDP_EXIT; } #endif
if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) {
if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) &&
valid_container_hdr((void *)header)) { struct spl_load_info load; load.dev = header;
diff --git a/arch/arm/include/asm/mach-imx/image.h b/include/imx_container.h similarity index 100% rename from arch/arm/include/asm/mach-imx/image.h rename to include/imx_container.h

On 10/12/23 03:44, Heinrich Schuchardt wrote:
On 10/12/23 03:56, Sean Anderson wrote:
Make sure we have an IMX header before calling spl_load_imx_container, since if we don't it will fail with -ENOENT. This allows us to fall back to legacy/raw images if they are also enabled.
Looking at CONFIG_AHAB_BOOT (related to secure boot) we must be sure that we don't introduce any unsolicited fallback on existing configurations.
There are no in-tree boards with SPL_LOAD_IMX_CONTAINER and AHAB_BOOT both enabled.
--Sean
To avoid too much bloat, Legacy/Raw images are disabled for the four configs which only boot from raw MMC.
Future work could include merging imx_container.h with imx8image.h, since they appear to define mostly the same structures.
Signed-off-by: Sean Anderson seanga2@gmail.com
MAINTAINERS | 1 + arch/arm/include/asm/mach-imx/ahab.h | 2 +- arch/arm/mach-imx/cmd_dek.c | 4 ++-- arch/arm/mach-imx/ele_ahab.c | 2 +- arch/arm/mach-imx/image-container.c | 2 +- arch/arm/mach-imx/imx8/ahab.c | 2 +- arch/arm/mach-imx/parse-container.c | 2 +- arch/arm/mach-imx/spl_imx_romapi.c | 5 +++-- common/spl/spl_mmc.c | 4 +++- common/spl/spl_nand.c | 4 +++- common/spl/spl_nor.c | 4 +++- common/spl/spl_spi.c | 4 +++- configs/deneb_defconfig | 2 ++ configs/giedi_defconfig | 2 ++ configs/imx8qm_mek_defconfig | 2 ++ configs/imx8qxp_mek_defconfig | 2 ++ drivers/usb/gadget/f_sdp.c | 4 +++- .../include/asm/mach-imx/image.h => include/imx_container.h | 0 18 files changed, 34 insertions(+), 14 deletions(-) rename arch/arm/include/asm/mach-imx/image.h => include/imx_container.h (100%)
diff --git a/MAINTAINERS b/MAINTAINERS index 7d5d05320c0..35209e73af5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -300,6 +300,7 @@ F: arch/arm/include/asm/mach-imx/ F: board/freescale/*mx*/ F: board/freescale/common/ F: drivers/serial/serial_mxc.c +F: include/imx_container.h
ARM HISILICON M: Peter Griffin peter.griffin@linaro.org diff --git a/arch/arm/include/asm/mach-imx/ahab.h b/arch/arm/include/asm/mach-imx/ahab.h index 4222e3db278..4884f056251 100644 --- a/arch/arm/include/asm/mach-imx/ahab.h +++ b/arch/arm/include/asm/mach-imx/ahab.h @@ -6,7 +6,7 @@ #ifndef __IMX_AHAB_H__ #define __IMX_AHAB_H__
-#include <asm/mach-imx/image.h> +#include <imx_container.h>
int ahab_auth_cntr_hdr(struct container_hdr *container, u16 length); int ahab_auth_release(void); diff --git a/arch/arm/mach-imx/cmd_dek.c b/arch/arm/mach-imx/cmd_dek.c index 6fa5b41fcd3..2f389dbe8df 100644 --- a/arch/arm/mach-imx/cmd_dek.c +++ b/arch/arm/mach-imx/cmd_dek.c @@ -18,12 +18,12 @@ #include <mapmem.h> #include <tee.h> #ifdef CONFIG_IMX_SECO_DEK_ENCAP +#include <imx_container.h> #include <firmware/imx/sci/sci.h> -#include <asm/mach-imx/image.h> #endif #ifdef CONFIG_IMX_ELE_DEK_ENCAP +#include <imx_container.h> #include <asm/mach-imx/ele_api.h> -#include <asm/mach-imx/image.h> #endif
#include <cpu_func.h> diff --git a/arch/arm/mach-imx/ele_ahab.c b/arch/arm/mach-imx/ele_ahab.c index 6a1ad198f89..295c055ad0a 100644 --- a/arch/arm/mach-imx/ele_ahab.c +++ b/arch/arm/mach-imx/ele_ahab.c @@ -6,12 +6,12 @@ #include <common.h> #include <command.h> #include <errno.h> +#include <imx_container.h> #include <asm/io.h> #include <asm/mach-imx/ele_api.h> #include <asm/mach-imx/sys_proto.h> #include <asm/arch-imx/cpu.h> #include <asm/arch/sys_proto.h> -#include <asm/mach-imx/image.h> #include <console.h> #include <cpu_func.h> #include <asm/global_data.h> diff --git a/arch/arm/mach-imx/image-container.c b/arch/arm/mach-imx/image-container.c index eff9e0c4597..ebc8021d7cc 100644 --- a/arch/arm/mach-imx/image-container.c +++ b/arch/arm/mach-imx/image-container.c @@ -5,6 +5,7 @@
#include <common.h> #include <errno.h> +#include <imx_container.h> #include <log.h> #include <malloc.h> #include <asm/io.h> @@ -12,7 +13,6 @@ #include <spi_flash.h> #include <spl.h> #include <nand.h> -#include <asm/mach-imx/image.h> #include <asm/arch/sys_proto.h> #include <asm/mach-imx/boot_mode.h>
diff --git a/arch/arm/mach-imx/imx8/ahab.c b/arch/arm/mach-imx/imx8/ahab.c index 44ea63584aa..994becccefd 100644 --- a/arch/arm/mach-imx/imx8/ahab.c +++ b/arch/arm/mach-imx/imx8/ahab.c @@ -6,6 +6,7 @@ #include <common.h> #include <command.h> #include <errno.h> +#include <imx_container.h> #include <log.h> #include <asm/global_data.h> #include <asm/io.h> @@ -13,7 +14,6 @@ #include <asm/mach-imx/sys_proto.h> #include <asm/arch-imx/cpu.h> #include <asm/arch/sys_proto.h> -#include <asm/mach-imx/image.h> #include <console.h> #include <cpu_func.h> #include "u-boot/sha256.h" diff --git a/arch/arm/mach-imx/parse-container.c b/arch/arm/mach-imx/parse-container.c index 0a3d41f411e..126ab7c57a1 100644 --- a/arch/arm/mach-imx/parse-container.c +++ b/arch/arm/mach-imx/parse-container.c @@ -6,9 +6,9 @@ #include <common.h> #include <stdlib.h> #include <errno.h> +#include <imx_container.h> #include <log.h> #include <spl.h> -#include <asm/mach-imx/image.h> #ifdef CONFIG_AHAB_BOOT #include <asm/mach-imx/ahab.h> #endif diff --git a/arch/arm/mach-imx/spl_imx_romapi.c b/arch/arm/mach-imx/spl_imx_romapi.c index b51061b987b..8816566b364 100644 --- a/arch/arm/mach-imx/spl_imx_romapi.c +++ b/arch/arm/mach-imx/spl_imx_romapi.c @@ -6,11 +6,11 @@ #include <common.h> #include <errno.h> #include <image.h> +#include <imx_container.h> #include <log.h> #include <asm/global_data.h> #include <linux/libfdt.h> #include <spl.h> -#include <asm/mach-imx/image.h> #include <asm/arch/sys_proto.h>
DECLARE_GLOBAL_DATA_PTR; @@ -111,7 +111,8 @@ static int spl_romapi_load_image_seekable(struct spl_image_info *spl_image, load.read = spl_romapi_read_seekable; load.priv = &pagesize; return spl_load_simple_fit(spl_image, &load, offset / pagesize, header); - } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && + valid_container_hdr((void *)header)) { struct spl_load_info load;
memset(&load, 0, sizeof(load)); diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 02ad32a23e0..67c7ae34a58 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -16,6 +16,7 @@ #include <errno.h> #include <mmc.h> #include <image.h> +#include <imx_container.h>
static int mmc_load_legacy(struct spl_image_info *spl_image, struct spl_boot_device *bootdev, @@ -108,7 +109,8 @@ int mmc_load_image_raw_sector(struct spl_image_info *spl_image, load.bl_len = mmc->read_bl_len; load.read = h_spl_load_read; ret = spl_load_simple_fit(spl_image, &load, sector, header); - } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && + valid_container_hdr((void *)header)) { struct spl_load_info load;
load.dev = mmc; diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c index 6cc34004f49..07916bedbb9 100644 --- a/common/spl/spl_nand.c +++ b/common/spl/spl_nand.c @@ -7,6 +7,7 @@ #include <config.h> #include <fdt_support.h> #include <image.h> +#include <imx_container.h> #include <log.h> #include <spl.h> #include <asm/io.h> @@ -99,7 +100,8 @@ static int spl_nand_load_element(struct spl_image_info *spl_image, load.bl_len = bl_len; load.read = spl_nand_fit_read; return spl_load_simple_fit(spl_image, &load, offset / bl_len, header); - } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && + valid_container_hdr((void *)header)) { struct spl_load_info load;
load.dev = NULL; diff --git a/common/spl/spl_nor.c b/common/spl/spl_nor.c index c141a9ae629..dd447982071 100644 --- a/common/spl/spl_nor.c +++ b/common/spl/spl_nor.c @@ -5,6 +5,7 @@
#include <common.h> #include <image.h> +#include <imx_container.h> #include <log.h> #include <spl.h>
@@ -102,7 +103,8 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, (void *)header); } #endif - if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && + valid_container_hdr((void *)header)) { load.bl_len = 1; load.read = spl_nor_load_read; return spl_load_imx_container(spl_image, &load, diff --git a/common/spl/spl_spi.c b/common/spl/spl_spi.c index d69069a75bf..1427c9478c0 100644 --- a/common/spl/spl_spi.c +++ b/common/spl/spl_spi.c @@ -10,6 +10,7 @@
#include <common.h> #include <image.h> +#include <imx_container.h> #include <log.h> #include <spi.h> #include <spi_flash.h> @@ -153,7 +154,8 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, err = spl_load_simple_fit(spl_image, &load, payload_offs, header); - } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && + valid_container_hdr((void *)header)) { struct spl_load_info load;
load.dev = flash; diff --git a/configs/deneb_defconfig b/configs/deneb_defconfig index 82869e4e0f9..ee2478aa0bb 100644 --- a/configs/deneb_defconfig +++ b/configs/deneb_defconfig @@ -44,6 +44,8 @@ CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x128000 CONFIG_SPL_BSS_MAX_SIZE=0x1000 CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +# CONFIG_SPL_LEGACY_IMAGE_FORMAT is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set CONFIG_SPL_SYS_MALLOC=y diff --git a/configs/giedi_defconfig b/configs/giedi_defconfig index b56b736c436..5e403c90c8c 100644 --- a/configs/giedi_defconfig +++ b/configs/giedi_defconfig @@ -44,6 +44,8 @@ CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x128000 CONFIG_SPL_BSS_MAX_SIZE=0x1000 CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +# CONFIG_SPL_LEGACY_IMAGE_FORMAT is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set CONFIG_SPL_SYS_MALLOC=y diff --git a/configs/imx8qm_mek_defconfig b/configs/imx8qm_mek_defconfig index b9083b0453f..4c5206306ee 100644 --- a/configs/imx8qm_mek_defconfig +++ b/configs/imx8qm_mek_defconfig @@ -38,6 +38,8 @@ CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x128000 CONFIG_SPL_BSS_MAX_SIZE=0x1000 CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +# CONFIG_SPL_LEGACY_IMAGE_FORMAT is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set CONFIG_SPL_SYS_MALLOC=y diff --git a/configs/imx8qxp_mek_defconfig b/configs/imx8qxp_mek_defconfig index f516b0b5557..f312d3945fb 100644 --- a/configs/imx8qxp_mek_defconfig +++ b/configs/imx8qxp_mek_defconfig @@ -38,6 +38,8 @@ CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x128000 CONFIG_SPL_BSS_MAX_SIZE=0x1000 CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +# CONFIG_SPL_LEGACY_IMAGE_FORMAT is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set CONFIG_SPL_SYS_MALLOC=y diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c index 2b3a9c5fd4c..ee9384fb37e 100644 --- a/drivers/usb/gadget/f_sdp.c +++ b/drivers/usb/gadget/f_sdp.c @@ -34,6 +34,7 @@ #include <spl.h> #include <image.h> #include <imximage.h> +#include <imx_container.h> #include <watchdog.h>
#define HID_REPORT_ID_MASK 0x000000ff @@ -852,7 +853,8 @@ static int sdp_handle_in_ep(struct spl_image_info *spl_image, return SDP_EXIT; } #endif - if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && + valid_container_hdr((void *)header)) { struct spl_load_info load;
load.dev = header; diff --git a/arch/arm/include/asm/mach-imx/image.h b/include/imx_container.h similarity index 100% rename from arch/arm/include/asm/mach-imx/image.h rename to include/imx_container.h

On Wed, Oct 11, 2023 at 09:56:07PM -0400, Sean Anderson wrote:
Make sure we have an IMX header before calling spl_load_imx_container, since if we don't it will fail with -ENOENT. This allows us to fall back to legacy/raw images if they are also enabled.
To avoid too much bloat, Legacy/Raw images are disabled for the four configs which only boot from raw MMC.
Future work could include merging imx_container.h with imx8image.h, since they appear to define mostly the same structures.
Signed-off-by: Sean Anderson seanga2@gmail.com
So, since you mention bloat, this sounds like it's making functional changes here, but that's not intentional, yes? Or to ask another way, is deneb disabling features here, to save space now that it can, or because they're growing "a bunch" and this reduces the growth?

On 10/12/23 12:40, Tom Rini wrote:
On Wed, Oct 11, 2023 at 09:56:07PM -0400, Sean Anderson wrote:
Make sure we have an IMX header before calling spl_load_imx_container, since if we don't it will fail with -ENOENT. This allows us to fall back to legacy/raw images if they are also enabled.
To avoid too much bloat, Legacy/Raw images are disabled for the four configs which only boot from raw MMC.
Future work could include merging imx_container.h with imx8image.h, since they appear to define mostly the same structures.
Signed-off-by: Sean Anderson seanga2@gmail.com
So, since you mention bloat, this sounds like it's making functional changes here, but that's not intentional, yes? Or to ask another way, is deneb disabling features here, to save space now that it can, or because they're growing "a bunch" and this reduces the growth?
This is a functional change, one which likely should have been in place from the start, but a functional change nonetheless. Previously, all non-IMX8 images (except FITs without FIT_FULL) would be optimized out if the only image load method supported IMX8 images. With this change, support for these image types now has an effect.
There are seven boards with SPL_LOAD_IMX_CONTAINER enabled:
imx93_11x11_evk_ld imx8qm_mek imx8qxp_mek giedi imx93_11x11_evk imx8ulp_evk deneb
All of these boards also have SPL_RAW_IMAGE_SUPPORT and SPL_LEGACY_IMAGE_FORMAT enabled as well. However, none have FIT support enabled. Of the six load methods affected by this patch, only SPL_MMC and SPL_BOOTROM_SUPPORT are enabled with SPL_LOAD_IMX_CONTAINER. spl_romapi_load_image_seekable does not support legacy or raw images, so there is no growth. However, mmc_load_image_raw_sector does support loading legacy/raw images. Since these images could not have been booted before, I have disabled support for legacy/raw images on these four boards. This reduces bloat from around 800 bytes to around 200.
--Sean

On Thu, Oct 12, 2023 at 09:39:22PM -0400, Sean Anderson wrote:
On 10/12/23 12:40, Tom Rini wrote:
On Wed, Oct 11, 2023 at 09:56:07PM -0400, Sean Anderson wrote:
Make sure we have an IMX header before calling spl_load_imx_container, since if we don't it will fail with -ENOENT. This allows us to fall back to legacy/raw images if they are also enabled.
To avoid too much bloat, Legacy/Raw images are disabled for the four configs which only boot from raw MMC.
Future work could include merging imx_container.h with imx8image.h, since they appear to define mostly the same structures.
Signed-off-by: Sean Anderson seanga2@gmail.com
So, since you mention bloat, this sounds like it's making functional changes here, but that's not intentional, yes? Or to ask another way, is deneb disabling features here, to save space now that it can, or because they're growing "a bunch" and this reduces the growth?
This is a functional change, one which likely should have been in place from the start, but a functional change nonetheless. Previously, all non-IMX8 images (except FITs without FIT_FULL) would be optimized out if the only image load method supported IMX8 images. With this change, support for these image types now has an effect.
There are seven boards with SPL_LOAD_IMX_CONTAINER enabled:
imx93_11x11_evk_ld imx8qm_mek imx8qxp_mek giedi imx93_11x11_evk imx8ulp_evk deneb
All of these boards also have SPL_RAW_IMAGE_SUPPORT and SPL_LEGACY_IMAGE_FORMAT enabled as well. However, none have FIT support enabled. Of the six load methods affected by this patch, only SPL_MMC and SPL_BOOTROM_SUPPORT are enabled with SPL_LOAD_IMX_CONTAINER. spl_romapi_load_image_seekable does not support legacy or raw images, so there is no growth. However, mmc_load_image_raw_sector does support loading legacy/raw images. Since these images could not have been booted before, I have disabled support for legacy/raw images on these four boards. This reduces bloat from around 800 bytes to around 200.
Ah, OK, thanks for explaining.

To facilitate testing loading i.MX8 container images, move the parse-container code to common/spl.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
MAINTAINERS | 1 + arch/arm/mach-imx/Kconfig | 13 ------------- arch/arm/mach-imx/Makefile | 2 +- common/spl/Kconfig | 14 ++++++++++++++ common/spl/Makefile | 1 + .../spl/spl_imx_container.c | 0 6 files changed, 17 insertions(+), 14 deletions(-) rename arch/arm/mach-imx/parse-container.c => common/spl/spl_imx_container.c (100%)
diff --git a/MAINTAINERS b/MAINTAINERS index 35209e73af5..dd6bb558dc4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -299,6 +299,7 @@ F: arch/arm/include/asm/arch-vf610/ F: arch/arm/include/asm/mach-imx/ F: board/freescale/*mx*/ F: board/freescale/common/ +F: common/spl/spl_imx_container.c F: drivers/serial/serial_mxc.c F: include/imx_container.h
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 266bb20df9d..08ab7069187 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -194,19 +194,6 @@ config IMX_DCD_ADDR This information is shared with the user via mkimage -l just so the image can be signed.
-config SPL_LOAD_IMX_CONTAINER - bool "Enable SPL loading U-Boot as a i.MX Container image" - depends on SPL - help - This is to let SPL could load i.MX Container image - -config IMX_CONTAINER_CFG - string "i.MX Container config file" - depends on SPL - help - This is to specific the cfg file for generating container - image which will be loaded by SPL. - config IOMUX_LPSR bool
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index aebfa6517bd..7c4e03278e3 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -79,7 +79,7 @@ obj-$(CONFIG_CMD_NANDBCB) += cmd_nandbcb.o endif
ifeq ($(CONFIG_SPL_BUILD),y) -obj-$(CONFIG_SPL_LOAD_IMX_CONTAINER) += image-container.o parse-container.o +obj-$(CONFIG_SPL_LOAD_IMX_CONTAINER) += image-container.o endif
ifeq ($(SOC),$(filter $(SOC),imx8ulp imx9)) diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 46323597942..ad574a600e3 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -330,6 +330,20 @@ config SPL_LEGACY_IMAGE_CRC_CHECK If disabled, Legacy images are booted if the image magic and size are correct, without further integrity checks.
+config SPL_LOAD_IMX_CONTAINER + bool "Enable SPL loading and booting of i.MX8 Containers" + depends on SPL + help + Support booting U-Boot from an i.MX8 container image. If you are not + using i.MX8, say 'n'. + +config IMX_CONTAINER_CFG + string "i.MX8 Container config file" + depends on SPL && SPL_LOAD_IMX_CONTAINER + help + Specify the cfg file for generating the container image which will be + loaded by SPL. + config SPL_SYS_MALLOC_SIMPLE bool "Only use malloc_simple functions in the SPL" help diff --git a/common/spl/Makefile b/common/spl/Makefile index bad2bbf6cf1..4f8eb2ec0ca 100644 --- a/common/spl/Makefile +++ b/common/spl/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_$(SPL_TPL_)OPENSBI) += spl_opensbi.o obj-$(CONFIG_$(SPL_TPL_)USB_STORAGE) += spl_usb.o obj-$(CONFIG_$(SPL_TPL_)FS_FAT) += spl_fat.o obj-$(CONFIG_$(SPL_TPL_)FS_EXT4) += spl_ext.o +obj-$(CONFIG_$(SPL_TPL_)LOAD_IMX_CONTAINER) += spl_imx_container.o obj-$(CONFIG_$(SPL_TPL_)SATA) += spl_sata.o obj-$(CONFIG_$(SPL_TPL_)NVME) += spl_nvme.o obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += spl_semihosting.o diff --git a/arch/arm/mach-imx/parse-container.c b/common/spl/spl_imx_container.c similarity index 100% rename from arch/arm/mach-imx/parse-container.c rename to common/spl/spl_imx_container.c

Sandbox unit tests in U-Boot proper load a test device tree to have some devices to work with. In order to do the same in SPL, we must enable SPL_OF_REAL. However, we already have SPL_OF_PLATDATA enabled. When generating platdata from a devicetree, it is expected that we will not need devicetree access functions (even though SPL_OF_CONTROL is enabled). This expectation does not hold for sandbox, so allow user control of SPL_OF_REAL.
There are several places in the tree where conditions involving OF_PLATDATA or OF_REAL no longer function correctly when both of these options can be selected at the same time. Adjust these conditions accordingly.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
drivers/core/Makefile | 1 + drivers/i2c/i2c-emul-uclass.c | 2 +- drivers/serial/sandbox.c | 2 +- drivers/sysreset/sysreset_sandbox.c | 2 +- dts/Kconfig | 8 +++++--- test/test-main.c | 2 +- 6 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/drivers/core/Makefile b/drivers/core/Makefile index bce0a3f65cb..acbd2bf2cef 100644 --- a/drivers/core/Makefile +++ b/drivers/core/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_$(SPL_)OF_LIVE) += of_access.o of_addr.o ifndef CONFIG_DM_DEV_READ_INLINE obj-$(CONFIG_OF_CONTROL) += read.o endif +obj-$(CONFIG_$(SPL_)OF_PLATDATA) += read.o obj-$(CONFIG_OF_CONTROL) += of_extra.o ofnode.o read_extra.o
ccflags-$(CONFIG_DM_DEBUG) += -DDEBUG diff --git a/drivers/i2c/i2c-emul-uclass.c b/drivers/i2c/i2c-emul-uclass.c index 1107cf309fc..d421ddfcbe2 100644 --- a/drivers/i2c/i2c-emul-uclass.c +++ b/drivers/i2c/i2c-emul-uclass.c @@ -46,7 +46,7 @@ int i2c_emul_find(struct udevice *dev, struct udevice **emulp) struct udevice *emul; int ret;
- if (!CONFIG_IS_ENABLED(OF_PLATDATA)) { + if (CONFIG_IS_ENABLED(OF_REAL)) { ret = uclass_find_device_by_phandle(UCLASS_I2C_EMUL, dev, "sandbox,emul", &emul); } else { diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c index f4003811ee7..f6ac3d22852 100644 --- a/drivers/serial/sandbox.c +++ b/drivers/serial/sandbox.c @@ -280,7 +280,7 @@ U_BOOT_DRIVER(sandbox_serial) = { .flags = DM_FLAG_PRE_RELOC, };
-#if CONFIG_IS_ENABLED(OF_REAL) +#if CONFIG_IS_ENABLED(OF_REAL) && !CONFIG_IS_ENABLED(OF_PLATDATA) static const struct sandbox_serial_plat platdata_non_fdt = { .colour = -1, }; diff --git a/drivers/sysreset/sysreset_sandbox.c b/drivers/sysreset/sysreset_sandbox.c index 3750c60b9b9..f485a135299 100644 --- a/drivers/sysreset/sysreset_sandbox.c +++ b/drivers/sysreset/sysreset_sandbox.c @@ -132,7 +132,7 @@ U_BOOT_DRIVER(warm_sysreset_sandbox) = { .ops = &sandbox_warm_sysreset_ops, };
-#if CONFIG_IS_ENABLED(OF_REAL) +#if CONFIG_IS_ENABLED(OF_REAL) && !CONFIG_IS_ENABLED(OF_PLATDATA) /* This is here in case we don't have a device tree */ U_BOOT_DRVINFO(sysreset_sandbox_non_fdt) = { .name = "sysreset_sandbox", diff --git a/dts/Kconfig b/dts/Kconfig index 9152f5885e9..c6fb193ca89 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -410,12 +410,14 @@ config SPL_OF_PLATDATA declarations for each node. See of-plat.txt for more information.
config SPL_OF_REAL - bool + bool "Support a real devicetree in SPL" + depends on SPL_OF_CONTROL + select SPL_OF_LIBFDT help Indicates that a real devicetree is available which can be accessed at runtime. This means that dev_read_...() functions can be used to - read data from the devicetree for each device. This is true if - SPL_OF_CONTROL is enabled and not SPL_OF_PLATDATA + read data from the devicetree for each device. You do not need to + enable this option if you have enabled SPL_OF_PLATDATA.
if SPL_OF_PLATDATA
diff --git a/test/test-main.c b/test/test-main.c index edb20bc4b9c..b7015d9f38d 100644 --- a/test/test-main.c +++ b/test/test-main.c @@ -303,7 +303,7 @@ static int test_pre_run(struct unit_test_state *uts, struct unit_test *test) if (test->flags & UT_TESTF_PROBE_TEST) ut_assertok(do_autoprobe(uts));
- if (!CONFIG_IS_ENABLED(OF_PLATDATA) && + if (CONFIG_IS_ENABLED(OF_REAL) && (test->flags & UT_TESTF_SCAN_FDT)) { /* * only set this if we know the ethernet uclass will be created

Hi Sean,
On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
Sandbox unit tests in U-Boot proper load a test device tree to have some devices to work with. In order to do the same in SPL, we must enable SPL_OF_REAL. However, we already have SPL_OF_PLATDATA enabled. When generating platdata from a devicetree, it is expected that we will not need devicetree access functions (even though SPL_OF_CONTROL is enabled). This expectation does not hold for sandbox, so allow user control of SPL_OF_REAL.
There are several places in the tree where conditions involving OF_PLATDATA or OF_REAL no longer function correctly when both of these options can be selected at the same time. Adjust these conditions accordingly.
Signed-off-by: Sean Anderson seanga2@gmail.com
drivers/core/Makefile | 1 + drivers/i2c/i2c-emul-uclass.c | 2 +- drivers/serial/sandbox.c | 2 +- drivers/sysreset/sysreset_sandbox.c | 2 +- dts/Kconfig | 8 +++++--- test/test-main.c | 2 +- 6 files changed, 10 insertions(+), 7 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
with a due sense of foreboding
I wonder whether this might create confusion?
diff --git a/drivers/core/Makefile b/drivers/core/Makefile index bce0a3f65cb..acbd2bf2cef 100644 --- a/drivers/core/Makefile +++ b/drivers/core/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_$(SPL_)OF_LIVE) += of_access.o of_addr.o ifndef CONFIG_DM_DEV_READ_INLINE obj-$(CONFIG_OF_CONTROL) += read.o endif +obj-$(CONFIG_$(SPL_)OF_PLATDATA) += read.o obj-$(CONFIG_OF_CONTROL) += of_extra.o ofnode.o read_extra.o
ccflags-$(CONFIG_DM_DEBUG) += -DDEBUG diff --git a/drivers/i2c/i2c-emul-uclass.c b/drivers/i2c/i2c-emul-uclass.c index 1107cf309fc..d421ddfcbe2 100644 --- a/drivers/i2c/i2c-emul-uclass.c +++ b/drivers/i2c/i2c-emul-uclass.c @@ -46,7 +46,7 @@ int i2c_emul_find(struct udevice *dev, struct udevice **emulp) struct udevice *emul; int ret;
if (!CONFIG_IS_ENABLED(OF_PLATDATA)) {
if (CONFIG_IS_ENABLED(OF_REAL)) { ret = uclass_find_device_by_phandle(UCLASS_I2C_EMUL, dev, "sandbox,emul", &emul); } else {
diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c index f4003811ee7..f6ac3d22852 100644 --- a/drivers/serial/sandbox.c +++ b/drivers/serial/sandbox.c @@ -280,7 +280,7 @@ U_BOOT_DRIVER(sandbox_serial) = { .flags = DM_FLAG_PRE_RELOC, };
-#if CONFIG_IS_ENABLED(OF_REAL) +#if CONFIG_IS_ENABLED(OF_REAL) && !CONFIG_IS_ENABLED(OF_PLATDATA) static const struct sandbox_serial_plat platdata_non_fdt = { .colour = -1, }; diff --git a/drivers/sysreset/sysreset_sandbox.c b/drivers/sysreset/sysreset_sandbox.c index 3750c60b9b9..f485a135299 100644 --- a/drivers/sysreset/sysreset_sandbox.c +++ b/drivers/sysreset/sysreset_sandbox.c @@ -132,7 +132,7 @@ U_BOOT_DRIVER(warm_sysreset_sandbox) = { .ops = &sandbox_warm_sysreset_ops, };
-#if CONFIG_IS_ENABLED(OF_REAL) +#if CONFIG_IS_ENABLED(OF_REAL) && !CONFIG_IS_ENABLED(OF_PLATDATA) /* This is here in case we don't have a device tree */ U_BOOT_DRVINFO(sysreset_sandbox_non_fdt) = { .name = "sysreset_sandbox", diff --git a/dts/Kconfig b/dts/Kconfig index 9152f5885e9..c6fb193ca89 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -410,12 +410,14 @@ config SPL_OF_PLATDATA declarations for each node. See of-plat.txt for more information.
config SPL_OF_REAL
bool
bool "Support a real devicetree in SPL"
To avoid the user doing something silly, I wonder if it would be better to keep this option hidden, but enable it for sandbox_spl via Kconfig?
depends on SPL_OF_CONTROL
select SPL_OF_LIBFDT help Indicates that a real devicetree is available which can be accessed at runtime. This means that dev_read_...() functions can be used to
read data from the devicetree for each device. This is true if
SPL_OF_CONTROL is enabled and not SPL_OF_PLATDATA
read data from the devicetree for each device. You do not need to
enable this option if you have enabled SPL_OF_PLATDATA.
if SPL_OF_PLATDATA
diff --git a/test/test-main.c b/test/test-main.c index edb20bc4b9c..b7015d9f38d 100644 --- a/test/test-main.c +++ b/test/test-main.c @@ -303,7 +303,7 @@ static int test_pre_run(struct unit_test_state *uts, struct unit_test *test) if (test->flags & UT_TESTF_PROBE_TEST) ut_assertok(do_autoprobe(uts));
if (!CONFIG_IS_ENABLED(OF_PLATDATA) &&
if (CONFIG_IS_ENABLED(OF_REAL) && (test->flags & UT_TESTF_SCAN_FDT)) { /* * only set this if we know the ethernet uclass will be created
-- 2.37.1
Regards, Simon

On 10/11/23 23:41, Simon Glass wrote:
Hi Sean,
On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
Sandbox unit tests in U-Boot proper load a test device tree to have some devices to work with. In order to do the same in SPL, we must enable SPL_OF_REAL. However, we already have SPL_OF_PLATDATA enabled. When generating platdata from a devicetree, it is expected that we will not need devicetree access functions (even though SPL_OF_CONTROL is enabled). This expectation does not hold for sandbox, so allow user control of SPL_OF_REAL.
There are several places in the tree where conditions involving OF_PLATDATA or OF_REAL no longer function correctly when both of these options can be selected at the same time. Adjust these conditions accordingly.
Signed-off-by: Sean Anderson seanga2@gmail.com
drivers/core/Makefile | 1 + drivers/i2c/i2c-emul-uclass.c | 2 +- drivers/serial/sandbox.c | 2 +- drivers/sysreset/sysreset_sandbox.c | 2 +- dts/Kconfig | 8 +++++--- test/test-main.c | 2 +- 6 files changed, 10 insertions(+), 7 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
with a due sense of foreboding
I wonder whether this might create confusion?
Yeah, I was a bit worried about that as well.
diff --git a/drivers/core/Makefile b/drivers/core/Makefile index bce0a3f65cb..acbd2bf2cef 100644 --- a/drivers/core/Makefile +++ b/drivers/core/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_$(SPL_)OF_LIVE) += of_access.o of_addr.o ifndef CONFIG_DM_DEV_READ_INLINE obj-$(CONFIG_OF_CONTROL) += read.o endif +obj-$(CONFIG_$(SPL_)OF_PLATDATA) += read.o obj-$(CONFIG_OF_CONTROL) += of_extra.o ofnode.o read_extra.o
ccflags-$(CONFIG_DM_DEBUG) += -DDEBUG diff --git a/drivers/i2c/i2c-emul-uclass.c b/drivers/i2c/i2c-emul-uclass.c index 1107cf309fc..d421ddfcbe2 100644 --- a/drivers/i2c/i2c-emul-uclass.c +++ b/drivers/i2c/i2c-emul-uclass.c @@ -46,7 +46,7 @@ int i2c_emul_find(struct udevice *dev, struct udevice **emulp) struct udevice *emul; int ret;
if (!CONFIG_IS_ENABLED(OF_PLATDATA)) {
if (CONFIG_IS_ENABLED(OF_REAL)) { ret = uclass_find_device_by_phandle(UCLASS_I2C_EMUL, dev, "sandbox,emul", &emul); } else {
diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c index f4003811ee7..f6ac3d22852 100644 --- a/drivers/serial/sandbox.c +++ b/drivers/serial/sandbox.c @@ -280,7 +280,7 @@ U_BOOT_DRIVER(sandbox_serial) = { .flags = DM_FLAG_PRE_RELOC, };
-#if CONFIG_IS_ENABLED(OF_REAL) +#if CONFIG_IS_ENABLED(OF_REAL) && !CONFIG_IS_ENABLED(OF_PLATDATA) static const struct sandbox_serial_plat platdata_non_fdt = { .colour = -1, }; diff --git a/drivers/sysreset/sysreset_sandbox.c b/drivers/sysreset/sysreset_sandbox.c index 3750c60b9b9..f485a135299 100644 --- a/drivers/sysreset/sysreset_sandbox.c +++ b/drivers/sysreset/sysreset_sandbox.c @@ -132,7 +132,7 @@ U_BOOT_DRIVER(warm_sysreset_sandbox) = { .ops = &sandbox_warm_sysreset_ops, };
-#if CONFIG_IS_ENABLED(OF_REAL) +#if CONFIG_IS_ENABLED(OF_REAL) && !CONFIG_IS_ENABLED(OF_PLATDATA) /* This is here in case we don't have a device tree */ U_BOOT_DRVINFO(sysreset_sandbox_non_fdt) = { .name = "sysreset_sandbox", diff --git a/dts/Kconfig b/dts/Kconfig index 9152f5885e9..c6fb193ca89 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -410,12 +410,14 @@ config SPL_OF_PLATDATA declarations for each node. See of-plat.txt for more information.
config SPL_OF_REAL
bool
bool "Support a real devicetree in SPL"
To avoid the user doing something silly, I wonder if it would be better to keep this option hidden, but enable it for sandbox_spl via Kconfig?
So
visible if SANDBOX
?
depends on SPL_OF_CONTROL
select SPL_OF_LIBFDT help Indicates that a real devicetree is available which can be accessed at runtime. This means that dev_read_...() functions can be used to
read data from the devicetree for each device. This is true if
SPL_OF_CONTROL is enabled and not SPL_OF_PLATDATA
read data from the devicetree for each device. You do not need to
enable this option if you have enabled SPL_OF_PLATDATA.
if SPL_OF_PLATDATA
diff --git a/test/test-main.c b/test/test-main.c index edb20bc4b9c..b7015d9f38d 100644 --- a/test/test-main.c +++ b/test/test-main.c @@ -303,7 +303,7 @@ static int test_pre_run(struct unit_test_state *uts, struct unit_test *test) if (test->flags & UT_TESTF_PROBE_TEST) ut_assertok(do_autoprobe(uts));
if (!CONFIG_IS_ENABLED(OF_PLATDATA) &&
if (CONFIG_IS_ENABLED(OF_REAL) && (test->flags & UT_TESTF_SCAN_FDT)) { /* * only set this if we know the ethernet uclass will be created
-- 2.37.1
Regards, Simon

lib/acpi/acpigen.o is only compiled into SPL when SPL_ACPIGEN is enabled. Update several files which reference these functions accordingly.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
drivers/core/root.c | 2 +- drivers/i2c/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/core/root.c b/drivers/core/root.c index 126b3140666..d4ae652bcfb 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -426,7 +426,7 @@ void dm_get_mem(struct dm_stats *stats) stats->tag_size; }
-#ifdef CONFIG_ACPIGEN +#if CONFIG_IS_ENABLED(ACPIGEN) static int root_acpi_get_name(const struct udevice *dev, char *out_name) { return acpi_copy_name(out_name, "\_SB"); diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index d5b85f398db..a96a8c7e955 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -3,7 +3,7 @@ # (C) Copyright 2000-2007 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. obj-$(CONFIG_$(SPL_)DM_I2C) += i2c-uclass.o -ifdef CONFIG_ACPIGEN +ifdef CONFIG_$(SPL_)ACPIGEN obj-$(CONFIG_$(SPL_)DM_I2C) += acpi_i2c.o endif obj-$(CONFIG_$(SPL_)DM_I2C_GPIO) += i2c-gpio.o

On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
lib/acpi/acpigen.o is only compiled into SPL when SPL_ACPIGEN is enabled. Update several files which reference these functions accordingly.
Signed-off-by: Sean Anderson seanga2@gmail.com
drivers/core/root.c | 2 +- drivers/i2c/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

If EXT4_WRITE is enabled, write capabilities will be compiled into SPL, but not CRC16. Add an option to enable CRC16 to avoid linker errors.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
common/spl/Kconfig | 1 + lib/Kconfig | 6 ++++++ lib/Makefile | 1 + 3 files changed, 8 insertions(+)
diff --git a/common/spl/Kconfig b/common/spl/Kconfig index ad574a600e3..6bc4066fad7 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -657,6 +657,7 @@ config SPL_ETH
config SPL_FS_EXT4 bool "Support EXT filesystems" + select SPL_CRC16 if EXT4_WRITE help Enable support for EXT2/3/4 filesystems with SPL. This permits U-Boot (or Linux in Falcon mode) to be loaded from an EXT diff --git a/lib/Kconfig b/lib/Kconfig index 79cf9ef0fa3..f6ca559897e 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -687,6 +687,12 @@ config SPL_CRC8 checksum with feedback to produce an 8-bit result. The code is small and it does not require a lookup table (unlike CRC32).
+config SPL_CRC16 + bool "Support CRC16 in SPL" + depends on SPL + help + Enables CRC16 support in SPL. This is not normally required. + config CRC32 def_bool y help diff --git a/lib/Makefile b/lib/Makefile index 1c31ad9531e..2a76acf100d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_TPM_V2) += tpm-v2.o endif
obj-$(CONFIG_$(SPL_TPL_)CRC8) += crc8.o +obj-$(CONFIG_$(SPL_TPL_)CRC16) += crc16.o
obj-y += crypto/

On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
If EXT4_WRITE is enabled, write capabilities will be compiled into SPL, but not CRC16. Add an option to enable CRC16 to avoid linker errors.
Signed-off-by: Sean Anderson seanga2@gmail.com
common/spl/Kconfig | 1 + lib/Kconfig | 6 ++++++ lib/Makefile | 1 + 3 files changed, 8 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

fs.c thinks that the sandbox filesystem is available if SANDBOX is enabled, but it is not in SPL. Compile it in SPL to avoid linker errors.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
fs/Makefile | 1 + 1 file changed, 1 insertion(+)
diff --git a/fs/Makefile b/fs/Makefile index 4bed2ff2d99..592c7542bde 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_FS_LOADER) += fs.o obj-$(CONFIG_SPL_FS_FAT) += fat/ obj-$(CONFIG_SPL_FS_EXT4) += ext4/ obj-$(CONFIG_SPL_FS_CBFS) += cbfs/ +obj-$(CONFIG_SANDBOX) += sandbox/ obj-$(CONFIG_SPL_FS_SQUASHFS) += squashfs/ else obj-y += fs.o

On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
fs.c thinks that the sandbox filesystem is available if SANDBOX is enabled, but it is not in SPL. Compile it in SPL to avoid linker errors.
Signed-off-by: Sean Anderson seanga2@gmail.com
fs/Makefile | 1 + 1 file changed, 1 insertion(+)
Reviewed-by: Simon Glass sjg@chromium.org

On 10/12/23 03:56, Sean Anderson wrote:
fs.c thinks that the sandbox filesystem is available if SANDBOX is enabled, but it is not in SPL. Compile it in SPL to avoid linker errors.
Signed-off-by: Sean Anderson seanga2@gmail.com
fs/Makefile | 1 + 1 file changed, 1 insertion(+)
diff --git a/fs/Makefile b/fs/Makefile index 4bed2ff2d99..592c7542bde 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_FS_LOADER) += fs.o obj-$(CONFIG_SPL_FS_FAT) += fat/ obj-$(CONFIG_SPL_FS_EXT4) += ext4/ obj-$(CONFIG_SPL_FS_CBFS) += cbfs/ +obj-$(CONFIG_SANDBOX) += sandbox/
Why wouldn't you use CONFIG_SANDBOX_SPL here?
Best regards
Heinrich
obj-$(CONFIG_SPL_FS_SQUASHFS) += squashfs/ else obj-y += fs.o

On 10/12/23 02:39, Heinrich Schuchardt wrote:
On 10/12/23 03:56, Sean Anderson wrote:
fs.c thinks that the sandbox filesystem is available if SANDBOX is enabled, but it is not in SPL. Compile it in SPL to avoid linker errors.
Signed-off-by: Sean Anderson seanga2@gmail.com
fs/Makefile | 1 + 1 file changed, 1 insertion(+)
diff --git a/fs/Makefile b/fs/Makefile index 4bed2ff2d99..592c7542bde 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_FS_LOADER) += fs.o obj-$(CONFIG_SPL_FS_FAT) += fat/ obj-$(CONFIG_SPL_FS_EXT4) += ext4/ obj-$(CONFIG_SPL_FS_CBFS) += cbfs/ +obj-$(CONFIG_SANDBOX) += sandbox/
Why wouldn't you use CONFIG_SANDBOX_SPL here?
Because that's what the check is in fs.c. Maybe it should be CONFIG_IS_ENABLED(SANDBOX) in there.
--Sean

On Thu, Oct 12, 2023 at 10:15:45AM -0400, Sean Anderson wrote:
On 10/12/23 02:39, Heinrich Schuchardt wrote:
On 10/12/23 03:56, Sean Anderson wrote:
fs.c thinks that the sandbox filesystem is available if SANDBOX is enabled, but it is not in SPL. Compile it in SPL to avoid linker errors.
Signed-off-by: Sean Anderson seanga2@gmail.com
fs/Makefile | 1 + 1 file changed, 1 insertion(+)
diff --git a/fs/Makefile b/fs/Makefile index 4bed2ff2d99..592c7542bde 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_FS_LOADER) += fs.o obj-$(CONFIG_SPL_FS_FAT) += fat/ obj-$(CONFIG_SPL_FS_EXT4) += ext4/ obj-$(CONFIG_SPL_FS_CBFS) += cbfs/ +obj-$(CONFIG_SANDBOX) += sandbox/
Why wouldn't you use CONFIG_SANDBOX_SPL here?
Because that's what the check is in fs.c. Maybe it should be CONFIG_IS_ENABLED(SANDBOX) in there.
"CONFIG_SANDBOX_SPL" is not "CONFIG_SPL_SANDBOX", so CONFIG_IS_ENABLED doesn't work. I would suggest that fs/Makefile needs a bit of cleaning to make use of obj-$(CONFIG_$(SPL_)_... logic instead of ifdef CONFIG_SPL_BUILD, but I think Simon dislikes that form. We could just move the existing line outside of the SPL/else conditional.

On Thu, Oct 12, 2023 at 10:15:45AM -0400, Sean Anderson wrote:
On 10/12/23 02:39, Heinrich Schuchardt wrote:
On 10/12/23 03:56, Sean Anderson wrote:
fs.c thinks that the sandbox filesystem is available if SANDBOX is enabled, but it is not in SPL. Compile it in SPL to avoid linker errors.
Signed-off-by: Sean Anderson seanga2@gmail.com
fs/Makefile | 1 + 1 file changed, 1 insertion(+)
diff --git a/fs/Makefile b/fs/Makefile index 4bed2ff2d99..592c7542bde 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_FS_LOADER) += fs.o obj-$(CONFIG_SPL_FS_FAT) += fat/ obj-$(CONFIG_SPL_FS_EXT4) += ext4/ obj-$(CONFIG_SPL_FS_CBFS) += cbfs/ +obj-$(CONFIG_SANDBOX) += sandbox/
Why wouldn't you use CONFIG_SANDBOX_SPL here?
Because that's what the check is in fs.c. Maybe it should be CONFIG_IS_ENABLED(SANDBOX) in there.
And, yes I just said one thing, but on the other hand, if we don't need this for tests in SPL then fixing fs/fs.c instead is indeed better.

When fastboot is enabled in U-Boot proper and SPL_NET is enabled, we will try to (unsuccessfully) reference it in SPL. Fix these linker errors by conditioning on SPL_UDP/TCP_FUNCTION_FASTBOOT.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
net/Makefile | 4 ++-- net/net.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/Makefile b/net/Makefile index 3e2d061338d..5ea58eef7e4 100644 --- a/net/Makefile +++ b/net/Makefile @@ -27,8 +27,8 @@ obj-$(CONFIG_CMD_PCAP) += pcap.o obj-$(CONFIG_CMD_RARP) += rarp.o obj-$(CONFIG_CMD_SNTP) += sntp.o obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o -obj-$(CONFIG_UDP_FUNCTION_FASTBOOT) += fastboot_udp.o -obj-$(CONFIG_TCP_FUNCTION_FASTBOOT) += fastboot_tcp.o +obj-$(CONFIG_$(SPL_)UDP_FUNCTION_FASTBOOT) += fastboot_udp.o +obj-$(CONFIG_$(SPL_)TCP_FUNCTION_FASTBOOT) += fastboot_tcp.o obj-$(CONFIG_CMD_WOL) += wol.o obj-$(CONFIG_PROT_UDP) += udp.o obj-$(CONFIG_PROT_TCP) += tcp.o diff --git a/net/net.c b/net/net.c index e6f61f0f8f6..8357f084101 100644 --- a/net/net.c +++ b/net/net.c @@ -511,12 +511,12 @@ restart: tftp_start_server(); break; #endif -#if defined(CONFIG_UDP_FUNCTION_FASTBOOT) +#if CONFIG_IS_ENABLED(UDP_FUNCTION_FASTBOOT) case FASTBOOT_UDP: fastboot_udp_start_server(); break; #endif -#if defined(CONFIG_TCP_FUNCTION_FASTBOOT) +#if CONFIG_IS_ENABLED(TCP_FUNCTION_FASTBOOT) case FASTBOOT_TCP: fastboot_tcp_start_server(); break;

On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
When fastboot is enabled in U-Boot proper and SPL_NET is enabled, we will try to (unsuccessfully) reference it in SPL. Fix these linker errors by conditioning on SPL_UDP/TCP_FUNCTION_FASTBOOT.
Signed-off-by: Sean Anderson seanga2@gmail.com
net/Makefile | 4 ++-- net/net.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

On 10/12/23 03:56, Sean Anderson wrote:
When fastboot is enabled in U-Boot proper and SPL_NET is enabled, we will try to (unsuccessfully) reference it in SPL. Fix these linker errors by conditioning on SPL_UDP/TCP_FUNCTION_FASTBOOT.
Signed-off-by: Sean Anderson seanga2@gmail.com
net/Makefile | 4 ++-- net/net.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/Makefile b/net/Makefile index 3e2d061338d..5ea58eef7e4 100644 --- a/net/Makefile +++ b/net/Makefile @@ -27,8 +27,8 @@ obj-$(CONFIG_CMD_PCAP) += pcap.o obj-$(CONFIG_CMD_RARP) += rarp.o obj-$(CONFIG_CMD_SNTP) += sntp.o obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o -obj-$(CONFIG_UDP_FUNCTION_FASTBOOT) += fastboot_udp.o -obj-$(CONFIG_TCP_FUNCTION_FASTBOOT) += fastboot_tcp.o +obj-$(CONFIG_$(SPL_)UDP_FUNCTION_FASTBOOT) += fastboot_udp.o +obj-$(CONFIG_$(SPL_)TCP_FUNCTION_FASTBOOT) += fastboot_tcp.o
Please, use $(SPL_TPL) so that we don't have to revisit this should we ever decide to enable fastboot in SPL in future.
Best regards
Heinrich
obj-$(CONFIG_CMD_WOL) += wol.o obj-$(CONFIG_PROT_UDP) += udp.o obj-$(CONFIG_PROT_TCP) += tcp.o diff --git a/net/net.c b/net/net.c index e6f61f0f8f6..8357f084101 100644 --- a/net/net.c +++ b/net/net.c @@ -511,12 +511,12 @@ restart: tftp_start_server(); break; #endif -#if defined(CONFIG_UDP_FUNCTION_FASTBOOT) +#if CONFIG_IS_ENABLED(UDP_FUNCTION_FASTBOOT) case FASTBOOT_UDP: fastboot_udp_start_server(); break; #endif -#if defined(CONFIG_TCP_FUNCTION_FASTBOOT) +#if CONFIG_IS_ENABLED(TCP_FUNCTION_FASTBOOT) case FASTBOOT_TCP: fastboot_tcp_start_server(); break;

On 10/12/23 02:52, Heinrich Schuchardt wrote:
On 10/12/23 03:56, Sean Anderson wrote:
When fastboot is enabled in U-Boot proper and SPL_NET is enabled, we will try to (unsuccessfully) reference it in SPL. Fix these linker errors by conditioning on SPL_UDP/TCP_FUNCTION_FASTBOOT.
Signed-off-by: Sean Anderson seanga2@gmail.com
net/Makefile | 4 ++-- net/net.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/Makefile b/net/Makefile index 3e2d061338d..5ea58eef7e4 100644 --- a/net/Makefile +++ b/net/Makefile @@ -27,8 +27,8 @@ obj-$(CONFIG_CMD_PCAP) += pcap.o obj-$(CONFIG_CMD_RARP) += rarp.o obj-$(CONFIG_CMD_SNTP) += sntp.o obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o -obj-$(CONFIG_UDP_FUNCTION_FASTBOOT) += fastboot_udp.o -obj-$(CONFIG_TCP_FUNCTION_FASTBOOT) += fastboot_tcp.o +obj-$(CONFIG_$(SPL_)UDP_FUNCTION_FASTBOOT) += fastboot_udp.o +obj-$(CONFIG_$(SPL_)TCP_FUNCTION_FASTBOOT) += fastboot_tcp.o
Please, use $(SPL_TPL) so that we don't have to revisit this should we ever decide to enable fastboot in SPL in future.
You are going to enable fastboot in TPL?
--Sean

On Wed, Oct 11, 2023 at 09:56:13PM -0400, Sean Anderson wrote:
When fastboot is enabled in U-Boot proper and SPL_NET is enabled, we will try to (unsuccessfully) reference it in SPL. Fix these linker errors by conditioning on SPL_UDP/TCP_FUNCTION_FASTBOOT.
Signed-off-by: Sean Anderson seanga2@gmail.com
Reviewed-by: Tom Rini trini@konsulko.com

These defines are useful when testing bootp.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
net/bootp.c | 3 --- net/bootp.h | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/bootp.c b/net/bootp.c index 8b1a4ae2ef8..2053cce88c6 100644 --- a/net/bootp.c +++ b/net/bootp.c @@ -41,9 +41,6 @@ */ #define TIMEOUT_MS ((3 + (CONFIG_NET_RETRY_COUNT * 5)) * 1000)
-#define PORT_BOOTPS 67 /* BOOTP server UDP port */ -#define PORT_BOOTPC 68 /* BOOTP client UDP port */ - #ifndef CFG_DHCP_MIN_EXT_LEN /* minimal length of extension list */ #define CFG_DHCP_MIN_EXT_LEN 64 #endif diff --git a/net/bootp.h b/net/bootp.h index 567340ec5d4..4e32b19d424 100644 --- a/net/bootp.h +++ b/net/bootp.h @@ -15,6 +15,9 @@
/**********************************************************************/
+#define PORT_BOOTPS 67 /* BOOTP server UDP port */ +#define PORT_BOOTPC 68 /* BOOTP client UDP port */ + /* * BOOTP header. */

On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
These defines are useful when testing bootp.
Signed-off-by: Sean Anderson seanga2@gmail.com
net/bootp.c | 3 --- net/bootp.h | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

On 10/12/23 03:56, Sean Anderson wrote:
These defines are useful when testing bootp.
Signed-off-by: Sean Anderson seanga2@gmail.com
Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de
net/bootp.c | 3 --- net/bootp.h | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/bootp.c b/net/bootp.c index 8b1a4ae2ef8..2053cce88c6 100644 --- a/net/bootp.c +++ b/net/bootp.c @@ -41,9 +41,6 @@ */ #define TIMEOUT_MS ((3 + (CONFIG_NET_RETRY_COUNT * 5)) * 1000)
-#define PORT_BOOTPS 67 /* BOOTP server UDP port */ -#define PORT_BOOTPC 68 /* BOOTP client UDP port */
- #ifndef CFG_DHCP_MIN_EXT_LEN /* minimal length of extension list */ #define CFG_DHCP_MIN_EXT_LEN 64 #endif
diff --git a/net/bootp.h b/net/bootp.h index 567340ec5d4..4e32b19d424 100644 --- a/net/bootp.h +++ b/net/bootp.h @@ -15,6 +15,9 @@
/**********************************************************************/
+#define PORT_BOOTPS 67 /* BOOTP server UDP port */ +#define PORT_BOOTPC 68 /* BOOTP client UDP port */
- /*
*/
- BOOTP header.

If we sent a DHCP packet and get a BOOTP response from the server, we shouldn't try to send a DHCPREQUEST packet, since it won't be DHCPACKed. Transition straight to BIND. This is only enabled for UNIT_TEST to avoid bloat, since I suspect the number of BOOTP servers in the wild is vanishingly small.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
net/bootp.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/net/bootp.c b/net/bootp.c index 2053cce88c6..7b0f45e18a9 100644 --- a/net/bootp.c +++ b/net/bootp.c @@ -1073,6 +1073,11 @@ static void dhcp_handler(uchar *pkt, unsigned dest, struct in_addr sip, CONFIG_SYS_BOOTFILE_PREFIX, strlen(CONFIG_SYS_BOOTFILE_PREFIX)) == 0) { #endif /* CONFIG_SYS_BOOTFILE_PREFIX */ + if (CONFIG_IS_ENABLED(UNIT_TEST) && + dhcp_message_type((u8 *)bp->bp_vend) == -1) { + debug("got BOOTP response; transitioning to BOUND\n"); + goto dhcp_got_bootp; + } dhcp_packet_process_options(bp); if (CONFIG_IS_ENABLED(EFI_LOADER) && IS_ENABLED(CONFIG_NETDEVICES)) @@ -1099,6 +1104,7 @@ static void dhcp_handler(uchar *pkt, unsigned dest, struct in_addr sip, debug("DHCP State: REQUESTING\n");
if (dhcp_message_type((u8 *)bp->bp_vend) == DHCP_ACK) { +dhcp_got_bootp: dhcp_packet_process_options(bp); /* Store net params from reply */ store_net_params(bp);

On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
If we sent a DHCP packet and get a BOOTP response from the server, we shouldn't try to send a DHCPREQUEST packet, since it won't be DHCPACKed. Transition straight to BIND. This is only enabled for UNIT_TEST to avoid bloat, since I suspect the number of BOOTP servers in the wild is vanishingly small.
Signed-off-by: Sean Anderson seanga2@gmail.com
net/bootp.c | 6 ++++++ 1 file changed, 6 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

On 10/12/23 03:56, Sean Anderson wrote:
If we sent a DHCP packet and get a BOOTP response from the server, we shouldn't try to send a DHCPREQUEST packet, since it won't be DHCPACKed. Transition straight to BIND. This is only enabled for UNIT_TEST to avoid bloat, since I suspect the number of BOOTP servers in the wild is vanishingly small.
Signed-off-by: Sean Anderson seanga2@gmail.com
net/bootp.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/net/bootp.c b/net/bootp.c index 2053cce88c6..7b0f45e18a9 100644 --- a/net/bootp.c +++ b/net/bootp.c @@ -1073,6 +1073,11 @@ static void dhcp_handler(uchar *pkt, unsigned dest, struct in_addr sip, CONFIG_SYS_BOOTFILE_PREFIX, strlen(CONFIG_SYS_BOOTFILE_PREFIX)) == 0) { #endif /* CONFIG_SYS_BOOTFILE_PREFIX */
if (CONFIG_IS_ENABLED(UNIT_TEST) &&
dhcp_message_type((u8 *)bp->bp_vend) == -1) {
debug("got BOOTP response; transitioning to BOUND\n");
goto dhcp_got_bootp;
This may result in unexpected behavior when running tests against an actual network. Please, avoid this.
Best regards
Heinrich
} dhcp_packet_process_options(bp); if (CONFIG_IS_ENABLED(EFI_LOADER) && IS_ENABLED(CONFIG_NETDEVICES))
@@ -1099,6 +1104,7 @@ static void dhcp_handler(uchar *pkt, unsigned dest, struct in_addr sip, debug("DHCP State: REQUESTING\n");
if (dhcp_message_type((u8 *)bp->bp_vend) == DHCP_ACK) {
+dhcp_got_bootp: dhcp_packet_process_options(bp); /* Store net params from reply */ store_net_params(bp);

On 10/12/23 03:16, Heinrich Schuchardt wrote:
On 10/12/23 03:56, Sean Anderson wrote:
If we sent a DHCP packet and get a BOOTP response from the server, we shouldn't try to send a DHCPREQUEST packet, since it won't be DHCPACKed. Transition straight to BIND. This is only enabled for UNIT_TEST to avoid bloat, since I suspect the number of BOOTP servers in the wild is vanishingly small.
Signed-off-by: Sean Anderson seanga2@gmail.com
net/bootp.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/net/bootp.c b/net/bootp.c index 2053cce88c6..7b0f45e18a9 100644 --- a/net/bootp.c +++ b/net/bootp.c @@ -1073,6 +1073,11 @@ static void dhcp_handler(uchar *pkt, unsigned dest, struct in_addr sip, CONFIG_SYS_BOOTFILE_PREFIX, strlen(CONFIG_SYS_BOOTFILE_PREFIX)) == 0) { #endif /* CONFIG_SYS_BOOTFILE_PREFIX */ + if (CONFIG_IS_ENABLED(UNIT_TEST) && + dhcp_message_type((u8 *)bp->bp_vend) == -1) { + debug("got BOOTP response; transitioning to BOUND\n"); + goto dhcp_got_bootp;
This may result in unexpected behavior when running tests against an actual network. Please, avoid this.
What is unexpected behavior? If you get a BOOTP (not DHCP) packet, you should behave according to the BOOTP protocol, not the DHCP protocol.
--Sean

Several SPL functions try to avoid performing initialization twice by caching devices. This is fine for regular boot, but does not work with UNIT_TEST, since all devices are torn down after each test. Disable caching so we don't use stale devices.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
common/spl/spl_fat.c | 2 +- common/spl/spl_mmc.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/common/spl/spl_fat.c b/common/spl/spl_fat.c index c6e2526ade1..8bec9cce5ca 100644 --- a/common/spl/spl_fat.c +++ b/common/spl/spl_fat.c @@ -24,7 +24,7 @@ static int spl_register_fat_device(struct blk_desc *block_dev, int partition) { int err = 0;
- if (fat_registered) + if (!CONFIG_IS_ENABLED(UNIT_TEST) && fat_registered) return err;
err = fat_register_device(block_dev, partition); diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 67c7ae34a58..a8579e29dee 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -417,7 +417,8 @@ int spl_mmc_load(struct spl_image_info *spl_image,
/* Perform peripheral init only once for an mmc device */ mmc_dev = spl_mmc_get_device_index(bootdev->boot_device); - if (!mmc || spl_mmc_get_mmc_devnum(mmc) != mmc_dev) { + if (CONFIG_IS_ENABLED(UNIT_TEST) || !mmc || + spl_mmc_get_mmc_devnum(mmc) != mmc_dev) { err = spl_mmc_find_device(&mmc, bootdev->boot_device); if (err) return err;

Hi Sean,
On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
Several SPL functions try to avoid performing initialization twice by caching devices. This is fine for regular boot, but does not work with UNIT_TEST, since all devices are torn down after each test. Disable caching so we don't use stale devices.
Signed-off-by: Sean Anderson seanga2@gmail.com
common/spl/spl_fat.c | 2 +- common/spl/spl_mmc.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/common/spl/spl_fat.c b/common/spl/spl_fat.c index c6e2526ade1..8bec9cce5ca 100644 --- a/common/spl/spl_fat.c +++ b/common/spl/spl_fat.c @@ -24,7 +24,7 @@ static int spl_register_fat_device(struct blk_desc *block_dev, int partition) { int err = 0;
if (fat_registered)
if (!CONFIG_IS_ENABLED(UNIT_TEST) && fat_registered)
These sort of things worry me, since we are bringing test code / conditions into the 'real' code. Is it possible to pass this as a parameter, or adjust the value of fat_registered?
return err; err = fat_register_device(block_dev, partition);
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 67c7ae34a58..a8579e29dee 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -417,7 +417,8 @@ int spl_mmc_load(struct spl_image_info *spl_image,
/* Perform peripheral init only once for an mmc device */ mmc_dev = spl_mmc_get_device_index(bootdev->boot_device);
if (!mmc || spl_mmc_get_mmc_devnum(mmc) != mmc_dev) {
if (CONFIG_IS_ENABLED(UNIT_TEST) || !mmc ||
spl_mmc_get_mmc_devnum(mmc) != mmc_dev) { err = spl_mmc_find_device(&mmc, bootdev->boot_device); if (err) return err;
-- 2.37.1
Regards, Simon

On 10/11/23 23:41, Simon Glass wrote:
Hi Sean,
On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
Several SPL functions try to avoid performing initialization twice by caching devices. This is fine for regular boot, but does not work with UNIT_TEST, since all devices are torn down after each test. Disable caching so we don't use stale devices.
Signed-off-by: Sean Anderson seanga2@gmail.com
common/spl/spl_fat.c | 2 +- common/spl/spl_mmc.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/common/spl/spl_fat.c b/common/spl/spl_fat.c index c6e2526ade1..8bec9cce5ca 100644 --- a/common/spl/spl_fat.c +++ b/common/spl/spl_fat.c @@ -24,7 +24,7 @@ static int spl_register_fat_device(struct blk_desc *block_dev, int partition) { int err = 0;
if (fat_registered)
if (!CONFIG_IS_ENABLED(UNIT_TEST) && fat_registered)
These sort of things worry me, since we are bringing test code / conditions into the 'real' code. Is it possible to pass this as a parameter, or adjust the value of fat_registered?
At the moment these variables are static, and I would like to keep them that way to avoid size growth. We really are doing an unusual thing with UNIT_TEST where devices which were previously valid can be free'd and then recreated later. This is why I decided on using UNIT_TEST as the determiner here, since nothing else should cause this situation.
--Sean
return err; err = fat_register_device(block_dev, partition);
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 67c7ae34a58..a8579e29dee 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -417,7 +417,8 @@ int spl_mmc_load(struct spl_image_info *spl_image,
/* Perform peripheral init only once for an mmc device */ mmc_dev = spl_mmc_get_device_index(bootdev->boot_device);
if (!mmc || spl_mmc_get_mmc_devnum(mmc) != mmc_dev) {
if (CONFIG_IS_ENABLED(UNIT_TEST) || !mmc ||
spl_mmc_get_mmc_devnum(mmc) != mmc_dev) { err = spl_mmc_find_device(&mmc, bootdev->boot_device); if (err) return err;
-- 2.37.1
Regards, Simon

On 10/12/23 03:56, Sean Anderson wrote:
Several SPL functions try to avoid performing initialization twice by caching devices. This is fine for regular boot, but does not work with UNIT_TEST, since all devices are torn down after each test. Disable caching so we don't use stale devices.
Signed-off-by: Sean Anderson seanga2@gmail.com
common/spl/spl_fat.c | 2 +- common/spl/spl_mmc.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/common/spl/spl_fat.c b/common/spl/spl_fat.c index c6e2526ade1..8bec9cce5ca 100644 --- a/common/spl/spl_fat.c +++ b/common/spl/spl_fat.c @@ -24,7 +24,7 @@ static int spl_register_fat_device(struct blk_desc *block_dev, int partition) { int err = 0;
- if (fat_registered)
- if (!CONFIG_IS_ENABLED(UNIT_TEST) && fat_registered)
Please, avoid separate code paths depending on CONFIG_UNIT_TESTS.
We shouldn't change normal behavior if unit tests are not running. It is preferable to let the unit test framework call a new function resetting fat_registered when needed. This will allow future tests to test all code paths separately.
Best regards
Heinrich
return err;
err = fat_register_device(block_dev, partition); diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 67c7ae34a58..a8579e29dee 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -417,7 +417,8 @@ int spl_mmc_load(struct spl_image_info *spl_image,
/* Perform peripheral init only once for an mmc device */ mmc_dev = spl_mmc_get_device_index(bootdev->boot_device);
- if (!mmc || spl_mmc_get_mmc_devnum(mmc) != mmc_dev) {
- if (CONFIG_IS_ENABLED(UNIT_TEST) || !mmc ||
err = spl_mmc_find_device(&mmc, bootdev->boot_device); if (err) return err;spl_mmc_get_mmc_devnum(mmc) != mmc_dev) {

On 10/12/23 03:23, Heinrich Schuchardt wrote:
On 10/12/23 03:56, Sean Anderson wrote:
Several SPL functions try to avoid performing initialization twice by caching devices. This is fine for regular boot, but does not work with UNIT_TEST, since all devices are torn down after each test. Disable caching so we don't use stale devices.
Signed-off-by: Sean Anderson seanga2@gmail.com
common/spl/spl_fat.c | 2 +- common/spl/spl_mmc.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/common/spl/spl_fat.c b/common/spl/spl_fat.c index c6e2526ade1..8bec9cce5ca 100644 --- a/common/spl/spl_fat.c +++ b/common/spl/spl_fat.c @@ -24,7 +24,7 @@ static int spl_register_fat_device(struct blk_desc *block_dev, int partition) { int err = 0;
- if (fat_registered) + if (!CONFIG_IS_ENABLED(UNIT_TEST) && fat_registered)
Please, avoid separate code paths depending on CONFIG_UNIT_TESTS.
We shouldn't change normal behavior if unit tests are not running. It is preferable to let the unit test framework call a new function resetting fat_registered when needed. This will allow future tests to test all code paths separately.
OK, that sounds reasonable to me.
--Sean

All "physical" addresses in SPL must be converted to virtual addresses before access in order for sandbox to work. Add some calls to map_sysmem in appropriate places. We do not generally call unmap_sysmem, since we need the image memory to still be mapped when we jump to the image. This doesn't matter at the moment since unmap_sysmem is a no-op.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
common/spl/spl.c | 4 +++- common/spl/spl_blk_fs.c | 6 ++++-- common/spl/spl_ext.c | 4 +++- common/spl/spl_fat.c | 11 +++++++---- common/spl/spl_fit.c | 36 +++++++++++++++++++++------------- common/spl/spl_imx_container.c | 4 +++- common/spl/spl_legacy.c | 6 ++++-- common/spl/spl_mmc.c | 4 +++- common/spl/spl_net.c | 10 +++++++--- common/spl/spl_nor.c | 5 +++-- common/spl/spl_spi.c | 14 +++++++++---- 11 files changed, 69 insertions(+), 35 deletions(-)
diff --git a/common/spl/spl.c b/common/spl/spl.c index 66eeea41a34..732d90d39e6 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -653,7 +653,9 @@ void board_init_r(gd_t *dummy1, ulong dummy2) spl_set_bd();
if (IS_ENABLED(CONFIG_SPL_SYS_MALLOC)) { - mem_malloc_init(SPL_SYS_MALLOC_START, SPL_SYS_MALLOC_SIZE); + mem_malloc_init((ulong)map_sysmem(SPL_SYS_MALLOC_START, + SPL_SYS_MALLOC_SIZE), + SPL_SYS_MALLOC_SIZE); gd->flags |= GD_FLG_FULL_MALLOC_INIT; } if (!(gd->flags & GD_FLG_SPL_INIT)) { diff --git a/common/spl/spl_blk_fs.c b/common/spl/spl_blk_fs.c index ea5d1a51d9f..63825d620d1 100644 --- a/common/spl/spl_blk_fs.c +++ b/common/spl/spl_blk_fs.c @@ -9,6 +9,7 @@ #include <spl.h> #include <image.h> #include <fs.h> +#include <asm/io.h>
struct blk_dev { const char *ifname; @@ -29,7 +30,8 @@ static ulong spl_fit_read(struct spl_load_info *load, ulong file_offset, return ret; }
- ret = fs_read(load->filename, (ulong)buf, file_offset, size, &actlen); + ret = fs_read(load->filename, virt_to_phys(buf), file_offset, size, + &actlen); if (ret < 0) { printf("spl: error reading image %s. Err - %d\n", load->filename, ret); @@ -69,7 +71,7 @@ int spl_blk_load_image(struct spl_image_info *spl_image, goto out; }
- ret = fs_read(filename, (ulong)header, 0, + ret = fs_read(filename, virt_to_phys(header), 0, sizeof(struct legacy_img_hdr), &actlen); if (ret) { printf("spl: unable to read file %s. Err - %d\n", filename, diff --git a/common/spl/spl_ext.c b/common/spl/spl_ext.c index 902564a6077..af836ca15b8 100644 --- a/common/spl/spl_ext.c +++ b/common/spl/spl_ext.c @@ -2,6 +2,7 @@
#include <common.h> #include <env.h> +#include <mapmem.h> #include <part.h> #include <spl.h> #include <asm/u-boot.h> @@ -53,7 +54,8 @@ int spl_load_image_ext(struct spl_image_info *spl_image, goto end; }
- err = ext4fs_read((char *)spl_image->load_addr, 0, filelen, &actlen); + err = ext4fs_read(map_sysmem(spl_image->load_addr, filelen), 0, filelen, + &actlen);
end: #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT diff --git a/common/spl/spl_fat.c b/common/spl/spl_fat.c index 8bec9cce5ca..ff9892356f6 100644 --- a/common/spl/spl_fat.c +++ b/common/spl/spl_fat.c @@ -11,6 +11,7 @@ #include <common.h> #include <env.h> #include <log.h> +#include <mapmem.h> #include <spl.h> #include <asm/u-boot.h> #include <fat.h> @@ -74,11 +75,13 @@ int spl_load_image_fat(struct spl_image_info *spl_image,
if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL) && image_get_magic(header) == FDT_MAGIC) { - err = file_fat_read(filename, (void *)CONFIG_SYS_LOAD_ADDR, 0); + err = file_fat_read(filename, + map_sysmem(CONFIG_SYS_LOAD_ADDR, 0), 0); if (err <= 0) goto end; err = spl_parse_image_header(spl_image, bootdev, - (struct legacy_img_hdr *)CONFIG_SYS_LOAD_ADDR); + map_sysmem(CONFIG_SYS_LOAD_ADDR, + err)); if (err == -EAGAIN) return err; if (err == 0) @@ -99,8 +102,8 @@ int spl_load_image_fat(struct spl_image_info *spl_image, if (err) goto end;
- err = file_fat_read(filename, - (u8 *)(uintptr_t)spl_image->load_addr, 0); + err = file_fat_read(filename, map_sysmem(spl_image->load_addr, + spl_image->size), 0); }
end: diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index e3cdf8e5c05..f397cb40277 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -16,6 +16,7 @@ #include <sysinfo.h> #include <asm/cache.h> #include <asm/global_data.h> +#include <asm/io.h> #include <linux/libfdt.h> #include <linux/printk.h>
@@ -388,25 +389,32 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, /* Figure out which device tree the board wants to use */ node = spl_fit_get_image_node(ctx, FIT_FDT_PROP, index++); if (node < 0) { + size_t size; + debug("%s: cannot find FDT node\n", __func__);
/* * U-Boot did not find a device tree inside the FIT image. Use * the U-Boot device tree instead. */ - if (gd->fdt_blob) - memcpy((void *)image_info.load_addr, gd->fdt_blob, - fdt_totalsize(gd->fdt_blob)); - else + if (!gd->fdt_blob) return node; + + /* + * Make the load-address of the FDT available for the SPL + * framework + */ + size = fdt_totalsize(gd->fdt_blob); + spl_image->fdt_addr = map_sysmem(image_info.load_addr, size); + memcpy(spl_image->fdt_addr, gd->fdt_blob, size); } else { ret = load_simple_fit(info, sector, ctx, node, &image_info); if (ret < 0) return ret; + + spl_image->fdt_addr = phys_to_virt(image_info.load_addr); }
- /* Make the load-address of the FDT available for the SPL framework */ - spl_image->fdt_addr = map_sysmem(image_info.load_addr, 0); if (CONFIG_IS_ENABLED(FIT_IMAGE_TINY)) return 0;
@@ -859,7 +867,7 @@ int spl_load_fit_image(struct spl_image_info *spl_image, #ifdef CONFIG_SPL_FIT_SIGNATURE images.verify = 1; #endif - ret = fit_image_load(&images, (ulong)header, + ret = fit_image_load(&images, virt_to_phys((void *)header), NULL, &fit_uname_config, IH_ARCH_DEFAULT, IH_TYPE_STANDALONE, -1, FIT_LOAD_OPTIONAL, &fw_data, &fw_len); @@ -867,15 +875,15 @@ int spl_load_fit_image(struct spl_image_info *spl_image, printf("DEPRECATED: 'standalone = ' property."); printf("Please use either 'firmware =' or 'kernel ='\n"); } else { - ret = fit_image_load(&images, (ulong)header, NULL, - &fit_uname_config, IH_ARCH_DEFAULT, + ret = fit_image_load(&images, virt_to_phys((void *)header), + NULL, &fit_uname_config, IH_ARCH_DEFAULT, IH_TYPE_FIRMWARE, -1, FIT_LOAD_OPTIONAL, &fw_data, &fw_len); }
if (ret < 0) { - ret = fit_image_load(&images, (ulong)header, NULL, - &fit_uname_config, IH_ARCH_DEFAULT, + ret = fit_image_load(&images, virt_to_phys((void *)header), + NULL, &fit_uname_config, IH_ARCH_DEFAULT, IH_TYPE_KERNEL, -1, FIT_LOAD_OPTIONAL, &fw_data, &fw_len); } @@ -898,9 +906,9 @@ int spl_load_fit_image(struct spl_image_info *spl_image, #ifdef CONFIG_SPL_FIT_SIGNATURE images.verify = 1; #endif - ret = fit_image_load(&images, (ulong)header, NULL, &fit_uname_config, - IH_ARCH_DEFAULT, IH_TYPE_FLATDT, -1, - FIT_LOAD_OPTIONAL, &dt_data, &dt_len); + ret = fit_image_load(&images, virt_to_phys((void *)header), NULL, + &fit_uname_config, IH_ARCH_DEFAULT, IH_TYPE_FLATDT, + -1, FIT_LOAD_OPTIONAL, &dt_data, &dt_len); if (ret >= 0) { spl_image->fdt_addr = (void *)dt_data;
diff --git a/common/spl/spl_imx_container.c b/common/spl/spl_imx_container.c index 126ab7c57a1..ed671278522 100644 --- a/common/spl/spl_imx_container.c +++ b/common/spl/spl_imx_container.c @@ -8,6 +8,7 @@ #include <errno.h> #include <imx_container.h> #include <log.h> +#include <mapmem.h> #include <spl.h> #ifdef CONFIG_AHAB_BOOT #include <asm/mach-imx/ahab.h> @@ -45,7 +46,8 @@ static struct boot_img_t *read_auth_image(struct spl_image_info *spl_image, debug("%s: container: %p sector: %lu sectors: %u\n", __func__, container, sector, sectors); if (info->read(info, sector, sectors, - (void *)images[image_index].dst) != sectors) { + map_sysmem(images[image_index].dst, + images[image_index].size)) != sectors) { printf("%s wrong\n", __func__); return NULL; } diff --git a/common/spl/spl_legacy.c b/common/spl/spl_legacy.c index e9564e5c2a5..51656fb9617 100644 --- a/common/spl/spl_legacy.c +++ b/common/spl/spl_legacy.c @@ -7,6 +7,7 @@ #include <image.h> #include <log.h> #include <malloc.h> +#include <mapmem.h> #include <asm/sections.h> #include <spl.h>
@@ -129,7 +130,7 @@ int spl_load_legacy_img(struct spl_image_info *spl_image, dataptr += sizeof(*hdr);
load->read(load, dataptr, spl_image->size, - (void *)(unsigned long)spl_image->load_addr); + map_sysmem(spl_image->load_addr, spl_image->size)); break;
case IH_COMP_LZMA: @@ -148,7 +149,8 @@ int spl_load_legacy_img(struct spl_image_info *spl_image, }
load->read(load, dataptr, spl_image->size, src); - ret = lzmaBuffToBuffDecompress((void *)spl_image->load_addr, + ret = lzmaBuffToBuffDecompress(map_sysmem(spl_image->load_addr, + spl_image->size), &lzma_len, src, spl_image->size); if (ret) { printf("LZMA decompression error: %d\n", ret); diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index a8579e29dee..a937c1762b1 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -8,6 +8,7 @@ #include <common.h> #include <dm.h> #include <log.h> +#include <mapmem.h> #include <part.h> #include <spl.h> #include <linux/compiler.h> @@ -46,7 +47,8 @@ static int mmc_load_legacy(struct spl_image_info *spl_image, count = blk_dread(mmc_get_blk_desc(mmc), sector + image_offset_sectors, image_size_sectors, - (void *)(ulong)spl_image->load_addr); + map_sysmem(spl_image->load_addr, + image_size_sectors * mmc->read_bl_len)); debug("read %x sectors to %lx\n", image_size_sectors, spl_image->load_addr); if (count != image_size_sectors) diff --git a/common/spl/spl_net.c b/common/spl/spl_net.c index b2c901b554b..f01d4df8bc6 100644 --- a/common/spl/spl_net.c +++ b/common/spl/spl_net.c @@ -11,6 +11,7 @@ #include <errno.h> #include <image.h> #include <log.h> +#include <mapmem.h> #include <spl.h> #include <net.h> #include <linux/libfdt.h> @@ -21,14 +22,15 @@ static ulong spl_net_load_read(struct spl_load_info *load, ulong sector, { debug("%s: sector %lx, count %lx, buf %lx\n", __func__, sector, count, (ulong)buf); - memcpy(buf, (void *)(image_load_addr + sector), count); + memcpy(buf, map_sysmem(image_load_addr + sector, count), count); return count; }
static int spl_net_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) { - struct legacy_img_hdr *header = (struct legacy_img_hdr *)image_load_addr; + struct legacy_img_hdr *header = map_sysmem(image_load_addr, + sizeof(*header)); int rv;
env_init(); @@ -62,7 +64,9 @@ static int spl_net_load_image(struct spl_image_info *spl_image, if (rv) return rv;
- memcpy((void *)spl_image->load_addr, header, spl_image->size); + memcpy(map_sysmem(spl_image->load_addr, spl_image->size), + map_sysmem(image_load_addr, spl_image->size), + spl_image->size); }
return rv; diff --git a/common/spl/spl_nor.c b/common/spl/spl_nor.c index dd447982071..236b0718283 100644 --- a/common/spl/spl_nor.c +++ b/common/spl/spl_nor.c @@ -7,6 +7,7 @@ #include <image.h> #include <imx_container.h> #include <log.h> +#include <mapmem.h> #include <spl.h>
static ulong spl_nor_load_read(struct spl_load_info *load, ulong sector, @@ -14,7 +15,7 @@ static ulong spl_nor_load_read(struct spl_load_info *load, ulong sector, { debug("%s: sector %lx, count %lx, buf %p\n", __func__, sector, count, buf); - memcpy(buf, (void *)sector, count); + memcpy(buf, map_sysmem(sector, count), count);
return count; } @@ -92,7 +93,7 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, * Load real U-Boot from its location in NOR flash to its * defined location in SDRAM */ - header = (const struct legacy_img_hdr *)spl_nor_get_uboot_base(); + header = map_sysmem(spl_nor_get_uboot_base(), sizeof(*header)); #ifdef CONFIG_SPL_LOAD_FIT if (image_get_magic(header) == FDT_MAGIC) { debug("Found FIT format U-Boot\n"); diff --git a/common/spl/spl_spi.c b/common/spl/spl_spi.c index 1427c9478c0..3ac4b1b5091 100644 --- a/common/spl/spl_spi.c +++ b/common/spl/spl_spi.c @@ -12,11 +12,13 @@ #include <image.h> #include <imx_container.h> #include <log.h> +#include <mapmem.h> #include <spi.h> #include <spi_flash.h> #include <errno.h> #include <spl.h> #include <asm/global_data.h> +#include <asm/io.h> #include <dm/ofnode.h>
#if CONFIG_IS_ENABLED(OS_BOOT) @@ -134,13 +136,16 @@ static int spl_spi_load_image(struct spl_image_info *spl_image,
if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL) && image_get_magic(header) == FDT_MAGIC) { + u32 size = roundup(fdt_totalsize(header), 4); + err = spi_flash_read(flash, payload_offs, - roundup(fdt_totalsize(header), 4), - (void *)CONFIG_SYS_LOAD_ADDR); + size, + map_sysmem(CONFIG_SYS_LOAD_ADDR, + size)); if (err) return err; err = spl_parse_image_header(spl_image, bootdev, - (struct legacy_img_hdr *)CONFIG_SYS_LOAD_ADDR); + phys_to_virt(CONFIG_SYS_LOAD_ADDR)); } else if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && image_get_magic(header) == FDT_MAGIC) { struct spl_load_info load; @@ -172,7 +177,8 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, return err; err = spi_flash_read(flash, payload_offs + spl_image->offset, spl_image->size, - (void *)spl_image->load_addr); + map_sysmem(spl_image->load_addr, + spl_image->size)); } if (IS_ENABLED(CONFIG_SPI_FLASH_SOFT_RESET)) { err = spi_nor_remove(flash);

On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
All "physical" addresses in SPL must be converted to virtual addresses before access in order for sandbox to work. Add some calls to map_sysmem in appropriate places. We do not generally call unmap_sysmem, since we need the image memory to still be mapped when we jump to the image. This doesn't matter at the moment since unmap_sysmem is a no-op.
Signed-off-by: Sean Anderson seanga2@gmail.com
common/spl/spl.c | 4 +++- common/spl/spl_blk_fs.c | 6 ++++-- common/spl/spl_ext.c | 4 +++- common/spl/spl_fat.c | 11 +++++++---- common/spl/spl_fit.c | 36 +++++++++++++++++++++------------- common/spl/spl_imx_container.c | 4 +++- common/spl/spl_legacy.c | 6 ++++-- common/spl/spl_mmc.c | 4 +++- common/spl/spl_net.c | 10 +++++++--- common/spl/spl_nor.c | 5 +++-- common/spl/spl_spi.c | 14 +++++++++---- 11 files changed, 69 insertions(+), 35 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

In order to make adding new spl unit tests easier, especially when they may have many dependencies, add some Kconfigs for the existing image test. Split it into the parts which are generic (such as callbacks) and the test-specific parts.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
test/Kconfig | 1 + test/Makefile | 5 +-- test/image/Kconfig | 20 ++++++++++ test/image/Makefile | 3 +- test/image/spl_load.c | 76 +------------------------------------ test/image/spl_load_os.c | 81 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 107 insertions(+), 79 deletions(-) create mode 100644 test/image/Kconfig create mode 100644 test/image/spl_load_os.c
diff --git a/test/Kconfig b/test/Kconfig index 830245b6f9a..ca648d23376 100644 --- a/test/Kconfig +++ b/test/Kconfig @@ -101,6 +101,7 @@ config UT_UNICODE
source "test/dm/Kconfig" source "test/env/Kconfig" +source "test/image/Kconfig" source "test/lib/Kconfig" source "test/optee/Kconfig" source "test/overlay/Kconfig" diff --git a/test/Makefile b/test/Makefile index 178773647a8..8e1fed2c28b 100644 --- a/test/Makefile +++ b/test/Makefile @@ -3,9 +3,6 @@ # (C) Copyright 2012 The Chromium Authors
obj-y += test-main.o -ifdef CONFIG_SPL_LOAD_FIT -obj-$(CONFIG_SANDBOX) += image/ -endif
ifneq ($(CONFIG_$(SPL_)BLOBLIST),) obj-$(CONFIG_$(SPL_)CMDLINE) += bloblist.o @@ -30,4 +27,6 @@ obj-$(CONFIG_UNIT_TEST) += boot/ obj-$(CONFIG_UNIT_TEST) += common/ obj-y += log/ obj-$(CONFIG_$(SPL_)UT_UNICODE) += unicode_ut.o +else +obj-$(CONFIG_SPL_UT_LOAD) += image/ endif diff --git a/test/image/Kconfig b/test/image/Kconfig new file mode 100644 index 00000000000..70ffe0ff276 --- /dev/null +++ b/test/image/Kconfig @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (C) 2023 Sean Anderson seanga2@gmail.com + +config SPL_UT_LOAD + bool "Unit tests for SPL load methods" + depends on SPL_UNIT_TEST + default y if SANDBOX + help + Test various SPL load methods. + +if SPL_UT_LOAD + +config SPL_UT_LOAD_OS + bool "Test loading from the host OS" + depends on SANDBOX && SPL_LOAD_FIT + default y + help + Smoke test to ensure that loading U-boot works in sandbox. + +endif diff --git a/test/image/Makefile b/test/image/Makefile index c4039df707f..1f62d54453c 100644 --- a/test/image/Makefile +++ b/test/image/Makefile @@ -2,4 +2,5 @@ # # Copyright 2021 Google LLC
-obj-$(CONFIG_SPL_BUILD) += spl_load.o +obj-$(CONFIG_SPL_UT_LOAD) += spl_load.o +obj-$(CONFIG_SPL_UT_LOAD_OS) += spl_load_os.o diff --git a/test/image/spl_load.c b/test/image/spl_load.c index 4e27ff460ab..1a57bf846d2 100644 --- a/test/image/spl_load.c +++ b/test/image/spl_load.c @@ -1,48 +1,10 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright 2021 Google LLC - * Written by Simon Glass sjg@chromium.org + * Copyright (C) 2023 Sean Anderson seanga2@gmail.com */
#include <common.h> -#include <image.h> #include <mapmem.h> -#include <os.h> -#include <spl.h> -#include <test/ut.h> - -/* Declare a new SPL test */ -#define SPL_TEST(_name, _flags) UNIT_TEST(_name, _flags, spl_test) - -/* Context used for this test */ -struct text_ctx { - int fd; -}; - -static ulong read_fit_image(struct spl_load_info *load, ulong sector, - ulong count, void *buf) -{ - struct text_ctx *text_ctx = load->priv; - off_t offset, ret; - ssize_t res; - - offset = sector * load->bl_len; - ret = os_lseek(text_ctx->fd, offset, OS_SEEK_SET); - if (ret != offset) { - printf("Failed to seek to %zx, got %zx (errno=%d)\n", offset, - ret, errno); - return 0; - } - - res = os_read(text_ctx->fd, buf, count * load->bl_len); - if (res == -1) { - printf("Failed to read %lx bytes, got %ld (errno=%d)\n", - count * load->bl_len, res, errno); - return 0; - } - - return count; -}
int board_fit_config_name_match(const char *name) { @@ -53,39 +15,3 @@ struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size) { return map_sysmem(0x100000, 0); } - -static int spl_test_load(struct unit_test_state *uts) -{ - struct spl_image_info image; - struct legacy_img_hdr *header; - struct text_ctx text_ctx; - struct spl_load_info load; - char fname[256]; - int ret; - int fd; - - memset(&load, '\0', sizeof(load)); - load.bl_len = 512; - load.read = read_fit_image; - - ret = sandbox_find_next_phase(fname, sizeof(fname), true); - if (ret) { - printf("(%s not found, error %d)\n", fname, ret); - return ret; - } - load.filename = fname; - - header = spl_get_load_buffer(-sizeof(*header), sizeof(*header)); - - fd = os_open(fname, OS_O_RDONLY); - ut_assert(fd >= 0); - ut_asserteq(512, os_read(fd, header, 512)); - text_ctx.fd = fd; - - load.priv = &text_ctx; - - ut_assertok(spl_load_simple_fit(&image, &load, 0, header)); - - return 0; -} -SPL_TEST(spl_test_load, 0); diff --git a/test/image/spl_load_os.c b/test/image/spl_load_os.c new file mode 100644 index 00000000000..06daa3700b8 --- /dev/null +++ b/test/image/spl_load_os.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2021 Google LLC + * Written by Simon Glass sjg@chromium.org + */ + +#include <common.h> +#include <image.h> +#include <mapmem.h> +#include <os.h> +#include <spl.h> +#include <test/ut.h> + +/* Declare a new SPL test */ +#define SPL_TEST(_name, _flags) UNIT_TEST(_name, _flags, spl_test) + +/* Context used for this test */ +struct text_ctx { + int fd; +}; + +static ulong read_fit_image(struct spl_load_info *load, ulong sector, + ulong count, void *buf) +{ + struct text_ctx *text_ctx = load->priv; + off_t offset, ret; + ssize_t res; + + offset = sector * load->bl_len; + ret = os_lseek(text_ctx->fd, offset, OS_SEEK_SET); + if (ret != offset) { + printf("Failed to seek to %zx, got %zx (errno=%d)\n", offset, + ret, errno); + return 0; + } + + res = os_read(text_ctx->fd, buf, count * load->bl_len); + if (res == -1) { + printf("Failed to read %lx bytes, got %ld (errno=%d)\n", + count * load->bl_len, res, errno); + return 0; + } + + return count; +} + +static int spl_test_load(struct unit_test_state *uts) +{ + struct spl_image_info image; + struct legacy_img_hdr *header; + struct text_ctx text_ctx; + struct spl_load_info load; + char fname[256]; + int ret; + int fd; + + memset(&load, '\0', sizeof(load)); + load.bl_len = 512; + load.read = read_fit_image; + + ret = sandbox_find_next_phase(fname, sizeof(fname), true); + if (ret) { + printf("(%s not found, error %d)\n", fname, ret); + return ret; + } + load.filename = fname; + + header = spl_get_load_buffer(-sizeof(*header), sizeof(*header)); + + fd = os_open(fname, OS_O_RDONLY); + ut_assert(fd >= 0); + ut_asserteq(512, os_read(fd, header, 512)); + text_ctx.fd = fd; + + load.priv = &text_ctx; + + ut_assertok(spl_load_simple_fit(&image, &load, 0, header)); + + return 0; +} +SPL_TEST(spl_test_load, 0);

On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
In order to make adding new spl unit tests easier, especially when they may have many dependencies, add some Kconfigs for the existing image test. Split it into the parts which are generic (such as callbacks) and the test-specific parts.
Signed-off-by: Sean Anderson seanga2@gmail.com
test/Kconfig | 1 + test/Makefile | 5 +-- test/image/Kconfig | 20 ++++++++++ test/image/Makefile | 3 +- test/image/spl_load.c | 76 +------------------------------------ test/image/spl_load_os.c | 81 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 107 insertions(+), 79 deletions(-) create mode 100644 test/image/Kconfig create mode 100644 test/image/spl_load_os.c
Reviewed-by: Simon Glass sjg@chromium.org

Returning a negative value from a unit test doesn't automatically fail the test. We have to fail an assertion. Modify the test to do so.
This now causes the test to count as a failure on VPL. This is because the fname of SPL (and U-Boot) is generated with make_exec in os_jump_to_image. The original name of SPL is gone, and we can't determine the name of U-Boot from the generated name.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
configs/sandbox_vpl_defconfig | 1 + test/image/spl_load_os.c | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/configs/sandbox_vpl_defconfig b/configs/sandbox_vpl_defconfig index 8d76f19729b..5bd0281796d 100644 --- a/configs/sandbox_vpl_defconfig +++ b/configs/sandbox_vpl_defconfig @@ -262,3 +262,4 @@ CONFIG_UNIT_TEST=y CONFIG_SPL_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y +# CONFIG_SPL_UT_LOAD_OS is not set diff --git a/test/image/spl_load_os.c b/test/image/spl_load_os.c index 06daa3700b8..500867ffd49 100644 --- a/test/image/spl_load_os.c +++ b/test/image/spl_load_os.c @@ -59,10 +59,8 @@ static int spl_test_load(struct unit_test_state *uts) load.read = read_fit_image;
ret = sandbox_find_next_phase(fname, sizeof(fname), true); - if (ret) { - printf("(%s not found, error %d)\n", fname, ret); - return ret; - } + if (ret) + ut_assertf(0, "%s not found, error %d\n", fname, ret); load.filename = fname;
header = spl_get_load_buffer(-sizeof(*header), sizeof(*header));

On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
Returning a negative value from a unit test doesn't automatically fail the test. We have to fail an assertion. Modify the test to do so.
This now causes the test to count as a failure on VPL. This is because the fname of SPL (and U-Boot) is generated with make_exec in os_jump_to_image. The original name of SPL is gone, and we can't determine the name of U-Boot from the generated name.
Signed-off-by: Sean Anderson seanga2@gmail.com
configs/sandbox_vpl_defconfig | 1 + test/image/spl_load_os.c | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

This add some basic functions to create images, and a test for said functions. This is not intended to be a test of the image parsing functions, but rather a framework for creating minimal images for testing load methods. That said, it does do an OK job at finding bugs in the image parsing directly.
Since we have two methods for loading/parsing FIT images, add LOAD_FIT_FULL as a separate CI run.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
.azure-pipelines.yml | 4 + .gitlab-ci.yml | 7 + arch/sandbox/cpu/u-boot-spl.lds | 2 + configs/sandbox_noinst_defconfig | 6 + configs/sandbox_spl_defconfig | 6 + include/test/spl.h | 117 ++++++++++ test/image/spl_load.c | 352 +++++++++++++++++++++++++++++++ test/image/spl_load_os.c | 5 +- 8 files changed, 495 insertions(+), 4 deletions(-) create mode 100644 include/test/spl.h
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 7985ff5523c..6f91553e861 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -299,6 +299,10 @@ stages: sandbox_noinst: TEST_PY_BD: "sandbox_noinst" TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl" + sandbox_noinst_load_fit_full: + TEST_PY_BD: "sandbox_noinst" + TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl" + OVERRIDE: "-a CONFIG_SPL_LOAD_FIT_FULL=y" sandbox_flattree: TEST_PY_BD: "sandbox_flattree" sandbox_trace: diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 129234ba3db..6decdfdee33 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -293,6 +293,13 @@ sandbox_noinst_test.py: TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl" <<: *buildman_and_testpy_dfn
+sandbox_noinst with LOAD_FIT_FULL test.py: + variables: + TEST_PY_BD: "sandbox_noinst" + TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl" + OVERRIDE: "-a CONFIG_SPL_LOAD_FIT_FULL=y" + <<: *buildman_and_testpy_dfn + sandbox_vpl test.py: variables: TEST_PY_BD: "sandbox_vpl" diff --git a/arch/sandbox/cpu/u-boot-spl.lds b/arch/sandbox/cpu/u-boot-spl.lds index ef885fd0cb0..a81d66a6f2e 100644 --- a/arch/sandbox/cpu/u-boot-spl.lds +++ b/arch/sandbox/cpu/u-boot-spl.lds @@ -26,6 +26,8 @@ SECTIONS KEEP(*(_u_boot_sandbox_getopt)) *(_u_boot_sandbox_getopt_end) } + + _image_binary_end = .; }
INSERT AFTER .data; diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig index d39e54f98d2..908155be8a3 100644 --- a/configs/sandbox_noinst_defconfig +++ b/configs/sandbox_noinst_defconfig @@ -32,6 +32,12 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_SPL_NO_BSS_LIMIT=y CONFIG_HANDOFF=y CONFIG_SPL_BOARD_INIT=y +CONFIG_SPL_LEGACY_IMAGE_FORMAT=y +CONFIG_SPL_LOAD_IMX_CONTAINER=y +CONFIG_SPL_SYS_MALLOC=y +CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y +CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0xa000000 +CONFIG_SPL_SYS_MALLOC_SIZE=0x4000000 CONFIG_SPL_ENV_SUPPORT=y CONFIG_SPL_I2C=y CONFIG_SPL_RTC=y diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig index 4a67af2f088..b578cc8e443 100644 --- a/configs/sandbox_spl_defconfig +++ b/configs/sandbox_spl_defconfig @@ -32,6 +32,12 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_SPL_NO_BSS_LIMIT=y CONFIG_HANDOFF=y CONFIG_SPL_BOARD_INIT=y +CONFIG_SPL_LEGACY_IMAGE_FORMAT=y +CONFIG_SPL_LOAD_IMX_CONTAINER=y +CONFIG_SPL_SYS_MALLOC=y +CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y +CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0xa000000 +CONFIG_SPL_SYS_MALLOC_SIZE=0x4000000 CONFIG_SPL_ENV_SUPPORT=y CONFIG_SPL_FPGA=y CONFIG_SPL_I2C=y diff --git a/include/test/spl.h b/include/test/spl.h new file mode 100644 index 00000000000..a2f8d77b88f --- /dev/null +++ b/include/test/spl.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2023 Sean Anderson seanga2@gmail.com + */ + +#ifndef TEST_SPL_H +#define TEST_SPL_H + +struct unit_test_state; +struct spl_image_info; + +/* Declare a new SPL test */ +#define SPL_TEST(_name, _flags) UNIT_TEST(_name, _flags, spl_test) + +/** + * generate_data() - Generate some test payload data + * @data: The location to fill + * @size: The size of @data + * @test_name: The seed for the data + * + * Fill @data with data. The upper nibbles will be an incrementing counter + * (0x00, 0x10, 0x20...) to make the data identifiable in a hex dump. The lower + * nibbles are random bits seeded with @test_name. + */ +void generate_data(char *data, size_t size, const char *test_name); + +/** + * enum spl_test_image - Image types for testing + * @LEGACY: "Legacy" uImages + * @IMX8: i.MX8 Container images + * @FIT_INTERNAL: FITs with internal data + * @FIT_EXTERNAL: FITs with external data + */ +enum spl_test_image { + LEGACY, + IMX8, + FIT_INTERNAL, + FIT_EXTERNAL, +}; + +/** + * create_image() - Create an image for testing + * @dst: The location to create the image at + * @type: The type of image to create + * @info: Image parameters + * @data_offset: Offset of payload data within the image + * + * Create a new image at @dst. @dst must be initialized to all zeros. @info + * should already have name and size filled in. All other parameters will be + * filled in by this function. @info can later be passed to check_image_info(). + * + * If @dst is %NULL, then no data is written. Otherwise, @dst must be + * initialized to zeros, except payload data which must already be present at + * @data_offset. @data_offset may be %NULL if unnecessary. + * + * Typically, this function will be called as follows: + * + * size = create_image(NULL, type, &info, &off); + * img = calloc(size, 1); + * generate_data(img + off, ...); + * create_image(img, type, &info, NULL); + * + * Return: The size of the image, or 0 on error + */ +size_t create_image(void *dst, enum spl_test_image type, + struct spl_image_info *info, size_t *data_offset); + +/** + * check_image_info() - Check image info after loading + * @uts: Current unit test state + * @info1: The base, known good info + * @info2: The info to check + * + * Check @info2 against @info1. This function is typically called after calling + * a function to load/parse an image. Image data is not checked. + * + * Return: 0 on success, or -1 on failure + */ +int check_image_info(struct unit_test_state *uts, struct spl_image_info *info1, + struct spl_image_info *info2); + +/** + * image_supported() - Determine whether an image type is supported + * @type: The image type to check + * + * Return: %true if supported and %false otherwise + */ +static inline bool image_supported(enum spl_test_image type) +{ + switch (type) { + case LEGACY: + return IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_FORMAT); + case IMX8: + return IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER); + case FIT_INTERNAL: + case FIT_EXTERNAL: + return IS_ENABLED(CONFIG_SPL_LOAD_FIT) || + IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL); + } + + return false; +} + +/* Declare an image test (skipped if the image type is unsupported) */ +#define SPL_IMG_TEST(func, type, flags) \ +static int func##_##type(struct unit_test_state *uts) \ +{ \ + if (!image_supported(type)) \ + return -EAGAIN; \ + return func(uts, __func__, type); \ +} \ +SPL_TEST(func##_##type, flags) + +/* More than a couple blocks, and will not be aligned to anything */ +#define SPL_TEST_DATA_SIZE 4099 + +#endif /* TEST_SPL_H */ diff --git a/test/image/spl_load.c b/test/image/spl_load.c index 1a57bf846d2..ca3777cab37 100644 --- a/test/image/spl_load.c +++ b/test/image/spl_load.c @@ -4,7 +4,15 @@ */
#include <common.h> +#include <image.h> +#include <imx_container.h> #include <mapmem.h> +#include <memalign.h> +#include <rand.h> +#include <spl.h> +#include <test/spl.h> +#include <test/ut.h> +#include <u-boot/crc.h>
int board_fit_config_name_match(const char *name) { @@ -15,3 +23,347 @@ struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size) { return map_sysmem(0x100000, 0); } + +/* Try to reuse the load buffer to conserve memory */ +void *board_spl_fit_buffer_addr(ulong fit_size, int sectors, int bl_len) +{ + static void *buf; + static size_t size; + static bool invalid = true; + + if (invalid || size < sectors * bl_len) { + if (!invalid) + free(buf); + buf = malloc_cache_aligned(sectors * bl_len); + invalid = false; + } + return buf; +} + +/* Local flags for spl_image; start from the "top" to avoid conflicts */ +#define SPL_IMX_CONTAINER 0x80000000 + +void generate_data(char *data, size_t size, const char *test_name) +{ + int i; + unsigned int seed = 1; + + while (*test_name) { + seed += *test_name++; + rand_r(&seed); + } + + for (i = 0; i < size; i++) + data[i] = (i & 0xf) << 4 | (rand_r(&seed) & 0xf); +} + +static size_t create_legacy(void *dst, struct spl_image_info *spl_image, + size_t *data_offset) +{ + struct legacy_img_hdr *hdr = dst; + void *data = dst + sizeof(*hdr); + + if (data_offset) + *data_offset = data - dst; + + if (!dst) + goto out; + + image_set_magic(hdr, IH_MAGIC); + image_set_time(hdr, 0); + image_set_size(hdr, spl_image->size); + image_set_load(hdr, spl_image->load_addr); + image_set_ep(hdr, spl_image->entry_point); + image_set_dcrc(hdr, crc32(0, data, spl_image->size)); + image_set_os(hdr, spl_image->os); + image_set_arch(hdr, IH_ARCH_DEFAULT); + image_set_type(hdr, IH_TYPE_FIRMWARE); + image_set_comp(hdr, IH_COMP_NONE); + image_set_name(hdr, spl_image->name); + image_set_hcrc(hdr, crc32(0, (void *)hdr, sizeof(*hdr))); + +out: + return sizeof(*hdr) + spl_image->size; +} + +static size_t create_imx8(void *dst, struct spl_image_info *spl_image, + size_t *data_offset) +{ + struct container_hdr *hdr = dst; + struct boot_img_t *img = dst + sizeof(*hdr); + size_t length = sizeof(*hdr) + sizeof(*img); + /* Align to MMC block size for now */ + void *data = dst + 512; + + if (data_offset) + *data_offset = data - dst; + + if (!dst) + goto out; + + hdr->version = CONTAINER_HDR_VERSION; + hdr->length_lsb = length & 0xff; + hdr->length_msb = length >> 8; + hdr->tag = CONTAINER_HDR_TAG; + hdr->num_images = 1; + + /* spl_load_imx_container doesn't handle endianness; whoops! */ + img->offset = data - dst; + img->size = spl_image->size; + img->dst = spl_image->load_addr; + img->entry = spl_image->entry_point; + +out: + return data - dst + spl_image->size; +} + +#define ADDRESS_CELLS (sizeof(uintptr_t) / sizeof(u32)) + +static inline int fdt_property_addr(void *fdt, const char *name, uintptr_t val) +{ + if (sizeof(uintptr_t) == sizeof(u32)) + return fdt_property_u32(fdt, name, val); + return fdt_property_u64(fdt, name, val); +} + +static size_t start_fit(void *dst, size_t fit_size, size_t data_size, + bool external) +{ + void *data; + + if (fdt_create(dst, fit_size)) + return 0; + if (fdt_finish_reservemap(dst)) + return 0; + if (fdt_begin_node(dst, "")) + return 0; + if (fdt_property_u32(dst, FIT_TIMESTAMP_PROP, 0)) + return 0; + if (fdt_property_u32(dst, "#address-cells", ADDRESS_CELLS)) + return 0; + if (fdt_property_string(dst, FIT_DESC_PROP, "")) + return 0; + + if (fdt_begin_node(dst, "images")) + return 0; + if (fdt_begin_node(dst, "u-boot")) + return 0; + + if (external) { + if (fdt_property_u32(dst, FIT_DATA_OFFSET_PROP, 0)) + return 0; + return fit_size; + } + + if (fdt_property_placeholder(dst, FIT_DATA_PROP, data_size, &data)) + return 0; + return data - dst; +} + +static size_t create_fit(void *dst, struct spl_image_info *spl_image, + size_t *data_offset, bool external) +{ + size_t prop_size = 596, total_size = prop_size + spl_image->size; + size_t off, size; + + if (external) { + size = prop_size; + off = size; + } else { + char tmp[256]; + + size = total_size; + off = start_fit(tmp, sizeof(tmp), 0, false); + if (!off) + return 0; + } + + if (data_offset) + *data_offset = off; + + if (!dst) + goto out; + + if (start_fit(dst, size, spl_image->size, external) != off) + return 0; + + if (fdt_property_string(dst, FIT_DESC_PROP, spl_image->name)) + return 0; + if (fdt_property_string(dst, FIT_TYPE_PROP, "firmware")) + return 0; + if (fdt_property_string(dst, FIT_COMP_PROP, "none")) + return 0; + if (fdt_property_u32(dst, FIT_DATA_SIZE_PROP, spl_image->size)) + return 0; + if (fdt_property_string(dst, FIT_OS_PROP, + genimg_get_os_short_name(spl_image->os))) + return 0; + if (fdt_property_string(dst, FIT_ARCH_PROP, + genimg_get_arch_short_name(IH_ARCH_DEFAULT))) + return 0; + if (fdt_property_addr(dst, FIT_ENTRY_PROP, spl_image->entry_point)) + return 0; + if (fdt_property_addr(dst, FIT_LOAD_PROP, spl_image->load_addr)) + return 0; + if (fdt_end_node(dst)) /* u-boot */ + return 0; + if (fdt_end_node(dst)) /* images */ + return 0; + + if (fdt_begin_node(dst, "configurations")) + return 0; + if (fdt_property_string(dst, FIT_DEFAULT_PROP, "config-1")) + return 0; + if (fdt_begin_node(dst, "config-1")) + return 0; + if (fdt_property_string(dst, FIT_DESC_PROP, spl_image->name)) + return 0; + if (fdt_property_string(dst, FIT_FIRMWARE_PROP, "u-boot")) + return 0; + if (fdt_end_node(dst)) /* configurations */ + return 0; + if (fdt_end_node(dst)) /* config-1 */ + return 0; + + if (fdt_end_node(dst)) /* root */ + return 0; + if (fdt_finish(dst)) + return 0; + + if (external) { + if (fdt_totalsize(dst) > size) + return 0; + fdt_set_totalsize(dst, size); + } + +out: + return total_size; +} + +size_t create_image(void *dst, enum spl_test_image type, + struct spl_image_info *info, size_t *data_offset) +{ + bool external = false; + + info->os = IH_OS_U_BOOT; + info->load_addr = CONFIG_TEXT_BASE; + info->entry_point = CONFIG_TEXT_BASE + 0x100; + info->flags = 0; + + switch (type) { + case LEGACY: + return create_legacy(dst, info, data_offset); + case IMX8: + info->flags = SPL_IMX_CONTAINER; + return create_imx8(dst, info, data_offset); + case FIT_EXTERNAL: + /* + * spl_fit_append_fdt will clobber external images with U-Boot's + * FDT if the image doesn't have one. Just set the OS to + * something which doesn't take a devicetree. + */ + if (!IS_ENABLED(CONFIG_LOAD_FIT_FULL)) + info->os = IH_OS_TEE; + external = true; + case FIT_INTERNAL: + info->flags = SPL_FIT_FOUND; + return create_fit(dst, info, data_offset, external); + } + + return 0; +} + +int check_image_info(struct unit_test_state *uts, struct spl_image_info *info1, + struct spl_image_info *info2) +{ + if (info2->name) { + if (info1->flags & SPL_FIT_FOUND) + ut_asserteq_str(genimg_get_os_name(info1->os), + info2->name); + else + ut_asserteq_str(info1->name, info2->name); + } + + if (info1->flags & SPL_IMX_CONTAINER) + ut_asserteq(IH_OS_INVALID, info2->os); + else + ut_asserteq(info1->os, info2->os); + + ut_asserteq(info1->entry_point, info2->entry_point); + if (info1->flags & (SPL_FIT_FOUND | SPL_IMX_CONTAINER) || + info2->flags & SPL_COPY_PAYLOAD_ONLY) { + ut_asserteq(info1->load_addr, info2->load_addr); + if (info1->flags & SPL_IMX_CONTAINER) + ut_asserteq(0, info2->size); + else + ut_asserteq(info1->size, info2->size); + } else { + ut_asserteq(info1->load_addr - sizeof(struct legacy_img_hdr), + info2->load_addr); + ut_asserteq(info1->size + sizeof(struct legacy_img_hdr), + info2->size); + } + + return 0; +} + +static ulong spl_test_read(struct spl_load_info *load, ulong sector, + ulong count, void *buf) +{ + memcpy(buf, load->priv + sector, count); + return count; +} + +static int spl_test_image(struct unit_test_state *uts, const char *test_name, + enum spl_test_image type) +{ + size_t img_size, img_data, data_size = SPL_TEST_DATA_SIZE; + struct spl_image_info info_write = { + .name = test_name, + .size = data_size, + }, info_read = { }; + char *data; + void *img; + + img_size = create_image(NULL, type, &info_write, &img_data); + ut_assert(img_size); + img = calloc(img_size, 1); + ut_assertnonnull(img); + + data = img + img_data; + generate_data(data, data_size, test_name); + ut_asserteq(img_size, create_image(img, type, &info_write, NULL)); + + if (type == LEGACY) { + ut_assertok(spl_parse_image_header(&info_read, NULL, img)); + if (check_image_info(uts, &info_write, &info_read)) + return CMD_RET_FAILURE; + } else { + struct spl_load_info load = { + .bl_len = 1, + .priv = img, + .read = spl_test_read, + }; + + if (type == IMX8) + ut_assertok(spl_load_imx_container(&info_read, &load, + 0)); + else if (IS_ENABLED(CONFIG_SPL_FIT_FULL)) + ut_assertok(spl_parse_image_header(&info_read, NULL, + img)); + else + ut_assertok(spl_load_simple_fit(&info_read, &load, 0, + img)); + if (check_image_info(uts, &info_write, &info_read)) + return CMD_RET_FAILURE; + ut_asserteq_mem(data, phys_to_virt(info_write.load_addr), + data_size); + } + + free(img); + return 0; +} +SPL_IMG_TEST(spl_test_image, LEGACY, 0); +SPL_IMG_TEST(spl_test_image, IMX8, 0); +SPL_IMG_TEST(spl_test_image, FIT_INTERNAL, 0); +SPL_IMG_TEST(spl_test_image, FIT_EXTERNAL, 0); diff --git a/test/image/spl_load_os.c b/test/image/spl_load_os.c index 500867ffd49..49edf152d78 100644 --- a/test/image/spl_load_os.c +++ b/test/image/spl_load_os.c @@ -6,14 +6,11 @@
#include <common.h> #include <image.h> -#include <mapmem.h> #include <os.h> #include <spl.h> +#include <test/spl.h> #include <test/ut.h>
-/* Declare a new SPL test */ -#define SPL_TEST(_name, _flags) UNIT_TEST(_name, _flags, spl_test) - /* Context used for this test */ struct text_ctx { int fd;

On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
This add some basic functions to create images, and a test for said functions. This is not intended to be a test of the image parsing functions, but rather a framework for creating minimal images for testing load methods. That said, it does do an OK job at finding bugs in the image parsing directly.
Since we have two methods for loading/parsing FIT images, add LOAD_FIT_FULL as a separate CI run.
Signed-off-by: Sean Anderson seanga2@gmail.com
.azure-pipelines.yml | 4 + .gitlab-ci.yml | 7 + arch/sandbox/cpu/u-boot-spl.lds | 2 + configs/sandbox_noinst_defconfig | 6 + configs/sandbox_spl_defconfig | 6 + include/test/spl.h | 117 ++++++++++ test/image/spl_load.c | 352 +++++++++++++++++++++++++++++++ test/image/spl_load_os.c | 5 +- 8 files changed, 495 insertions(+), 4 deletions(-) create mode 100644 include/test/spl.h
Reviewed-by: Simon Glass sjg@chromium.org
The error handling for the FDT creation is a bit unusual, but it is test code, so if it fails all bets are off. So OK.

El Wed, Oct 11, 2023 at 09:56:20PM -0400, Sean Anderson deia:
This add some basic functions to create images, and a test for said functions. This is not intended to be a test of the image parsing functions, but rather a framework for creating minimal images for testing load methods. That said, it does do an OK job at finding bugs in the image parsing directly.
Since we have two methods for loading/parsing FIT images, add LOAD_FIT_FULL as a separate CI run.
Signed-off-by: Sean Anderson seanga2@gmail.com
.azure-pipelines.yml | 4 + .gitlab-ci.yml | 7 + arch/sandbox/cpu/u-boot-spl.lds | 2 + configs/sandbox_noinst_defconfig | 6 + configs/sandbox_spl_defconfig | 6 + include/test/spl.h | 117 ++++++++++ test/image/spl_load.c | 352 +++++++++++++++++++++++++++++++ test/image/spl_load_os.c | 5 +- 8 files changed, 495 insertions(+), 4 deletions(-) create mode 100644 include/test/spl.h
[...]
diff --git a/test/image/spl_load.c b/test/image/spl_load.c index 1a57bf846d2..ca3777cab37 100644 --- a/test/image/spl_load.c +++ b/test/image/spl_load.c @@ -4,7 +4,15 @@ */
#include <common.h> +#include <image.h> +#include <imx_container.h> #include <mapmem.h> +#include <memalign.h> +#include <rand.h> +#include <spl.h> +#include <test/spl.h> +#include <test/ut.h> +#include <u-boot/crc.h>
int board_fit_config_name_match(const char *name) { @@ -15,3 +23,347 @@ struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size) { return map_sysmem(0x100000, 0); }
+/* Try to reuse the load buffer to conserve memory */ +void *board_spl_fit_buffer_addr(ulong fit_size, int sectors, int bl_len) +{
- static void *buf;
- static size_t size;
- static bool invalid = true;
- if (invalid || size < sectors * bl_len) {
if (!invalid)
free(buf);
buf = malloc_cache_aligned(sectors * bl_len);
invalid = false;
Should size be updated here or am I being thick ? size = ALIGN(sectors * bl_len, ARCH_DMA_MINALIGN);
- }
- return buf;
+}

On 10/13/23 15:44, Xavier Drudis Ferran wrote:
El Wed, Oct 11, 2023 at 09:56:20PM -0400, Sean Anderson deia:
This add some basic functions to create images, and a test for said functions. This is not intended to be a test of the image parsing functions, but rather a framework for creating minimal images for testing load methods. That said, it does do an OK job at finding bugs in the image parsing directly.
Since we have two methods for loading/parsing FIT images, add LOAD_FIT_FULL as a separate CI run.
Signed-off-by: Sean Anderson seanga2@gmail.com
.azure-pipelines.yml | 4 + .gitlab-ci.yml | 7 + arch/sandbox/cpu/u-boot-spl.lds | 2 + configs/sandbox_noinst_defconfig | 6 + configs/sandbox_spl_defconfig | 6 + include/test/spl.h | 117 ++++++++++ test/image/spl_load.c | 352 +++++++++++++++++++++++++++++++ test/image/spl_load_os.c | 5 +- 8 files changed, 495 insertions(+), 4 deletions(-) create mode 100644 include/test/spl.h
[...]
diff --git a/test/image/spl_load.c b/test/image/spl_load.c index 1a57bf846d2..ca3777cab37 100644 --- a/test/image/spl_load.c +++ b/test/image/spl_load.c @@ -4,7 +4,15 @@ */
#include <common.h> +#include <image.h> +#include <imx_container.h> #include <mapmem.h> +#include <memalign.h> +#include <rand.h> +#include <spl.h> +#include <test/spl.h> +#include <test/ut.h> +#include <u-boot/crc.h>
int board_fit_config_name_match(const char *name) { @@ -15,3 +23,347 @@ struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size) { return map_sysmem(0x100000, 0); }
+/* Try to reuse the load buffer to conserve memory */ +void *board_spl_fit_buffer_addr(ulong fit_size, int sectors, int bl_len) +{
- static void *buf;
- static size_t size;
- static bool invalid = true;
- if (invalid || size < sectors * bl_len) {
if (!invalid)
free(buf);
buf = malloc_cache_aligned(sectors * bl_len);
invalid = false;
Should size be updated here or am I being thick ? size = ALIGN(sectors * bl_len, ARCH_DMA_MINALIGN);
It should.
--Sean

Add some functions for creating fat/ext2 filesystems with a single file and a test for them. Filesystems require block devices, and it is easiest to just use MMC for this. To get an MMC, we must also pull in the test device tree.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
arch/sandbox/cpu/start.c | 9 +- configs/sandbox_noinst_defconfig | 7 + include/ext4fs.h | 1 + include/ext_common.h | 14 ++ include/test/spl.h | 3 + test/image/Kconfig | 11 ++ test/image/Makefile | 1 + test/image/spl_load.c | 1 + test/image/spl_load_fs.c | 305 +++++++++++++++++++++++++++++++ 9 files changed, 350 insertions(+), 2 deletions(-) create mode 100644 test/image/spl_load_fs.c
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 2c8a72590b5..f5728e6e7ee 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -13,6 +13,7 @@ #include <log.h> #include <os.h> #include <sort.h> +#include <spl.h> #include <asm/getopt.h> #include <asm/global_data.h> #include <asm/io.h> @@ -202,10 +203,14 @@ static int sandbox_cmdline_cb_test_fdt(struct sandbox_state *state, { char buf[256]; char *fname; + char *relname; int len;
- len = state_get_rel_filename("arch/sandbox/dts/test.dtb", buf, - sizeof(buf)); + if (spl_phase() < PHASE_BOARD_F) + relname = "../arch/sandbox/dts/test.dtb"; + else + relname = "arch/sandbox/dts/test.dtb"; + len = state_get_rel_filename(relname, buf, sizeof(buf)); if (len < 0) return len;
diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig index 908155be8a3..0a542cfb6aa 100644 --- a/configs/sandbox_noinst_defconfig +++ b/configs/sandbox_noinst_defconfig @@ -6,10 +6,12 @@ CONFIG_NR_DRAM_BANKS=1 CONFIG_ENV_SIZE=0x2000 CONFIG_DEFAULT_DEVICE_TREE="sandbox" CONFIG_DM_RESET=y +CONFIG_SPL_MMC=y CONFIG_SPL_SERIAL=y CONFIG_SPL_DRIVERS_MISC=y CONFIG_SPL_SYS_MALLOC_F_LEN=0x8000 CONFIG_SPL=y +CONFIG_SPL_FS_FAT=y CONFIG_SYS_LOAD_ADDR=0x0 CONFIG_PCI=y CONFIG_SANDBOX_SPL=y @@ -39,7 +41,9 @@ CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0xa000000 CONFIG_SPL_SYS_MALLOC_SIZE=0x4000000 CONFIG_SPL_ENV_SUPPORT=y +CONFIG_SPL_FS_EXT4=y CONFIG_SPL_I2C=y +CONFIG_SPL_MMC_WRITE=y CONFIG_SPL_RTC=y CONFIG_CMD_CPU=y CONFIG_CMD_LICENSE=y @@ -97,6 +101,7 @@ CONFIG_AMIGA_PARTITION=y CONFIG_OF_CONTROL=y CONFIG_SPL_OF_CONTROL=y CONFIG_SPL_OF_PLATDATA=y +CONFIG_SPL_OF_REAL=y CONFIG_ENV_IS_NOWHERE=y CONFIG_ENV_IS_IN_EXT4=y CONFIG_ENV_EXT4_INTERFACE="host" @@ -159,6 +164,7 @@ CONFIG_CROS_EC_SPI=y CONFIG_P2SB=y CONFIG_PWRSEQ=y CONFIG_SPL_PWRSEQ=y +CONFIG_FS_LOADER=y CONFIG_MMC_SANDBOX=y CONFIG_SPI_FLASH_SANDBOX=y CONFIG_SPI_FLASH_ATMEL=y @@ -220,6 +226,7 @@ CONFIG_SYSRESET=y CONFIG_SPL_SYSRESET=y CONFIG_DM_THERMAL=y CONFIG_TIMER=y +CONFIG_SPL_TIMER=y CONFIG_TIMER_EARLY=y CONFIG_SANDBOX_TIMER=y CONFIG_USB=y diff --git a/include/ext4fs.h b/include/ext4fs.h index cb5d9cc0a5c..dd66d27f776 100644 --- a/include/ext4fs.h +++ b/include/ext4fs.h @@ -31,6 +31,7 @@ struct disk_partition;
#define EXT4_INDEX_FL 0x00001000 /* Inode uses hash tree index */ +#define EXT4_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/ #define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ #define EXT4_EXT_MAGIC 0xf30a #define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010 diff --git a/include/ext_common.h b/include/ext_common.h index 30a0c248414..b09bbde116a 100644 --- a/include/ext_common.h +++ b/include/ext_common.h @@ -35,6 +35,16 @@ struct cmd_tbl; #define EXT2_PATH_MAX 4096 /* Maximum nesting of symlinks, used to prevent a loop. */ #define EXT2_MAX_SYMLINKCNT 8 +/* Maximum file name length */ +#define EXT2_NAME_LEN 255 + +/* + * Revision levels + */ +#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */ +#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */ + +#define EXT2_GOOD_OLD_INODE_SIZE 128
/* Filetype used in directory entry. */ #define FILETYPE_UNKNOWN 0 @@ -48,6 +58,10 @@ struct cmd_tbl; #define FILETYPE_INO_DIRECTORY 0040000 #define FILETYPE_INO_SYMLINK 0120000 #define EXT2_ROOT_INO 2 /* Root inode */ +#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */ + +/* First non-reserved inode for old ext2 filesystems */ +#define EXT2_GOOD_OLD_FIRST_INO 11
/* The size of an ext2 block in bytes. */ #define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE(data)) diff --git a/include/test/spl.h b/include/test/spl.h index a2f8d77b88f..7ae32a1020b 100644 --- a/include/test/spl.h +++ b/include/test/spl.h @@ -114,4 +114,7 @@ SPL_TEST(func##_##type, flags) /* More than a couple blocks, and will not be aligned to anything */ #define SPL_TEST_DATA_SIZE 4099
+/* Flags necessary for accessing DM devices */ +#define DM_FLAGS (UT_TESTF_DM | UT_TESTF_SCAN_FDT) + #endif /* TEST_SPL_H */ diff --git a/test/image/Kconfig b/test/image/Kconfig index 70ffe0ff276..963c86cc290 100644 --- a/test/image/Kconfig +++ b/test/image/Kconfig @@ -10,6 +10,17 @@ config SPL_UT_LOAD
if SPL_UT_LOAD
+config SPL_UT_LOAD_FS + bool "Unit tests for filesystems" + depends on SANDBOX && SPL_OF_REAL + depends on FS_LOADER + depends on SPL_FS_FAT + depends on SPL_FS_EXT4 + depends on SPL_MMC_WRITE + default y + help + Test filesystems in SPL. + config SPL_UT_LOAD_OS bool "Test loading from the host OS" depends on SANDBOX && SPL_LOAD_FIT diff --git a/test/image/Makefile b/test/image/Makefile index 1f62d54453c..9427e69bd3b 100644 --- a/test/image/Makefile +++ b/test/image/Makefile @@ -3,4 +3,5 @@ # Copyright 2021 Google LLC
obj-$(CONFIG_SPL_UT_LOAD) += spl_load.o +obj-$(CONFIG_SPL_UT_LOAD_FS) += spl_load_fs.o obj-$(CONFIG_SPL_UT_LOAD_OS) += spl_load_os.o diff --git a/test/image/spl_load.c b/test/image/spl_load.c index ca3777cab37..4338da417ce 100644 --- a/test/image/spl_load.c +++ b/test/image/spl_load.c @@ -4,6 +4,7 @@ */
#include <common.h> +#include <dm.h> #include <image.h> #include <imx_container.h> #include <mapmem.h> diff --git a/test/image/spl_load_fs.c b/test/image/spl_load_fs.c new file mode 100644 index 00000000000..8cd90b73518 --- /dev/null +++ b/test/image/spl_load_fs.c @@ -0,0 +1,305 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2023 Sean Anderson seanga2@gmail.com + */ + +#include <common.h> +#include <blk.h> +#include <ext_common.h> +#include <ext4fs.h> +#include <fat.h> +#include <fs.h> +#include <memalign.h> +#include <asm/io.h> +#include <linux/stat.h> +#include <test/spl.h> +#include <test/ut.h> + +/** + * create_ext2() - Create an "ext2" filesystem with a single file + * @dst: The location of the new filesystem; MUST be zeroed + * @size: The size of the file + * @filename: The name of the file + * @data_offset: Filled with the offset of the file data from @dst + * + * Budget mke2fs. We use 1k blocks (to reduce overhead) with a single block + * group, which limits us to 8M of data. Almost every feature which increases + * complexity (checksums, hash tree directories, etc.) is disabled. We do cheat + * a little and use extents from ext4 to save having to deal with indirects, but + * U-Boot doesn't care. + * + * If @dst is %NULL, nothing is copied. + * + * Return: The size of the filesystem in bytes + */ +static size_t create_ext2(void *dst, size_t size, const char *filename, + size_t *data_offset) +{ + u32 super_block = 1; + u32 group_block = 2; + u32 block_bitmap_block = 3; + u32 inode_bitmap_block = 4; + u32 inode_table_block = 5; + u32 root_block = 6; + u32 file_block = 7; + + u32 root_ino = EXT2_ROOT_INO; + u32 file_ino = EXT2_BOOT_LOADER_INO; + + u32 block_size = EXT2_MIN_BLOCK_SIZE; + u32 inode_size = sizeof(struct ext2_inode); + + u32 file_blocks = (size + block_size - 1) / block_size; + u32 blocks = file_block + file_blocks; + u32 inodes = block_size / inode_size; + u32 filename_len = strlen(filename); + u32 dirent_len = ALIGN(filename_len, sizeof(struct ext2_dirent)) + + sizeof(struct ext2_dirent); + + struct ext2_sblock *sblock = dst + super_block * block_size; + struct ext2_block_group *bg = dst + group_block * block_size; + struct ext2_inode *inode_table = dst + inode_table_block * block_size; + struct ext2_inode *root_inode = &inode_table[root_ino - 1]; + struct ext2_inode *file_inode = &inode_table[file_ino - 1]; + struct ext4_extent_header *ext_block = (void *)&file_inode->b; + struct ext4_extent *extent = (void *)(ext_block + 1); + struct ext2_dirent *dot = dst + root_block * block_size; + struct ext2_dirent *dotdot = dot + 2; + struct ext2_dirent *dirent = dotdot + 2; + struct ext2_dirent *last = ((void *)dirent) + dirent_len; + + /* Make sure we fit in one block group */ + if (blocks > block_size * 8) + return 0; + + if (filename_len > EXT2_NAME_LEN) + return 0; + + if (data_offset) + *data_offset = file_block * block_size; + + if (!dst) + goto out; + + sblock->total_inodes = cpu_to_le32(inodes); + sblock->total_blocks = cpu_to_le32(blocks); + sblock->first_data_block = cpu_to_le32(super_block); + sblock->blocks_per_group = cpu_to_le32(blocks); + sblock->fragments_per_group = cpu_to_le32(blocks); + sblock->inodes_per_group = cpu_to_le32(inodes); + sblock->magic = cpu_to_le16(EXT2_MAGIC); + /* Done mostly so we can pretend to be (in)compatible */ + sblock->revision_level = cpu_to_le32(EXT2_DYNAMIC_REV); + /* Not really accurate but it doesn't matter */ + sblock->first_inode = cpu_to_le32(EXT2_GOOD_OLD_FIRST_INO); + sblock->inode_size = cpu_to_le32(inode_size); + sblock->feature_incompat = cpu_to_le32(EXT4_FEATURE_INCOMPAT_EXTENTS); + + bg->block_id = cpu_to_le32(block_bitmap_block); + bg->inode_id = cpu_to_le32(inode_bitmap_block); + bg->inode_table_id = cpu_to_le32(inode_table_block); + + /* + * All blocks/inodes are in-use. I don't want to have to deal with + * endianness, so just fill everything in. + */ + memset(dst + block_bitmap_block * block_size, 0xff, block_size * 2); + + root_inode->mode = cpu_to_le16(S_IFDIR | 0755); + root_inode->size = cpu_to_le32(block_size); + root_inode->nlinks = cpu_to_le16(3); + root_inode->blockcnt = cpu_to_le32(1); + root_inode->flags = cpu_to_le32(EXT4_TOPDIR_FL); + root_inode->b.blocks.dir_blocks[0] = root_block; + + file_inode->mode = cpu_to_le16(S_IFREG | 0644); + file_inode->size = cpu_to_le32(size); + file_inode->nlinks = cpu_to_le16(1); + file_inode->blockcnt = cpu_to_le32(file_blocks); + file_inode->flags = cpu_to_le32(EXT4_EXTENTS_FL); + ext_block->eh_magic = cpu_to_le16(EXT4_EXT_MAGIC); + ext_block->eh_entries = cpu_to_le16(1); + ext_block->eh_max = cpu_to_le16(sizeof(file_inode->b) / + sizeof(*ext_block) - 1); + extent->ee_len = cpu_to_le16(file_blocks); + extent->ee_start_lo = cpu_to_le16(file_block); + + /* I'm not sure we need these, but it can't hurt */ + dot->inode = cpu_to_le32(root_ino); + dot->direntlen = cpu_to_le16(2 * sizeof(*dot)); + dot->namelen = 1; + dot->filetype = FILETYPE_DIRECTORY; + memcpy(dot + 1, ".", dot->namelen); + + dotdot->inode = cpu_to_le32(root_ino); + dotdot->direntlen = cpu_to_le16(2 * sizeof(*dotdot)); + dotdot->namelen = 2; + dotdot->filetype = FILETYPE_DIRECTORY; + memcpy(dotdot + 1, "..", dotdot->namelen); + + dirent->inode = cpu_to_le32(file_ino); + dirent->direntlen = cpu_to_le16(dirent_len); + dirent->namelen = filename_len; + dirent->filetype = FILETYPE_REG; + memcpy(dirent + 1, filename, filename_len); + + last->direntlen = block_size - dirent_len; + +out: + return (size_t)blocks * block_size; +} + +/** + * create_fat() - Create a FAT32 filesystem with a single file + * @dst: The location of the new filesystem; MUST be zeroed + * @size: The size of the file + * @filename: The name of the file + * @data_offset: Filled with the offset of the file data from @dst + * + * Budget mkfs.fat. We use FAT32 (so I don't have to deal with FAT12) with no + * info sector, and a single one-sector FAT. This limits us to 64k of data + * (enough for anyone). The filename must fit in 8.3. + * + * If @dst is %NULL, nothing is copied. + * + * Return: The size of the filesystem in bytes + */ +static size_t create_fat(void *dst, size_t size, const char *filename, + size_t *data_offset) +{ + u16 boot_sector = 0; + u16 fat_sector = 1; + u32 root_sector = 2; + u32 file_sector = 3; + + u16 sector_size = 512; + u32 file_sectors = (size + sector_size - 1) / sector_size; + u32 sectors = file_sector + file_sectors; + + char *ext; + size_t filename_len, ext_len; + int i; + + struct boot_sector *bs = dst + boot_sector * sector_size; + struct volume_info *vi = (void *)(bs + 1); + __le32 *fat = dst + fat_sector * sector_size; + struct dir_entry *dirent = dst + root_sector * sector_size; + + /* Make sure we fit in the FAT */ + if (sectors > sector_size / sizeof(u32)) + return 0; + + ext = strchr(filename, '.'); + if (ext) { + filename_len = ext - filename; + ext++; + ext_len = strlen(ext); + } else { + filename_len = strlen(filename); + ext_len = 0; + } + + if (filename_len > 8 || ext_len > 3) + return 0; + + if (data_offset) + *data_offset = file_sector * sector_size; + + if (!dst) + goto out; + + bs->sector_size[0] = sector_size & 0xff; + bs->sector_size[1] = sector_size >> 8; + bs->cluster_size = 1; + bs->reserved = cpu_to_le16(fat_sector); + bs->fats = 1; + bs->media = 0xf8; + bs->total_sect = cpu_to_le32(sectors); + bs->fat32_length = cpu_to_le32(1); + bs->root_cluster = cpu_to_le32(root_sector); + + vi->ext_boot_sign = 0x29; + memcpy(vi->fs_type, FAT32_SIGN, sizeof(vi->fs_type)); + + memcpy(dst + 0x1fe, "\x55\xAA", 2); + + fat[0] = cpu_to_le32(0x0ffffff8); + fat[1] = cpu_to_le32(0x0fffffff); + fat[2] = cpu_to_le32(0x0ffffff8); + for (i = file_sector; file_sectors > 1; file_sectors--, i++) + fat[i] = cpu_to_le32(i + 1); + fat[i] = cpu_to_le32(0x0ffffff8); + + for (i = 0; i < sizeof(dirent->nameext.name); i++) { + if (i < filename_len) + dirent->nameext.name[i] = toupper(filename[i]); + else + dirent->nameext.name[i] = ' '; + } + + for (i = 0; i < sizeof(dirent->nameext.ext); i++) { + if (i < ext_len) + dirent->nameext.ext[i] = toupper(ext[i]); + else + dirent->nameext.ext[i] = ' '; + } + + dirent->start = cpu_to_le16(file_sector); + dirent->size = cpu_to_le32(size); + +out: + return sectors * sector_size; +} + +typedef size_t (*create_fs_t)(void *, size_t, const char *, size_t *); + +static int spl_test_fs(struct unit_test_state *uts, const char *test_name, + create_fs_t create) +{ + const char *filename = CONFIG_SPL_FS_LOAD_PAYLOAD_NAME; + struct blk_desc *dev_desc; + char *data_write, *data_read; + void *fs; + size_t fs_size, fs_data, fs_blocks, data_size = SPL_TEST_DATA_SIZE; + loff_t actread; + + fs_size = create(NULL, data_size, filename, &fs_data); + ut_assert(fs_size); + fs = calloc(fs_size, 1); + ut_assertnonnull(fs); + + data_write = fs + fs_data; + generate_data(data_write, data_size, test_name); + ut_asserteq(fs_size, create(fs, data_size, filename, NULL)); + + dev_desc = blk_get_devnum_by_uclass_id(UCLASS_MMC, 0); + ut_assertnonnull(dev_desc); + ut_asserteq(512, dev_desc->blksz); + fs_blocks = fs_size / dev_desc->blksz; + ut_asserteq(fs_blocks, blk_dwrite(dev_desc, 0, fs_blocks, fs)); + + /* We have to use malloc so we can call virt_to_phys */ + data_read = malloc_cache_aligned(data_size); + ut_assertnonnull(data_read); + ut_assertok(fs_set_blk_dev_with_part(dev_desc, 0)); + ut_assertok(fs_read("/" CONFIG_SPL_FS_LOAD_PAYLOAD_NAME, + virt_to_phys(data_read), 0, data_size, &actread)); + ut_asserteq(data_size, actread); + ut_asserteq_mem(data_write, data_read, data_size); + + free(data_read); + free(fs); + return 0; +} + +static int spl_test_ext(struct unit_test_state *uts) +{ + return spl_test_fs(uts, __func__, create_ext2); +} +SPL_TEST(spl_test_ext, DM_FLAGS); + +static int spl_test_fat(struct unit_test_state *uts) +{ + return spl_test_fs(uts, __func__, create_fat); +} +SPL_TEST(spl_test_fat, DM_FLAGS);

Hi Sean,
On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
Add some functions for creating fat/ext2 filesystems with a single file and a test for them. Filesystems require block devices, and it is easiest to just use MMC for this. To get an MMC, we must also pull in the test device tree.
Signed-off-by: Sean Anderson seanga2@gmail.com
arch/sandbox/cpu/start.c | 9 +- configs/sandbox_noinst_defconfig | 7 + include/ext4fs.h | 1 + include/ext_common.h | 14 ++ include/test/spl.h | 3 + test/image/Kconfig | 11 ++ test/image/Makefile | 1 + test/image/spl_load.c | 1 + test/image/spl_load_fs.c | 305 +++++++++++++++++++++++++++++++ 9 files changed, 350 insertions(+), 2 deletions(-) create mode 100644 test/image/spl_load_fs.c
Reviewed-by: Simon Glass sjg@chromium.org
Wow there is a lot going on in this patch. It might be good to split it.
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 2c8a72590b5..f5728e6e7ee 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -13,6 +13,7 @@ #include <log.h> #include <os.h> #include <sort.h> +#include <spl.h> #include <asm/getopt.h> #include <asm/global_data.h> #include <asm/io.h> @@ -202,10 +203,14 @@ static int sandbox_cmdline_cb_test_fdt(struct sandbox_state *state, { char buf[256]; char *fname;
char *relname; int len;
len = state_get_rel_filename("arch/sandbox/dts/test.dtb", buf,
sizeof(buf));
if (spl_phase() < PHASE_BOARD_F)
I think <= PHASE_SPL is better since you care about whether it is in SPL or not. I did send a patch to check for SPL, but I don't think it is merged yet.
relname = "../arch/sandbox/dts/test.dtb";
else
relname = "arch/sandbox/dts/test.dtb";
len = state_get_rel_filename(relname, buf, sizeof(buf)); if (len < 0) return len;
diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig index 908155be8a3..0a542cfb6aa 100644 --- a/configs/sandbox_noinst_defconfig +++ b/configs/sandbox_noinst_defconfig @@ -6,10 +6,12 @@ CONFIG_NR_DRAM_BANKS=1 CONFIG_ENV_SIZE=0x2000 CONFIG_DEFAULT_DEVICE_TREE="sandbox" CONFIG_DM_RESET=y +CONFIG_SPL_MMC=y CONFIG_SPL_SERIAL=y CONFIG_SPL_DRIVERS_MISC=y CONFIG_SPL_SYS_MALLOC_F_LEN=0x8000 CONFIG_SPL=y +CONFIG_SPL_FS_FAT=y CONFIG_SYS_LOAD_ADDR=0x0 CONFIG_PCI=y CONFIG_SANDBOX_SPL=y @@ -39,7 +41,9 @@ CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0xa000000 CONFIG_SPL_SYS_MALLOC_SIZE=0x4000000 CONFIG_SPL_ENV_SUPPORT=y +CONFIG_SPL_FS_EXT4=y CONFIG_SPL_I2C=y +CONFIG_SPL_MMC_WRITE=y CONFIG_SPL_RTC=y CONFIG_CMD_CPU=y CONFIG_CMD_LICENSE=y @@ -97,6 +101,7 @@ CONFIG_AMIGA_PARTITION=y CONFIG_OF_CONTROL=y CONFIG_SPL_OF_CONTROL=y CONFIG_SPL_OF_PLATDATA=y +CONFIG_SPL_OF_REAL=y CONFIG_ENV_IS_NOWHERE=y CONFIG_ENV_IS_IN_EXT4=y CONFIG_ENV_EXT4_INTERFACE="host" @@ -159,6 +164,7 @@ CONFIG_CROS_EC_SPI=y CONFIG_P2SB=y CONFIG_PWRSEQ=y CONFIG_SPL_PWRSEQ=y +CONFIG_FS_LOADER=y CONFIG_MMC_SANDBOX=y CONFIG_SPI_FLASH_SANDBOX=y CONFIG_SPI_FLASH_ATMEL=y @@ -220,6 +226,7 @@ CONFIG_SYSRESET=y CONFIG_SPL_SYSRESET=y CONFIG_DM_THERMAL=y CONFIG_TIMER=y +CONFIG_SPL_TIMER=y CONFIG_TIMER_EARLY=y CONFIG_SANDBOX_TIMER=y CONFIG_USB=y
I think these would be better in their own patch
diff --git a/include/ext4fs.h b/include/ext4fs.h index cb5d9cc0a5c..dd66d27f776 100644 --- a/include/ext4fs.h +++ b/include/ext4fs.h @@ -31,6 +31,7 @@ struct disk_partition;
#define EXT4_INDEX_FL 0x00001000 /* Inode uses hash tree index */ +#define EXT4_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/ #define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ #define EXT4_EXT_MAGIC 0xf30a #define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010 diff --git a/include/ext_common.h b/include/ext_common.h index 30a0c248414..b09bbde116a 100644 --- a/include/ext_common.h +++ b/include/ext_common.h @@ -35,6 +35,16 @@ struct cmd_tbl; #define EXT2_PATH_MAX 4096 /* Maximum nesting of symlinks, used to prevent a loop. */ #define EXT2_MAX_SYMLINKCNT 8 +/* Maximum file name length */ +#define EXT2_NAME_LEN 255
+/*
- Revision levels
- */
+#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */ +#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
+#define EXT2_GOOD_OLD_INODE_SIZE 128
/* Filetype used in directory entry. */ #define FILETYPE_UNKNOWN 0 @@ -48,6 +58,10 @@ struct cmd_tbl; #define FILETYPE_INO_DIRECTORY 0040000 #define FILETYPE_INO_SYMLINK 0120000 #define EXT2_ROOT_INO 2 /* Root inode */ +#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
+/* First non-reserved inode for old ext2 filesystems */ +#define EXT2_GOOD_OLD_FIRST_INO 11
/* The size of an ext2 block in bytes. */ #define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE(data))
Again I think these ext2 changes would be better in their own patch
diff --git a/include/test/spl.h b/include/test/spl.h index a2f8d77b88f..7ae32a1020b 100644 --- a/include/test/spl.h +++ b/include/test/spl.h @@ -114,4 +114,7 @@ SPL_TEST(func##_##type, flags) /* More than a couple blocks, and will not be aligned to anything */ #define SPL_TEST_DATA_SIZE 4099
+/* Flags necessary for accessing DM devices */ +#define DM_FLAGS (UT_TESTF_DM | UT_TESTF_SCAN_FDT)
#endif /* TEST_SPL_H */ diff --git a/test/image/Kconfig b/test/image/Kconfig index 70ffe0ff276..963c86cc290 100644 --- a/test/image/Kconfig +++ b/test/image/Kconfig @@ -10,6 +10,17 @@ config SPL_UT_LOAD
if SPL_UT_LOAD
+config SPL_UT_LOAD_FS
bool "Unit tests for filesystems"
depends on SANDBOX && SPL_OF_REAL
depends on FS_LOADER
depends on SPL_FS_FAT
depends on SPL_FS_EXT4
depends on SPL_MMC_WRITE
default y
help
Test filesystems in SPL.
config SPL_UT_LOAD_OS bool "Test loading from the host OS" depends on SANDBOX && SPL_LOAD_FIT diff --git a/test/image/Makefile b/test/image/Makefile index 1f62d54453c..9427e69bd3b 100644 --- a/test/image/Makefile +++ b/test/image/Makefile @@ -3,4 +3,5 @@ # Copyright 2021 Google LLC
obj-$(CONFIG_SPL_UT_LOAD) += spl_load.o +obj-$(CONFIG_SPL_UT_LOAD_FS) += spl_load_fs.o obj-$(CONFIG_SPL_UT_LOAD_OS) += spl_load_os.o diff --git a/test/image/spl_load.c b/test/image/spl_load.c index ca3777cab37..4338da417ce 100644 --- a/test/image/spl_load.c +++ b/test/image/spl_load.c @@ -4,6 +4,7 @@ */
#include <common.h> +#include <dm.h> #include <image.h> #include <imx_container.h> #include <mapmem.h> diff --git a/test/image/spl_load_fs.c b/test/image/spl_load_fs.c new file mode 100644 index 00000000000..8cd90b73518 --- /dev/null +++ b/test/image/spl_load_fs.c @@ -0,0 +1,305 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (C) 2023 Sean Anderson seanga2@gmail.com
- */
+#include <common.h> +#include <blk.h> +#include <ext_common.h> +#include <ext4fs.h> +#include <fat.h> +#include <fs.h> +#include <memalign.h> +#include <asm/io.h> +#include <linux/stat.h> +#include <test/spl.h> +#include <test/ut.h>
+/**
- create_ext2() - Create an "ext2" filesystem with a single file
- @dst: The location of the new filesystem; MUST be zeroed
- @size: The size of the file
- @filename: The name of the file
- @data_offset: Filled with the offset of the file data from @dst
- Budget mke2fs. We use 1k blocks (to reduce overhead) with a single block
- group, which limits us to 8M of data. Almost every feature which increases
- complexity (checksums, hash tree directories, etc.) is disabled. We do cheat
- a little and use extents from ext4 to save having to deal with indirects, but
- U-Boot doesn't care.
- If @dst is %NULL, nothing is copied.
- Return: The size of the filesystem in bytes
- */
+static size_t create_ext2(void *dst, size_t size, const char *filename,
size_t *data_offset)
+{
u32 super_block = 1;
u32 group_block = 2;
u32 block_bitmap_block = 3;
u32 inode_bitmap_block = 4;
u32 inode_table_block = 5;
u32 root_block = 6;
u32 file_block = 7;
u32 root_ino = EXT2_ROOT_INO;
u32 file_ino = EXT2_BOOT_LOADER_INO;
u32 block_size = EXT2_MIN_BLOCK_SIZE;
u32 inode_size = sizeof(struct ext2_inode);
u32 file_blocks = (size + block_size - 1) / block_size;
u32 blocks = file_block + file_blocks;
u32 inodes = block_size / inode_size;
u32 filename_len = strlen(filename);
u32 dirent_len = ALIGN(filename_len, sizeof(struct ext2_dirent)) +
sizeof(struct ext2_dirent);
struct ext2_sblock *sblock = dst + super_block * block_size;
struct ext2_block_group *bg = dst + group_block * block_size;
struct ext2_inode *inode_table = dst + inode_table_block * block_size;
struct ext2_inode *root_inode = &inode_table[root_ino - 1];
struct ext2_inode *file_inode = &inode_table[file_ino - 1];
struct ext4_extent_header *ext_block = (void *)&file_inode->b;
struct ext4_extent *extent = (void *)(ext_block + 1);
struct ext2_dirent *dot = dst + root_block * block_size;
struct ext2_dirent *dotdot = dot + 2;
struct ext2_dirent *dirent = dotdot + 2;
struct ext2_dirent *last = ((void *)dirent) + dirent_len;
/* Make sure we fit in one block group */
if (blocks > block_size * 8)
return 0;
if (filename_len > EXT2_NAME_LEN)
return 0;
if (data_offset)
*data_offset = file_block * block_size;
if (!dst)
goto out;
sblock->total_inodes = cpu_to_le32(inodes);
sblock->total_blocks = cpu_to_le32(blocks);
sblock->first_data_block = cpu_to_le32(super_block);
sblock->blocks_per_group = cpu_to_le32(blocks);
sblock->fragments_per_group = cpu_to_le32(blocks);
sblock->inodes_per_group = cpu_to_le32(inodes);
sblock->magic = cpu_to_le16(EXT2_MAGIC);
/* Done mostly so we can pretend to be (in)compatible */
sblock->revision_level = cpu_to_le32(EXT2_DYNAMIC_REV);
/* Not really accurate but it doesn't matter */
sblock->first_inode = cpu_to_le32(EXT2_GOOD_OLD_FIRST_INO);
sblock->inode_size = cpu_to_le32(inode_size);
sblock->feature_incompat = cpu_to_le32(EXT4_FEATURE_INCOMPAT_EXTENTS);
bg->block_id = cpu_to_le32(block_bitmap_block);
bg->inode_id = cpu_to_le32(inode_bitmap_block);
bg->inode_table_id = cpu_to_le32(inode_table_block);
/*
* All blocks/inodes are in-use. I don't want to have to deal with
* endianness, so just fill everything in.
*/
memset(dst + block_bitmap_block * block_size, 0xff, block_size * 2);
root_inode->mode = cpu_to_le16(S_IFDIR | 0755);
root_inode->size = cpu_to_le32(block_size);
root_inode->nlinks = cpu_to_le16(3);
root_inode->blockcnt = cpu_to_le32(1);
root_inode->flags = cpu_to_le32(EXT4_TOPDIR_FL);
root_inode->b.blocks.dir_blocks[0] = root_block;
file_inode->mode = cpu_to_le16(S_IFREG | 0644);
file_inode->size = cpu_to_le32(size);
file_inode->nlinks = cpu_to_le16(1);
file_inode->blockcnt = cpu_to_le32(file_blocks);
file_inode->flags = cpu_to_le32(EXT4_EXTENTS_FL);
ext_block->eh_magic = cpu_to_le16(EXT4_EXT_MAGIC);
ext_block->eh_entries = cpu_to_le16(1);
ext_block->eh_max = cpu_to_le16(sizeof(file_inode->b) /
sizeof(*ext_block) - 1);
extent->ee_len = cpu_to_le16(file_blocks);
extent->ee_start_lo = cpu_to_le16(file_block);
/* I'm not sure we need these, but it can't hurt */
dot->inode = cpu_to_le32(root_ino);
dot->direntlen = cpu_to_le16(2 * sizeof(*dot));
dot->namelen = 1;
dot->filetype = FILETYPE_DIRECTORY;
memcpy(dot + 1, ".", dot->namelen);
dotdot->inode = cpu_to_le32(root_ino);
dotdot->direntlen = cpu_to_le16(2 * sizeof(*dotdot));
dotdot->namelen = 2;
dotdot->filetype = FILETYPE_DIRECTORY;
memcpy(dotdot + 1, "..", dotdot->namelen);
dirent->inode = cpu_to_le32(file_ino);
dirent->direntlen = cpu_to_le16(dirent_len);
dirent->namelen = filename_len;
dirent->filetype = FILETYPE_REG;
memcpy(dirent + 1, filename, filename_len);
last->direntlen = block_size - dirent_len;
+out:
return (size_t)blocks * block_size;
+}
+/**
- create_fat() - Create a FAT32 filesystem with a single file
- @dst: The location of the new filesystem; MUST be zeroed
- @size: The size of the file
- @filename: The name of the file
- @data_offset: Filled with the offset of the file data from @dst
- Budget mkfs.fat. We use FAT32 (so I don't have to deal with FAT12) with no
- info sector, and a single one-sector FAT. This limits us to 64k of data
- (enough for anyone). The filename must fit in 8.3.
- If @dst is %NULL, nothing is copied.
- Return: The size of the filesystem in bytes
- */
+static size_t create_fat(void *dst, size_t size, const char *filename,
size_t *data_offset)
+{
u16 boot_sector = 0;
u16 fat_sector = 1;
u32 root_sector = 2;
u32 file_sector = 3;
u16 sector_size = 512;
u32 file_sectors = (size + sector_size - 1) / sector_size;
u32 sectors = file_sector + file_sectors;
char *ext;
size_t filename_len, ext_len;
int i;
struct boot_sector *bs = dst + boot_sector * sector_size;
struct volume_info *vi = (void *)(bs + 1);
__le32 *fat = dst + fat_sector * sector_size;
struct dir_entry *dirent = dst + root_sector * sector_size;
/* Make sure we fit in the FAT */
if (sectors > sector_size / sizeof(u32))
return 0;
ext = strchr(filename, '.');
if (ext) {
filename_len = ext - filename;
ext++;
ext_len = strlen(ext);
} else {
filename_len = strlen(filename);
ext_len = 0;
}
if (filename_len > 8 || ext_len > 3)
return 0;
if (data_offset)
*data_offset = file_sector * sector_size;
if (!dst)
goto out;
bs->sector_size[0] = sector_size & 0xff;
bs->sector_size[1] = sector_size >> 8;
bs->cluster_size = 1;
bs->reserved = cpu_to_le16(fat_sector);
bs->fats = 1;
bs->media = 0xf8;
bs->total_sect = cpu_to_le32(sectors);
bs->fat32_length = cpu_to_le32(1);
bs->root_cluster = cpu_to_le32(root_sector);
vi->ext_boot_sign = 0x29;
memcpy(vi->fs_type, FAT32_SIGN, sizeof(vi->fs_type));
memcpy(dst + 0x1fe, "\x55\xAA", 2);
fat[0] = cpu_to_le32(0x0ffffff8);
fat[1] = cpu_to_le32(0x0fffffff);
fat[2] = cpu_to_le32(0x0ffffff8);
for (i = file_sector; file_sectors > 1; file_sectors--, i++)
fat[i] = cpu_to_le32(i + 1);
fat[i] = cpu_to_le32(0x0ffffff8);
for (i = 0; i < sizeof(dirent->nameext.name); i++) {
if (i < filename_len)
dirent->nameext.name[i] = toupper(filename[i]);
else
dirent->nameext.name[i] = ' ';
}
for (i = 0; i < sizeof(dirent->nameext.ext); i++) {
if (i < ext_len)
dirent->nameext.ext[i] = toupper(ext[i]);
else
dirent->nameext.ext[i] = ' ';
}
dirent->start = cpu_to_le16(file_sector);
dirent->size = cpu_to_le32(size);
+out:
return sectors * sector_size;
+}
+typedef size_t (*create_fs_t)(void *, size_t, const char *, size_t *);
+static int spl_test_fs(struct unit_test_state *uts, const char *test_name,
create_fs_t create)
+{
const char *filename = CONFIG_SPL_FS_LOAD_PAYLOAD_NAME;
struct blk_desc *dev_desc;
char *data_write, *data_read;
void *fs;
size_t fs_size, fs_data, fs_blocks, data_size = SPL_TEST_DATA_SIZE;
loff_t actread;
fs_size = create(NULL, data_size, filename, &fs_data);
ut_assert(fs_size);
fs = calloc(fs_size, 1);
ut_assertnonnull(fs);
data_write = fs + fs_data;
generate_data(data_write, data_size, test_name);
ut_asserteq(fs_size, create(fs, data_size, filename, NULL));
dev_desc = blk_get_devnum_by_uclass_id(UCLASS_MMC, 0);
ut_assertnonnull(dev_desc);
ut_asserteq(512, dev_desc->blksz);
fs_blocks = fs_size / dev_desc->blksz;
ut_asserteq(fs_blocks, blk_dwrite(dev_desc, 0, fs_blocks, fs));
/* We have to use malloc so we can call virt_to_phys */
data_read = malloc_cache_aligned(data_size);
ut_assertnonnull(data_read);
ut_assertok(fs_set_blk_dev_with_part(dev_desc, 0));
ut_assertok(fs_read("/" CONFIG_SPL_FS_LOAD_PAYLOAD_NAME,
virt_to_phys(data_read), 0, data_size, &actread));
ut_asserteq(data_size, actread);
ut_asserteq_mem(data_write, data_read, data_size);
free(data_read);
free(fs);
return 0;
+}
+static int spl_test_ext(struct unit_test_state *uts) +{
return spl_test_fs(uts, __func__, create_ext2);
+} +SPL_TEST(spl_test_ext, DM_FLAGS);
+static int spl_test_fat(struct unit_test_state *uts) +{
return spl_test_fs(uts, __func__, create_fat);
+}
+SPL_TEST(spl_test_fat, DM_FLAGS);
2.37.1
Regards, Simon

On 10/11/23 23:41, Simon Glass wrote:
Hi Sean,
On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
Add some functions for creating fat/ext2 filesystems with a single file and a test for them. Filesystems require block devices, and it is easiest to just use MMC for this. To get an MMC, we must also pull in the test device tree.
Signed-off-by: Sean Anderson seanga2@gmail.com
arch/sandbox/cpu/start.c | 9 +- configs/sandbox_noinst_defconfig | 7 + include/ext4fs.h | 1 + include/ext_common.h | 14 ++ include/test/spl.h | 3 + test/image/Kconfig | 11 ++ test/image/Makefile | 1 + test/image/spl_load.c | 1 + test/image/spl_load_fs.c | 305 +++++++++++++++++++++++++++++++ 9 files changed, 350 insertions(+), 2 deletions(-) create mode 100644 test/image/spl_load_fs.c
Reviewed-by: Simon Glass sjg@chromium.org
Wow there is a lot going on in this patch. It might be good to split it.
OK.
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 2c8a72590b5..f5728e6e7ee 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -13,6 +13,7 @@ #include <log.h> #include <os.h> #include <sort.h> +#include <spl.h> #include <asm/getopt.h> #include <asm/global_data.h> #include <asm/io.h> @@ -202,10 +203,14 @@ static int sandbox_cmdline_cb_test_fdt(struct sandbox_state *state, { char buf[256]; char *fname;
char *relname; int len;
len = state_get_rel_filename("arch/sandbox/dts/test.dtb", buf,
sizeof(buf));
if (spl_phase() < PHASE_BOARD_F)
I think <= PHASE_SPL is better since you care about whether it is in SPL or not. I did send a patch to check for SPL, but I don't think it is merged yet.
Fine by me.
relname = "../arch/sandbox/dts/test.dtb";
else
relname = "arch/sandbox/dts/test.dtb";
len = state_get_rel_filename(relname, buf, sizeof(buf)); if (len < 0) return len;
diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig index 908155be8a3..0a542cfb6aa 100644 --- a/configs/sandbox_noinst_defconfig +++ b/configs/sandbox_noinst_defconfig @@ -6,10 +6,12 @@ CONFIG_NR_DRAM_BANKS=1 CONFIG_ENV_SIZE=0x2000 CONFIG_DEFAULT_DEVICE_TREE="sandbox" CONFIG_DM_RESET=y +CONFIG_SPL_MMC=y CONFIG_SPL_SERIAL=y CONFIG_SPL_DRIVERS_MISC=y CONFIG_SPL_SYS_MALLOC_F_LEN=0x8000 CONFIG_SPL=y +CONFIG_SPL_FS_FAT=y CONFIG_SYS_LOAD_ADDR=0x0 CONFIG_PCI=y CONFIG_SANDBOX_SPL=y @@ -39,7 +41,9 @@ CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0xa000000 CONFIG_SPL_SYS_MALLOC_SIZE=0x4000000 CONFIG_SPL_ENV_SUPPORT=y +CONFIG_SPL_FS_EXT4=y CONFIG_SPL_I2C=y +CONFIG_SPL_MMC_WRITE=y CONFIG_SPL_RTC=y CONFIG_CMD_CPU=y CONFIG_CMD_LICENSE=y @@ -97,6 +101,7 @@ CONFIG_AMIGA_PARTITION=y CONFIG_OF_CONTROL=y CONFIG_SPL_OF_CONTROL=y CONFIG_SPL_OF_PLATDATA=y +CONFIG_SPL_OF_REAL=y CONFIG_ENV_IS_NOWHERE=y CONFIG_ENV_IS_IN_EXT4=y CONFIG_ENV_EXT4_INTERFACE="host" @@ -159,6 +164,7 @@ CONFIG_CROS_EC_SPI=y CONFIG_P2SB=y CONFIG_PWRSEQ=y CONFIG_SPL_PWRSEQ=y +CONFIG_FS_LOADER=y CONFIG_MMC_SANDBOX=y CONFIG_SPI_FLASH_SANDBOX=y CONFIG_SPI_FLASH_ATMEL=y @@ -220,6 +226,7 @@ CONFIG_SYSRESET=y CONFIG_SPL_SYSRESET=y CONFIG_DM_THERMAL=y CONFIG_TIMER=y +CONFIG_SPL_TIMER=y CONFIG_TIMER_EARLY=y CONFIG_SANDBOX_TIMER=y CONFIG_USB=y
I think these would be better in their own patch
Surprisingly, MMC_WRITE actually depends on SPL_TIMER. I didn't check on the exact dependency, but presumably there is some poll/timeout loop in the MMC write code.
diff --git a/include/ext4fs.h b/include/ext4fs.h index cb5d9cc0a5c..dd66d27f776 100644 --- a/include/ext4fs.h +++ b/include/ext4fs.h @@ -31,6 +31,7 @@ struct disk_partition;
#define EXT4_INDEX_FL 0x00001000 /* Inode uses hash tree index */ +#define EXT4_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/ #define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ #define EXT4_EXT_MAGIC 0xf30a #define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010 diff --git a/include/ext_common.h b/include/ext_common.h index 30a0c248414..b09bbde116a 100644 --- a/include/ext_common.h +++ b/include/ext_common.h @@ -35,6 +35,16 @@ struct cmd_tbl; #define EXT2_PATH_MAX 4096 /* Maximum nesting of symlinks, used to prevent a loop. */ #define EXT2_MAX_SYMLINKCNT 8 +/* Maximum file name length */ +#define EXT2_NAME_LEN 255
+/*
- Revision levels
- */
+#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */ +#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
+#define EXT2_GOOD_OLD_INODE_SIZE 128
/* Filetype used in directory entry. */ #define FILETYPE_UNKNOWN 0 @@ -48,6 +58,10 @@ struct cmd_tbl; #define FILETYPE_INO_DIRECTORY 0040000 #define FILETYPE_INO_SYMLINK 0120000 #define EXT2_ROOT_INO 2 /* Root inode */ +#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
+/* First non-reserved inode for old ext2 filesystems */ +#define EXT2_GOOD_OLD_FIRST_INO 11
/* The size of an ext2 block in bytes. */ #define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE(data))
Again I think these ext2 changes would be better in their own patch
OK.
FWIW These are really only used by this patch.
--Sean
diff --git a/include/test/spl.h b/include/test/spl.h index a2f8d77b88f..7ae32a1020b 100644 --- a/include/test/spl.h +++ b/include/test/spl.h @@ -114,4 +114,7 @@ SPL_TEST(func##_##type, flags) /* More than a couple blocks, and will not be aligned to anything */ #define SPL_TEST_DATA_SIZE 4099
+/* Flags necessary for accessing DM devices */ +#define DM_FLAGS (UT_TESTF_DM | UT_TESTF_SCAN_FDT)
- #endif /* TEST_SPL_H */
diff --git a/test/image/Kconfig b/test/image/Kconfig index 70ffe0ff276..963c86cc290 100644 --- a/test/image/Kconfig +++ b/test/image/Kconfig @@ -10,6 +10,17 @@ config SPL_UT_LOAD
if SPL_UT_LOAD
+config SPL_UT_LOAD_FS
bool "Unit tests for filesystems"
depends on SANDBOX && SPL_OF_REAL
depends on FS_LOADER
depends on SPL_FS_FAT
depends on SPL_FS_EXT4
depends on SPL_MMC_WRITE
default y
help
Test filesystems in SPL.
- config SPL_UT_LOAD_OS bool "Test loading from the host OS" depends on SANDBOX && SPL_LOAD_FIT
diff --git a/test/image/Makefile b/test/image/Makefile index 1f62d54453c..9427e69bd3b 100644 --- a/test/image/Makefile +++ b/test/image/Makefile @@ -3,4 +3,5 @@ # Copyright 2021 Google LLC
obj-$(CONFIG_SPL_UT_LOAD) += spl_load.o +obj-$(CONFIG_SPL_UT_LOAD_FS) += spl_load_fs.o obj-$(CONFIG_SPL_UT_LOAD_OS) += spl_load_os.o diff --git a/test/image/spl_load.c b/test/image/spl_load.c index ca3777cab37..4338da417ce 100644 --- a/test/image/spl_load.c +++ b/test/image/spl_load.c @@ -4,6 +4,7 @@ */
#include <common.h> +#include <dm.h> #include <image.h> #include <imx_container.h> #include <mapmem.h> diff --git a/test/image/spl_load_fs.c b/test/image/spl_load_fs.c new file mode 100644 index 00000000000..8cd90b73518 --- /dev/null +++ b/test/image/spl_load_fs.c @@ -0,0 +1,305 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (C) 2023 Sean Anderson seanga2@gmail.com
- */
+#include <common.h> +#include <blk.h> +#include <ext_common.h> +#include <ext4fs.h> +#include <fat.h> +#include <fs.h> +#include <memalign.h> +#include <asm/io.h> +#include <linux/stat.h> +#include <test/spl.h> +#include <test/ut.h>
+/**
- create_ext2() - Create an "ext2" filesystem with a single file
- @dst: The location of the new filesystem; MUST be zeroed
- @size: The size of the file
- @filename: The name of the file
- @data_offset: Filled with the offset of the file data from @dst
- Budget mke2fs. We use 1k blocks (to reduce overhead) with a single block
- group, which limits us to 8M of data. Almost every feature which increases
- complexity (checksums, hash tree directories, etc.) is disabled. We do cheat
- a little and use extents from ext4 to save having to deal with indirects, but
- U-Boot doesn't care.
- If @dst is %NULL, nothing is copied.
- Return: The size of the filesystem in bytes
- */
+static size_t create_ext2(void *dst, size_t size, const char *filename,
size_t *data_offset)
+{
u32 super_block = 1;
u32 group_block = 2;
u32 block_bitmap_block = 3;
u32 inode_bitmap_block = 4;
u32 inode_table_block = 5;
u32 root_block = 6;
u32 file_block = 7;
u32 root_ino = EXT2_ROOT_INO;
u32 file_ino = EXT2_BOOT_LOADER_INO;
u32 block_size = EXT2_MIN_BLOCK_SIZE;
u32 inode_size = sizeof(struct ext2_inode);
u32 file_blocks = (size + block_size - 1) / block_size;
u32 blocks = file_block + file_blocks;
u32 inodes = block_size / inode_size;
u32 filename_len = strlen(filename);
u32 dirent_len = ALIGN(filename_len, sizeof(struct ext2_dirent)) +
sizeof(struct ext2_dirent);
struct ext2_sblock *sblock = dst + super_block * block_size;
struct ext2_block_group *bg = dst + group_block * block_size;
struct ext2_inode *inode_table = dst + inode_table_block * block_size;
struct ext2_inode *root_inode = &inode_table[root_ino - 1];
struct ext2_inode *file_inode = &inode_table[file_ino - 1];
struct ext4_extent_header *ext_block = (void *)&file_inode->b;
struct ext4_extent *extent = (void *)(ext_block + 1);
struct ext2_dirent *dot = dst + root_block * block_size;
struct ext2_dirent *dotdot = dot + 2;
struct ext2_dirent *dirent = dotdot + 2;
struct ext2_dirent *last = ((void *)dirent) + dirent_len;
/* Make sure we fit in one block group */
if (blocks > block_size * 8)
return 0;
if (filename_len > EXT2_NAME_LEN)
return 0;
if (data_offset)
*data_offset = file_block * block_size;
if (!dst)
goto out;
sblock->total_inodes = cpu_to_le32(inodes);
sblock->total_blocks = cpu_to_le32(blocks);
sblock->first_data_block = cpu_to_le32(super_block);
sblock->blocks_per_group = cpu_to_le32(blocks);
sblock->fragments_per_group = cpu_to_le32(blocks);
sblock->inodes_per_group = cpu_to_le32(inodes);
sblock->magic = cpu_to_le16(EXT2_MAGIC);
/* Done mostly so we can pretend to be (in)compatible */
sblock->revision_level = cpu_to_le32(EXT2_DYNAMIC_REV);
/* Not really accurate but it doesn't matter */
sblock->first_inode = cpu_to_le32(EXT2_GOOD_OLD_FIRST_INO);
sblock->inode_size = cpu_to_le32(inode_size);
sblock->feature_incompat = cpu_to_le32(EXT4_FEATURE_INCOMPAT_EXTENTS);
bg->block_id = cpu_to_le32(block_bitmap_block);
bg->inode_id = cpu_to_le32(inode_bitmap_block);
bg->inode_table_id = cpu_to_le32(inode_table_block);
/*
* All blocks/inodes are in-use. I don't want to have to deal with
* endianness, so just fill everything in.
*/
memset(dst + block_bitmap_block * block_size, 0xff, block_size * 2);
root_inode->mode = cpu_to_le16(S_IFDIR | 0755);
root_inode->size = cpu_to_le32(block_size);
root_inode->nlinks = cpu_to_le16(3);
root_inode->blockcnt = cpu_to_le32(1);
root_inode->flags = cpu_to_le32(EXT4_TOPDIR_FL);
root_inode->b.blocks.dir_blocks[0] = root_block;
file_inode->mode = cpu_to_le16(S_IFREG | 0644);
file_inode->size = cpu_to_le32(size);
file_inode->nlinks = cpu_to_le16(1);
file_inode->blockcnt = cpu_to_le32(file_blocks);
file_inode->flags = cpu_to_le32(EXT4_EXTENTS_FL);
ext_block->eh_magic = cpu_to_le16(EXT4_EXT_MAGIC);
ext_block->eh_entries = cpu_to_le16(1);
ext_block->eh_max = cpu_to_le16(sizeof(file_inode->b) /
sizeof(*ext_block) - 1);
extent->ee_len = cpu_to_le16(file_blocks);
extent->ee_start_lo = cpu_to_le16(file_block);
/* I'm not sure we need these, but it can't hurt */
dot->inode = cpu_to_le32(root_ino);
dot->direntlen = cpu_to_le16(2 * sizeof(*dot));
dot->namelen = 1;
dot->filetype = FILETYPE_DIRECTORY;
memcpy(dot + 1, ".", dot->namelen);
dotdot->inode = cpu_to_le32(root_ino);
dotdot->direntlen = cpu_to_le16(2 * sizeof(*dotdot));
dotdot->namelen = 2;
dotdot->filetype = FILETYPE_DIRECTORY;
memcpy(dotdot + 1, "..", dotdot->namelen);
dirent->inode = cpu_to_le32(file_ino);
dirent->direntlen = cpu_to_le16(dirent_len);
dirent->namelen = filename_len;
dirent->filetype = FILETYPE_REG;
memcpy(dirent + 1, filename, filename_len);
last->direntlen = block_size - dirent_len;
+out:
return (size_t)blocks * block_size;
+}
+/**
- create_fat() - Create a FAT32 filesystem with a single file
- @dst: The location of the new filesystem; MUST be zeroed
- @size: The size of the file
- @filename: The name of the file
- @data_offset: Filled with the offset of the file data from @dst
- Budget mkfs.fat. We use FAT32 (so I don't have to deal with FAT12) with no
- info sector, and a single one-sector FAT. This limits us to 64k of data
- (enough for anyone). The filename must fit in 8.3.
- If @dst is %NULL, nothing is copied.
- Return: The size of the filesystem in bytes
- */
+static size_t create_fat(void *dst, size_t size, const char *filename,
size_t *data_offset)
+{
u16 boot_sector = 0;
u16 fat_sector = 1;
u32 root_sector = 2;
u32 file_sector = 3;
u16 sector_size = 512;
u32 file_sectors = (size + sector_size - 1) / sector_size;
u32 sectors = file_sector + file_sectors;
char *ext;
size_t filename_len, ext_len;
int i;
struct boot_sector *bs = dst + boot_sector * sector_size;
struct volume_info *vi = (void *)(bs + 1);
__le32 *fat = dst + fat_sector * sector_size;
struct dir_entry *dirent = dst + root_sector * sector_size;
/* Make sure we fit in the FAT */
if (sectors > sector_size / sizeof(u32))
return 0;
ext = strchr(filename, '.');
if (ext) {
filename_len = ext - filename;
ext++;
ext_len = strlen(ext);
} else {
filename_len = strlen(filename);
ext_len = 0;
}
if (filename_len > 8 || ext_len > 3)
return 0;
if (data_offset)
*data_offset = file_sector * sector_size;
if (!dst)
goto out;
bs->sector_size[0] = sector_size & 0xff;
bs->sector_size[1] = sector_size >> 8;
bs->cluster_size = 1;
bs->reserved = cpu_to_le16(fat_sector);
bs->fats = 1;
bs->media = 0xf8;
bs->total_sect = cpu_to_le32(sectors);
bs->fat32_length = cpu_to_le32(1);
bs->root_cluster = cpu_to_le32(root_sector);
vi->ext_boot_sign = 0x29;
memcpy(vi->fs_type, FAT32_SIGN, sizeof(vi->fs_type));
memcpy(dst + 0x1fe, "\x55\xAA", 2);
fat[0] = cpu_to_le32(0x0ffffff8);
fat[1] = cpu_to_le32(0x0fffffff);
fat[2] = cpu_to_le32(0x0ffffff8);
for (i = file_sector; file_sectors > 1; file_sectors--, i++)
fat[i] = cpu_to_le32(i + 1);
fat[i] = cpu_to_le32(0x0ffffff8);
for (i = 0; i < sizeof(dirent->nameext.name); i++) {
if (i < filename_len)
dirent->nameext.name[i] = toupper(filename[i]);
else
dirent->nameext.name[i] = ' ';
}
for (i = 0; i < sizeof(dirent->nameext.ext); i++) {
if (i < ext_len)
dirent->nameext.ext[i] = toupper(ext[i]);
else
dirent->nameext.ext[i] = ' ';
}
dirent->start = cpu_to_le16(file_sector);
dirent->size = cpu_to_le32(size);
+out:
return sectors * sector_size;
+}
+typedef size_t (*create_fs_t)(void *, size_t, const char *, size_t *);
+static int spl_test_fs(struct unit_test_state *uts, const char *test_name,
create_fs_t create)
+{
const char *filename = CONFIG_SPL_FS_LOAD_PAYLOAD_NAME;
struct blk_desc *dev_desc;
char *data_write, *data_read;
void *fs;
size_t fs_size, fs_data, fs_blocks, data_size = SPL_TEST_DATA_SIZE;
loff_t actread;
fs_size = create(NULL, data_size, filename, &fs_data);
ut_assert(fs_size);
fs = calloc(fs_size, 1);
ut_assertnonnull(fs);
data_write = fs + fs_data;
generate_data(data_write, data_size, test_name);
ut_asserteq(fs_size, create(fs, data_size, filename, NULL));
dev_desc = blk_get_devnum_by_uclass_id(UCLASS_MMC, 0);
ut_assertnonnull(dev_desc);
ut_asserteq(512, dev_desc->blksz);
fs_blocks = fs_size / dev_desc->blksz;
ut_asserteq(fs_blocks, blk_dwrite(dev_desc, 0, fs_blocks, fs));
/* We have to use malloc so we can call virt_to_phys */
data_read = malloc_cache_aligned(data_size);
ut_assertnonnull(data_read);
ut_assertok(fs_set_blk_dev_with_part(dev_desc, 0));
ut_assertok(fs_read("/" CONFIG_SPL_FS_LOAD_PAYLOAD_NAME,
virt_to_phys(data_read), 0, data_size, &actread));
ut_asserteq(data_size, actread);
ut_asserteq_mem(data_write, data_read, data_size);
free(data_read);
free(fs);
return 0;
+}
+static int spl_test_ext(struct unit_test_state *uts) +{
return spl_test_fs(uts, __func__, create_ext2);
+} +SPL_TEST(spl_test_ext, DM_FLAGS);
+static int spl_test_fat(struct unit_test_state *uts) +{
return spl_test_fs(uts, __func__, create_fat);
+}
+SPL_TEST(spl_test_fat, DM_FLAGS);
2.37.1
Regards, Simon

Add a test for spl_blk_load_image, currently used only by NVMe. Because there is no sandbox NVMe driver, just use MMC instead. Avoid falling back to raw images to make failures more obvious.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
configs/sandbox_noinst_defconfig | 2 ++ test/image/Kconfig | 3 +- test/image/spl_load_fs.c | 62 ++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-)
diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig index 0a542cfb6aa..11be2dccf7d 100644 --- a/configs/sandbox_noinst_defconfig +++ b/configs/sandbox_noinst_defconfig @@ -34,6 +34,7 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_SPL_NO_BSS_LIMIT=y CONFIG_HANDOFF=y CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set CONFIG_SPL_LEGACY_IMAGE_FORMAT=y CONFIG_SPL_LOAD_IMX_CONTAINER=y CONFIG_SPL_SYS_MALLOC=y @@ -123,6 +124,7 @@ CONFIG_ADC=y CONFIG_ADC_SANDBOX=y CONFIG_AXI=y CONFIG_AXI_SANDBOX=y +CONFIG_SPL_BLK_FS=y CONFIG_SYS_IDE_MAXBUS=1 CONFIG_SYS_ATA_BASE_ADDR=0x100 CONFIG_SYS_ATA_STRIDE=4 diff --git a/test/image/Kconfig b/test/image/Kconfig index 963c86cc290..a52766b77d4 100644 --- a/test/image/Kconfig +++ b/test/image/Kconfig @@ -14,12 +14,13 @@ config SPL_UT_LOAD_FS bool "Unit tests for filesystems" depends on SANDBOX && SPL_OF_REAL depends on FS_LOADER + depends on SPL_BLK_FS depends on SPL_FS_FAT depends on SPL_FS_EXT4 depends on SPL_MMC_WRITE default y help - Test filesystems in SPL. + Test filesystems and the various load methods which use them.
config SPL_UT_LOAD_OS bool "Test loading from the host OS" diff --git a/test/image/spl_load_fs.c b/test/image/spl_load_fs.c index 8cd90b73518..45059f91999 100644 --- a/test/image/spl_load_fs.c +++ b/test/image/spl_load_fs.c @@ -10,6 +10,7 @@ #include <fat.h> #include <fs.h> #include <memalign.h> +#include <spl.h> #include <asm/io.h> #include <linux/stat.h> #include <test/spl.h> @@ -303,3 +304,64 @@ static int spl_test_fat(struct unit_test_state *uts) return spl_test_fs(uts, __func__, create_fat); } SPL_TEST(spl_test_fat, DM_FLAGS); + +static int spl_test_mmc_fs(struct unit_test_state *uts, const char *test_name, + enum spl_test_image type, create_fs_t create_fs) +{ + const char *filename = CONFIG_SPL_FS_LOAD_PAYLOAD_NAME; + struct blk_desc *dev_desc; + size_t fs_size, fs_data, img_size, img_data, + data_size = SPL_TEST_DATA_SIZE; + struct spl_image_info info_write = { + .name = test_name, + .size = data_size, + }, info_read = { }; + struct disk_partition part = { + .start = 1, + .sys_ind = 0x83, + }; + struct spl_boot_device bootdev = { }; + void *fs; + char *data; + + img_size = create_image(NULL, type, &info_write, &img_data); + ut_assert(img_size); + fs_size = create_fs(NULL, img_size, filename, &fs_data); + ut_assert(fs_size); + fs = calloc(fs_size, 1); + ut_assertnonnull(fs); + + data = fs + fs_data + img_data; + generate_data(data, data_size, test_name); + ut_asserteq(img_size, create_image(fs + fs_data, type, &info_write, + NULL)); + ut_asserteq(fs_size, create_fs(fs, img_size, filename, NULL)); + + dev_desc = blk_get_devnum_by_uclass_id(UCLASS_MMC, 0); + ut_assertnonnull(dev_desc); + + ut_asserteq(512, dev_desc->blksz); + part.size = fs_size / dev_desc->blksz; + ut_assertok(write_mbr_partitions(dev_desc, &part, 1, 0)); + ut_asserteq(part.size, blk_dwrite(dev_desc, part.start, part.size, fs)); + + ut_assertok(spl_blk_load_image(&info_read, &bootdev, UCLASS_MMC, 0, 1)); + if (check_image_info(uts, &info_write, &info_read)) + return CMD_RET_FAILURE; + ut_asserteq_mem(data, phys_to_virt(info_write.load_addr), data_size); + + free(fs); + return 0; +} + +static int spl_test_blk(struct unit_test_state *uts, const char *test_name, + enum spl_test_image type) +{ + if (spl_test_mmc_fs(uts, test_name, type, create_fat)) + return CMD_RET_FAILURE; + + return spl_test_mmc_fs(uts, test_name, type, create_ext2); +} +SPL_IMG_TEST(spl_test_blk, LEGACY, DM_FLAGS); +SPL_IMG_TEST(spl_test_blk, FIT_EXTERNAL, DM_FLAGS); +SPL_IMG_TEST(spl_test_blk, FIT_INTERNAL, DM_FLAGS);

On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
Add a test for spl_blk_load_image, currently used only by NVMe. Because there is no sandbox NVMe driver, just use MMC instead. Avoid falling back to raw images to make failures more obvious.
Signed-off-by: Sean Anderson seanga2@gmail.com
configs/sandbox_noinst_defconfig | 2 ++ test/image/Kconfig | 3 +- test/image/spl_load_fs.c | 62 ++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org

Add a test for the MMC load method. This shows the general shape of tests to come: The main test function calls do_spl_test_load with an appropriate callback to write the image to the medium.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
configs/sandbox_noinst_defconfig | 2 + include/spl.h | 4 ++ include/test/spl.h | 30 +++++++++++++++ test/image/Kconfig | 1 + test/image/spl_load.c | 36 +++++++++++++++++ test/image/spl_load_fs.c | 66 +++++++++++++++++++++++++++++--- 6 files changed, 134 insertions(+), 5 deletions(-)
diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig index 11be2dccf7d..4f16d9860d2 100644 --- a/configs/sandbox_noinst_defconfig +++ b/configs/sandbox_noinst_defconfig @@ -41,6 +41,8 @@ CONFIG_SPL_SYS_MALLOC=y CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0xa000000 CONFIG_SPL_SYS_MALLOC_SIZE=0x4000000 +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x0 CONFIG_SPL_ENV_SUPPORT=y CONFIG_SPL_FS_EXT4=y CONFIG_SPL_I2C=y diff --git a/include/spl.h b/include/spl.h index 7d30fb57dac..8229d40adab 100644 --- a/include/spl.h +++ b/include/spl.h @@ -673,6 +673,10 @@ static inline const char *spl_loader_name(const struct spl_image_loader *loader) } #endif
+#define SPL_LOAD_IMAGE_GET(_priority, _boot_device, _method) \ + ll_entry_get(struct spl_image_loader, \ + _boot_device ## _priority ## _method, spl_image_loader) + /* SPL FAT image functions */ int spl_load_image_fat(struct spl_image_info *spl_image, struct spl_boot_device *bootdev, diff --git a/include/test/spl.h b/include/test/spl.h index 7ae32a1020b..cfb52c90855 100644 --- a/include/test/spl.h +++ b/include/test/spl.h @@ -79,6 +79,36 @@ size_t create_image(void *dst, enum spl_test_image type, int check_image_info(struct unit_test_state *uts, struct spl_image_info *info1, struct spl_image_info *info2);
+/** + * typedef write_image_t - Callback for writing an image + * @uts: Current unit test state + * @img: Image to write + * @size: Size of @img + * + * Write @img to a location which will be read by a &struct spl_image_loader. + * + * Return: 0 on success or -1 on failure + */ +typedef int write_image_t(struct unit_test_state *its, void *img, size_t size); + +/** + * do_spl_test_load() - Test loading with an SPL image loader + * @uts: Current unit test state + * @test_name: Name of the current test + * @type: Type of image to try loading + * @loader: The loader to test + * @write_image: Callback to write the image to the backing storage + * + * Test @loader, performing the common tasks of setting up the image and + * checking it was loaded correctly. The caller must supply a @write_image + * callback to write the image to a location which will be read by @loader. + * + * Return: 0 on success or -1 on failure + */ +int do_spl_test_load(struct unit_test_state *uts, const char *test_name, + enum spl_test_image type, struct spl_image_loader *loader, + write_image_t write_image); + /** * image_supported() - Determine whether an image type is supported * @type: The image type to check diff --git a/test/image/Kconfig b/test/image/Kconfig index a52766b77d4..e6be1b829f3 100644 --- a/test/image/Kconfig +++ b/test/image/Kconfig @@ -18,6 +18,7 @@ config SPL_UT_LOAD_FS depends on SPL_FS_FAT depends on SPL_FS_EXT4 depends on SPL_MMC_WRITE + depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR default y help Test filesystems and the various load methods which use them. diff --git a/test/image/spl_load.c b/test/image/spl_load.c index 4338da417ce..06249044f9b 100644 --- a/test/image/spl_load.c +++ b/test/image/spl_load.c @@ -368,3 +368,39 @@ SPL_IMG_TEST(spl_test_image, LEGACY, 0); SPL_IMG_TEST(spl_test_image, IMX8, 0); SPL_IMG_TEST(spl_test_image, FIT_INTERNAL, 0); SPL_IMG_TEST(spl_test_image, FIT_EXTERNAL, 0); + +int do_spl_test_load(struct unit_test_state *uts, const char *test_name, + enum spl_test_image type, struct spl_image_loader *loader, + int (*write_image)(struct unit_test_state *, void *, size_t)) +{ + size_t img_size, img_data, plain_size = SPL_TEST_DATA_SIZE; + struct spl_image_info info_write = { + .name = test_name, + .size = plain_size, + }, info_read = { }; + struct spl_boot_device bootdev = { + .boot_device = loader->boot_device, + }; + char *plain; + void *img; + + img_size = create_image(NULL, type, &info_write, &img_data); + ut_assert(img_size); + img = calloc(img_size, 1); + ut_assertnonnull(img); + + plain = img + img_data; + generate_data(plain, plain_size, test_name); + ut_asserteq(img_size, create_image(img, type, &info_write, NULL)); + + if (write_image(uts, img, img_size)) + return CMD_RET_FAILURE; + + ut_assertok(loader->load_image(&info_read, &bootdev)); + if (check_image_info(uts, &info_write, &info_read)) + return CMD_RET_FAILURE; + ut_asserteq_mem(plain, phys_to_virt(info_write.load_addr), plain_size); + + free(img); + return 0; +} diff --git a/test/image/spl_load_fs.c b/test/image/spl_load_fs.c index 45059f91999..77a6956fb95 100644 --- a/test/image/spl_load_fs.c +++ b/test/image/spl_load_fs.c @@ -305,8 +305,16 @@ static int spl_test_fat(struct unit_test_state *uts) } SPL_TEST(spl_test_fat, DM_FLAGS);
+static bool spl_mmc_raw; + +u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device) +{ + return spl_mmc_raw ? MMCSD_MODE_RAW : MMCSD_MODE_FS; +} + static int spl_test_mmc_fs(struct unit_test_state *uts, const char *test_name, - enum spl_test_image type, create_fs_t create_fs) + enum spl_test_image type, create_fs_t create_fs, + bool blk_mode) { const char *filename = CONFIG_SPL_FS_LOAD_PAYLOAD_NAME; struct blk_desc *dev_desc; @@ -320,7 +328,11 @@ static int spl_test_mmc_fs(struct unit_test_state *uts, const char *test_name, .start = 1, .sys_ind = 0x83, }; - struct spl_boot_device bootdev = { }; + struct spl_image_loader *loader = + SPL_LOAD_IMAGE_GET(0, BOOT_DEVICE_MMC1, spl_mmc_load_image); + struct spl_boot_device bootdev = { + .boot_device = loader->boot_device, + }; void *fs; char *data;
@@ -345,7 +357,12 @@ static int spl_test_mmc_fs(struct unit_test_state *uts, const char *test_name, ut_assertok(write_mbr_partitions(dev_desc, &part, 1, 0)); ut_asserteq(part.size, blk_dwrite(dev_desc, part.start, part.size, fs));
- ut_assertok(spl_blk_load_image(&info_read, &bootdev, UCLASS_MMC, 0, 1)); + spl_mmc_raw = false; + if (blk_mode) + ut_assertok(spl_blk_load_image(&info_read, &bootdev, UCLASS_MMC, + 0, 1)); + else + ut_assertok(loader->load_image(&info_read, &bootdev)); if (check_image_info(uts, &info_write, &info_read)) return CMD_RET_FAILURE; ut_asserteq_mem(data, phys_to_virt(info_write.load_addr), data_size); @@ -357,11 +374,50 @@ static int spl_test_mmc_fs(struct unit_test_state *uts, const char *test_name, static int spl_test_blk(struct unit_test_state *uts, const char *test_name, enum spl_test_image type) { - if (spl_test_mmc_fs(uts, test_name, type, create_fat)) + if (spl_test_mmc_fs(uts, test_name, type, create_fat, true)) return CMD_RET_FAILURE;
- return spl_test_mmc_fs(uts, test_name, type, create_ext2); + return spl_test_mmc_fs(uts, test_name, type, create_ext2, true); } SPL_IMG_TEST(spl_test_blk, LEGACY, DM_FLAGS); SPL_IMG_TEST(spl_test_blk, FIT_EXTERNAL, DM_FLAGS); SPL_IMG_TEST(spl_test_blk, FIT_INTERNAL, DM_FLAGS); + +static int spl_test_mmc_write_image(struct unit_test_state *uts, void *img, + size_t img_size) +{ + struct blk_desc *dev_desc; + size_t img_blocks; + + dev_desc = blk_get_devnum_by_uclass_id(UCLASS_MMC, 0); + ut_assertnonnull(dev_desc); + + img_blocks = DIV_ROUND_UP(img_size, dev_desc->blksz); + ut_asserteq(img_blocks, blk_dwrite(dev_desc, + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR, + img_blocks, img)); + + spl_mmc_raw = true; + return 0; +} + +static int spl_test_mmc(struct unit_test_state *uts, const char *test_name, + enum spl_test_image type) +{ + if (type == LEGACY && + spl_test_mmc_fs(uts, test_name, type, create_ext2, false)) + return CMD_RET_FAILURE; + + if (type != IMX8 && + spl_test_mmc_fs(uts, test_name, type, create_fat, false)) + return CMD_RET_FAILURE; + + return do_spl_test_load(uts, test_name, type, + SPL_LOAD_IMAGE_GET(0, BOOT_DEVICE_MMC1, + spl_mmc_load_image), + spl_test_mmc_write_image); +} +SPL_IMG_TEST(spl_test_mmc, LEGACY, DM_FLAGS); +SPL_IMG_TEST(spl_test_mmc, IMX8, DM_FLAGS); +SPL_IMG_TEST(spl_test_mmc, FIT_EXTERNAL, DM_FLAGS); +SPL_IMG_TEST(spl_test_mmc, FIT_INTERNAL, DM_FLAGS);

Hi Sean,
On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
Add a test for the MMC load method. This shows the general shape of tests to come: The main test function calls do_spl_test_load with an appropriate callback to write the image to the medium.
Signed-off-by: Sean Anderson seanga2@gmail.com
configs/sandbox_noinst_defconfig | 2 + include/spl.h | 4 ++ include/test/spl.h | 30 +++++++++++++++ test/image/Kconfig | 1 + test/image/spl_load.c | 36 +++++++++++++++++ test/image/spl_load_fs.c | 66 +++++++++++++++++++++++++++++--- 6 files changed, 134 insertions(+), 5 deletions(-)
diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig index 11be2dccf7d..4f16d9860d2 100644 --- a/configs/sandbox_noinst_defconfig +++ b/configs/sandbox_noinst_defconfig @@ -41,6 +41,8 @@ CONFIG_SPL_SYS_MALLOC=y CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0xa000000 CONFIG_SPL_SYS_MALLOC_SIZE=0x4000000 +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x0 CONFIG_SPL_ENV_SUPPORT=y CONFIG_SPL_FS_EXT4=y CONFIG_SPL_I2C=y diff --git a/include/spl.h b/include/spl.h index 7d30fb57dac..8229d40adab 100644 --- a/include/spl.h +++ b/include/spl.h @@ -673,6 +673,10 @@ static inline const char *spl_loader_name(const struct spl_image_loader *loader) } #endif
+#define SPL_LOAD_IMAGE_GET(_priority, _boot_device, _method) \
ll_entry_get(struct spl_image_loader, \
_boot_device ## _priority ## _method, spl_image_loader)
/* SPL FAT image functions */ int spl_load_image_fat(struct spl_image_info *spl_image, struct spl_boot_device *bootdev, diff --git a/include/test/spl.h b/include/test/spl.h index 7ae32a1020b..cfb52c90855 100644 --- a/include/test/spl.h +++ b/include/test/spl.h @@ -79,6 +79,36 @@ size_t create_image(void *dst, enum spl_test_image type, int check_image_info(struct unit_test_state *uts, struct spl_image_info *info1, struct spl_image_info *info2);
+/**
- typedef write_image_t - Callback for writing an image
- @uts: Current unit test state
- @img: Image to write
- @size: Size of @img
- Write @img to a location which will be read by a &struct spl_image_loader.
- Return: 0 on success or -1 on failure
- */
+typedef int write_image_t(struct unit_test_state *its, void *img, size_t size);
+/**
- do_spl_test_load() - Test loading with an SPL image loader
- @uts: Current unit test state
- @test_name: Name of the current test
- @type: Type of image to try loading
- @loader: The loader to test
- @write_image: Callback to write the image to the backing storage
- Test @loader, performing the common tasks of setting up the image and
- checking it was loaded correctly. The caller must supply a @write_image
- callback to write the image to a location which will be read by @loader.
- Return: 0 on success or -1 on failure
Do you mean 1 ?
Reviewed-by: Simon Glass sjg@chromium.org

On 10/11/23 23:41, Simon Glass wrote:
Hi Sean,
On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
Add a test for the MMC load method. This shows the general shape of tests to come: The main test function calls do_spl_test_load with an appropriate callback to write the image to the medium.
Signed-off-by: Sean Anderson seanga2@gmail.com
configs/sandbox_noinst_defconfig | 2 + include/spl.h | 4 ++ include/test/spl.h | 30 +++++++++++++++ test/image/Kconfig | 1 + test/image/spl_load.c | 36 +++++++++++++++++ test/image/spl_load_fs.c | 66 +++++++++++++++++++++++++++++--- 6 files changed, 134 insertions(+), 5 deletions(-)
diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig index 11be2dccf7d..4f16d9860d2 100644 --- a/configs/sandbox_noinst_defconfig +++ b/configs/sandbox_noinst_defconfig @@ -41,6 +41,8 @@ CONFIG_SPL_SYS_MALLOC=y CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0xa000000 CONFIG_SPL_SYS_MALLOC_SIZE=0x4000000 +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x0 CONFIG_SPL_ENV_SUPPORT=y CONFIG_SPL_FS_EXT4=y CONFIG_SPL_I2C=y diff --git a/include/spl.h b/include/spl.h index 7d30fb57dac..8229d40adab 100644 --- a/include/spl.h +++ b/include/spl.h @@ -673,6 +673,10 @@ static inline const char *spl_loader_name(const struct spl_image_loader *loader) } #endif
+#define SPL_LOAD_IMAGE_GET(_priority, _boot_device, _method) \
ll_entry_get(struct spl_image_loader, \
_boot_device ## _priority ## _method, spl_image_loader)
- /* SPL FAT image functions */ int spl_load_image_fat(struct spl_image_info *spl_image, struct spl_boot_device *bootdev,
diff --git a/include/test/spl.h b/include/test/spl.h index 7ae32a1020b..cfb52c90855 100644 --- a/include/test/spl.h +++ b/include/test/spl.h @@ -79,6 +79,36 @@ size_t create_image(void *dst, enum spl_test_image type, int check_image_info(struct unit_test_state *uts, struct spl_image_info *info1, struct spl_image_info *info2);
+/**
- typedef write_image_t - Callback for writing an image
- @uts: Current unit test state
- @img: Image to write
- @size: Size of @img
- Write @img to a location which will be read by a &struct spl_image_loader.
- Return: 0 on success or -1 on failure
- */
+typedef int write_image_t(struct unit_test_state *its, void *img, size_t size);
+/**
- do_spl_test_load() - Test loading with an SPL image loader
- @uts: Current unit test state
- @test_name: Name of the current test
- @type: Type of image to try loading
- @loader: The loader to test
- @write_image: Callback to write the image to the backing storage
- Test @loader, performing the common tasks of setting up the image and
- checking it was loaded correctly. The caller must supply a @write_image
- callback to write the image to a location which will be read by @loader.
- Return: 0 on success or -1 on failure
Do you mean 1 ?
Reviewed-by: Simon Glass sjg@chromium.org
Huh... I guess I do.
--Sean

Add a test for loading U-Boot over TFTP. As with other sandbox net routines, we need to initialize our packets manually since things like net_set_ether and net_set_udp_header always use "our" addresses. We use BOOTP instead of DHCP, since DHCP has a tag/length-based format which is harder to parse. Our TFTP implementation doesn't define as many constants as I'd like, so I create some here. Note that the TFTP block size is one-based, but offsets are zero-based.
In order to avoid address errors, we need to set up/define some additional address information settings. dram_init_banksize would be a good candidate for settig up bi_dram, but it gets called too late in board_init_r.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
arch/sandbox/cpu/spl.c | 3 + arch/sandbox/include/asm/spl.h | 1 + configs/sandbox_noinst_defconfig | 6 +- test/image/Kconfig | 9 ++ test/image/Makefile | 1 + test/image/spl_load_net.c | 252 +++++++++++++++++++++++++++++++ 6 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 test/image/spl_load_net.c
diff --git a/arch/sandbox/cpu/spl.c b/arch/sandbox/cpu/spl.c index 09e3d10d6a5..8153df18d68 100644 --- a/arch/sandbox/cpu/spl.c +++ b/arch/sandbox/cpu/spl.c @@ -126,6 +126,9 @@ void spl_board_init(void) { struct sandbox_state *state = state_get_current();
+ gd->bd->bi_dram[0].start = gd->ram_base; + gd->bd->bi_dram[0].size = get_effective_memsize(); + if (state->run_unittests) { struct unit_test *tests = UNIT_TEST_ALL_START(); const int count = UNIT_TEST_ALL_COUNT(); diff --git a/arch/sandbox/include/asm/spl.h b/arch/sandbox/include/asm/spl.h index 2f8b5fcfcfe..ab9475567e0 100644 --- a/arch/sandbox/include/asm/spl.h +++ b/arch/sandbox/include/asm/spl.h @@ -12,6 +12,7 @@ enum { BOOT_DEVICE_MMC2_2, BOOT_DEVICE_BOARD, BOOT_DEVICE_VBE, + BOOT_DEVICE_CPGMAC, };
/** diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig index 4f16d9860d2..57cbadedb7d 100644 --- a/configs/sandbox_noinst_defconfig +++ b/configs/sandbox_noinst_defconfig @@ -12,7 +12,7 @@ CONFIG_SPL_DRIVERS_MISC=y CONFIG_SPL_SYS_MALLOC_F_LEN=0x8000 CONFIG_SPL=y CONFIG_SPL_FS_FAT=y -CONFIG_SYS_LOAD_ADDR=0x0 +CONFIG_SYS_LOAD_ADDR=0x1000000 CONFIG_PCI=y CONFIG_SANDBOX_SPL=y CONFIG_DEBUG_UART=y @@ -44,9 +44,11 @@ CONFIG_SPL_SYS_MALLOC_SIZE=0x4000000 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x0 CONFIG_SPL_ENV_SUPPORT=y +CONFIG_SPL_ETH=y CONFIG_SPL_FS_EXT4=y CONFIG_SPL_I2C=y CONFIG_SPL_MMC_WRITE=y +CONFIG_SPL_NET=y CONFIG_SPL_RTC=y CONFIG_CMD_CPU=y CONFIG_CMD_LICENSE=y @@ -109,6 +111,8 @@ CONFIG_ENV_IS_NOWHERE=y CONFIG_ENV_IS_IN_EXT4=y CONFIG_ENV_EXT4_INTERFACE="host" CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0" +CONFIG_USE_BOOTFILE=y +CONFIG_BOOTFILE="uImage" CONFIG_BOOTP_SEND_HOSTNAME=y CONFIG_NETCONSOLE=y CONFIG_IP_DEFRAG=y diff --git a/test/image/Kconfig b/test/image/Kconfig index e6be1b829f3..99c50787816 100644 --- a/test/image/Kconfig +++ b/test/image/Kconfig @@ -23,6 +23,15 @@ config SPL_UT_LOAD_FS help Test filesystems and the various load methods which use them.
+config SPL_UT_LOAD_NET + bool "Test loading over TFTP" + depends on SANDBOX && SPL_OF_REAL + depends on SPL_ETH + depends on USE_BOOTFILE + default y + help + Test loading images over TFTP using the NET image load method. + config SPL_UT_LOAD_OS bool "Test loading from the host OS" depends on SANDBOX && SPL_LOAD_FIT diff --git a/test/image/Makefile b/test/image/Makefile index 9427e69bd3b..ddbc39bf959 100644 --- a/test/image/Makefile +++ b/test/image/Makefile @@ -4,4 +4,5 @@
obj-$(CONFIG_SPL_UT_LOAD) += spl_load.o obj-$(CONFIG_SPL_UT_LOAD_FS) += spl_load_fs.o +obj-$(CONFIG_SPL_UT_LOAD_NET) += spl_load_net.o obj-$(CONFIG_SPL_UT_LOAD_OS) += spl_load_os.o diff --git a/test/image/spl_load_net.c b/test/image/spl_load_net.c new file mode 100644 index 00000000000..f570cef163f --- /dev/null +++ b/test/image/spl_load_net.c @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2023 Sean Anderson seanga2@gmail.com + */ + +#include <common.h> +#include <dm.h> +#include <spl.h> +#include <test/spl.h> +#include <asm/eth.h> +#include <test/ut.h> +#include "../../net/bootp.h" + +/* + * sandbox_eth_bootp_req_to_reply() + * + * Check if a BOOTP request was sent. If so, inject a reply + * + * returns 0 if injected, -EAGAIN if not + */ +static int sandbox_eth_bootp_req_to_reply(struct udevice *dev, void *packet, + unsigned int len) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct ethernet_hdr *eth = packet; + struct ip_udp_hdr *ip; + struct bootp_hdr *bp; + struct ethernet_hdr *eth_recv; + struct ip_udp_hdr *ipr; + struct bootp_hdr *bpr; + + if (ntohs(eth->et_protlen) != PROT_IP) + return -EAGAIN; + + ip = packet + ETHER_HDR_SIZE; + if (ip->ip_p != IPPROTO_UDP) + return -EAGAIN; + + if (ntohs(ip->udp_dst) != PORT_BOOTPS) + return -EAGAIN; + + bp = (void *)ip + IP_UDP_HDR_SIZE; + if (bp->bp_op != OP_BOOTREQUEST) + return -EAGAIN; + + /* Don't allow the buffer to overrun */ + if (priv->recv_packets >= PKTBUFSRX) + return 0; + + /* reply to the request */ + eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets]; + memcpy(eth_recv, packet, len); + ipr = (void *)eth_recv + ETHER_HDR_SIZE; + bpr = (void *)ipr + IP_UDP_HDR_SIZE; + memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN); + memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN); + ipr->ip_sum = 0; + ipr->ip_off = 0; + net_write_ip(&ipr->ip_dst, net_ip); + net_write_ip(&ipr->ip_src, priv->fake_host_ipaddr); + ipr->ip_sum = compute_ip_checksum(ipr, IP_HDR_SIZE); + ipr->udp_src = ip->udp_dst; + ipr->udp_dst = ip->udp_src; + + bpr->bp_op = OP_BOOTREPLY; + net_write_ip(&bpr->bp_yiaddr, net_ip); + net_write_ip(&bpr->bp_siaddr, priv->fake_host_ipaddr); + copy_filename(bpr->bp_file, CONFIG_BOOTFILE, sizeof(CONFIG_BOOTFILE)); + memset(&bpr->bp_vend, 0, sizeof(bpr->bp_vend)); + + priv->recv_packet_length[priv->recv_packets] = len; + ++priv->recv_packets; + + return 0; +} + +struct spl_test_net_priv { + struct unit_test_state *uts; + void *img; + size_t img_size; + u16 port; +}; + +/* Well known TFTP port # */ +#define TFTP_PORT 69 +/* Transaction ID, chosen at random */ +#define TFTP_TID 21313 + +/* + * TFTP operations. + */ +#define TFTP_RRQ 1 +#define TFTP_DATA 3 +#define TFTP_ACK 4 + +/* default TFTP block size */ +#define TFTP_BLOCK_SIZE 512 + +struct tftp_hdr { + u16 opcode; + u16 block; +}; + +#define TFTP_HDR_SIZE sizeof(struct tftp_hdr) + +/* + * sandbox_eth_tftp_req_to_reply() + * + * Check if a TFTP request was sent. If so, inject a reply. We don't support + * options, and we don't check for rollover, so we are limited files of less + * than 32M. + * + * returns 0 if injected, -EAGAIN if not + */ +static int sandbox_eth_tftp_req_to_reply(struct udevice *dev, void *packet, + unsigned int len) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct spl_test_net_priv *test_priv = priv->priv; + struct ethernet_hdr *eth = packet; + struct ip_udp_hdr *ip; + struct tftp_hdr *tftp; + struct ethernet_hdr *eth_recv; + struct ip_udp_hdr *ipr; + struct tftp_hdr *tftpr; + size_t size; + u16 block; + + if (ntohs(eth->et_protlen) != PROT_IP) + return -EAGAIN; + + ip = packet + ETHER_HDR_SIZE; + if (ip->ip_p != IPPROTO_UDP) + return -EAGAIN; + + if (ntohs(ip->udp_dst) == TFTP_PORT) { + tftp = (void *)ip + IP_UDP_HDR_SIZE; + if (htons(tftp->opcode) != TFTP_RRQ) + return -EAGAIN; + + block = 0; + } else if (ntohs(ip->udp_dst) == TFTP_TID) { + tftp = (void *)ip + IP_UDP_HDR_SIZE; + if (htons(tftp->opcode) != TFTP_ACK) + return -EAGAIN; + + block = htons(tftp->block); + } else { + return -EAGAIN; + } + + if (block * TFTP_BLOCK_SIZE > test_priv->img_size) + return 0; + + size = min(test_priv->img_size - block * TFTP_BLOCK_SIZE, + (size_t)TFTP_BLOCK_SIZE); + + /* Don't allow the buffer to overrun */ + if (priv->recv_packets >= PKTBUFSRX) + return 0; + + /* reply to the request */ + eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets]; + memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN); + memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN); + eth_recv->et_protlen = htons(PROT_IP); + + ipr = (void *)eth_recv + ETHER_HDR_SIZE; + ipr->ip_hl_v = 0x45; + ipr->ip_len = htons(IP_UDP_HDR_SIZE + TFTP_HDR_SIZE + size); + ipr->ip_off = htons(IP_FLAGS_DFRAG); + ipr->ip_ttl = 255; + ipr->ip_p = IPPROTO_UDP; + ipr->ip_sum = 0; + net_copy_ip(&ipr->ip_dst, &ip->ip_src); + net_copy_ip(&ipr->ip_src, &ip->ip_dst); + ipr->ip_sum = compute_ip_checksum(ipr, IP_HDR_SIZE); + + ipr->udp_src = htons(TFTP_TID); + ipr->udp_dst = ip->udp_src; + ipr->udp_len = htons(UDP_HDR_SIZE + TFTP_HDR_SIZE + size); + ipr->udp_xsum = 0; + + tftpr = (void *)ipr + IP_UDP_HDR_SIZE; + tftpr->opcode = htons(TFTP_DATA); + tftpr->block = htons(block + 1); + memcpy((void *)tftpr + TFTP_HDR_SIZE, + test_priv->img + block * TFTP_BLOCK_SIZE, size); + + priv->recv_packet_length[priv->recv_packets] = + ETHER_HDR_SIZE + IP_UDP_HDR_SIZE + TFTP_HDR_SIZE + size; + ++priv->recv_packets; + + return 0; +} + +static int spl_net_handler(struct udevice *dev, void *packet, + unsigned int len) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + int old_packets = priv->recv_packets; + + priv->fake_host_ipaddr = string_to_ip("1.1.2.4"); + net_ip = string_to_ip("1.1.2.2"); + + sandbox_eth_arp_req_to_reply(dev, packet, len); + sandbox_eth_bootp_req_to_reply(dev, packet, len); + sandbox_eth_tftp_req_to_reply(dev, packet, len); + + if (old_packets == priv->recv_packets) + return 0; + + return 0; +} + +static int spl_test_net_write_image(struct unit_test_state *uts, void *img, + size_t img_size) +{ + struct spl_test_net_priv *test_priv = malloc(sizeof(*test_priv)); + + ut_assertnonnull(test_priv); + test_priv->uts = uts; + test_priv->img = img; + test_priv->img_size = img_size; + + sandbox_eth_set_tx_handler(0, spl_net_handler); + sandbox_eth_set_priv(0, test_priv); + return 0; +} + +static int spl_test_net(struct unit_test_state *uts, const char *test_name, + enum spl_test_image type) +{ + struct eth_sandbox_priv *priv; + struct udevice *dev; + int ret; + + net_server_ip = string_to_ip("1.1.2.4"); + ret = do_spl_test_load(uts, test_name, type, + SPL_LOAD_IMAGE_GET(0, BOOT_DEVICE_CPGMAC, + spl_net_load_image_cpgmac), + spl_test_net_write_image); + + sandbox_eth_set_tx_handler(0, NULL); + ut_assertok(uclass_get_device(UCLASS_ETH, 0, &dev)); + priv = dev_get_priv(dev); + free(priv->priv); + return ret; +} +SPL_IMG_TEST(spl_test_net, LEGACY, DM_FLAGS); +SPL_IMG_TEST(spl_test_net, FIT_INTERNAL, DM_FLAGS); +SPL_IMG_TEST(spl_test_net, FIT_EXTERNAL, DM_FLAGS);

On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
Add a test for loading U-Boot over TFTP. As with other sandbox net routines, we need to initialize our packets manually since things like net_set_ether and net_set_udp_header always use "our" addresses. We use BOOTP instead of DHCP, since DHCP has a tag/length-based format which is harder to parse. Our TFTP implementation doesn't define as many constants as I'd like, so I create some here. Note that the TFTP block size is one-based, but offsets are zero-based.
In order to avoid address errors, we need to set up/define some additional address information settings. dram_init_banksize would be a good candidate for settig up bi_dram, but it gets called too late in board_init_r.
Signed-off-by: Sean Anderson seanga2@gmail.com
arch/sandbox/cpu/spl.c | 3 + arch/sandbox/include/asm/spl.h | 1 + configs/sandbox_noinst_defconfig | 6 +- test/image/Kconfig | 9 ++ test/image/Makefile | 1 + test/image/spl_load_net.c | 252 +++++++++++++++++++++++++++++++ 6 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 test/image/spl_load_net.c
Reviewed-by: Simon Glass sjg@chromium.org
diff --git a/arch/sandbox/cpu/spl.c b/arch/sandbox/cpu/spl.c index 09e3d10d6a5..8153df18d68 100644 --- a/arch/sandbox/cpu/spl.c +++ b/arch/sandbox/cpu/spl.c @@ -126,6 +126,9 @@ void spl_board_init(void) { struct sandbox_state *state = state_get_current();
gd->bd->bi_dram[0].start = gd->ram_base;
gd->bd->bi_dram[0].size = get_effective_memsize();
These could use a common as to why they are needed here.
[..]
Regards, Simon

On 10/11/23 23:41, Simon Glass wrote:
On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
Add a test for loading U-Boot over TFTP. As with other sandbox net routines, we need to initialize our packets manually since things like net_set_ether and net_set_udp_header always use "our" addresses. We use BOOTP instead of DHCP, since DHCP has a tag/length-based format which is harder to parse. Our TFTP implementation doesn't define as many constants as I'd like, so I create some here. Note that the TFTP block size is one-based, but offsets are zero-based.
In order to avoid address errors, we need to set up/define some additional address information settings. dram_init_banksize would be a good candidate for settig up bi_dram, but it gets called too late in board_init_r.
Signed-off-by: Sean Anderson seanga2@gmail.com
arch/sandbox/cpu/spl.c | 3 + arch/sandbox/include/asm/spl.h | 1 + configs/sandbox_noinst_defconfig | 6 +- test/image/Kconfig | 9 ++ test/image/Makefile | 1 + test/image/spl_load_net.c | 252 +++++++++++++++++++++++++++++++ 6 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 test/image/spl_load_net.c
Reviewed-by: Simon Glass sjg@chromium.org
diff --git a/arch/sandbox/cpu/spl.c b/arch/sandbox/cpu/spl.c index 09e3d10d6a5..8153df18d68 100644 --- a/arch/sandbox/cpu/spl.c +++ b/arch/sandbox/cpu/spl.c @@ -126,6 +126,9 @@ void spl_board_init(void) { struct sandbox_state *state = state_get_current();
gd->bd->bi_dram[0].start = gd->ram_base;
gd->bd->bi_dram[0].size = get_effective_memsize();
These could use a common as to why they are needed here.
OK.
--Sean

Add a test for the NOR load method. Since NOR is memory-mapped we can substitute a buffer instead. The only major complication is testing LZMA decompression. It's too complex to implement LZMA compression in a test, so we just include some pre-compressed data.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
arch/sandbox/include/asm/spl.h | 1 + configs/sandbox_noinst_defconfig | 2 + configs/sandbox_spl_defconfig | 2 + include/configs/sandbox.h | 3 + include/test/spl.h | 5 + test/image/Makefile | 1 + test/image/spl_load.c | 269 ++++++++++++++++++++++++++++++- test/image/spl_load_nor.c | 39 +++++ 8 files changed, 316 insertions(+), 6 deletions(-) create mode 100644 test/image/spl_load_nor.c
diff --git a/arch/sandbox/include/asm/spl.h b/arch/sandbox/include/asm/spl.h index ab9475567e0..cf16af5278a 100644 --- a/arch/sandbox/include/asm/spl.h +++ b/arch/sandbox/include/asm/spl.h @@ -13,6 +13,7 @@ enum { BOOT_DEVICE_BOARD, BOOT_DEVICE_VBE, BOOT_DEVICE_CPGMAC, + BOOT_DEVICE_NOR, };
/** diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig index 57cbadedb7d..085cc30c1e2 100644 --- a/configs/sandbox_noinst_defconfig +++ b/configs/sandbox_noinst_defconfig @@ -49,6 +49,7 @@ CONFIG_SPL_FS_EXT4=y CONFIG_SPL_I2C=y CONFIG_SPL_MMC_WRITE=y CONFIG_SPL_NET=y +CONFIG_SPL_NOR_SUPPORT=y CONFIG_SPL_RTC=y CONFIG_CMD_CPU=y CONFIG_CMD_LICENSE=y @@ -257,6 +258,7 @@ CONFIG_RSA_VERIFY_WITH_PKEY=y CONFIG_TPM=y CONFIG_LZ4=y CONFIG_ZSTD=y +CONFIG_SPL_LZMA=y CONFIG_ERRNO_STR=y CONFIG_EFI_CAPSULE_ON_DISK=y CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig index b578cc8e443..56072b15ad2 100644 --- a/configs/sandbox_spl_defconfig +++ b/configs/sandbox_spl_defconfig @@ -41,6 +41,7 @@ CONFIG_SPL_SYS_MALLOC_SIZE=0x4000000 CONFIG_SPL_ENV_SUPPORT=y CONFIG_SPL_FPGA=y CONFIG_SPL_I2C=y +CONFIG_SPL_NOR_SUPPORT=y CONFIG_SPL_RTC=y CONFIG_CMD_CPU=y CONFIG_CMD_LICENSE=y @@ -249,6 +250,7 @@ CONFIG_TPM=y CONFIG_SPL_CRC8=y CONFIG_LZ4=y CONFIG_ZSTD=y +CONFIG_SPL_LZMA=y CONFIG_ERRNO_STR=y CONFIG_SPL_HEXDUMP=y CONFIG_EFI_CAPSULE_ON_DISK=y diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index 4e5653dc886..2372485c84e 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -18,4 +18,7 @@ #define CFG_SYS_BAUDRATE_TABLE {4800, 9600, 19200, 38400, 57600,\ 115200}
+/* Unused but necessary to build */ +#define CFG_SYS_UBOOT_BASE CONFIG_TEXT_BASE + #endif diff --git a/include/test/spl.h b/include/test/spl.h index cfb52c90855..82325702d4a 100644 --- a/include/test/spl.h +++ b/include/test/spl.h @@ -27,12 +27,14 @@ void generate_data(char *data, size_t size, const char *test_name); /** * enum spl_test_image - Image types for testing * @LEGACY: "Legacy" uImages + * @LEGACY_LZMA: "Legacy" uImages, LZMA compressed * @IMX8: i.MX8 Container images * @FIT_INTERNAL: FITs with internal data * @FIT_EXTERNAL: FITs with external data */ enum spl_test_image { LEGACY, + LEGACY_LZMA, IMX8, FIT_INTERNAL, FIT_EXTERNAL, @@ -118,6 +120,9 @@ int do_spl_test_load(struct unit_test_state *uts, const char *test_name, static inline bool image_supported(enum spl_test_image type) { switch (type) { + case LEGACY_LZMA: + if (!IS_ENABLED(CONFIG_SPL_LZMA)) + return false; case LEGACY: return IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_FORMAT); case IMX8: diff --git a/test/image/Makefile b/test/image/Makefile index ddbc39bf959..41b29995993 100644 --- a/test/image/Makefile +++ b/test/image/Makefile @@ -5,4 +5,5 @@ obj-$(CONFIG_SPL_UT_LOAD) += spl_load.o obj-$(CONFIG_SPL_UT_LOAD_FS) += spl_load_fs.o obj-$(CONFIG_SPL_UT_LOAD_NET) += spl_load_net.o +obj-$(CONFIG_SPL_NOR_SUPPORT) += spl_load_nor.o obj-$(CONFIG_SPL_UT_LOAD_OS) += spl_load_os.o diff --git a/test/image/spl_load.c b/test/image/spl_load.c index 06249044f9b..3f69e652630 100644 --- a/test/image/spl_load.c +++ b/test/image/spl_load.c @@ -43,6 +43,7 @@ void *board_spl_fit_buffer_addr(ulong fit_size, int sectors, int bl_len)
/* Local flags for spl_image; start from the "top" to avoid conflicts */ #define SPL_IMX_CONTAINER 0x80000000 +#define SPL_COMP_LZMA 0x40000000
void generate_data(char *data, size_t size, const char *test_name) { @@ -79,7 +80,8 @@ static size_t create_legacy(void *dst, struct spl_image_info *spl_image, image_set_os(hdr, spl_image->os); image_set_arch(hdr, IH_ARCH_DEFAULT); image_set_type(hdr, IH_TYPE_FIRMWARE); - image_set_comp(hdr, IH_COMP_NONE); + image_set_comp(hdr, spl_image->flags & SPL_COMP_LZMA ? IH_COMP_LZMA : + IH_COMP_NONE); image_set_name(hdr, spl_image->name); image_set_hcrc(hdr, crc32(0, (void *)hdr, sizeof(*hdr)));
@@ -252,6 +254,8 @@ size_t create_image(void *dst, enum spl_test_image type, info->flags = 0;
switch (type) { + case LEGACY_LZMA: + info->flags = SPL_COMP_LZMA; case LEGACY: return create_legacy(dst, info, data_offset); case IMX8: @@ -296,7 +300,7 @@ int check_image_info(struct unit_test_state *uts, struct spl_image_info *info1, ut_asserteq(info1->load_addr, info2->load_addr); if (info1->flags & SPL_IMX_CONTAINER) ut_asserteq(0, info2->size); - else + else if (!(info1->flags & SPL_COMP_LZMA)) ut_asserteq(info1->size, info2->size); } else { ut_asserteq(info1->load_addr - sizeof(struct legacy_img_hdr), @@ -369,6 +373,246 @@ SPL_IMG_TEST(spl_test_image, IMX8, 0); SPL_IMG_TEST(spl_test_image, FIT_INTERNAL, 0); SPL_IMG_TEST(spl_test_image, FIT_EXTERNAL, 0);
+/* + * LZMA is too complex to generate on the fly, so let's use some data I put in + * the oven^H^H^H^H compressed earlier + */ +static const char lzma_compressed[] = { + 0x5d, 0x00, 0x00, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x02, 0x05, 0x55, 0x4e, 0x82, 0xbc, 0xc2, 0x42, 0xf6, 0x88, + 0x6c, 0x99, 0xd6, 0x82, 0x48, 0xa6, 0x06, 0x67, 0xf8, 0x46, 0x7c, 0xe9, + 0x41, 0x79, 0xfe, 0x90, 0x0b, 0x31, 0x7b, 0x79, 0x91, 0xb8, 0x5f, 0x33, + 0x11, 0x04, 0xc3, 0x4f, 0xf5, 0x71, 0xd1, 0xfb, 0x94, 0x6b, 0x5f, 0x78, + 0xe2, 0xfa, 0x6a, 0x21, 0xb6, 0x1d, 0x11, 0x0e, 0x5b, 0x56, 0x6a, 0x5b, + 0xe9, 0x56, 0x5f, 0x8b, 0x87, 0x61, 0x96, 0x6d, 0xce, 0x66, 0xbb, 0xb6, + 0xe7, 0x13, 0x5a, 0xd8, 0x84, 0x29, 0x60, 0xa0, 0x80, 0x43, 0xdd, 0x0f, + 0x4b, 0x85, 0xb0, 0x04, 0x9d, 0x9f, 0x28, 0x97, 0x0a, 0x1e, 0x16, 0xb0, + 0x45, 0x33, 0x5e, 0x79, 0x4f, 0xaa, 0xee, 0x79, 0x6e, 0xc3, 0x4e, 0x3d, + 0xe8, 0x67, 0x7c, 0xe0, 0xd0, 0xcc, 0x05, 0x40, 0xae, 0x6b, 0x97, 0x82, + 0x97, 0x02, 0x01, 0xe2, 0xe3, 0xbc, 0xe4, 0x9b, 0xb3, 0x28, 0xed, 0x5e, + 0x0d, 0x68, 0x6e, 0xe5, 0x17, 0x0a, 0x86, 0x5a, 0xcd, 0x8d, 0x46, 0x2d, + 0x06, 0x10, 0xa6, 0x90, 0x44, 0xa1, 0xfc, 0x66, 0x6d, 0x7c, 0x57, 0x57, + 0x07, 0xbc, 0x95, 0xb2, 0x8d, 0xf0, 0x9f, 0x4d, 0x90, 0x04, 0xaf, 0x0c, + 0x23, 0x51, 0x1b, 0x34, 0xd5, 0x5c, 0x5d, 0x87, 0x5e, 0x10, 0x2b, 0x71, + 0xc2, 0xcf, 0xc5, 0x9d, 0x4b, 0x89, 0x01, 0xc4, 0x97, 0xf2, 0xea, 0x83, + 0x97, 0xfa, 0xe0, 0x51, 0x96, 0x78, 0x4f, 0x44, 0xb8, 0xa8, 0x9d, 0x03, + 0x1c, 0x6e, 0xb7, 0xc6, 0xd7, 0xc5, 0x3e, 0x32, 0x65, 0xa7, 0x06, 0xab, + 0x86, 0xfb, 0xd2, 0x9b, 0xd7, 0x86, 0xa8, 0xfe, 0x46, 0x41, 0x2e, 0xc2, + 0x4e, 0xed, 0xa2, 0x9b, 0x79, 0x36, 0x37, 0x49, 0x90, 0xfc, 0xa6, 0x14, + 0x93, 0x17, 0x82, 0x62, 0x3f, 0x79, 0x6b, 0x86, 0xc2, 0xeb, 0x82, 0xfe, + 0x87, 0x49, 0xa5, 0x7e, 0x41, 0xe3, 0x59, 0x60, 0x15, 0x61, 0x4e, 0x3b, + 0x16, 0xcf, 0xdb, 0x49, 0x2c, 0x84, 0x92, 0x26, 0x40, 0x04, 0x78, 0xd3, + 0xd6, 0xa6, 0xed, 0x6e, 0x63, 0x49, 0xcb, 0xea, 0xfe, 0x43, 0x85, 0x21, + 0x1a, 0x28, 0x36, 0x0a, 0x3e, 0x2a, 0xad, 0xba, 0xfc, 0x8a, 0x37, 0x18, + 0xb4, 0x80, 0xbe, 0x6a, 0x36, 0x14, 0x03, 0xdd, 0xa3, 0x37, 0xbd, 0xc1, + 0x8a, 0xbb, 0x2d, 0xd4, 0x08, 0xd7, 0x4b, 0xc4, 0xe9, 0xb8, 0xb4, 0x65, + 0xdd, 0xf6, 0xe8, 0x17, 0x2c, 0x2c, 0x9b, 0x1e, 0x92, 0x0b, 0xcb, 0x22, + 0x7c, 0x1b, 0x74, 0x8d, 0x65, 0x11, 0x5f, 0xfe, 0xf5, 0x2a, 0xc2, 0xbe, + 0xea, 0xa2, 0xf1, 0x7b, 0xe8, 0xaf, 0x32, 0x5a, 0x0a, 0x5b, 0xd2, 0x5a, + 0x11, 0x22, 0x79, 0xfa, 0xae, 0x2d, 0xe8, 0xc6, 0x17, 0xba, 0x17, 0x81, + 0x6a, 0x63, 0xb5, 0x26, 0xd7, 0x8d, 0xd0, 0x66, 0x0c, 0x4a, 0x0c, 0x22, + 0x1b, 0x20, 0x9f, 0x3d, 0x0b, 0x1b, 0x59, 0x53, 0x89, 0x9b, 0x5e, 0xbd, + 0x3d, 0xd1, 0xdd, 0xff, 0xca, 0xb2, 0xb7, 0x12, 0x8d, 0x03, 0xaa, 0xc3, + 0x1d, 0x56, 0x76, 0x14, 0xf8, 0xee, 0xb3, 0xeb, 0x80, 0x38, 0xc1, 0xc1, + 0x1a, 0xef, 0x4a, 0xd5, 0x16, 0x1f, 0x5e, 0x21, 0x5d, 0x46, 0x01, 0xb3, + 0xa4, 0xf7, 0x99, 0x94, 0x05, 0xc6, 0xc8, 0x06, 0xd8, 0x1c, 0xac, 0x47, + 0x13, 0x54, 0x13, 0x1b, 0x1f, 0xb6, 0x23, 0x9c, 0x73, 0x2b, 0x57, 0x32, + 0x94, 0x92, 0xf1, 0x71, 0x44, 0x40, 0x02, 0xc3, 0x21, 0x4a, 0x2f, 0x36, + 0x5e, 0x8a, 0xd0, 0x4b, 0x02, 0xc7, 0x6e, 0xcf, 0xed, 0xa2, 0xdb, 0xce, + 0x0a, 0x0f, 0x66, 0x4f, 0xb2, 0x3d, 0xb6, 0xcc, 0x75, 0x45, 0x80, 0x0a, + 0x49, 0x4a, 0xe7, 0xe7, 0x24, 0x62, 0x65, 0xc7, 0x02, 0x22, 0x13, 0xbe, + 0x6c, 0xa9, 0x9a, 0x8b, 0xa9, 0x1b, 0x2b, 0x3a, 0xde, 0x5e, 0x37, 0xbd, + 0x7f, 0x85, 0xd1, 0x32, 0x1d, 0xbf, 0x03, 0x8a, 0x3b, 0xe5, 0xb3, 0xfd, + 0x01, 0xca, 0xde, 0x0d, 0x7a, 0x5b, 0x01, 0x05, 0x1d, 0x3c, 0x23, 0x00, + 0x60, 0xb7, 0x50, 0xfd, 0x0d, 0xd7, 0x63, 0x92, 0xd6, 0xb0, 0x48, 0x3a, + 0x2d, 0xa3, 0xf8, 0xf6, 0x44, 0xe1, 0xda, 0x3b, 0xf4, 0x39, 0x47, 0xc4, + 0x4d, 0x8f, 0x54, 0x78, 0xec, 0x27, 0x7b, 0xc6, 0xe4, 0x81, 0x3a, 0x3f, + 0xa5, 0x61, 0x9d, 0xcb, 0x71, 0x0b, 0x0d, 0x55, 0xea, 0x5b, 0xeb, 0x58, + 0xa5, 0x49, 0xb5, 0x44, 0x1b, 0xb0, 0x0d, 0x1f, 0x58, 0xfb, 0x7a, 0xd4, + 0x09, 0x1e, 0x9a, 0x7e, 0x21, 0xba, 0xb3, 0x36, 0xa6, 0x04, 0x74, 0xe1, + 0xd0, 0xca, 0x02, 0x11, 0x84, 0x93, 0x8f, 0x86, 0x3d, 0x79, 0xbf, 0xa8, + 0xec, 0x0a, 0x23, 0x5e, 0xde, 0xc4, 0xc6, 0xda, 0x45, 0xbd, 0x95, 0x74, + 0x7b, 0xbf, 0xc1, 0x80, 0x48, 0x3f, 0x10, 0xb6, 0xb9, 0x5c, 0x31, 0x52, + 0x06, 0x5a, 0xac, 0xec, 0x94, 0x21, 0x80, 0x51, 0xba, 0x64, 0xed, 0x9d, + 0x27, 0x72, 0x8d, 0x17, 0x43, 0x5f, 0xf1, 0x60, 0xfa, 0xb5, 0x65, 0xd4, + 0xb9, 0xf8, 0xfc, 0x48, 0x7b, 0xe3, 0xfe, 0xae, 0xe4, 0x71, 0x4a, 0x3d, + 0x8c, 0xf5, 0x72, 0x8b, 0xbf, 0x60, 0xd8, 0x6a, 0x8f, 0x51, 0x82, 0xae, + 0x98, 0xd0, 0x56, 0xf9, 0xa8, 0x3a, 0xad, 0x86, 0x26, 0xa8, 0x5a, 0xf8, + 0x63, 0x87, 0x2c, 0x74, 0xbf, 0xf9, 0x7d, 0x00, 0xa0, 0x2f, 0x17, 0x23, + 0xb7, 0x62, 0x94, 0x19, 0x47, 0x57, 0xf9, 0xa8, 0xe7, 0x4b, 0xe9, 0x2b, + 0xe8, 0xb4, 0x03, 0xbf, 0x23, 0x75, 0xfe, 0xc3, 0x94, 0xc0, 0xa9, 0x5b, + 0x07, 0xb5, 0x75, 0x87, 0xcc, 0xa5, 0xb5, 0x9b, 0x35, 0x29, 0xe4, 0xb1, + 0xaa, 0x04, 0x57, 0xe9, 0xa3, 0xd0, 0xa3, 0xe4, 0x11, 0xe1, 0xaa, 0x3b, + 0x67, 0x09, 0x60, 0x83, 0x23, 0x72, 0xa6, 0x7b, 0x73, 0x22, 0x5b, 0x4a, + 0xe0, 0xf0, 0xa3, 0xeb, 0x9c, 0x91, 0xda, 0xba, 0x8b, 0xc1, 0x32, 0xa9, + 0x24, 0x13, 0x51, 0xe4, 0x67, 0x49, 0x4a, 0xd9, 0x3d, 0xae, 0x80, 0xfd, + 0x0a, 0x0d, 0x56, 0x98, 0x66, 0xa2, 0x6d, 0x92, 0x54, 0x7f, 0x82, 0xe5, + 0x17, 0x39, 0xd3, 0xaa, 0xc4, 0x4e, 0x6f, 0xe1, 0x2e, 0xfe, 0x03, 0x44, + 0x8a, 0xdd, 0xeb, 0xc0, 0x74, 0x79, 0x63, 0x33, 0x2b, 0x4b, 0xb5, 0x62, + 0xdd, 0x47, 0xba, 0x6e, 0xfc, 0x91, 0x08, 0xa9, 0x17, 0x8c, 0x47, 0x61, + 0xd9, 0x32, 0xe9, 0xa0, 0xb3, 0xa2, 0x82, 0xc9, 0xa6, 0x32, 0xa1, 0xca, + 0x7c, 0x41, 0xa6, 0x5a, 0xe2, 0x46, 0xb6, 0x45, 0x53, 0x72, 0x55, 0x9e, + 0xdf, 0xac, 0x96, 0x68, 0xe5, 0xdc, 0x4e, 0x2d, 0xa8, 0x1e, 0x7a, 0x8e, + 0xff, 0x54, 0xe4, 0x0a, 0x33, 0x5d, 0x97, 0xdf, 0x4e, 0x36, 0x96, 0xba, + 0x52, 0xd9, 0xa9, 0xec, 0x52, 0xe5, 0x1d, 0x94, 0xfe, 0x1c, 0x46, 0x54, + 0xa6, 0x8e, 0x85, 0x47, 0xba, 0xeb, 0x4b, 0x8d, 0x57, 0xe4, 0x34, 0x24, + 0x9e, 0x80, 0xb5, 0xc9, 0xa9, 0x94, 0x1d, 0xe4, 0x18, 0xb6, 0x07, 0x1e, + 0xfa, 0xe0, 0x1c, 0x88, 0x06, 0x84, 0xaa, 0xcb, 0x5e, 0xfa, 0x15, 0x5a, + 0xdd, 0x10, 0x43, 0x81, 0xf2, 0x50, 0x3e, 0x93, 0x26, 0x77, 0x1c, 0x77, + 0xe9, 0x0c, 0xfc, 0x5f, 0xdd, 0x67, 0x31, 0x02, 0xc6, 0xdd, 0xf4, 0x30, + 0x76, 0x51, 0xce, 0x56, 0xba, 0x7f, 0x44, 0xbd, 0x42, 0x9f, 0x10, 0x8c, + 0x56, 0x49, 0x48, 0xa2, 0xcb, 0xc4, 0xdd, 0x29, 0xae, 0xf0, 0x33, 0x35, + 0x46, 0x69, 0x1d, 0xae, 0xde, 0xde, 0x98, 0x82, 0x79, 0xa6, 0x50, 0x28, + 0xb3, 0x5f, 0x10, 0x24, 0x63, 0xee, 0x9a, 0x22, 0xbe, 0xf8, 0x3a, 0xf4, + 0xab, 0x98, 0xfe, 0xdf, 0x30, 0x03, 0xe8, 0x45, 0x8c, 0xf4, 0x85, 0xc6, + 0x98, 0x7b, 0x35, 0xb8, 0x30, 0x9c, 0x15, 0xa6, 0x45, 0xbd, 0x39, 0x84, + 0xe7, 0x43, 0x4b, 0x05, 0xa4, 0x8f, 0x52, 0x8e, 0x4a, 0xe4, 0x87, 0xc1, + 0xdc, 0xdf, 0x25, 0x9c, 0x5c, 0x37, 0xd0, 0x66, 0x12, 0x41, 0x66, 0x8c, + 0x28, 0xd0, 0x3f, 0x5c, 0x7f, 0x15, 0x9b, 0xcf, 0xa0, 0xae, 0x29, 0x33, + 0xb0, 0xe4, 0xb7, 0x36, 0x2a, 0x45, 0x83, 0xff, 0x86, 0x75, 0xcf, 0xa7, + 0x4d, 0x5c, 0xa8, 0xcf, 0x3f, 0xf2, 0xc8, 0xde, 0xdd, 0xad, 0x42, 0x8f, + 0x0e, 0xd0, 0x11, 0x24, 0x42, 0x86, 0x51, 0x52, 0x76, 0x21, 0x68, 0xf1, + 0xa7, 0x8f, 0xdb, 0x5b, 0x78, 0xfa, 0x44, 0x5f, 0xee, 0x31, 0xda, 0x62, + 0x5f, 0xfe, 0x69, 0xae, 0x97, 0xc9, 0xb5, 0x04, 0x76, 0x79, 0x2e, 0xb9, + 0xd9, 0x1b, 0xdd, 0xb7, 0xc4, 0x12, 0x78, 0xb2, 0x4d, 0xab, 0xd2, 0x29, + 0x25, 0x8c, 0xd5, 0x52, 0x4a, 0xd7, 0x2e, 0x18, 0x9d, 0xa2, 0xee, 0x7b, + 0xa5, 0xe5, 0x35, 0x3c, 0xb5, 0x54, 0x1c, 0x7f, 0x87, 0x4b, 0xc0, 0xbb, + 0x1a, 0x85, 0x19, 0xc0, 0xa9, 0x2b, 0x4d, 0xed, 0x71, 0xc0, 0x15, 0xb3, + 0x49, 0x2c, 0x46, 0xfc, 0x37, 0x40, 0xc0, 0x60, 0xd0, 0x00, 0x96, 0xfa, + 0x7f, 0xbb, 0x30, 0x94, 0x6b, 0x81, 0x61, 0xc5, 0x13, 0x93, 0x95, 0xaa, + 0xf3, 0x8d, 0x1d, 0xac, 0xdb, 0xbd, 0xc3, 0x90, 0xf3, 0xd2, 0x5f, 0x3a, + 0x08, 0xb1, 0xc9, 0x3a, 0xe8, 0x25, 0x4d, 0x20, 0x2a, 0xe9, 0x4c, 0xaf, + 0x9b, 0x54, 0x7b, 0xaf, 0x89, 0x44, 0x3a, 0x60, 0x23, 0xd3, 0x02, 0xb1, + 0xb3, 0x9a, 0x3a, 0xb0, 0xa0, 0xdb, 0x61, 0x0b, 0xac, 0x55, 0xa1, 0x36, + 0x55, 0x5b, 0xc4, 0xc5, 0xbd, 0x2a, 0x16, 0xe9, 0xe7, 0x86, 0x7f, 0xdb, + 0xee, 0x90, 0xfa, 0xfd, 0x08, 0x7f, 0x1a, 0x43, 0xe0, 0xb8, 0x21, 0xb3, + 0xe3, 0xdf, 0x27, 0x56, 0x61, 0xc4, 0xe8, 0xd5, 0x60, 0xe9, 0x6d, 0x49, + 0xd9, 0xa8, 0xf5, 0xd9, 0xfc, 0x66, 0x82, 0xe9, 0x80, 0x5b, 0x85, 0x16, + 0x55, 0x2b, 0xef, 0x50, 0x90, 0x6c, 0x5d, 0x81, 0x00, 0x00, 0x88, 0x9b, + 0xb4, 0x62, 0x49, 0x46, 0x2e, 0x5d, 0x71, 0x95, 0xff, 0x63, 0xfb, 0x93, + 0x23, 0xf8, 0x9f, 0xa2, 0x55, 0x56, 0xd4, 0xd5, 0xf7, 0xae, 0xaf, 0xd3, + 0xf6, 0x82, 0xc8, 0xdd, 0x89, 0x0f, 0x7e, 0x89, 0x0d, 0x0d, 0x7f, 0x4f, + 0x84, 0xa7, 0x16, 0xe8, 0xaf, 0xf2, 0x95, 0xd7, 0xc3, 0x66, 0xd6, 0x85, + 0x5b, 0xa1, 0xbb, 0xea, 0x31, 0x02, 0xac, 0xa2, 0x7b, 0x50, 0xf4, 0x78, + 0x29, 0x49, 0x59, 0xf6, 0x41, 0x42, 0x52, 0xa8, 0x19, 0xfb, 0x3d, 0xda, + 0xa9, 0x8d, 0xac, 0xe1, 0x25, 0xd4, 0x12, 0x1e, 0x2b, 0x48, 0x44, 0xb0, + 0xf6, 0x29, 0xd0, 0x55, 0x22, 0xb4, 0xe7, 0xbc, 0x22, 0x97, 0x1f, 0xe2, + 0xe1, 0x73, 0x16, 0x13, 0x7a, 0x00, 0x62, 0x14, 0xcb, 0x25, 0x9b, 0x21, + 0x98, 0x9d, 0xb8, 0xd8, 0xf4, 0x65, 0xf6, 0x8f, 0x39, 0xe4, 0x76, 0xf7, + 0x30, 0xaf, 0xbc, 0x3a, 0xfe, 0x0e, 0xf1, 0x81, 0xa7, 0xff, 0x4d, 0xa7, + 0xff, 0xbf, 0x15, 0x60, 0x0b, 0xcd, 0x69, 0xd5, 0x77, 0xba, 0xcb, 0x7b, + 0x5a, 0xfb, 0x34, 0xc7, 0x5d, 0x13, 0x33, 0xd7, 0x86, 0x02, 0x43, 0x57, + 0x52, 0x2c, 0x74, 0x61, 0x21, 0xa3, 0x34, 0xf5, 0x89, 0x51, 0x44, 0x89, + 0xfc, 0xbb, 0x57, 0x5c, 0x6d, 0xb0, 0x2e, 0x8c, 0xff, 0x73, 0xe5, 0x09, + 0x13, 0x3b, 0x45, 0x5b, 0x27, 0x88, 0xee, 0x9b, 0xab, 0x57, 0x7c, 0x9b, + 0xb9, 0x78, 0x73, 0xd2, 0x2d, 0x98, 0x6f, 0xd2, 0x78, 0xb3, 0xeb, 0xaa, + 0x18, 0x44, 0x87, 0x6d, 0x51, 0x1e, 0x9b, 0x73, 0xaa, 0x91, 0x1a, 0x4f, + 0x69, 0x78, 0xef, 0x3f, 0xb1, 0x2d, 0x39, 0x3e, 0xda, 0x31, 0xfc, 0x99, + 0xf6, 0xa2, 0x8c, 0xe5, 0xfd, 0x97, 0x95, 0x77, 0x37, 0xef, 0xf5, 0xd1, + 0xc8, 0x74, 0x2c, 0x9a, 0x1f, 0x23, 0x8f, 0x72, 0x96, 0x3d, 0xb5, 0xad, + 0x28, 0xa0, 0x6c, 0x66, 0xe8, 0xee, 0xaa, 0x9d, 0xc2, 0x8a, 0x56, 0x54, + 0x89, 0x74, 0x56, 0xdc, 0x57, 0x49, 0xc3, 0x8e, 0xb9, 0x3a, 0x91, 0x34, + 0xc4, 0x5e, 0x0b, 0x13, 0x63, 0x5e, 0xeb, 0xc5, 0xef, 0xc7, 0xe9, 0x7f, + 0x27, 0xe8, 0xe7, 0xe5, 0x0d, 0x83, 0x95, 0x5f, 0x8a, 0xf2, 0xb2, 0x22, + 0x03, 0x8d, 0x71, 0x4f, 0x62, 0xb7, 0xf1, 0x87, 0xf5, 0x3f, 0xc4, 0x23, + 0x21, 0x40, 0x35, 0xcf, 0x79, 0x7a, 0x5b, 0x9d, 0x76, 0xb2, 0xdc, 0x6a, + 0xb5, 0x1d, 0x8b, 0xb6, 0x9a, 0x19, 0xe4, 0x87, 0xf5, 0xce, 0x38, 0xf3, + 0x70, 0xbf, 0x9e, 0x86, 0xa6, 0x07, 0x53, 0xdd, 0x5d, 0xc7, 0x72, 0x84, + 0x47, 0x38, 0xd0, 0xe2, 0xeb, 0x64, 0x4c, 0x3a, 0x1e, 0xf6, 0x56, 0x79, + 0x75, 0x75, 0x14, 0x5d, 0xe4, 0x1d, 0x9d, 0xbb, 0xe1, 0x35, 0x03, 0x5e, + 0x4f, 0x8f, 0xea, 0x95, 0xde, 0x19, 0x57, 0x98, 0xe9, 0x2c, 0x42, 0x22, + 0xcb, 0x0f, 0x15, 0x7a, 0x6b, 0x53, 0xc3, 0xec, 0xdc, 0xa0, 0x66, 0x26, + 0x91, 0x04, 0x83, 0x75, 0x09, 0x0c, 0x22, 0x05, 0xec, 0x3a, 0x2d, 0x39, + 0xea, 0x19, 0xf2, 0x1d, 0xdb, 0xba, 0x5c, 0x46, 0x47, 0xd4, 0x94, 0x6d, + 0x51, 0xdb, 0x68, 0xde, 0x0c, 0xa0, 0x36, 0x8f, 0xbc, 0xfd, 0x9b, 0x8f, + 0xfe, 0x04, 0x1f, 0xde, 0x1e, 0x77, 0xb5, 0x80, 0xb9, 0x9c, 0x1b, 0x24, + 0x61, 0xfc, 0x2b, 0xc0, 0x42, 0x2b, 0xc5, 0x90, 0x58, 0xa2, 0xb1, 0x38, + 0x58, 0xf2, 0x8b, 0x65, 0xbf, 0xe8, 0xe6, 0x79, 0xcf, 0x65, 0x35, 0xa5, + 0xe1, 0xb7, 0x8b, 0x95, 0x54, 0xd7, 0x1d, 0xf0, 0x91, 0x18, 0xc0, 0x5d, + 0x2c, 0xb5, 0xca, 0x1a, 0x7f, 0x8d, 0xfb, 0x9e, 0x57, 0x1c, 0x5c, 0xf0, + 0x94, 0x36, 0x51, 0x95, 0x27, 0x62, 0xca, 0x92, 0x96, 0xe5, 0x00, 0x2e, + 0xa4, 0x41, 0x97, 0xbf, 0x28, 0x3c, 0x6d, 0xc1, 0xb7, 0xe9, 0x1c, 0x2e, + 0x3e, 0xe0, 0x5e, 0x89, 0x0c, 0x78, 0x88, 0x80, 0xb8, 0x30, 0xd2, 0x22, + 0xf9, 0x71, 0xb4, 0xc8, 0xee, 0xe6, 0x80, 0x04, 0x04, 0x9a, 0xfb, 0x0c, + 0x36, 0xcb, 0xea, 0x66, 0xf9, 0x52, 0x8c, 0x66, 0xbf, 0x4c, 0x0f, 0xf4, + 0xf8, 0x1e, 0x7e, 0x39, 0x80, 0xe8, 0x82, 0x4b, 0x0e, 0x66, 0x1d, 0x51, + 0x16, 0xa9, 0x8d, 0xd6, 0xea, 0x33, 0xb0, 0x2c, 0x36, 0x25, 0xf5, 0x01, + 0x30, 0x7e, 0x03, 0x7f, 0xae, 0x8e, 0xd6, 0x25, 0x62, 0x6d, 0x99, 0x8c, + 0x1f, 0xc1, 0x22, 0xf0, 0x94, 0x80, 0xbf, 0x82, 0x51, 0xea, 0xc2, 0x5a, + 0x3c, 0x85, 0x2a, 0x5d, 0xbe, 0xae, 0xe1, 0xe3, 0x07, 0x92, 0xd2, 0x40, + 0x47, 0xe8, 0x0f, 0x1a, 0xa5, 0x73, 0x64, 0x26, 0xc4, 0xac, 0xca, 0xc2, + 0x83, 0x5a, 0x56, 0xbc, 0x81, 0x21, 0xcb, 0x72, 0xf3, 0xe7, 0x82, 0x1e, + 0xc8, 0x54, 0x18, 0x42, 0xfe, 0xd6, 0xfc, 0x96, 0x0e, 0x03, 0x29, 0x98, + 0x4f, 0xd1, 0xd2, 0x98, 0x7c, 0x9e, 0x4e, 0x1a, 0x0f, 0xd6, 0x4e, 0xa4, + 0x52, 0x1b, 0xd1, 0xd8, 0x36, 0xf7, 0x47, 0x5f, 0xce, 0xcb, 0x87, 0x36, + 0xc8, 0x9b, 0x44, 0xc6, 0x7a, 0xf3, 0x45, 0x28, 0xae, 0x96, 0x5a, 0x85, + 0x62, 0x8b, 0x10, 0xc2, 0x7b, 0x39, 0x51, 0xdf, 0xf4, 0x21, 0xc2, 0x6b, + 0x6f, 0x93, 0x27, 0xed, 0xf6, 0xea, 0xff, 0x2a, 0x21, 0x70, 0x84, 0x4e, + 0x21, 0xac, 0xbc, 0x06, 0x41, 0xd3, 0x59, 0xa0, 0xa1, 0x50, 0xa6, 0x87, + 0xa2, 0x48, 0xad, 0x94, 0x44, 0x8d, 0x2f, 0xa8, 0xc6, 0x10, 0xb5, 0xeb, + 0x66, 0x82, 0x94, 0x5f, 0xae, 0x6a, 0x56, 0xb4, 0x8d, 0xf4, 0x62, 0x80, + 0xe4, 0x42, 0xc4, 0xbc, 0xe7, 0xee, 0xa6, 0x96, 0x3b, 0xfd, 0xc0, 0x92, + 0x7d, 0xcd, 0xe7, 0x0c, 0x99, 0x9a, 0xb6, 0x83, 0xcf, 0x45, 0xe5, 0x74, + 0xb3, 0xbc, 0xc0, 0x40, 0xad, 0x4d, 0xfc, 0xa7, 0x92, 0x35, 0x13, 0x81, + 0x5c, 0x9c, 0x21, 0x00, 0xa4, 0x37, 0x07, 0x1d, 0x19, 0xfc, 0x88, 0x4d, + 0x71, 0x43, 0x7d, 0x94, 0xf7, 0x32, 0xb8, 0x4b, 0x8a, 0x54, 0xd6, 0xe4, + 0x37, 0x4f, 0x27, 0x1f, 0xfd, 0x45, 0x83, 0xb9, 0x14, 0x5a, 0xf7, 0x36, + 0xdc, 0x98, 0xad, 0x99, 0xb9, 0x38, 0x69, 0xac, 0x18, 0x7e, 0x47, 0xd0, + 0x63, 0x27, 0xba, 0xe7, 0xd5, 0x1d, 0x7b, 0x6e, 0xde, 0x28, 0x7b, 0xf1, + 0x84, 0x4d, 0x2d, 0x7c, 0x16, 0x38, 0x4b, 0x16, 0xa9, 0x10, 0x83, 0xfb, + 0xe0, 0xe0, 0x6f, 0xdd, 0x03, 0x0a, 0xb8, 0x81, 0xf5, 0x8c, 0x98, 0xc3, + 0xf4, 0xc8, 0x31, 0x3a, 0xed, 0x14, 0x83, 0x89, 0xc3, 0x0e, 0xf7, 0xba, + 0x84, 0xb0, 0x49, 0xdf, 0xc6, 0x6b, 0xed, 0xbe, 0xd4, 0xa3, 0x83, 0x3a, + 0xe6, 0x6d, 0xa3, 0x83, 0x17, 0x43, 0x5e, 0x3a, 0x83, 0xda, 0x81, 0xe3, + 0x26, 0x95, 0x6b, 0xe5, 0x30, 0x28, 0x6d, 0xec, 0xd7, 0xd7, 0x35, 0xfa, + 0x1a, 0xad, 0x86, 0x04, 0x05, 0x2c, 0x76, 0x3f, 0xb2, 0x83, 0x92, 0x4e, + 0xef, 0x05, 0xde, 0x13, 0x26, 0x68, 0x80, 0x57, 0xee, 0x92, 0x80, 0xa3, + 0x99, 0xb4, 0xac, 0x98, 0x31, 0xd4, 0xf3, 0xe2, 0x60, 0xd9, 0xb9, 0x8d, + 0x20, 0xf7, 0x97, 0x70, 0x10, 0xd6, 0xba, 0x86, 0xb8, 0x9c, 0xb8, 0xf8, + 0x49, 0x71, 0x28, 0x9d, 0x05, 0x38, 0x1f, 0x63, 0xba, 0xf7, 0x15, 0x60, + 0x96, 0x61, 0x84, 0x68, 0xeb, 0x5d, 0x28, 0x51, 0xe3, 0x51, 0xdd, 0x69, + 0x8a, 0xdd, 0xba, 0xec, 0xbd, 0xd3, 0xa1, 0x42, 0x83, 0x59, 0x77, 0x11, + 0x12, 0x86, 0x5b, 0x8d, 0x30, 0xcf, 0xdf, 0x6f, 0xea, 0x9d, 0x31, 0xa2, + 0x65, 0xa5, 0x61, 0xc0, 0xde, 0x52, 0x6c, 0x72, 0x71, 0x0b, 0x4c, 0x7a, + 0x4c, 0x9f, 0x75, 0x74, 0x38, 0xc8, 0xdd, 0x12, 0xba, 0x21, 0x57, 0x1b, + 0x45, 0xb3, 0x02, 0x1d, 0x67, 0x22, 0x66, 0x53, 0x18, 0x48, 0xed, 0x60, + 0x40, 0x55, 0xd1, 0x25, 0x3b, 0xbc, 0x08, 0x7b, 0x19, 0x8a, 0x30, 0x5b, + 0x02, 0x4f, 0x65, 0x42, 0xff, 0xce, 0x87, 0xe8, 0x97, 0x2b, 0xbb, 0xfe, + 0x52, 0x52, 0x72, 0xe8, 0xb5, 0x77, 0xb7, 0x8e, 0x94, 0x34, 0xbc, 0x46, + 0xf1, 0xe1, 0x94, 0x98, 0x19, 0xbe, 0x7c, 0x3f, 0xf6, 0x0e, 0xe4, 0xbb, + 0x88, 0x32, 0x07, 0x83, 0x64, 0xad, 0xd7, 0xd1, 0xe8, 0x35, 0x8d, 0x5d, + 0x70, 0x16, 0xc8, 0x11, 0x94, 0x39, 0xc9, 0xac, 0xd6, 0xed, 0x6b, 0xdf, + 0xc8, 0xf3, 0x1d, 0x5e, 0x37, 0xd8, 0xb5, 0x86, 0x9b, 0xc2, 0xdc, 0x3c, + 0x5c, 0x04, 0x52, 0x5c, 0x11, 0x88, 0x0a, 0x2b, 0x78, 0x48, 0x9e, 0x5e, + 0x98, 0x57, 0x5a, 0xd1, 0x77, 0x1c, 0x7d, 0x5f, 0x60, 0xbb, 0x61, 0x7e, + 0x7e, 0x2a, 0xaf, 0x44, 0x14, 0x88, 0xfc, 0xa5, 0x31, 0xb7, 0xd4, 0x44, + 0x48, 0xda, 0xb5, 0x71, 0xa8, 0xd8, 0x4f, 0x79, 0xcd, 0xe4, 0xbe, 0xb6, + 0x1a, 0x61, 0x74, 0x4b, 0xd8, 0xec, 0xd7, 0xbf, 0xad, 0x57, 0x00, 0x42, + 0x04, 0xe8, 0xb3, 0xec, 0x47, 0x1d, 0x2a, 0x0a, 0xde, 0x7c, 0x6e, 0x5e, + 0xf8, 0xaa, 0x44, 0x05, 0x10, 0xab, 0xe9, 0x4e, 0xd7, 0x44, 0x0b, 0x97, + 0x6f, 0x1a, 0xc1, 0x59, 0x2b, 0xe4, 0xe1, 0x8a, 0x13, 0x82, 0x65, 0xd8, + 0xae, 0x5f, 0x2b, 0xbc, 0xa6, 0x14, 0x39, 0xaf, 0x38, 0x41, 0x26, 0x74, + 0xdb, 0x55, 0x6b, 0xe2, 0x21, 0x80, 0x5d, 0x20, 0xc3, 0xf5, 0x82, 0xee, + 0xcc, 0x3c, 0xc9, 0xb4, 0xeb, 0x52, 0xe9, 0x13, 0x8a, 0xea, 0xc6, 0x19, + 0x70, 0x37, 0x1b, 0xb8, 0x2e, 0x86, 0xa2, 0xe9, 0x9d, 0xb6, 0xd5, 0xd6, + 0xf3, 0xa8, 0x31, 0xf3, 0x02, 0xaa, 0x10, 0x33, 0x3f, 0xba, 0xf8, 0xf9, + 0x46, 0x5b, 0xe1, 0xd7, 0x34, 0x9f, 0x94, 0xcb, 0xfb, 0xb1, 0x3d, 0x60, + 0x77, 0x85, 0x14, 0xd4, 0xcf, 0x55, 0x60, 0x5d, 0x47, 0x6c, 0x07, 0xb4, + 0xc7, 0x73, 0xbd, 0x49, 0xbd, 0xa5, 0x31, 0xa1, 0xfa, 0x34, 0x3a, 0x8b, + 0x77, 0x1b, 0xaa, 0xaf, 0xa5, 0x87, 0x12, 0x4e, 0x36, 0x06, 0x14, 0xe7, + 0xb3, 0xb8, 0x87, 0x6c, 0x4b, 0x50, 0xc9, 0x52, 0x1b, 0x19, 0x48, 0x69, + 0x5b, 0x7f, 0xd8, 0xc9, 0x14, 0xb8, 0x11, 0xa0, 0x51, 0x09, 0xbd, 0x42, + 0x5a, 0x50, 0x32, 0x57, 0x69, 0x39, 0x30, 0xdb, 0xbf, 0x8b, 0x93, 0x54, + 0x43, 0x80, 0x4e, 0xd0, 0xc6, 0xf2, 0x81, 0x15, 0x6d, 0xef, 0x5a, 0xb6, + 0x4d, 0x70, 0x93, 0x88, 0x8d, 0xce, 0x0d, 0xb8, 0xe9, 0xac, 0xa2, 0xcd, + 0xc7, 0x18, 0xa5, 0x95, 0xb7, 0xf6, 0x0c, 0x6f, 0xe1, 0x10, 0x7b, 0x22, + 0xf8, 0x81, 0x18, 0x42, 0x6a, 0x09, 0x75, 0x20, 0xb4, 0x2f, 0x67, 0x7a, + 0xda, 0x55, 0x28, 0xc3, 0x81, 0xf7, 0xc1, 0xf0, 0xe6, 0x1b, 0x29, 0x9c, + 0x72, 0x87, 0xe5, 0x4c, 0xa9, 0x5b, 0x5b, 0x62, 0xb5, 0xb7, 0x1e, 0x82, + 0xc3, 0x7b, 0xaf, 0xe9, 0x6f, 0x37, 0x31, 0x9f, 0x79, 0xe7, 0x4f, 0x06, + 0x1e, 0xff, 0xff, 0x80, 0x8e, 0x00, 0x00 +}; + int do_spl_test_load(struct unit_test_state *uts, const char *test_name, enum spl_test_image type, struct spl_image_loader *loader, int (*write_image)(struct unit_test_state *, void *, size_t)) @@ -376,12 +620,13 @@ int do_spl_test_load(struct unit_test_state *uts, const char *test_name, size_t img_size, img_data, plain_size = SPL_TEST_DATA_SIZE; struct spl_image_info info_write = { .name = test_name, - .size = plain_size, + .size = type == LEGACY_LZMA ? sizeof(lzma_compressed) : + plain_size, }, info_read = { }; struct spl_boot_device bootdev = { .boot_device = loader->boot_device, }; - char *plain; + char *data, *plain; void *img;
img_size = create_image(NULL, type, &info_write, &img_data); @@ -389,8 +634,16 @@ int do_spl_test_load(struct unit_test_state *uts, const char *test_name, img = calloc(img_size, 1); ut_assertnonnull(img);
- plain = img + img_data; - generate_data(plain, plain_size, test_name); + data = img + img_data; + if (type == LEGACY_LZMA) { + plain = malloc(plain_size); + ut_assertnonnull(plain); + generate_data(plain, plain_size, "lzma"); + memcpy(data, lzma_compressed, sizeof(lzma_compressed)); + } else { + plain = data; + generate_data(plain, plain_size, test_name); + } ut_asserteq(img_size, create_image(img, type, &info_write, NULL));
if (write_image(uts, img, img_size)) @@ -399,8 +652,12 @@ int do_spl_test_load(struct unit_test_state *uts, const char *test_name, ut_assertok(loader->load_image(&info_read, &bootdev)); if (check_image_info(uts, &info_write, &info_read)) return CMD_RET_FAILURE; + if (type == LEGACY_LZMA) + ut_asserteq(plain_size, info_read.size); ut_asserteq_mem(plain, phys_to_virt(info_write.load_addr), plain_size);
+ if (type == LEGACY_LZMA) + free(plain); free(img); return 0; } diff --git a/test/image/spl_load_nor.c b/test/image/spl_load_nor.c new file mode 100644 index 00000000000..a62bb60d253 --- /dev/null +++ b/test/image/spl_load_nor.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2023 Sean Anderson seanga2@gmail.com + */ + +#include <common.h> +#include <dm.h> +#include <spl.h> +#include <asm/io.h> +#include <test/spl.h> +#include <test/ut.h> + +static void *spl_test_nor_base; + +unsigned long spl_nor_get_uboot_base(void) +{ + return virt_to_phys(spl_test_nor_base); +} + +static int spl_test_nor_write_image(struct unit_test_state *uts, void *img, + size_t img_size) +{ + spl_test_nor_base = img; + return 0; +} + +static int spl_test_nor(struct unit_test_state *uts, const char *test_name, + enum spl_test_image type) +{ + return do_spl_test_load(uts, test_name, type, + SPL_LOAD_IMAGE_GET(0, BOOT_DEVICE_NOR, + spl_nor_load_image), + spl_test_nor_write_image); +} +SPL_IMG_TEST(spl_test_nor, LEGACY, 0); +SPL_IMG_TEST(spl_test_nor, LEGACY_LZMA, 0); +SPL_IMG_TEST(spl_test_nor, IMX8, 0); +SPL_IMG_TEST(spl_test_nor, FIT_INTERNAL, 0); +SPL_IMG_TEST(spl_test_nor, FIT_EXTERNAL, 0);

Hi Sean,
On Wed, 11 Oct 2023 at 18:57, Sean Anderson seanga2@gmail.com wrote:
Add a test for the NOR load method. Since NOR is memory-mapped we can substitute a buffer instead. The only major complication is testing LZMA decompression. It's too complex to implement LZMA compression in a test, so we just include some pre-compressed data.
How about using the in-tree compression code?
Signed-off-by: Sean Anderson seanga2@gmail.com
arch/sandbox/include/asm/spl.h | 1 + configs/sandbox_noinst_defconfig | 2 + configs/sandbox_spl_defconfig | 2 + include/configs/sandbox.h | 3 + include/test/spl.h | 5 + test/image/Makefile | 1 + test/image/spl_load.c | 269 ++++++++++++++++++++++++++++++- test/image/spl_load_nor.c | 39 +++++ 8 files changed, 316 insertions(+), 6 deletions(-) create mode 100644 test/image/spl_load_nor.c
Reviewed-by: Simon Glass sjg@chromium.org
diff --git a/arch/sandbox/include/asm/spl.h b/arch/sandbox/include/asm/spl.h index ab9475567e0..cf16af5278a 100644 --- a/arch/sandbox/include/asm/spl.h +++ b/arch/sandbox/include/asm/spl.h @@ -13,6 +13,7 @@ enum { BOOT_DEVICE_BOARD, BOOT_DEVICE_VBE, BOOT_DEVICE_CPGMAC,
BOOT_DEVICE_NOR,
};
/** diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig index 57cbadedb7d..085cc30c1e2 100644 --- a/configs/sandbox_noinst_defconfig +++ b/configs/sandbox_noinst_defconfig @@ -49,6 +49,7 @@ CONFIG_SPL_FS_EXT4=y CONFIG_SPL_I2C=y CONFIG_SPL_MMC_WRITE=y CONFIG_SPL_NET=y +CONFIG_SPL_NOR_SUPPORT=y CONFIG_SPL_RTC=y CONFIG_CMD_CPU=y CONFIG_CMD_LICENSE=y @@ -257,6 +258,7 @@ CONFIG_RSA_VERIFY_WITH_PKEY=y CONFIG_TPM=y CONFIG_LZ4=y CONFIG_ZSTD=y +CONFIG_SPL_LZMA=y CONFIG_ERRNO_STR=y CONFIG_EFI_CAPSULE_ON_DISK=y CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig index b578cc8e443..56072b15ad2 100644 --- a/configs/sandbox_spl_defconfig +++ b/configs/sandbox_spl_defconfig @@ -41,6 +41,7 @@ CONFIG_SPL_SYS_MALLOC_SIZE=0x4000000 CONFIG_SPL_ENV_SUPPORT=y CONFIG_SPL_FPGA=y CONFIG_SPL_I2C=y +CONFIG_SPL_NOR_SUPPORT=y CONFIG_SPL_RTC=y CONFIG_CMD_CPU=y CONFIG_CMD_LICENSE=y @@ -249,6 +250,7 @@ CONFIG_TPM=y CONFIG_SPL_CRC8=y CONFIG_LZ4=y CONFIG_ZSTD=y +CONFIG_SPL_LZMA=y CONFIG_ERRNO_STR=y CONFIG_SPL_HEXDUMP=y CONFIG_EFI_CAPSULE_ON_DISK=y diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index 4e5653dc886..2372485c84e 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -18,4 +18,7 @@ #define CFG_SYS_BAUDRATE_TABLE {4800, 9600, 19200, 38400, 57600,\ 115200}
+/* Unused but necessary to build */ +#define CFG_SYS_UBOOT_BASE CONFIG_TEXT_BASE
#endif diff --git a/include/test/spl.h b/include/test/spl.h index cfb52c90855..82325702d4a 100644 --- a/include/test/spl.h +++ b/include/test/spl.h @@ -27,12 +27,14 @@ void generate_data(char *data, size_t size, const char *test_name); /**
- enum spl_test_image - Image types for testing
- @LEGACY: "Legacy" uImages
*/
- @LEGACY_LZMA: "Legacy" uImages, LZMA compressed
- @IMX8: i.MX8 Container images
- @FIT_INTERNAL: FITs with internal data
- @FIT_EXTERNAL: FITs with external data
enum spl_test_image { LEGACY,
LEGACY_LZMA, IMX8, FIT_INTERNAL, FIT_EXTERNAL,
@@ -118,6 +120,9 @@ int do_spl_test_load(struct unit_test_state *uts, const char *test_name, static inline bool image_supported(enum spl_test_image type) { switch (type) {
case LEGACY_LZMA:
if (!IS_ENABLED(CONFIG_SPL_LZMA))
return false; case LEGACY: return IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_FORMAT); case IMX8:
diff --git a/test/image/Makefile b/test/image/Makefile index ddbc39bf959..41b29995993 100644 --- a/test/image/Makefile +++ b/test/image/Makefile @@ -5,4 +5,5 @@ obj-$(CONFIG_SPL_UT_LOAD) += spl_load.o obj-$(CONFIG_SPL_UT_LOAD_FS) += spl_load_fs.o obj-$(CONFIG_SPL_UT_LOAD_NET) += spl_load_net.o +obj-$(CONFIG_SPL_NOR_SUPPORT) += spl_load_nor.o obj-$(CONFIG_SPL_UT_LOAD_OS) += spl_load_os.o diff --git a/test/image/spl_load.c b/test/image/spl_load.c index 06249044f9b..3f69e652630 100644 --- a/test/image/spl_load.c +++ b/test/image/spl_load.c @@ -43,6 +43,7 @@ void *board_spl_fit_buffer_addr(ulong fit_size, int sectors, int bl_len)
/* Local flags for spl_image; start from the "top" to avoid conflicts */ #define SPL_IMX_CONTAINER 0x80000000 +#define SPL_COMP_LZMA 0x40000000
void generate_data(char *data, size_t size, const char *test_name) { @@ -79,7 +80,8 @@ static size_t create_legacy(void *dst, struct spl_image_info *spl_image, image_set_os(hdr, spl_image->os); image_set_arch(hdr, IH_ARCH_DEFAULT); image_set_type(hdr, IH_TYPE_FIRMWARE);
image_set_comp(hdr, IH_COMP_NONE);
image_set_comp(hdr, spl_image->flags & SPL_COMP_LZMA ? IH_COMP_LZMA :
IH_COMP_NONE); image_set_name(hdr, spl_image->name); image_set_hcrc(hdr, crc32(0, (void *)hdr, sizeof(*hdr)));
@@ -252,6 +254,8 @@ size_t create_image(void *dst, enum spl_test_image type, info->flags = 0;
switch (type) {
case LEGACY_LZMA:
info->flags = SPL_COMP_LZMA; case LEGACY: return create_legacy(dst, info, data_offset); case IMX8:
@@ -296,7 +300,7 @@ int check_image_info(struct unit_test_state *uts, struct spl_image_info *info1, ut_asserteq(info1->load_addr, info2->load_addr); if (info1->flags & SPL_IMX_CONTAINER) ut_asserteq(0, info2->size);
else
else if (!(info1->flags & SPL_COMP_LZMA)) ut_asserteq(info1->size, info2->size); } else { ut_asserteq(info1->load_addr - sizeof(struct legacy_img_hdr),
@@ -369,6 +373,246 @@ SPL_IMG_TEST(spl_test_image, IMX8, 0); SPL_IMG_TEST(spl_test_image, FIT_INTERNAL, 0); SPL_IMG_TEST(spl_test_image, FIT_EXTERNAL, 0);
+/*
- LZMA is too complex to generate on the fly, so let's use some data I put in
- the oven^H^H^H^H compressed earlier
How would one create this data?
- */
+static const char lzma_compressed[] = {
0x5d, 0x00, 0x00, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0x02, 0x05, 0x55, 0x4e, 0x82, 0xbc, 0xc2, 0x42, 0xf6, 0x88,
0x6c, 0x99, 0xd6, 0x82, 0x48, 0xa6, 0x06, 0x67, 0xf8, 0x46, 0x7c, 0xe9,
0x41, 0x79, 0xfe, 0x90, 0x0b, 0x31, 0x7b, 0x79, 0x91, 0xb8, 0x5f, 0x33,
0x11, 0x04, 0xc3, 0x4f, 0xf5, 0x71, 0xd1, 0xfb, 0x94, 0x6b, 0x5f, 0x78,
0xe2, 0xfa, 0x6a, 0x21, 0xb6, 0x1d, 0x11, 0x0e, 0x5b, 0x56, 0x6a, 0x5b,
0xe9, 0x56, 0x5f, 0x8b, 0x87, 0x61, 0x96, 0x6d, 0xce, 0x66, 0xbb, 0xb6,
[..]
Regards, Simon

On 10/11/23 23:41, Simon Glass wrote:
Hi Sean,
On Wed, 11 Oct 2023 at 18:57, Sean Anderson seanga2@gmail.com wrote:
Add a test for the NOR load method. Since NOR is memory-mapped we can substitute a buffer instead. The only major complication is testing LZMA decompression. It's too complex to implement LZMA compression in a test, so we just include some pre-compressed data.
How about using the in-tree compression code?
We have that for LZMA? From what I could tell we only have decompression in-tree.
Signed-off-by: Sean Anderson seanga2@gmail.com
arch/sandbox/include/asm/spl.h | 1 + configs/sandbox_noinst_defconfig | 2 + configs/sandbox_spl_defconfig | 2 + include/configs/sandbox.h | 3 + include/test/spl.h | 5 + test/image/Makefile | 1 + test/image/spl_load.c | 269 ++++++++++++++++++++++++++++++- test/image/spl_load_nor.c | 39 +++++ 8 files changed, 316 insertions(+), 6 deletions(-) create mode 100644 test/image/spl_load_nor.c
Reviewed-by: Simon Glass sjg@chromium.org
diff --git a/arch/sandbox/include/asm/spl.h b/arch/sandbox/include/asm/spl.h index ab9475567e0..cf16af5278a 100644 --- a/arch/sandbox/include/asm/spl.h +++ b/arch/sandbox/include/asm/spl.h @@ -13,6 +13,7 @@ enum { BOOT_DEVICE_BOARD, BOOT_DEVICE_VBE, BOOT_DEVICE_CPGMAC,
BOOT_DEVICE_NOR,
};
/**
diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig index 57cbadedb7d..085cc30c1e2 100644 --- a/configs/sandbox_noinst_defconfig +++ b/configs/sandbox_noinst_defconfig @@ -49,6 +49,7 @@ CONFIG_SPL_FS_EXT4=y CONFIG_SPL_I2C=y CONFIG_SPL_MMC_WRITE=y CONFIG_SPL_NET=y +CONFIG_SPL_NOR_SUPPORT=y CONFIG_SPL_RTC=y CONFIG_CMD_CPU=y CONFIG_CMD_LICENSE=y @@ -257,6 +258,7 @@ CONFIG_RSA_VERIFY_WITH_PKEY=y CONFIG_TPM=y CONFIG_LZ4=y CONFIG_ZSTD=y +CONFIG_SPL_LZMA=y CONFIG_ERRNO_STR=y CONFIG_EFI_CAPSULE_ON_DISK=y CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig index b578cc8e443..56072b15ad2 100644 --- a/configs/sandbox_spl_defconfig +++ b/configs/sandbox_spl_defconfig @@ -41,6 +41,7 @@ CONFIG_SPL_SYS_MALLOC_SIZE=0x4000000 CONFIG_SPL_ENV_SUPPORT=y CONFIG_SPL_FPGA=y CONFIG_SPL_I2C=y +CONFIG_SPL_NOR_SUPPORT=y CONFIG_SPL_RTC=y CONFIG_CMD_CPU=y CONFIG_CMD_LICENSE=y @@ -249,6 +250,7 @@ CONFIG_TPM=y CONFIG_SPL_CRC8=y CONFIG_LZ4=y CONFIG_ZSTD=y +CONFIG_SPL_LZMA=y CONFIG_ERRNO_STR=y CONFIG_SPL_HEXDUMP=y CONFIG_EFI_CAPSULE_ON_DISK=y diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index 4e5653dc886..2372485c84e 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -18,4 +18,7 @@ #define CFG_SYS_BAUDRATE_TABLE {4800, 9600, 19200, 38400, 57600,\ 115200}
+/* Unused but necessary to build */ +#define CFG_SYS_UBOOT_BASE CONFIG_TEXT_BASE
- #endif
diff --git a/include/test/spl.h b/include/test/spl.h index cfb52c90855..82325702d4a 100644 --- a/include/test/spl.h +++ b/include/test/spl.h @@ -27,12 +27,14 @@ void generate_data(char *data, size_t size, const char *test_name); /**
- enum spl_test_image - Image types for testing
- @LEGACY: "Legacy" uImages
*/ enum spl_test_image { LEGACY,
- @LEGACY_LZMA: "Legacy" uImages, LZMA compressed
- @IMX8: i.MX8 Container images
- @FIT_INTERNAL: FITs with internal data
- @FIT_EXTERNAL: FITs with external data
LEGACY_LZMA, IMX8, FIT_INTERNAL, FIT_EXTERNAL,
@@ -118,6 +120,9 @@ int do_spl_test_load(struct unit_test_state *uts, const char *test_name, static inline bool image_supported(enum spl_test_image type) { switch (type) {
case LEGACY_LZMA:
if (!IS_ENABLED(CONFIG_SPL_LZMA))
return false; case LEGACY: return IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_FORMAT); case IMX8:
diff --git a/test/image/Makefile b/test/image/Makefile index ddbc39bf959..41b29995993 100644 --- a/test/image/Makefile +++ b/test/image/Makefile @@ -5,4 +5,5 @@ obj-$(CONFIG_SPL_UT_LOAD) += spl_load.o obj-$(CONFIG_SPL_UT_LOAD_FS) += spl_load_fs.o obj-$(CONFIG_SPL_UT_LOAD_NET) += spl_load_net.o +obj-$(CONFIG_SPL_NOR_SUPPORT) += spl_load_nor.o obj-$(CONFIG_SPL_UT_LOAD_OS) += spl_load_os.o diff --git a/test/image/spl_load.c b/test/image/spl_load.c index 06249044f9b..3f69e652630 100644 --- a/test/image/spl_load.c +++ b/test/image/spl_load.c @@ -43,6 +43,7 @@ void *board_spl_fit_buffer_addr(ulong fit_size, int sectors, int bl_len)
/* Local flags for spl_image; start from the "top" to avoid conflicts */ #define SPL_IMX_CONTAINER 0x80000000 +#define SPL_COMP_LZMA 0x40000000
void generate_data(char *data, size_t size, const char *test_name) { @@ -79,7 +80,8 @@ static size_t create_legacy(void *dst, struct spl_image_info *spl_image, image_set_os(hdr, spl_image->os); image_set_arch(hdr, IH_ARCH_DEFAULT); image_set_type(hdr, IH_TYPE_FIRMWARE);
image_set_comp(hdr, IH_COMP_NONE);
image_set_comp(hdr, spl_image->flags & SPL_COMP_LZMA ? IH_COMP_LZMA :
IH_COMP_NONE); image_set_name(hdr, spl_image->name); image_set_hcrc(hdr, crc32(0, (void *)hdr, sizeof(*hdr)));
@@ -252,6 +254,8 @@ size_t create_image(void *dst, enum spl_test_image type, info->flags = 0;
switch (type) {
case LEGACY_LZMA:
info->flags = SPL_COMP_LZMA; case LEGACY: return create_legacy(dst, info, data_offset); case IMX8:
@@ -296,7 +300,7 @@ int check_image_info(struct unit_test_state *uts, struct spl_image_info *info1, ut_asserteq(info1->load_addr, info2->load_addr); if (info1->flags & SPL_IMX_CONTAINER) ut_asserteq(0, info2->size);
else
else if (!(info1->flags & SPL_COMP_LZMA)) ut_asserteq(info1->size, info2->size); } else { ut_asserteq(info1->load_addr - sizeof(struct legacy_img_hdr),
@@ -369,6 +373,246 @@ SPL_IMG_TEST(spl_test_image, IMX8, 0); SPL_IMG_TEST(spl_test_image, FIT_INTERNAL, 0); SPL_IMG_TEST(spl_test_image, FIT_EXTERNAL, 0);
+/*
- LZMA is too complex to generate on the fly, so let's use some data I put in
- the oven^H^H^H^H compressed earlier
How would one create this data?
Same as test/compression.c. I modified this test to hexdump the output of generate_data(plain, plain_size, "lzma") and then piped it to lzma. I massaged the output somewhat in vim (mostly to adjust the number of columns). You could probably script this, but it was a one-off thing.
--Sean
- */
+static const char lzma_compressed[] = {
0x5d, 0x00, 0x00, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0x02, 0x05, 0x55, 0x4e, 0x82, 0xbc, 0xc2, 0x42, 0xf6, 0x88,
0x6c, 0x99, 0xd6, 0x82, 0x48, 0xa6, 0x06, 0x67, 0xf8, 0x46, 0x7c, 0xe9,
0x41, 0x79, 0xfe, 0x90, 0x0b, 0x31, 0x7b, 0x79, 0x91, 0xb8, 0x5f, 0x33,
0x11, 0x04, 0xc3, 0x4f, 0xf5, 0x71, 0xd1, 0xfb, 0x94, 0x6b, 0x5f, 0x78,
0xe2, 0xfa, 0x6a, 0x21, 0xb6, 0x1d, 0x11, 0x0e, 0x5b, 0x56, 0x6a, 0x5b,
0xe9, 0x56, 0x5f, 0x8b, 0x87, 0x61, 0x96, 0x6d, 0xce, 0x66, 0xbb, 0xb6,
[..]
Regards, Simon

Hi Sean,
On Wed, 11 Oct 2023 at 21:16, Sean Anderson seanga2@gmail.com wrote:
On 10/11/23 23:41, Simon Glass wrote:
Hi Sean,
On Wed, 11 Oct 2023 at 18:57, Sean Anderson seanga2@gmail.com wrote:
Add a test for the NOR load method. Since NOR is memory-mapped we can substitute a buffer instead. The only major complication is testing LZMA decompression. It's too complex to implement LZMA compression in a test, so we just include some pre-compressed data.
How about using the in-tree compression code?
We have that for LZMA? From what I could tell we only have decompression in-tree.
Ah yes, OK.
Signed-off-by: Sean Anderson seanga2@gmail.com
arch/sandbox/include/asm/spl.h | 1 + configs/sandbox_noinst_defconfig | 2 + configs/sandbox_spl_defconfig | 2 + include/configs/sandbox.h | 3 + include/test/spl.h | 5 + test/image/Makefile | 1 + test/image/spl_load.c | 269 ++++++++++++++++++++++++++++++- test/image/spl_load_nor.c | 39 +++++ 8 files changed, 316 insertions(+), 6 deletions(-) create mode 100644 test/image/spl_load_nor.c
Reviewed-by: Simon Glass sjg@chromium.org
diff --git a/arch/sandbox/include/asm/spl.h b/arch/sandbox/include/asm/spl.h index ab9475567e0..cf16af5278a 100644 --- a/arch/sandbox/include/asm/spl.h +++ b/arch/sandbox/include/asm/spl.h @@ -13,6 +13,7 @@ enum { BOOT_DEVICE_BOARD, BOOT_DEVICE_VBE, BOOT_DEVICE_CPGMAC,
BOOT_DEVICE_NOR,
};
/**
diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig index 57cbadedb7d..085cc30c1e2 100644 --- a/configs/sandbox_noinst_defconfig +++ b/configs/sandbox_noinst_defconfig @@ -49,6 +49,7 @@ CONFIG_SPL_FS_EXT4=y CONFIG_SPL_I2C=y CONFIG_SPL_MMC_WRITE=y CONFIG_SPL_NET=y +CONFIG_SPL_NOR_SUPPORT=y CONFIG_SPL_RTC=y CONFIG_CMD_CPU=y CONFIG_CMD_LICENSE=y @@ -257,6 +258,7 @@ CONFIG_RSA_VERIFY_WITH_PKEY=y CONFIG_TPM=y CONFIG_LZ4=y CONFIG_ZSTD=y +CONFIG_SPL_LZMA=y CONFIG_ERRNO_STR=y CONFIG_EFI_CAPSULE_ON_DISK=y CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig index b578cc8e443..56072b15ad2 100644 --- a/configs/sandbox_spl_defconfig +++ b/configs/sandbox_spl_defconfig @@ -41,6 +41,7 @@ CONFIG_SPL_SYS_MALLOC_SIZE=0x4000000 CONFIG_SPL_ENV_SUPPORT=y CONFIG_SPL_FPGA=y CONFIG_SPL_I2C=y +CONFIG_SPL_NOR_SUPPORT=y CONFIG_SPL_RTC=y CONFIG_CMD_CPU=y CONFIG_CMD_LICENSE=y @@ -249,6 +250,7 @@ CONFIG_TPM=y CONFIG_SPL_CRC8=y CONFIG_LZ4=y CONFIG_ZSTD=y +CONFIG_SPL_LZMA=y CONFIG_ERRNO_STR=y CONFIG_SPL_HEXDUMP=y CONFIG_EFI_CAPSULE_ON_DISK=y diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index 4e5653dc886..2372485c84e 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -18,4 +18,7 @@ #define CFG_SYS_BAUDRATE_TABLE {4800, 9600, 19200, 38400, 57600,\ 115200}
+/* Unused but necessary to build */ +#define CFG_SYS_UBOOT_BASE CONFIG_TEXT_BASE
- #endif
diff --git a/include/test/spl.h b/include/test/spl.h index cfb52c90855..82325702d4a 100644 --- a/include/test/spl.h +++ b/include/test/spl.h @@ -27,12 +27,14 @@ void generate_data(char *data, size_t size, const char *test_name); /**
- enum spl_test_image - Image types for testing
- @LEGACY: "Legacy" uImages
*/ enum spl_test_image { LEGACY,
- @LEGACY_LZMA: "Legacy" uImages, LZMA compressed
- @IMX8: i.MX8 Container images
- @FIT_INTERNAL: FITs with internal data
- @FIT_EXTERNAL: FITs with external data
LEGACY_LZMA, IMX8, FIT_INTERNAL, FIT_EXTERNAL,
@@ -118,6 +120,9 @@ int do_spl_test_load(struct unit_test_state *uts, const char *test_name, static inline bool image_supported(enum spl_test_image type) { switch (type) {
case LEGACY_LZMA:
if (!IS_ENABLED(CONFIG_SPL_LZMA))
return false; case LEGACY: return IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_FORMAT); case IMX8:
diff --git a/test/image/Makefile b/test/image/Makefile index ddbc39bf959..41b29995993 100644 --- a/test/image/Makefile +++ b/test/image/Makefile @@ -5,4 +5,5 @@ obj-$(CONFIG_SPL_UT_LOAD) += spl_load.o obj-$(CONFIG_SPL_UT_LOAD_FS) += spl_load_fs.o obj-$(CONFIG_SPL_UT_LOAD_NET) += spl_load_net.o +obj-$(CONFIG_SPL_NOR_SUPPORT) += spl_load_nor.o obj-$(CONFIG_SPL_UT_LOAD_OS) += spl_load_os.o diff --git a/test/image/spl_load.c b/test/image/spl_load.c index 06249044f9b..3f69e652630 100644 --- a/test/image/spl_load.c +++ b/test/image/spl_load.c @@ -43,6 +43,7 @@ void *board_spl_fit_buffer_addr(ulong fit_size, int sectors, int bl_len)
/* Local flags for spl_image; start from the "top" to avoid conflicts */ #define SPL_IMX_CONTAINER 0x80000000 +#define SPL_COMP_LZMA 0x40000000
void generate_data(char *data, size_t size, const char *test_name) { @@ -79,7 +80,8 @@ static size_t create_legacy(void *dst, struct spl_image_info *spl_image, image_set_os(hdr, spl_image->os); image_set_arch(hdr, IH_ARCH_DEFAULT); image_set_type(hdr, IH_TYPE_FIRMWARE);
image_set_comp(hdr, IH_COMP_NONE);
image_set_comp(hdr, spl_image->flags & SPL_COMP_LZMA ? IH_COMP_LZMA :
IH_COMP_NONE); image_set_name(hdr, spl_image->name); image_set_hcrc(hdr, crc32(0, (void *)hdr, sizeof(*hdr)));
@@ -252,6 +254,8 @@ size_t create_image(void *dst, enum spl_test_image type, info->flags = 0;
switch (type) {
case LEGACY_LZMA:
info->flags = SPL_COMP_LZMA; case LEGACY: return create_legacy(dst, info, data_offset); case IMX8:
@@ -296,7 +300,7 @@ int check_image_info(struct unit_test_state *uts, struct spl_image_info *info1, ut_asserteq(info1->load_addr, info2->load_addr); if (info1->flags & SPL_IMX_CONTAINER) ut_asserteq(0, info2->size);
else
else if (!(info1->flags & SPL_COMP_LZMA)) ut_asserteq(info1->size, info2->size); } else { ut_asserteq(info1->load_addr - sizeof(struct legacy_img_hdr),
@@ -369,6 +373,246 @@ SPL_IMG_TEST(spl_test_image, IMX8, 0); SPL_IMG_TEST(spl_test_image, FIT_INTERNAL, 0); SPL_IMG_TEST(spl_test_image, FIT_EXTERNAL, 0);
+/*
- LZMA is too complex to generate on the fly, so let's use some data I put in
- the oven^H^H^H^H compressed earlier
How would one create this data?
Same as test/compression.c. I modified this test to hexdump the output of generate_data(plain, plain_size, "lzma") and then piped it to lzma. I massaged the output somewhat in vim (mostly to adjust the number of columns). You could probably script this, but it was a one-off thing.
OK thanks.
--Sean
- */
+static const char lzma_compressed[] = {
0x5d, 0x00, 0x00, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0x02, 0x05, 0x55, 0x4e, 0x82, 0xbc, 0xc2, 0x42, 0xf6, 0x88,
0x6c, 0x99, 0xd6, 0x82, 0x48, 0xa6, 0x06, 0x67, 0xf8, 0x46, 0x7c, 0xe9,
0x41, 0x79, 0xfe, 0x90, 0x0b, 0x31, 0x7b, 0x79, 0x91, 0xb8, 0x5f, 0x33,
0x11, 0x04, 0xc3, 0x4f, 0xf5, 0x71, 0xd1, 0xfb, 0x94, 0x6b, 0x5f, 0x78,
0xe2, 0xfa, 0x6a, 0x21, 0xb6, 0x1d, 0x11, 0x0e, 0x5b, 0x56, 0x6a, 0x5b,
0xe9, 0x56, 0x5f, 0x8b, 0x87, 0x61, 0x96, 0x6d, 0xce, 0x66, 0xbb, 0xb6,
[..]
Regards, Simon

Add test for the SPI load method. This one is pretty straightforward. We can't enable FIT_EXTERNAL with LOAD_FIT_FULL because spl_spi_load_image doesn't know the total image size and has to guess from fdt_totalsize. This doesn't include external data, so loading it will fail.
Signed-off-by: Sean Anderson seanga2@gmail.com ---
arch/sandbox/include/asm/spl.h | 1 + configs/sandbox_noinst_defconfig | 6 +++++ include/spl.h | 10 ++++++++ test/image/Kconfig | 8 +++++++ test/image/Makefile | 1 + test/image/spl_load.c | 1 + test/image/spl_load_spi.c | 41 ++++++++++++++++++++++++++++++++ test/py/tests/test_spl.py | 10 ++++++++ 8 files changed, 78 insertions(+) create mode 100644 test/image/spl_load_spi.c
diff --git a/arch/sandbox/include/asm/spl.h b/arch/sandbox/include/asm/spl.h index cf16af5278a..f349ea19971 100644 --- a/arch/sandbox/include/asm/spl.h +++ b/arch/sandbox/include/asm/spl.h @@ -14,6 +14,7 @@ enum { BOOT_DEVICE_VBE, BOOT_DEVICE_CPGMAC, BOOT_DEVICE_NOR, + BOOT_DEVICE_SPI, };
/** diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig index 085cc30c1e2..db05e630832 100644 --- a/configs/sandbox_noinst_defconfig +++ b/configs/sandbox_noinst_defconfig @@ -4,6 +4,7 @@ CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_NR_DRAM_BANKS=1 CONFIG_ENV_SIZE=0x2000 +CONFIG_SPL_DM_SPI=y CONFIG_DEFAULT_DEVICE_TREE="sandbox" CONFIG_DM_RESET=y CONFIG_SPL_MMC=y @@ -12,6 +13,8 @@ CONFIG_SPL_DRIVERS_MISC=y CONFIG_SPL_SYS_MALLOC_F_LEN=0x8000 CONFIG_SPL=y CONFIG_SPL_FS_FAT=y +CONFIG_SPL_SPI_FLASH_SUPPORT=y +CONFIG_SPL_SPI=y CONFIG_SYS_LOAD_ADDR=0x1000000 CONFIG_PCI=y CONFIG_SANDBOX_SPL=y @@ -48,9 +51,12 @@ CONFIG_SPL_ETH=y CONFIG_SPL_FS_EXT4=y CONFIG_SPL_I2C=y CONFIG_SPL_MMC_WRITE=y +CONFIG_SPL_DM_SPI_FLASH=y CONFIG_SPL_NET=y CONFIG_SPL_NOR_SUPPORT=y CONFIG_SPL_RTC=y +# CONFIG_SPL_SPI_FLASH_TINY is not set +CONFIG_SPL_SPI_LOAD=y CONFIG_CMD_CPU=y CONFIG_CMD_LICENSE=y CONFIG_CMD_BOOTZ=y diff --git a/include/spl.h b/include/spl.h index 8229d40adab..cc343ada1ec 100644 --- a/include/spl.h +++ b/include/spl.h @@ -416,6 +416,16 @@ int spl_load_imx_container(struct spl_image_info *spl_image, void preloader_console_init(void); u32 spl_boot_device(void);
+struct spi_flash; + +/** + * spl_spi_get_uboot_offs() - Lookup function for the SPI boot offset + * @flash: The spi flash to boot from + * + * Return: The offset of U-Boot within the SPI flash + */ +unsigned int spl_spi_get_uboot_offs(struct spi_flash *flash); + /** * spl_spi_boot_bus() - Lookup function for the SPI boot bus source. * diff --git a/test/image/Kconfig b/test/image/Kconfig index 99c50787816..8f9e6ae036b 100644 --- a/test/image/Kconfig +++ b/test/image/Kconfig @@ -32,6 +32,14 @@ config SPL_UT_LOAD_NET help Test loading images over TFTP using the NET image load method.
+config SPL_UT_LOAD_SPI + bool "Test loading from SPI Flash" + depends on SANDBOX && SPL_OF_REAL + depends on SPL_SPI_LOAD + default y + help + Test the SPI flash image load metod. + config SPL_UT_LOAD_OS bool "Test loading from the host OS" depends on SANDBOX && SPL_LOAD_FIT diff --git a/test/image/Makefile b/test/image/Makefile index 41b29995993..4cb4f96cedc 100644 --- a/test/image/Makefile +++ b/test/image/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_SPL_UT_LOAD_FS) += spl_load_fs.o obj-$(CONFIG_SPL_UT_LOAD_NET) += spl_load_net.o obj-$(CONFIG_SPL_NOR_SUPPORT) += spl_load_nor.o obj-$(CONFIG_SPL_UT_LOAD_OS) += spl_load_os.o +obj-$(CONFIG_SPL_UT_LOAD_SPI) += spl_load_spi.o diff --git a/test/image/spl_load.c b/test/image/spl_load.c index 3f69e652630..7df411edafd 100644 --- a/test/image/spl_load.c +++ b/test/image/spl_load.c @@ -10,6 +10,7 @@ #include <mapmem.h> #include <memalign.h> #include <rand.h> +#include <spi_flash.h> #include <spl.h> #include <test/spl.h> #include <test/ut.h> diff --git a/test/image/spl_load_spi.c b/test/image/spl_load_spi.c new file mode 100644 index 00000000000..8f9b6e0139b --- /dev/null +++ b/test/image/spl_load_spi.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2023 Sean Anderson seanga2@gmail.com + */ + +#include <common.h> +#include <dm.h> +#include <spi_flash.h> +#include <spl.h> +#include <test/spl.h> +#include <test/ut.h> + +static int spl_test_spi_write_image(struct unit_test_state *uts, void *img, + size_t img_size) +{ + struct spi_flash *flash; + + flash = spi_flash_probe(spl_spi_boot_bus(), spl_spi_boot_cs(), + CONFIG_SF_DEFAULT_SPEED, + CONFIG_SF_DEFAULT_MODE); + ut_assertnonnull(flash); + ut_assertok(spi_flash_write(flash, spl_spi_get_uboot_offs(flash), + img_size, img)); + + return 0; +} + +static int spl_test_spi(struct unit_test_state *uts, const char *test_name, + enum spl_test_image type) +{ + return do_spl_test_load(uts, test_name, type, + SPL_LOAD_IMAGE_GET(1, BOOT_DEVICE_SPI, + spl_spi_load_image), + spl_test_spi_write_image); +} +SPL_IMG_TEST(spl_test_spi, LEGACY, DM_FLAGS); +SPL_IMG_TEST(spl_test_spi, IMX8, DM_FLAGS); +SPL_IMG_TEST(spl_test_spi, FIT_INTERNAL, DM_FLAGS); +#if !IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL) +SPL_IMG_TEST(spl_test_spi, FIT_EXTERNAL, DM_FLAGS); +#endif diff --git a/test/py/tests/test_spl.py b/test/py/tests/test_spl.py index bd273dad893..42e4c4342b2 100644 --- a/test/py/tests/test_spl.py +++ b/test/py/tests/test_spl.py @@ -5,6 +5,16 @@ import os.path import pytest
+@pytest.mark.buildconfigspec('spl_unit_test') +def test_ut_spl_init(u_boot_console): + """Initialize data for ut spl tests.""" + + fn = u_boot_console.config.source_dir + '/spi.bin' + if not os.path.exists(fn): + data = b'\x00' * (2 * 1024 * 1024) + with open(fn, 'wb') as fh: + fh.write(data) + def test_spl(u_boot_console, ut_spl_subtest): """Execute a "ut" subtest.

On Wed, 11 Oct 2023 at 18:57, Sean Anderson seanga2@gmail.com wrote:
Add test for the SPI load method. This one is pretty straightforward. We can't enable FIT_EXTERNAL with LOAD_FIT_FULL because spl_spi_load_image doesn't know the total image size and has to guess from fdt_totalsize. This doesn't include external data, so loading it will fail.
Signed-off-by: Sean Anderson seanga2@gmail.com
arch/sandbox/include/asm/spl.h | 1 + configs/sandbox_noinst_defconfig | 6 +++++ include/spl.h | 10 ++++++++ test/image/Kconfig | 8 +++++++ test/image/Makefile | 1 + test/image/spl_load.c | 1 + test/image/spl_load_spi.c | 41 ++++++++++++++++++++++++++++++++ test/py/tests/test_spl.py | 10 ++++++++ 8 files changed, 78 insertions(+) create mode 100644 test/image/spl_load_spi.c
Reviewed-by: Simon Glass sjg@chromium.org

On 10/11/23 21:56, Sean Anderson wrote:
This series adds some tests for various SPL load methods, with the intent of helping debug v6 of [1]. With that in mind, notable omissions include NAND and ROMAPI, which both lack sandbox implementations, and OS_BOOT, which I have deferred due to its complexity. Semihosting is also omitted, but I think we can test that with qemu.
In order to test all of these methods, we must first generate suitable images, possibly on filesystems. While other tests have historically generated these images using external tools (e.g. mkimage, mkfs, etc.), I have chosen to generate them on the fly. This is for a few reasons:
- By removing external dependencies on pytest to create certain files, the tests become self-contained. This makes them easier to iterate on and debug.
- By generating tests at runtime, we can dynamically vary the content. This helps detect test failures, as even if tests are loaded to the same location, the expected content will be different.
- We are not testing the image parsers themselves (e.g. spl_load_simple_fit or fs_read) but rather the load methods (e.g. spl_mmc_load_image). It is unnecessary to exercise full functionality or generate 100% correct images.
- By reducing functionality to only what is necessary, the complexity of various formats can often be greatly reduced.
This series depends on [2-3], which are small fixes identified through this patch set. The organization of patches in this series is as follows:
- General fixes for bugs which are unlikely to be triggered outside of this series
- Changes to IMX8 container images to facilitate testing
- General prep. work, particularly regarding linker issues
- The tests themselves
Mostly-passing CI at [4]; I have since fixed the typo/missing cast.
CI run for the series as-sent:
https://source.denx.de/u-boot/custodians/u-boot-clk/-/pipelines/18092
(hopefully by the time you read this it will have passed)
--Sean

Hi Sean,
On Wed, 11 Oct 2023 at 18:56, Sean Anderson seanga2@gmail.com wrote:
This series adds some tests for various SPL load methods, with the intent of helping debug v6 of [1]. With that in mind, notable omissions include NAND and ROMAPI, which both lack sandbox implementations, and OS_BOOT, which I have deferred due to its complexity. Semihosting is also omitted, but I think we can test that with qemu.
In order to test all of these methods, we must first generate suitable images, possibly on filesystems. While other tests have historically generated these images using external tools (e.g. mkimage, mkfs, etc.), I have chosen to generate them on the fly. This is for a few reasons:
- By removing external dependencies on pytest to create certain files, the tests become self-contained. This makes them easier to iterate on and debug.
- By generating tests at runtime, we can dynamically vary the content. This helps detect test failures, as even if tests are loaded to the same location, the expected content will be different.
- We are not testing the image parsers themselves (e.g. spl_load_simple_fit or fs_read) but rather the load methods (e.g. spl_mmc_load_image). It is unnecessary to exercise full functionality or generate 100% correct images.
- By reducing functionality to only what is necessary, the complexity of various formats can often be greatly reduced.
This makes sense to me. Also the code to generate the images is relatively small.
This series depends on [2-3], which are small fixes identified through this patch set. The organization of patches in this series is as follows:
- General fixes for bugs which are unlikely to be triggered outside of this series
- Changes to IMX8 container images to facilitate testing
- General prep. work, particularly regarding linker issues
- The tests themselves
Mostly-passing CI at [4]; I have since fixed the typo/missing cast.
[1] https://lore.kernel.org/all/20230731224304.111081-1-sean.anderson@seco.com/ [2] https://lore.kernel.org/all/20230930204246.515254-1-seanga2@gmail.com/ [3] https://lore.kernel.org/all/20231008014748.1987840-1-seanga2@gmail.com/ [4] https://source.denx.de/u-boot/custodians/u-boot-clk/-/pipelines/18091
Sean Anderson (26): spl: legacy: Fix referencing _image_binary_end spl: nor: Don't allocate header on stack spl: fit: Fix entry point for SPL_LOAD_FIT_FULL arm: imx: Fix i.MX8 container load address arm: imx: Add newlines after error messages arm: imx: Add function to validate i.MX8 containers arm: imx: Check header before calling spl_load_imx_container Move i.MX8 container image loading support to common/spl spl: Allow enabling SPL_OF_REAL and SPL_OF_PLATDATA at the same time lib: acpi: Fix linking SPL when ACPIGEN is enabled fs: ext4: Fix building ext4 in SPL if write is enabled fs: Compile in sandbox filesystem in SPL if it is enabled net: Fix compiling SPL when fastboot is enabled net: bootp: Move port numbers to header net: bootp: Fall back to BOOTP from DHCP when unit testing spl: Don't cache devices when UNIT_TEST is enabled spl: Use map_sysmem where appropriate test: spl: Split tests up and use some configs test: spl: Fix spl_test_load not failing if fname doesn't exist test: spl: Add functions to create images test: spl: Add functions to create filesystems test: spl: Add a test for spl_blk_load_image test: spl: Add a test for the MMC load method test: spl: Add a test for the NET load method test: spl: Add a test for the NOR load method test: spl: Add a test for the SPI load method
Reviewed-by: Simon Glass sjg@chromium.org
Yeoman's work, that.
Regards, Simon
participants (6)
-
Heinrich Schuchardt
-
Michael Nazzareno Trimarchi
-
Sean Anderson
-
Simon Glass
-
Tom Rini
-
Xavier Drudis Ferran