diff options
-rw-r--r-- | lib/efi_loader/efi_memory.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index c82b53f336..8a1e249430 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -13,6 +13,7 @@ #include <malloc.h> #include <asm/global_data.h> #include <libfdt_env.h> +#include <linux/list_sort.h> #include <inttypes.h> #include <watchdog.h> @@ -27,6 +28,31 @@ struct efi_mem_list { LIST_HEAD(efi_mem); /* + * Sorts the memory list from highest address to lowest address + * + * When allocating memory we should always start from the highest + * address chunk, so sort the memory list such that the first list + * iterator gets the highest address and goes lower from there. + */ +static int efi_mem_cmp(void *priv, struct list_head *a, struct list_head *b) +{ + struct efi_mem_list *mema = list_entry(a, struct efi_mem_list, link); + struct efi_mem_list *memb = list_entry(b, struct efi_mem_list, link); + + if (mema->desc.physical_start == memb->desc.physical_start) + return 0; + else if (mema->desc.physical_start < memb->desc.physical_start) + return 1; + else + return -1; +} + +static void efi_mem_sort(void) +{ + list_sort(NULL, &efi_mem, efi_mem_cmp); +} + +/* * Unmaps all memory occupied by the carve_desc region from the * list entry pointed to by map. * @@ -142,6 +168,9 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, /* Add our new map */ list_add_tail(&newlist->link, &efi_mem); + /* And make sure memory is listed in descending order */ + efi_mem_sort(); + return start; } |