1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <console/console.h>
7 #if CONFIG(DEBUG_MALLOC)
8 #define MALLOCDBG(x...) printk(BIOS_SPEW, x)
10 #define MALLOCDBG(x...)
13 extern unsigned char _heap
, _eheap
;
14 static void *free_mem_ptr
= &_heap
; /* Start of heap */
15 static void *free_mem_end_ptr
= &_eheap
; /* End of heap */
16 static void *free_last_alloc_ptr
= &_heap
; /* End of heap before
19 /* We don't restrict the boundary. This is firmware,
20 * you are supposed to know what you are doing.
22 void *memalign(size_t boundary
, size_t size
)
26 MALLOCDBG("%s Enter, boundary %zu, size %zu, free_mem_ptr %p\n",
27 __func__
, boundary
, size
, free_mem_ptr
);
29 free_mem_ptr
= (void *)ALIGN_UP((unsigned long)free_mem_ptr
, boundary
);
34 * Store last allocation pointer after ALIGN, as malloc() will
35 * return it. This may cause n bytes of gap between allocations
38 free_last_alloc_ptr
= p
;
40 if (free_mem_ptr
>= free_mem_end_ptr
) {
41 printk(BIOS_ERR
, "%s(boundary=%zu, size=%zu): failed: ",
42 __func__
, boundary
, size
);
43 printk(BIOS_ERR
, "Tried to round up free_mem_ptr %p to %p\n",
45 printk(BIOS_ERR
, "but free_mem_end_ptr is %p\n",
47 printk(BIOS_ERR
, "Error! %s: Out of memory "
48 "(free_mem_ptr >= free_mem_end_ptr)",
53 MALLOCDBG("%s %p\n", __func__
, p
);
58 void *malloc(size_t size
)
60 return memalign(sizeof(u64
), size
);
63 void *calloc(size_t nitems
, size_t size
)
65 void *p
= malloc(nitems
* size
);
67 memset(p
, 0, nitems
* size
);
77 if (ptr
< (void *)&_heap
|| ptr
>= free_mem_end_ptr
) {
78 printk(BIOS_WARNING
, "Pointer passed to %s is not "
79 "pointing to the heap\n", __func__
);
84 * Rewind the heap pointer to the end of heap
85 * before the last successful malloc().
87 if (ptr
== free_last_alloc_ptr
) {
88 free_mem_ptr
= free_last_alloc_ptr
;
89 free_last_alloc_ptr
= NULL
;