
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, because the first call of spl_load_simple_fit() will have written garbage to the various locations, so the board_spl_fit_post_load() call panics. The downstream NXP kernel carries a workaround for this, but that workaround should not be necessary with this, since we only ever memcpy() valid image data.
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 830d5d12c2..e4e2297ac0 100644 --- a/arch/arm/mach-imx/spl_imx_romapi.c +++ b/arch/arm/mach-imx/spl_imx_romapi.c @@ -126,6 +126,41 @@ static int spl_romapi_load_image_seekable(struct spl_image_info *spl_image, return 0; }
+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) { @@ -309,6 +344,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;