Always use our own (better) allocator
diff --git a/stage23/entry.s3.c b/stage23/entry.s3.c
index 46a07769..0064ae03 100644
--- a/stage23/entry.s3.c
+++ b/stage23/entry.s3.c
@@ -32,6 +32,8 @@ EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable
print("Limine " LIMINE_VERSION "\n\n", print);
+ init_memmap();
+
disk_create_index();
EFI_GUID loaded_img_prot_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
@@ -88,10 +90,6 @@ void stage3_common(struct volume *boot_volume) {
char *cmdline;
char *config = menu(&cmdline);
-#if defined (uefi)
- efi_exit_boot_services();
-#endif
-
char *proto = config_get_value(config, 0, "PROTOCOL");
if (proto == NULL) {
panic("PROTOCOL not specified");
diff --git a/stage23/lib/blib.c b/stage23/lib/blib.c
index 0d6019e7..bb5f05c3 100644
--- a/stage23/lib/blib.c
+++ b/stage23/lib/blib.c
@@ -78,15 +78,8 @@ bool efi_exit_boot_services(void) {
uefi_call_wrapper(gBS->GetMemoryMap, 5,
&mmap_size, tmp_mmap, &mmap_key, &desc_size, &desc_ver);
- EFI_MEMORY_DESCRIPTOR *efi_mmap = ext_mem_alloc(mmap_size);
-
- uefi_call_wrapper(gBS->GetMemoryMap, 5,
- &mmap_size, efi_mmap, &mmap_key, &desc_size, &desc_ver);
-
uefi_call_wrapper(gBS->ExitBootServices, 2, efi_image_handle, mmap_key);
- pmm_mmap_efi2ours(efi_mmap, desc_size, mmap_size / desc_size);
-
efi_boot_services_exited = true;
print("efi: Exited boot services.\n");
diff --git a/stage23/mm/pmm.h b/stage23/mm/pmm.h
index 5f0aff1f..b12014be 100644
--- a/stage23/mm/pmm.h
+++ b/stage23/mm/pmm.h
@@ -13,17 +13,11 @@
#define MEMMAP_BAD_MEMORY 5
#define MEMMAP_BOOTLOADER_RECLAIMABLE 0x1000
#define MEMMAP_KERNEL_AND_MODULES 0x1001
+#define MEMMAP_EFI_RECLAIMABLE 0x2000
extern struct e820_entry_t memmap[];
extern size_t memmap_entries;
-#if defined (uefi)
-#include <efi.h>
-
-bool pmm_mmap_efi2ours(EFI_MEMORY_DESCRIPTOR *efi_mmap,
- size_t desc_size, size_t entry_count);
-#endif
-
void init_memmap(void);
struct e820_entry_t *get_memmap(size_t *entries);
void print_memmap(struct e820_entry_t *mm, size_t size);
diff --git a/stage23/mm/pmm.s2.c b/stage23/mm/pmm.s2.c
index 06addbbb..7cae5a24 100644
--- a/stage23/mm/pmm.s2.c
+++ b/stage23/mm/pmm.s2.c
@@ -33,6 +33,8 @@ static const char *memmap_type(uint32_t type) {
return "Bootloader reclaimable";
case MEMMAP_KERNEL_AND_MODULES:
return "Kernel/Modules";
+ case MEMMAP_EFI_RECLAIMABLE:
+ return "EFI reclaimable";
default:
return "???";
}
@@ -202,70 +204,29 @@ void init_memmap(void) {
}
#endif
-void *ext_mem_alloc(size_t count) {
- return ext_mem_alloc_type(count, MEMMAP_BOOTLOADER_RECLAIMABLE);
-}
-
-void *ext_mem_alloc_aligned(size_t count, size_t alignment) {
- return ext_mem_alloc_aligned_type(count, alignment, MEMMAP_BOOTLOADER_RECLAIMABLE);
-}
-
-void *ext_mem_alloc_type(size_t count, uint32_t type) {
- return ext_mem_alloc_aligned_type(count, 4, type);
-}
-
-// Allocate memory top down, hopefully without bumping into kernel or modules
-static void *_ext_mem_alloc_aligned_type(size_t count, size_t alignment, uint32_t type) {
- if (allocations_disallowed)
- panic("Extended memory allocations disallowed");
-
- for (int i = memmap_entries - 1; i >= 0; i--) {
- if (memmap[i].type != 1)
- continue;
-
- int64_t entry_base = (int64_t)(memmap[i].base);
- int64_t entry_top = (int64_t)(memmap[i].base + memmap[i].length);
-
- // Let's make sure the entry is not > 4GiB
- if (entry_base >= 0x100000000 || entry_top >= 0x100000000) {
- // Theoretically there could be an entry which crosses the 4GiB
- // boundary, but realistically this does not happen as far as I
- // have seen. Let's just discard the entry.
- continue;
- }
-
- int64_t alloc_base = ALIGN_DOWN(entry_top - (int64_t)count, alignment);
-
- // This entry is too small for us.
- if (alloc_base < entry_base)
- continue;
+#if defined (uefi)
+void init_memmap(void) {
+ EFI_STATUS status;
- // We now reserve the range we need.
- int64_t aligned_length = entry_top - alloc_base;
- memmap_alloc_range((uint64_t)alloc_base, (uint64_t)aligned_length, type, true, true);
+ EFI_MEMORY_DESCRIPTOR tmp_mmap[1];
+ UINTN mmap_size = sizeof(tmp_mmap);
+ UINTN mmap_key = 0, desc_size = 0, desc_ver = 0;
- void *ret = (void *)(size_t)alloc_base;
+ status = uefi_call_wrapper(gBS->GetMemoryMap, 5,
+ &mmap_size, tmp_mmap, &mmap_key, &desc_size, &desc_ver);
- // Zero out allocated space
- memset(ret, 0, count);
+ EFI_MEMORY_DESCRIPTOR *efi_mmap;
- sanitise_entries(false);
+ mmap_size += 4096;
- return ret;
- }
+ status = uefi_call_wrapper(gBS->AllocatePool, 3,
+ EfiLoaderData, mmap_size, &efi_mmap);
- panic("High memory allocator: Out of memory");
-}
+ status = uefi_call_wrapper(gBS->GetMemoryMap, 5,
+ &mmap_size, efi_mmap, &mmap_key, &desc_size, &desc_ver);
-#if defined (bios)
-void *ext_mem_alloc_aligned_type(size_t count, size_t alignment, uint32_t type) {
- return _ext_mem_alloc_aligned_type(count, alignment, type);
-}
-#endif
+ size_t entry_count = mmap_size / desc_size;
-#if defined (uefi)
-bool pmm_mmap_efi2ours(EFI_MEMORY_DESCRIPTOR *efi_mmap,
- size_t desc_size, size_t entry_count) {
for (size_t i = 0; i < entry_count; i++) {
EFI_MEMORY_DESCRIPTOR *entry = (void *)efi_mmap + i * desc_size;
@@ -302,42 +263,81 @@ bool pmm_mmap_efi2ours(EFI_MEMORY_DESCRIPTOR *efi_mmap,
sanitise_entries(false);
- print_memmap(memmap, memmap_entries);
-
allocations_disallowed = false;
- return true;
+ // Let's leave 64MiB to the firmware
+ ext_mem_alloc_aligned_type(65536, 4096, MEMMAP_EFI_RECLAIMABLE);
+
+ // Now own all the usable entries
+ for (size_t i = 0; i < memmap_entries; i++) {
+ if (memmap[i].type != MEMMAP_USABLE)
+ continue;
+
+ EFI_PHYSICAL_ADDRESS base = memmap[i].base;
+
+ status = uefi_call_wrapper(gBS->AllocatePages, 4,
+ AllocateAddress, EfiLoaderData, memmap[i].length / 4096, &base);
+
+ if (status)
+ panic("AllocatePages %x", status);
+ }
+}
+#endif
+
+void *ext_mem_alloc(size_t count) {
+ return ext_mem_alloc_type(count, MEMMAP_BOOTLOADER_RECLAIMABLE);
+}
+
+void *ext_mem_alloc_aligned(size_t count, size_t alignment) {
+ return ext_mem_alloc_aligned_type(count, alignment, MEMMAP_BOOTLOADER_RECLAIMABLE);
+}
+
+void *ext_mem_alloc_type(size_t count, uint32_t type) {
+ return ext_mem_alloc_aligned_type(count, 4, type);
}
+// Allocate memory top down, hopefully without bumping into kernel or modules
void *ext_mem_alloc_aligned_type(size_t count, size_t alignment, uint32_t type) {
- if (efi_boot_services_exited) {
- return _ext_mem_alloc_aligned_type(count, alignment, type);
- }
+ if (allocations_disallowed)
+ panic("Extended memory allocations disallowed");
- EFI_STATUS status;
+ for (int i = memmap_entries - 1; i >= 0; i--) {
+ if (memmap[i].type != 1)
+ continue;
- void *ret;
+ int64_t entry_base = (int64_t)(memmap[i].base);
+ int64_t entry_top = (int64_t)(memmap[i].base + memmap[i].length);
- if (alignment && alignment % 4096 == 0) {
- status = uefi_call_wrapper(gBS->AllocatePages, 4, 0, 2,
- DIV_ROUNDUP(count, 4096), &ret);
- } else {
- status = uefi_call_wrapper(gBS->AllocatePool, 3, 4, count, &ret);
- }
+ // Let's make sure the entry is not > 4GiB
+ if (entry_base >= 0x100000000 || entry_top >= 0x100000000) {
+ // Theoretically there could be an entry which crosses the 4GiB
+ // boundary, but realistically this does not happen as far as I
+ // have seen. Let's just discard the entry.
+ continue;
+ }
- if (status) {
- panic("Memory allocation error %x", status);
- }
+ int64_t alloc_base = ALIGN_DOWN(entry_top - (int64_t)count, alignment);
- if ((uintptr_t)ret % alignment) {
- panic("Memory alloc align bad");
- }
+ // This entry is too small for us.
+ if (alloc_base < entry_base)
+ continue;
- memset(ret, 0, count);
+ // We now reserve the range we need.
+ int64_t aligned_length = entry_top - alloc_base;
+ memmap_alloc_range((uint64_t)alloc_base, (uint64_t)aligned_length, type, true, true);
- return ret;
+ void *ret = (void *)(size_t)alloc_base;
+
+ // Zero out allocated space
+ memset(ret, 0, count);
+
+ sanitise_entries(false);
+
+ return ret;
+ }
+
+ panic("High memory allocator: Out of memory");
}
-#endif
bool memmap_alloc_range(uint64_t base, uint64_t length, uint32_t type, bool free_only, bool do_panic) {
uint64_t top = base + length;
