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 <[email protected]>
---
 boot/bootm.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

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,
-- 
2.43.0

Reply via email to