summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBora Guvendik <bora.guvendik@intel.com>2019-12-23 16:44:06 -0800
committerAaron Durbin <adurbin@chromium.org>2020-01-02 18:22:53 +0000
commita347ea3787284483158aaa77846ab0b34c017fdb (patch)
tree82a8ac385958115c30871b43eb5be232bf8c8aed
parent320d6e88afa56f2c11d9118faf6e47036fcc6540 (diff)
downloadcoreboot-a347ea3787284483158aaa77846ab0b34c017fdb.tar.gz
coreboot-a347ea3787284483158aaa77846ab0b34c017fdb.tar.bz2
coreboot-a347ea3787284483158aaa77846ab0b34c017fdb.zip
lib/malloc: Implement a simple free() only for last malloc()
Implement a free() that supports only the last malloc(). Rewind the heap to the last allocation point if the ptr to be freed is matching the end of heap before last malloc(). With current situation, since free() is no-op, every call to malloc() is a memory leak. BUG=b:140124451 TEST=Wrote a test function to do malloc and free operations. Change-Id: I6d43cf54b79e6897cf6882335730b2310e4eae45 Signed-off-by: Bora Guvendik <bora.guvendik@intel.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/37919 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Aaron Durbin <adurbin@chromium.org>
-rw-r--r--src/include/stdlib.h3
-rw-r--r--src/lib/malloc.c29
2 files changed, 30 insertions, 2 deletions
diff --git a/src/include/stdlib.h b/src/include/stdlib.h
index a8297f82a594..f6369bf0f44b 100644
--- a/src/include/stdlib.h
+++ b/src/include/stdlib.h
@@ -5,7 +5,6 @@
void *memalign(size_t boundary, size_t size);
void *malloc(size_t size);
-/* We never free memory */
-static inline void free(void *ptr) {}
+void free(void *ptr);
#endif /* STDLIB_H */
diff --git a/src/lib/malloc.c b/src/lib/malloc.c
index aa266b44dc63..ddc7ea57398f 100644
--- a/src/lib/malloc.c
+++ b/src/lib/malloc.c
@@ -11,6 +11,8 @@
extern unsigned char _heap, _eheap;
static void *free_mem_ptr = &_heap; /* Start of heap */
static void *free_mem_end_ptr = &_eheap; /* End of heap */
+static void *free_last_alloc_ptr = &_heap; /* End of heap before
+ last allocation */
/* We don't restrict the boundary. This is firmware,
* you are supposed to know what you are doing.
@@ -26,6 +28,12 @@ void *memalign(size_t boundary, size_t size)
p = free_mem_ptr;
free_mem_ptr += size;
+ /*
+ * Store last allocation pointer after ALIGN, as malloc() will
+ * return it. This may cause n bytes of gap between allocations
+ * where n < boundary.
+ */
+ free_last_alloc_ptr = p;
if (free_mem_ptr >= free_mem_end_ptr) {
printk(BIOS_ERR, "memalign(boundary=%zu, size=%zu): failed: ",
@@ -46,3 +54,24 @@ void *malloc(size_t size)
{
return memalign(sizeof(u64), size);
}
+
+void free(void *ptr)
+{
+ if (ptr == NULL)
+ return;
+
+ if (ptr < (void *)&_heap || ptr >= free_mem_end_ptr) {
+ printk(BIOS_WARNING, "Warning - Pointer passed to %s is not "
+ "pointing to the heap\n", __func__);
+ return;
+ }
+
+ /*
+ * Rewind the heap pointer to the end of heap
+ * before the last successful malloc().
+ */
+ if (ptr == free_last_alloc_ptr) {
+ free_mem_ptr = free_last_alloc_ptr;
+ free_last_alloc_ptr = NULL;
+ }
+}