efi: Rework EFI memory map sanitisation
diff --git a/stage23/lib/blib.c b/stage23/lib/blib.c
index 12e2e276..6a9e991a 100644
--- a/stage23/lib/blib.c
+++ b/stage23/lib/blib.c
@@ -125,24 +125,81 @@ bool efi_exit_boot_services(void) {
// Go through new EFI memmap and free up bootloader entries
size_t entry_count = efi_mmap_size / efi_desc_size;
+ EFI_MEMORY_DESCRIPTOR *efi_copy = ext_mem_alloc(256 * efi_desc_size);
+ size_t efi_copy_i = 0;
+
for (size_t i = 0; i < entry_count; i++) {
- EFI_MEMORY_DESCRIPTOR *entry = (void *)efi_mmap + i * efi_desc_size;
+ EFI_MEMORY_DESCRIPTOR *orig_entry = (void *)efi_mmap + i * efi_desc_size;
+ EFI_MEMORY_DESCRIPTOR *new_entry = (void *)efi_copy + efi_copy_i * efi_desc_size;
+
+ memcpy(new_entry, orig_entry, efi_desc_size);
- uint64_t base = entry->PhysicalStart;
+ uint64_t base = orig_entry->PhysicalStart;
+ uint64_t length = orig_entry->NumberOfPages * 4096;
+ uint64_t top = base + length;
// Find for a match in the untouched memory map
for (size_t j = 0; j < untouched_memmap_entries; j++) {
if (untouched_memmap[j].type != MEMMAP_USABLE)
continue;
- if (untouched_memmap[j].base == base) {
- // It's a match!
- entry->Type = EfiConventionalMemory;
+ if (untouched_memmap[j].base >= base && untouched_memmap[j].base < top) {
+ if (untouched_memmap[j].base > base) {
+ new_entry->NumberOfPages = (untouched_memmap[j].base - base) / 4096;
+
+ efi_copy_i++;
+ if (efi_copy_i == 256) {
+ panic("efi: New memory map exhausted");
+ }
+ new_entry = (void *)efi_copy + efi_copy_i * efi_desc_size;
+ memcpy(new_entry, orig_entry, efi_desc_size);
+
+ new_entry->NumberOfPages -= (untouched_memmap[j].base - base) / 4096;
+ new_entry->PhysicalStart = untouched_memmap[j].base;
+ new_entry->VirtualStart = new_entry->PhysicalStart;
+
+ base = new_entry->PhysicalStart;
+ length = new_entry->NumberOfPages * 4096;
+ top = base + length;
+ }
+
+ if (length < untouched_memmap[j].length) {
+ panic("efi: Memory map corruption");
+ }
+
+ new_entry->Type = EfiConventionalMemory;
+
+ if (length == untouched_memmap[j].length) {
+ // It's a perfect match!
+ break;
+ }
+
+ new_entry->NumberOfPages = untouched_memmap[j].length / 4096;
+
+ efi_copy_i++;
+ if (efi_copy_i == 256) {
+ panic("efi: New memory map exhausted");
+ }
+ new_entry = (void *)efi_copy + efi_copy_i * efi_desc_size;
+ memcpy(new_entry, orig_entry, efi_desc_size);
+
+ new_entry->NumberOfPages = (length - untouched_memmap[j].length) / 4096;
+ new_entry->PhysicalStart = base + untouched_memmap[j].length;
+ new_entry->VirtualStart = new_entry->PhysicalStart;
+
break;
}
}
+
+ efi_copy_i++;
+ if (efi_copy_i == 256) {
+ panic("efi: New memory map exhausted");
+ }
}
+ efi_mmap = efi_copy;
+ efi_mmap_size = efi_copy_i * efi_desc_size;
+
efi_boot_services_exited = true;
printv("efi: Exited boot services.\n");
