summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAristo Chen <aristo.chen@canonical.com>2026-08-18 13:23:21 +0000
committerTom Rini <trini@konsulko.com>2026-08-18 14:36:57 -0600
commitb09cb251ab88a20efbb4b60806fb2479fcb207b0 (patch)
tree5f9d8efd3b89caa58ccb5f695a0d48932b545d81
parentf626ba24310c1c2edba80dc1ad945f1146cf4603 (diff)
downloadu-boot-b09cb251ab88a20efbb4b60806fb2479fcb207b0.tar.gz
u-boot-b09cb251ab88a20efbb4b60806fb2479fcb207b0.zip
bootm: size the noload lzma decompression buffer from the header
Add a small static helper bootm_lzma_uncompressed_size() that reads the uncompressed size out of the .lzma-alone header, and wire it into bootm_load_os() alongside gzip, lz4, and zstd. The .lzma-alone format keeps the uncompressed size in a fixed 8-byte field right after the 5-byte properties block; a marker of all ones means the size is unknown, and the caller falls back to the 8x heuristic in that case. Streaming encoders (xz-utils' 'lzma' shim, Python's lzma.FORMAT_ALONE) write the unknown marker, while LZMA SDK style encoders record the real size. Signed-off-by: Aristo Chen <aristo.chen@canonical.com>
-rw-r--r--boot/bootm.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/boot/bootm.c b/boot/bootm.c
index c5bdc909053..758edeb964c 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -26,6 +26,7 @@
#include <asm/unaligned.h>
#include <linux/sizes.h>
#include <linux/zstd.h>
+#include <lzma/LzmaDec.h>
#include <tpm-v2.h>
#include <tpm_tcg2.h>
#if defined(CONFIG_CMD_USB)
@@ -658,6 +659,28 @@ static ulong bootm_gzip_uncompressed_size(const void *src, ulong len)
}
#endif
+#if CONFIG_IS_ENABLED(LZMA)
+/*
+ * Return the uncompressed size recorded in the lzma stream header, or
+ * 0 if the buffer is too short or the size field carries the "unknown"
+ * marker (0xff..ff). The .lzma-alone format keeps the size in a fixed
+ * 8-byte field right after the 5-byte properties block; nothing else
+ * is validated since the value is only an allocation hint.
+ */
+static ulong bootm_lzma_uncompressed_size(const void *src, ulong len)
+{
+ const u8 *b = src;
+ u64 usize;
+
+ if (len < LZMA_PROPS_SIZE + 8)
+ return 0;
+ usize = get_unaligned_le64(b + LZMA_PROPS_SIZE);
+ if (usize == U64_MAX || usize > ULONG_MAX)
+ return 0;
+ return (ulong)usize;
+}
+#endif
+
#if CONFIG_IS_ENABLED(LZ4)
/*
* Return the lz4 frame's Content_Size, or 0 if the buffer is not an
@@ -752,6 +775,12 @@ static int bootm_load_os(struct bootm_headers *images, int boot_progress)
image_len);
break;
#endif
+#if CONFIG_IS_ENABLED(LZMA)
+ case IH_COMP_LZMA:
+ hdr_size = bootm_lzma_uncompressed_size(image_buf,
+ image_len);
+ break;
+#endif
#if CONFIG_IS_ENABLED(LZ4)
case IH_COMP_LZ4:
hdr_size = bootm_lz4_uncompressed_size(image_buf,