:: commit dadca8fe17f0b42a15a83b7c7c3fe70bcdd9c12d

mintsuki <mintsuki@protonmail.com> — 2021-08-22 13:02

parents: ee3131bdfa

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");
tab: 248 wrap: offon