UEFI LoadImage 不支持的类型

UEFI LoadImage Unsupported Type

我正在尝试使用 Bootservices.loadImage 从内存中加载 UEFI 应用程序映像。内存中的缓冲区加载了 HellowWorld.efi 应用程序的二进制内容。当我尝试从内存中加载它时,我发现这是一种不受支持的文件类型。

然而,在 运行 挖掘 UDK 核心时,我发现当我开始处理文件头时,我没有正确地从我的缓冲区读取。因此,所有的幻数都没有排列,所以它认为它是一种无法识别的文件格式。但是我一直无法追踪我指向源的指针在哪里弄乱了。

我猜问题出在 UDK 源代码中,所以问题出在我调用函数的方式上。

代码:

    #define SIZEOF_HELLO_EFI 39679
    UINT8 hexData[SIZEOF_HELLO_EFI] =  {//CONTENTS OF helloworld.efi
  0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
 0xFF, 0xFF, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 
0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD, 0x21, 0xB8, 0x01, 0x4C, 0xCD, 
0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 
0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 
0x6E, 0x20, 0x69, 0x6E, 0x20, 0x44, 0x4F, 0x53, 0x20, 0x6D, 0x6F, 0x64, 0x65, 
0x2E, 0x0D, 0x0D, 0x0A, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 
0x45, 0x00, 0x00, 0x4C, 0x01, 0x07, 0x00, 0x24, 0x80, 0x00, 0x00, 0x00, 0x7E, 
0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x06, 0x03, 0x0B, 0x01, 0x02, 
0x18, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0xB8, 0x84, 0x00, 
0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
    //CONTINUES FOR MANY MORE BYTES, BUT HERE IS THE HEADER INFO};
void copy_helloefi(UINT8* buff)
{
    int counter = 0;
    while(counter < SIZEOF_HELLO_EFI){
        buff[counter] = hexData[counter];
        counter++;
    }

}

EFI_STATUS
efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
        EFI_BOOT_SERVICES *BootServicesTable;
        UINT8* buff_ptr;
        EFI_STATUS status;
        MEMMAP_DEVICE_PATH mempath[2];
       EFI_HANDLE myLoadedImage = NULL;
        BootServicesTable = SystemTable->BootServices;
        BootServicesTable->AllocatePool(EfiLoaderCode, SIZEOF_HELLO_EFI, (void **)&buff_ptr);
        mempath[0].Header.Type = HARDWARE_DEVICE_PATH;
        mempath[0].Header.SubType = HW_MEMMAP_DP;
        mempath[0].Header.Length[0] = (UINT8)sizeof(MEMMAP_DEVICE_PATH);
        mempath[0].Header.Length[1] = (UINT8)(sizeof(MEMMAP_DEVICE_PATH)>> 8);
        mempath[0].MemoryType = EfiLoaderCode;
        mempath[0].StartingAddress = (UINT32)buff_ptr;
        mempath[0].EndingAddress = (UINT32)(buff_ptr + SIZEOF_HELLO_EFI);

        mempath[1].Header.Type = END_DEVICE_PATH_TYPE;
        mempath[1].Header.SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;
        mempath[1].Header.Length[0] = (UINT8)sizeof(EFI_DEVICE_PATH);
        mempath[1].Header.Length[1] = (UINT8)(sizeof(EFI_DEVICE_PATH)>> 8);

        copy_helloefi(buff_ptr); //put the contents of helloworld.efi in buffer

        status = BootServicesTable->LoadImage(FALSE, ImageHandle, (EFI_DEVICE_PATH*)&mempath, &buff_ptr, SIZEOF_HELLO_EFI, &myLoadedImage);
        if (EFI_ERROR(status)) {
            Print((CHAR16*)L"Could not LoadImage %r %x \r\n", status, status);
        }
        Print((CHAR16*)L"Loaded Image Handle %x\r\n", myLoadedImage);

        //__debugbreak();
        BootServicesTable->FreePool(buff_ptr);
    return EFI_SUCCESS;
}

我做错了什么? HelloWorld.efi 是 PE/COFF,如果我直接调用它,它运行良好,所以我知道它是一个有效的 efi 二进制文件。

解决了它,正如预期的那样,它是一些小而烦人的东西,但张贴在这里希望能帮助别人。

解决方法是将其 buff_ptr 作为 void* 而不是 void**

因此将 loadimage 的调用更新为:

status = BootServicesTable->LoadImage(FALSE, ImageHandle, 
(EFI_DEVICE_PATH*)&mempath, buff_ptr, SIZEOF_HELLO_EFI, &myLoadedImage);

然后将其添加到实际 运行 加载的图像

status = BootServicesTable->StartImage( myLoadedImage, (UINTN*)NULL, (CHAR16**)NULL);