Jonathon Hall has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/83475?usp=email )
Change subject: src/lib/malloc.c: If allocation fails, leave the heap unchanged ......................................................................
src/lib/malloc.c: If allocation fails, leave the heap unchanged
If an allocation fails because it is too large for the rest of the heap, don't consume the rest of the heap needlessly.
This started occurring with the Heads bootsplash image in 24.02.01, following the switch to the Wuffs JPEG decoder. The work area needed was too large for the heap. The bootsplash failed to show, but worse, the boot failed entirely because we were then out of heap space, even though we did not actually use the large allocation that failed.
With this change, that failure no longer prevents boot.
The error message is improved slightly also: * missing line break is added * "Tried to round up" now shows the beginning of the allocation before and after rounding instead of the unrounded beginning and rounded end (misleading, looked like it was trying to align by 1 MB when it was actually allocating 1 MB)
Change-Id: Ie72814027d9daa517c0794f3ea7abec2b9a9d596 Signed-off-by: Jonathon Hall jonathon.hall@puri.sm --- M src/lib/malloc.c 1 file changed, 15 insertions(+), 16 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/75/83475/1
diff --git a/src/lib/malloc.c b/src/lib/malloc.c index 3029806..281792c 100644 --- a/src/lib/malloc.c +++ b/src/lib/malloc.c @@ -26,10 +26,22 @@ MALLOCDBG("%s Enter, boundary %zu, size %zu, free_mem_ptr %p\n", __func__, boundary, size, free_mem_ptr);
- free_mem_ptr = (void *)ALIGN_UP((unsigned long)free_mem_ptr, boundary); + p = (void *)ALIGN_UP((unsigned long)free_mem_ptr, boundary);
- p = free_mem_ptr; - free_mem_ptr += size; + if (p + size >= free_mem_end_ptr) { + printk(BIOS_ERR, "%s(boundary=%zu, size=%zu): failed: ", + __func__, boundary, size); + printk(BIOS_ERR, "Tried to round up free_mem_ptr %p to %p\n", + free_mem_ptr, p); + printk(BIOS_ERR, "but free_mem_end_ptr is %p\n", + free_mem_end_ptr); + printk(BIOS_ERR, "Error! %s: Out of memory " + "(free_mem_ptr >= free_mem_end_ptr)\n", + __func__); + return NULL; + } + + free_mem_ptr = p + size; /* * Store last allocation pointer after ALIGN, as malloc() will * return it. This may cause n bytes of gap between allocations @@ -37,19 +49,6 @@ */ free_last_alloc_ptr = p;
- if (free_mem_ptr >= free_mem_end_ptr) { - printk(BIOS_ERR, "%s(boundary=%zu, size=%zu): failed: ", - __func__, boundary, size); - printk(BIOS_ERR, "Tried to round up free_mem_ptr %p to %p\n", - p, free_mem_ptr); - printk(BIOS_ERR, "but free_mem_end_ptr is %p\n", - free_mem_end_ptr); - printk(BIOS_ERR, "Error! %s: Out of memory " - "(free_mem_ptr >= free_mem_end_ptr)", - __func__); - return NULL; - } - MALLOCDBG("%s %p\n", __func__, p);
return p;