summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAristo Chen <[email protected]>2026-08-18 13:23:19 +0000
committerTom Rini <[email protected]>2026-09-01 15:10:29 -0600
commita85d598be2a3f36f4dd5f0884e4b41fa40d75710 (patch)
tree9461136bb8509fbf6c19e6f90ebd0e7d1b2cf372
parent6b88aee1dd076e2e2091b47ac2fb9fc5f31a3353 (diff)
bootm: size the noload lz4 decompression buffer from Content_Size
Add a small static helper bootm_lz4_uncompressed_size() that parses the lz4 frame header and returns Content_Size when the FLG bit is set, and wire it into bootm_load_os() alongside gzip and zstd. The header parse mirrors ulz4fn()'s validation (magic, version==1, reserved bits, independent-block flag) so the helper does not accept a frame the decoder itself would reject. Only Content_Size is extracted; the full validation still runs inside ulz4fn() during the actual decompression call. The lz4 command needs the --content-size option to set the FLG bit that carries the size; frames produced without it fall back to the existing 8x heuristic. Signed-off-by: Aristo Chen <[email protected]>
-rw-r--r--boot/bootm.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/boot/bootm.c b/boot/bootm.c
index e4284fe9844..c5bdc909053 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -658,6 +658,36 @@ static ulong bootm_gzip_uncompressed_size(const void *src, ulong len)
}
#endif
+#if CONFIG_IS_ENABLED(LZ4)
+/*
+ * Return the lz4 frame's Content_Size, or 0 if the buffer is not an
+ * lz4 frame or the frame does not carry the size. The header parse
+ * mirrors ulz4fn()'s validation so we do not accept a stream the
+ * decoder itself would refuse.
+ */
+static ulong bootm_lz4_uncompressed_size(const void *src, ulong len)
+{
+ const u8 *b = src;
+ u8 flg, version, indep_blocks, has_content_size, bd;
+ u64 cs;
+
+ if (len < 4 + 2 || get_unaligned_le32(b) != LZ4F_MAGIC)
+ return 0;
+ flg = b[4];
+ bd = b[5];
+ version = (flg >> 6) & 3;
+ indep_blocks = (flg >> 5) & 1;
+ has_content_size = (flg >> 3) & 1;
+ if (version != 1 || !indep_blocks || (flg & 3) || (bd & 0x8f) ||
+ !has_content_size)
+ return 0;
+ if (len < 4 + 2 + 8)
+ return 0;
+ cs = get_unaligned_le64(b + 6);
+ return cs > ULONG_MAX ? 0 : (ulong)cs;
+}
+#endif
+
#if CONFIG_IS_ENABLED(ZSTD)
/*
* Return the zstd frame's Frame_Content_Size, or 0 if the header does
@@ -722,6 +752,12 @@ static int bootm_load_os(struct bootm_headers *images, int boot_progress)
image_len);
break;
#endif
+#if CONFIG_IS_ENABLED(LZ4)
+ case IH_COMP_LZ4:
+ hdr_size = bootm_lz4_uncompressed_size(image_buf,
+ image_len);
+ break;
+#endif
#if CONFIG_IS_ENABLED(ZSTD)
case IH_COMP_ZSTD:
hdr_size = bootm_zstd_uncompressed_size(image_buf,