[PATCH resend 0/2] imx: spl_imx_romapi: simplify stream loading

This is essentially a resend of something I sent four months ago [1]. The patches themselves are unchanged, but the commit log for 1/2 is updated to reflect the change wrt. IMX_HAB.
Moreover, while they were previously "merely" a simplification, they are now required for making usb loading with IMX_HAB actually work.
[1] https://lore.kernel.org/u-boot/20230523113651.292806-1-rasmus.villemoes@prev...
Rasmus Villemoes (2): imx: spl_imx_romapi: avoid tricky use of spl_load_simple_fit() to get full FIT size imx: spl_imx_romapi.c: remove dead code
arch/arm/mach-imx/spl_imx_romapi.c | 75 +++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 23 deletions(-)

Currently, spl_imx_romapi uses a somewhat tricky workaround for the fact that a FIT image with external data doesn't directly allow one to know the full size of the file: It does a dummy spl_load_simple_fit(), having the ->read callback remember the largest offset requested, and then does a last call to rom_api_download_image() to fetch the remaining part of the full FIT image.
We can avoid that by just keeping track of how much we have downloaded already, and if the ->read() requests something outside the current valid buffer, fetch up to the end of the current request.
The current method also suffers from not working when CONFIG_IMX_HAB is enabled: While in that case u-boot.itb is not built with external data, so the fdt header does contain the full size of the dtb structure. However, it does not account for the extra CONFIG_CSF_SIZE added by board_spl_fit_size_align(). And also, the data it hands out during the first dummy spl_load_simple_fit() is of course garbage, and wouldn't pass the verification.
So we really need to call spl_load_simple_fit() only once, let that figure out just how big the FIT image is (including whatever data, CSF or "ordinary" external data, has been tacked on beyond the fdt structure), and always provide valid data from the ->read callback.
This only affects the CONFIG_SPL_LOAD_FIT case - I don't have any hardware or experience with the CONFIG_SPL_LOAD_IMX_CONTAINER case, so I leave that alone for now.
Signed-off-by: Rasmus Villemoes rasmus.villemoes@prevas.dk --- arch/arm/mach-imx/spl_imx_romapi.c | 50 ++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+)
diff --git a/arch/arm/mach-imx/spl_imx_romapi.c b/arch/arm/mach-imx/spl_imx_romapi.c index 4af4169967..b9dfb3d41d 100644 --- a/arch/arm/mach-imx/spl_imx_romapi.c +++ b/arch/arm/mach-imx/spl_imx_romapi.c @@ -133,6 +133,41 @@ err: return -1; }
+struct stream_state { + u8 *base; + u8 *end; + u32 pagesize; +}; + +static ulong spl_romapi_read_stream(struct spl_load_info *load, ulong sector, + ulong count, void *buf) +{ + struct stream_state *ss = load->priv; + u8 *end = (u8*)(sector + count); + u32 bytes; + int ret; + + if (end > ss->end) { + bytes = end - ss->end; + bytes += ss->pagesize - 1; + bytes /= ss->pagesize; + bytes *= ss->pagesize; + + debug("downloading another 0x%x bytes\n", bytes); + ret = rom_api_download_image(ss->end, 0, bytes); + + if (ret != ROM_API_OKAY) { + printf("Failure download %d\n", bytes); + return 0; + } + + ss->end = end; + } + + memcpy(buf, (void *)(sector), count); + return count; +} + static ulong spl_ram_load_read(struct spl_load_info *load, ulong sector, ulong count, void *buf) { @@ -316,6 +351,21 @@ static int spl_romapi_load_image_stream(struct spl_image_info *spl_image, } }
+ if (IS_ENABLED(CONFIG_SPL_LOAD_FIT)) { + struct stream_state ss; + + ss.base = phdr; + ss.end = p; + ss.pagesize = pagesize; + + memset(&load, 0, sizeof(load)); + load.bl_len = 1; + load.read = spl_romapi_read_stream; + load.priv = &ss; + + return spl_load_simple_fit(spl_image, &load, (ulong)phdr, phdr); + } + total = img_total_size(phdr); total += 3; total &= ~0x3;

On Tue, Sep 19, 2023 at 10:49 AM Rasmus Villemoes rasmus.villemoes@prevas.dk wrote:
Currently, spl_imx_romapi uses a somewhat tricky workaround for the fact that a FIT image with external data doesn't directly allow one to know the full size of the file: It does a dummy spl_load_simple_fit(), having the ->read callback remember the largest offset requested, and then does a last call to rom_api_download_image() to fetch the remaining part of the full FIT image.
We can avoid that by just keeping track of how much we have downloaded already, and if the ->read() requests something outside the current valid buffer, fetch up to the end of the current request.
The current method also suffers from not working when CONFIG_IMX_HAB is enabled: While in that case u-boot.itb is not built with external data, so the fdt header does contain the full size of the dtb structure. However, it does not account for the extra CONFIG_CSF_SIZE added by board_spl_fit_size_align(). And also, the data it hands out during the first dummy spl_load_simple_fit() is of course garbage, and wouldn't pass the verification.
So we really need to call spl_load_simple_fit() only once, let that figure out just how big the FIT image is (including whatever data, CSF or "ordinary" external data, has been tacked on beyond the fdt structure), and always provide valid data from the ->read callback.
This only affects the CONFIG_SPL_LOAD_FIT case - I don't have any hardware or experience with the CONFIG_SPL_LOAD_IMX_CONTAINER case, so I leave that alone for now.
Signed-off-by: Rasmus Villemoes rasmus.villemoes@prevas.dk
Reviewed-by: Fabio Estevam festevam@denx.de

