:: commit 12ec203f46c189fdc0e873c5cee6c5e2c6dc0ac5

mintsuki <mintsuki@protonmail.com> — 2021-05-12 10:53

parents: f650e4b41b

chainload: EFI workarounds

diff --git a/stage23/protos/chainload.c b/stage23/protos/chainload.c
index 6c69073a..1943e9d6 100644
--- a/stage23/protos/chainload.c
+++ b/stage23/protos/chainload.c
@@ -116,6 +116,7 @@ void chainload(char *config) {
         panic("chainload: Could not open image");
 
     void *ptr = freadall(image, MEMMAP_EFI_LOADER);
+    size_t image_size = image->size;
 
     term_deinit();
 
@@ -140,21 +141,43 @@ void chainload(char *config) {
 
     memdev_path[0].MemoryType       = EfiLoaderData;
     memdev_path[0].StartingAddress  = (uintptr_t)ptr;
-    memdev_path[0].EndingAddress    = (uintptr_t)ptr + image->size;
+    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(MEMMAP_DEVICE_PATH);
-    memdev_path[1].Header.Length[1] = sizeof(MEMMAP_DEVICE_PATH) >> 8;
+    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 = uefi_call_wrapper(gBS->LoadImage, 6, 0, efi_image_handle, memdev_path,
-                               ptr, image->size, &new_handle);
+                               ptr, image_size, &new_handle);
     if (status) {
         panic("chainload: LoadImage failure (%x)", status);
     }
 
+    // Apparently we need to make sure that the DeviceHandle field is the same
+    // 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 = uefi_call_wrapper(gBS->HandleProtocol, 3,
+                               efi_image_handle, &loaded_img_prot_guid,
+                               &loader_loaded_image);
+    if (status) {
+        panic("HandleProtocol failure (%x)\n", status);
+    }
+
+    EFI_LOADED_IMAGE_PROTOCOL *new_handle_loaded_image = NULL;
+    status = uefi_call_wrapper(gBS->HandleProtocol, 3,
+                               new_handle, &loaded_img_prot_guid,
+                               &new_handle_loaded_image);
+    if (status) {
+        panic("HandleProtocol failure (%x)\n", status);
+    }
+
+    new_handle_loaded_image->DeviceHandle = loader_loaded_image->DeviceHandle;
+
     status = uefi_call_wrapper(gBS->StartImage, 3, new_handle, NULL, NULL);
     if (status) {
         panic("chainload: StartImage failure (%x)", status);
tab: 248 wrap: offon