imx: spl_imx_romapi: avoid tricky use of spl_load_simple_fit() to get full FIT size
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>
diff --git a/arch/arm/mach-imx/spl_imx_romapi.c b/arch/arm/mach-imx/spl_imx_romapi.c
index 4af4169..b9dfb3d 100644
--- a/arch/arm/mach-imx/spl_imx_romapi.c
+++ b/arch/arm/mach-imx/spl_imx_romapi.c
@@ -133,6 +133,41 @@
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 @@
}
}
+ 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;