:: commit eae4dfea616bc3143e3fec59cb8fa732a7365ceb

Mintsuki <mintsuki@protonmail.com> — 2025-07-14 11:20

parents: 2d959e0d02

protos/efi: Hybridise loading mechanism with old memory-device based approach

diff --git a/common/protos/chainload.c b/common/protos/chainload.c
index 0629298d..fe1fcf41 100644
--- a/common/protos/chainload.c
+++ b/common/protos/chainload.c
@@ -277,6 +277,15 @@ noreturn void chainload(char *config, char *cmdline) {
 
     EFI_STATUS status;
 
+    EFI_HANDLE efi_part_handle = image->efi_part_handle;
+
+    void *ptr = freadall(image, MEMMAP_RESERVED);
+    size_t image_size = image->size;
+
+    memmap_alloc_range_in(untouched_memmap, &untouched_memmap_entries,
+                          (uintptr_t)ptr, ALIGN_UP(image_size, 4096),
+                          MEMMAP_RESERVED, MEMMAP_USABLE, true, false, true);
+
     size_t path_len = strlen(image->path);
 
     size_t efi_file_path_len = (path_len + 1) * sizeof(CHAR16);
@@ -341,11 +350,27 @@ noreturn void chainload(char *config, char *cmdline) {
 
     pmm_release_uefi_mem();
 
+    MEMMAP_DEVICE_PATH memdev_path[2];
+
+    memdev_path[0].Header.Type      = HARDWARE_DEVICE_PATH;
+    memdev_path[0].Header.SubType   = HW_MEMMAP_DP;
+    memdev_path[0].Header.Length[0] = sizeof(MEMMAP_DEVICE_PATH);
+    memdev_path[0].Header.Length[1] = sizeof(MEMMAP_DEVICE_PATH) >> 8;
+
+    memdev_path[0].MemoryType       = EfiLoaderCode;
+    memdev_path[0].StartingAddress  = (uintptr_t)ptr;
+    memdev_path[0].EndingAddress    = (uintptr_t)ptr + image_size;
+
+    memdev_path[1].Header.Type      = END_DEVICE_PATH_TYPE;
+    memdev_path[1].Header.SubType   = END_ENTIRE_DEVICE_PATH_SUBTYPE;
+    memdev_path[1].Header.Length[0] = sizeof(EFI_DEVICE_PATH);
+    memdev_path[1].Header.Length[1] = sizeof(EFI_DEVICE_PATH) >> 8;
+
     EFI_HANDLE new_handle = 0;
 
     status = gBS->LoadImage(0, efi_image_handle,
-                            device_path,
-                            NULL, 0, &new_handle);
+                            (EFI_DEVICE_PATH *)memdev_path,
+                            ptr, image_size, &new_handle);
     if (status) {
         panic(false, "efi: LoadImage failure (%x)", status);
     }
@@ -359,6 +384,12 @@ noreturn void chainload(char *config, char *cmdline) {
         panic(false, "efi: HandleProtocol failure (%x)", status);
     }
 
+    if (efi_part_handle != 0) {
+        new_handle_loaded_image->DeviceHandle = efi_part_handle;
+    }
+
+    new_handle_loaded_image->FilePath = device_path;
+
     new_handle_loaded_image->LoadOptionsSize = cmdline_len * sizeof(CHAR16);
     new_handle_loaded_image->LoadOptions = new_cmdline;
 
tab: 248 wrap: offon