For a compressed kernel_noload image, bootm_load_os() allocates a
per-image decompression buffer of ALIGN(image_len * 8, SZ_1M) rather
than the global CONFIG_SYS_BOOTM_LEN. When decompression fails on that
path, handle_decomp_error() still prints

    Image too large: increase CONFIG_SYS_BOOTM_LEN

which is misleading: increasing CONFIG_SYS_BOOTM_LEN does not help
because the smaller per-image buffer is the actual bound. Commit
2ff26c1e378d ("bootm: fix overflow of the noload kernel decompression
buffer") worked around this by printing a follow-up note right after
handle_decomp_error() returned, but the boot log then reads as two
contradictory sentences.

Introduce enum bootm_decomp_limit and pass it into
handle_decomp_error() so the helper picks the right message in one
place. For the noload path it now prints

    Image too large for the kernel_noload buffer (0x100000 bytes)

quoting the actual buffer size; the global path is unchanged. Drop the
trailing note in bootm_load_os() so only one line is printed.

Suggested-by: Simon Glass <[email protected]>
Signed-off-by: Aristo Chen <[email protected]>
---
 boot/bootm.c | 39 ++++++++++++++++++++++++++++++---------
 1 file changed, 30 insertions(+), 9 deletions(-)

diff --git a/boot/bootm.c b/boot/bootm.c
index 803d6406be4..a727bfea079 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -575,6 +575,19 @@ static int bootm_find_other(ulong img_addr, const char 
*conf_ramdisk,
 #endif /* USE_HOSTC */
 
 #if !defined(USE_HOSTCC) || defined(CONFIG_FIT_SIGNATURE)
+/**
+ * enum bootm_decomp_limit - What bounded the decompression buffer.
+ * @BOOTM_DECOMP_LIMIT_GLOBAL:    Global CONFIG_SYS_BOOTM_LEN limit.
+ * @BOOTM_DECOMP_LIMIT_PER_IMAGE: Per-image buffer sized from the
+ *                                compressed image (e.g. the
+ *                                kernel_noload noload decompression
+ *                                buffer).
+ */
+enum bootm_decomp_limit {
+       BOOTM_DECOMP_LIMIT_GLOBAL,
+       BOOTM_DECOMP_LIMIT_PER_IMAGE,
+};
+
 /**
  * handle_decomp_error() - display a decompression error
  *
@@ -585,11 +598,14 @@ static int bootm_find_other(ulong img_addr, const char 
*conf_ramdisk,
  * @comp_type:         Compression type being used (IH_COMP_...)
  * @uncomp_size:       Number of bytes uncompressed
  * @buf_size:          Number of bytes the decompresion buffer was
+ * @limit:             Which allocation actually bounded the buffer, so the
+ *                     hint points at the knob the reader can act on
  * @ret:               errno error code received from compression library
  * Return: Appropriate BOOTM_ERR_ error code
  */
 static int handle_decomp_error(int comp_type, size_t uncomp_size,
-                              size_t buf_size, int ret)
+                              size_t buf_size,
+                              enum bootm_decomp_limit limit, int ret)
 {
        const char *name = genimg_get_comp_name(comp_type);
 
@@ -598,10 +614,15 @@ static int handle_decomp_error(int comp_type, size_t 
uncomp_size,
                return BOOTM_ERR_UNIMPLEMENTED;
 
        if ((comp_type == IH_COMP_GZIP && ret == Z_BUF_ERROR) ||
-           uncomp_size >= buf_size)
-               printf("Image too large: increase CONFIG_SYS_BOOTM_LEN\n");
-       else
+           uncomp_size >= buf_size) {
+               if (limit == BOOTM_DECOMP_LIMIT_PER_IMAGE)
+                       printf("Image too large for the kernel_noload buffer 
(%#lx bytes)\n",
+                              (ulong)buf_size);
+               else
+                       printf("Image too large: increase 
CONFIG_SYS_BOOTM_LEN\n");
+       } else {
                printf("%s: uncompress error %d\n", name, ret);
+       }
 
        /*
         * The decompression routines are now safe, so will not write beyond
@@ -628,6 +649,7 @@ static int bootm_load_os(struct bootm_headers *images, int 
boot_progress)
        ulong image_start = os.image_start;
        ulong image_len = os.image_len;
        ulong decomp_len = CONFIG_SYS_BOOTM_LEN;
+       enum bootm_decomp_limit decomp_limit = BOOTM_DECOMP_LIMIT_GLOBAL;
        ulong flush_start;
        bool no_overlap;
        void *load_buf, *image_buf;
@@ -644,6 +666,7 @@ static int bootm_load_os(struct bootm_headers *images, int 
boot_progress)
                phys_addr_t addr;
 
                decomp_len = ALIGN(image_len * 8, SZ_1M);
+               decomp_limit = BOOTM_DECOMP_LIMIT_PER_IMAGE;
                err = lmb_alloc_mem(LMB_MEM_ALLOC_ANY, SZ_2M, &addr,
                                    decomp_len, LMB_NONE);
                if (err)
@@ -663,10 +686,7 @@ static int bootm_load_os(struct bootm_headers *images, int 
boot_progress)
                           decomp_len, &load_end);
        if (err) {
                err = handle_decomp_error(os.comp, load_end - load,
-                                         decomp_len, err);
-               if (os.type == IH_TYPE_KERNEL_NOLOAD && os.comp != IH_COMP_NONE)
-                       printf("Note: noload decompression buffer is %#lx bytes 
(not CONFIG_SYS_BOOTM_LEN)\n",
-                              decomp_len);
+                                         decomp_len, decomp_limit, err);
                bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE);
                return err;
        }
@@ -1288,7 +1308,8 @@ static int bootm_host_load_image(const void *fit, int 
req_image_type,
        free(load_buf);
 
        if (ret) {
-               ret = handle_decomp_error(image_comp, load_end - 0, buf_size, 
ret);
+               ret = handle_decomp_error(image_comp, load_end - 0, buf_size,
+                                         BOOTM_DECOMP_LIMIT_GLOBAL, ret);
                if (ret != BOOTM_ERR_UNIMPLEMENTED)
                        return ret;
        }
-- 
2.43.0

Reply via email to