1

我正在尝试使用 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 二进制文件。

4

1 回答 1

1

解决了它,正如预期的那样,这是一件小而烦人的事情,但在这里发布希望能帮助其他人。

修复是将 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);
于 2015-07-15T20:22:31.027 回答