On Mon, 24 Nov 2025 at 12:22, Philippe Mathieu-Daudé <[email protected]> wrote:
>
> U-Boot is able to decompress Zstandard images since almost
> 6 years (u-boot commit 8509f22a).
>
> Signed-off-by: Philippe Mathieu-Daudé <[email protected]>
> ---
> Based-on: <[email protected]>
> ---
> hw/core/loader.c | 22 ++++++++++++++++++----
> 1 file changed, 18 insertions(+), 4 deletions(-)
>
> diff --git a/hw/core/loader.c b/hw/core/loader.c
> index e5904cdafa1..97fa8248ce7 100644
> --- a/hw/core/loader.c
> +++ b/hw/core/loader.c
> @@ -635,7 +635,7 @@ static ssize_t load_uboot_image(const char *filename,
> hwaddr *ep,
> uboot_image_header_t *hdr = &h;
> uint8_t *data = NULL;
> int ret = -1;
> - int do_uncompress = 0;
> + bool do_uncompress = false;
>
> fd = open(filename, O_RDONLY | O_BINARY);
> if (fd < 0)
> @@ -685,7 +685,8 @@ static ssize_t load_uboot_image(const char *filename,
> hwaddr *ep,
> case IH_COMP_NONE:
> break;
> case IH_COMP_GZIP:
> - do_uncompress = 1;
> + case IH_COMP_ZSTD:
> + do_uncompress = true;
> break;
Here we set do_uncompress whether QEMU was built with
CONFIG_ZSTD or not...
> default:
> fprintf(stderr,
> @@ -747,10 +748,23 @@ static ssize_t load_uboot_image(const char *filename,
> hwaddr *ep,
> max_bytes = UBOOT_MAX_GUNZIP_BYTES;
> data = g_malloc(max_bytes);
>
> - bytes = gunzip(data, max_bytes, compressed_data, hdr->ih_size);
> + switch (hdr->ih_comp) {
> + case IH_COMP_GZIP:
> + bytes = gunzip(data, max_bytes, compressed_data, hdr->ih_size);
> + break;
> +#ifdef CONFIG_ZSTD
> + case IH_COMP_ZSTD: {
> + size_t ret = ZSTD_decompress(data, max_bytes,
> + compressed_data, hdr->ih_size);
> + bytes = ZSTD_isError(ret) ? -1 : (ssize_t) ret;
> + } break;
> +#endif
...so here if the user passes a ZSTD image to a QEMU
built without CONFIG_ZSTD I think we fall into the default
case and assert.
I think the neatest fix for this would be to have the
switch (hdr->ih_comp) that sets do_uncompress to have
an ifdef for CONFIG_ZSTD so that we can tell the user
"couldn't load this image because QEMU was compiled without
zstd support".
PS: do we need to cast ret to a ssize_t ? bytes is
already a ssize_t variable.
thanks
-- PMM