:: commit bd4646f0ad12281ee68f33c1ac3424b6b860e5c3

mintsuki <mintsuki@protonmail.com> — 2021-09-27 02:04

parents: fabf2aef8c

chainload: Misc bug fixes and improvements

diff --git a/stage23/drivers/disk.s2.c b/stage23/drivers/disk.s2.c
index 0832bcdf..08017dd6 100644
--- a/stage23/drivers/disk.s2.c
+++ b/stage23/drivers/disk.s2.c
@@ -372,6 +372,16 @@ static void find_unique_sectors(void) {
     }
 }
 
+static void find_part_handles(EFI_HANDLE *handles, size_t handle_count) {
+    for (size_t i = 0; i < handle_count; i++) {
+        struct volume *vol = disk_volume_from_efi_handle(handles[i]);
+        if (vol == NULL) {
+            continue;
+        }
+        vol->efi_part_handle = handles[i];
+    }
+}
+
 void disk_create_index(void) {
     EFI_STATUS status;
 
@@ -389,7 +399,9 @@ void disk_create_index(void) {
 
     int optical_indices = 1, hdd_indices = 1;
 
-    for (size_t i = 0; i < handles_size / sizeof(EFI_HANDLE); i++) {
+    size_t handle_count = handles_size / sizeof(EFI_HANDLE);
+
+    for (size_t i = 0; i < handle_count; i++) {
         if (volume_index_i == MAX_VOLUMES) {
             print("WARNING: TOO MANY VOLUMES!");
             break;
@@ -456,6 +468,7 @@ void disk_create_index(void) {
     }
 
     find_unique_sectors();
+    find_part_handles(handles, handle_count);
 }
 
 #endif
diff --git a/stage23/fs/file.h b/stage23/fs/file.h
index ac261f47..57d3a413 100644
--- a/stage23/fs/file.h
+++ b/stage23/fs/file.h
@@ -5,6 +5,9 @@
 #include <stddef.h>
 #include <stdbool.h>
 #include <lib/part.h>
+#if uefi == 1
+#  include <efi.h>
+#endif
 
 bool fs_get_guid(struct guid *guid, struct volume *part);
 
@@ -13,6 +16,9 @@ struct file_handle {
     void      *fd;
     int      (*read)(void *fd, void *buf, uint64_t loc, uint64_t count);
     uint64_t   size;
+#if uefi == 1
+    EFI_HANDLE efi_part_handle;
+#endif
 };
 
 int fopen(struct file_handle *ret, struct volume *part, const char *filename);
diff --git a/stage23/fs/file.s2.c b/stage23/fs/file.s2.c
index 74994402..a90e9fcb 100644
--- a/stage23/fs/file.s2.c
+++ b/stage23/fs/file.s2.c
@@ -36,6 +36,10 @@ int fopen(struct file_handle *ret, struct volume *part, const char *filename) {
     }
 #endif
 
+#if uefi == 1
+    ret->efi_part_handle = part->efi_part_handle;
+#endif
+
     if (iso9660_check_signature(part)) {
         struct iso9660_file_handle *fd = ext_mem_alloc(sizeof(struct iso9660_file_handle));
 
diff --git a/stage23/lib/part.h b/stage23/lib/part.h
index b6de033e..398e9d86 100644
--- a/stage23/lib/part.h
+++ b/stage23/lib/part.h
@@ -16,6 +16,7 @@
 struct volume {
 #if uefi == 1
     EFI_HANDLE efi_handle;
+    EFI_HANDLE efi_part_handle;
     EFI_BLOCK_IO *block_io;
 
     bool unique_sector_valid;
diff --git a/stage23/mm/pmm.s2.c b/stage23/mm/pmm.s2.c
index 063e4e16..85f4cc77 100644
--- a/stage23/mm/pmm.s2.c
+++ b/stage23/mm/pmm.s2.c
@@ -324,19 +324,26 @@ void init_memmap(void) {
                 our_type = MEMMAP_USABLE; break;
         }
 
-        memmap[memmap_entries].type = our_type;
-        memmap[memmap_entries].base = entry->PhysicalStart;
-        memmap[memmap_entries].length = entry->NumberOfPages * 4096;
+        uint64_t base = entry->PhysicalStart;
+        uint64_t length = entry->NumberOfPages * 4096;
+
+        if (our_type == MEMMAP_USABLE) {
+            if (base + length >= 0x100000000) {
+                our_type = MEMMAP_EFI_RECLAIMABLE;
+            } else if (base < 0x1000) {
+                if (base + length <= 0x1000) {
+                    continue;
+                }
 
-        if (memmap[memmap_entries].base < 0x1000) {
-            if (memmap[memmap_entries].base + memmap[memmap_entries].length <= 0x1000) {
-                continue;
+                length -= 0x1000 - base;
+                base = 0x1000;
             }
-
-            memmap[memmap_entries].length -= 0x1000 - memmap[memmap_entries].base;
-            memmap[memmap_entries].base = 0x1000;
         }
 
+        memmap[memmap_entries].base = base;
+        memmap[memmap_entries].length = length;
+        memmap[memmap_entries].type = our_type;
+
         memmap_entries++;
     }
 
@@ -344,7 +351,7 @@ void init_memmap(void) {
 
     allocations_disallowed = false;
 
-    // Let's leave 64MiB to the firmware
+    // Let's leave 64MiB to the firmware below 4GiB
     for (size_t i = 0; i < 64; i++) {
         ext_mem_alloc_type(0x100000, MEMMAP_EFI_RECLAIMABLE);
     }
diff --git a/stage23/protos/chainload.c b/stage23/protos/chainload.c
index acea5558..f773488c 100644
--- a/stage23/protos/chainload.c
+++ b/stage23/protos/chainload.c
@@ -120,6 +120,8 @@ void chainload(char *config) {
     if (!uri_open(image, image_path))
         panic("chainload: Failed to open image with path `%s`. Is the path correct?", image_path);
 
+    EFI_HANDLE efi_part_handle = image->efi_part_handle;
+
     void *_ptr = freadall(image, MEMMAP_RESERVED);
     size_t image_size = image->size;
     void *ptr;
@@ -171,13 +173,6 @@ void chainload(char *config) {
     // as us (the loader) for some EFI images to properly work (Windows for instance)
     EFI_GUID loaded_img_prot_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
 
-    EFI_LOADED_IMAGE_PROTOCOL *loader_loaded_image = NULL;
-    status = gBS->HandleProtocol(efi_image_handle, &loaded_img_prot_guid,
-                                 (void **)&loader_loaded_image);
-    if (status) {
-        panic("chainload: HandleProtocol failure (%x)", status);
-    }
-
     EFI_LOADED_IMAGE_PROTOCOL *new_handle_loaded_image = NULL;
     status = gBS->HandleProtocol(new_handle, &loaded_img_prot_guid,
                                  (void **)&new_handle_loaded_image);
@@ -185,7 +180,9 @@ void chainload(char *config) {
         panic("chainload: HandleProtocol failure (%x)", status);
     }
 
-    new_handle_loaded_image->DeviceHandle = loader_loaded_image->DeviceHandle;
+    if (efi_part_handle != 0) {
+        new_handle_loaded_image->DeviceHandle = efi_part_handle;
+    }
 
     UINTN exit_data_size = 0;
     CHAR16 *exit_data = NULL;
tab: 248 wrap: offon