Currently, spl_imx_romapi uses a somewhat tricky workaround for the fact that a FIT image with external data doesn't directly allow one to know the full size of the file: It does a dummy spl_load_simple_fit(), having the ->read callback remember the largest offset requested, and then does a last call to rom_api_download_image() to fetch the remaining part of the full FIT image. We can avoid that by just keeping track of how much we have downloaded already, and if the ->read() requests something outside the current valid buffer, fetch up to the end of the current request. The current method also suffers from not working when CONFIG_IMX_HAB is enabled: While in that case u-boot.itb is not built with external data, so the fdt header does contain the full size of the dtb structure. However, it does not account for the extra CONFIG_CSF_SIZE added by board_spl_fit_size_align(). And also, the data it hands out during the first dummy spl_load_simple_fit() is of course garbage, and wouldn't pass the verification. So we really need to call spl_load_simple_fit() only once, let that figure out just how big the FIT image is (including whatever data, CSF or "ordinary" external data, has been tacked on beyond the fdt structure), and always provide valid data from the ->read callback. This only affects the CONFIG_SPL_LOAD_FIT case - I don't have any hardware or experience with the CONFIG_SPL_LOAD_IMX_CONTAINER case, so I leave that alone for now. Signed-off-by: Rasmus Villemoes rasmus.villemoes@prevas.dk Reviewed-by: Fabio Estevam festevam@denx.de
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

These IS_ENABLED(CONFIG_SPL_LOAD_FIT) cases can no longer be reached, and thus get_fit_image_size() is also redundant.
Signed-off-by: Rasmus Villemoes rasmus.villemoes@prevas.dk --- arch/arm/mach-imx/spl_imx_romapi.c | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-)
diff --git a/arch/arm/mach-imx/spl_imx_romapi.c b/arch/arm/mach-imx/spl_imx_romapi.c index b9dfb3d41d..c4a4185eed 100644 --- a/arch/arm/mach-imx/spl_imx_romapi.c +++ b/arch/arm/mach-imx/spl_imx_romapi.c @@ -184,23 +184,6 @@ static ulong spl_ram_load_read(struct spl_load_info *load, ulong sector, return count; }
-static ulong get_fit_image_size(void *fit) -{ - struct spl_image_info spl_image; - struct spl_load_info spl_load_info; - ulong last = (ulong)fit; - - memset(&spl_load_info, 0, sizeof(spl_load_info)); - spl_load_info.bl_len = 1; - spl_load_info.read = spl_ram_load_read; - spl_load_info.priv = &last; - - spl_load_simple_fit(&spl_image, &spl_load_info, - (uintptr_t)fit, fit); - - return last - (ulong)fit; -} - static u8 *search_fit_header(u8 *p, int size) { int i; @@ -261,9 +244,7 @@ static int img_info_size(void *img_hdr)
static int img_total_size(void *img_hdr) { - if (IS_ENABLED(CONFIG_SPL_LOAD_FIT)) { - return get_fit_image_size(img_hdr); - } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { int total = get_container_size((ulong)img_hdr, NULL);
if (total < 0) { @@ -386,9 +367,7 @@ static int spl_romapi_load_image_stream(struct spl_image_info *spl_image, load.bl_len = 1; load.read = spl_ram_load_read;
- if (IS_ENABLED(CONFIG_SPL_LOAD_FIT)) - return spl_load_simple_fit(spl_image, &load, (ulong)phdr, phdr); - else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) + if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) return spl_load_imx_container(spl_image, &load, (ulong)phdr);
return -1;

On Tue, Sep 19, 2023 at 10:49 AM Rasmus Villemoes rasmus.villemoes@prevas.dk wrote:
These IS_ENABLED(CONFIG_SPL_LOAD_FIT) cases can no longer be reached, and thus get_fit_image_size() is also redundant.
Signed-off-by: Rasmus Villemoes rasmus.villemoes@prevas.dk
Reviewed-by: Fabio Estevam festevam@denx.de

These IS_ENABLED(CONFIG_SPL_LOAD_FIT) cases can no longer be reached, and thus get_fit_image_size() is also redundant. Signed-off-by: Rasmus Villemoes rasmus.villemoes@prevas.dk Reviewed-by: Fabio Estevam festevam@denx.de
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic
participants (3)
-
Fabio Estevam
-
Rasmus Villemoes
-
sbabic@denx.de