问题
I am looking at using Bootservices function LoadImage to load a UEFI application image from memory. Function parameters are:
typedef
EFI_STATUS
LoadImage (
IN BOOLEAN BootPolicy,
IN EFI_HANDLE ParentImageHandle,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN VOID *SourceBuffer OPTIONAL,
IN UINTN SourceSize,
OUT EFI_HANDLE *ImageHandle
);
I have sourcebuffer in memory and populated with the PE/COFF image to load.
I pass that in under SourceBuffer and set DevicePath to the following:
MEMMAP_DEVICE_PATH mempath[2];
mempath[0].Header.Type = HARDWARE_DEVICE_PATH;
mempath[0].Header.SubType = HW_MEMMAP_DP;
mempath[0].Header.Length[0] = (UINT8)sizeof(mempath);
mempath[0].Header.Length[1] = (UINT8)(sizeof(mempath)>> 8);
mempath[0].MemoryType = EfiLoaderCode;
mempath[0].StartingAddress = (UINT32)buff_ptr;
mempath[0].EndingAddress = (UINT32)(buff_ptr + BUFF_SIZE);
mempath[1].Header.Type = END_DEVICE_PATH_TYPE;
mempath[1].Header.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
mempath[1].Header.Length[0] = (UINT8)sizeof(EFI_DEVICE_PATH);
mempath[1].Header.Length[1] = (UINT8)(sizeof(EFI_DEVICE_PATH)>> 8);
When I call load image the application hangs. I have set up visual studio to allow me to debug UEFI EDK2 source and have isolated where i'm stuck. Below is the EDK2 call that I appear to be stuck in. DevicePath is set to the mempath I setup above. Am I configuring my path incorrectly such that I never exit the below?
EFI_STATUS
EFIAPI
CoreLocateDevicePath (
IN EFI_GUID *Protocol,
IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
OUT EFI_HANDLE *Device
)
{
......
EFI_DEVICE_PATH_PROTOCOL *SourcePath;
SourcePath = *DevicePath;
TmpDevicePath = SourcePath;
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//I NEVER GET OUT OF THIS LOOP!!!
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
while (!IsDevicePathEnd (TmpDevicePath)) {
if (IsDevicePathEndInstance (TmpDevicePath)) {
break;
}
TmpDevicePath = NextDevicePathNode (TmpDevicePath);
}
For more context this is the UDK callstack of where i'm stuck
DxeCore.dll!CoreLocateDevicePath(GUID * Protocol, EFI_DEVICE_PATH_PROTOCOL * * DevicePath, void * * Device) Line 452 C
DxeCore.dll!CoreLoadImageCommon(unsigned char BootPolicy, void * ParentImageHandle, EFI_DEVICE_PATH_PROTOCOL * FilePath, void * SourceBuffer, unsigned int SourceSize, unsigned __int64 DstBuffer, unsigned int * NumberOfPages, void * * ImageHandle, unsigned __int64 * EntryPoint, unsigned int Attribute) Line 1089 C
DxeCore.dll!CoreLoadImage(unsigned char BootPolicy, void * ParentImageHandle, EFI_DEVICE_PATH_PROTOCOL * FilePath, void * SourceBuffer, unsigned int SourceSize, void * * ImageHandle) Line 1425 C
MyApplication.dll!efi_main(void * ImageHandle, EFI_SYSTEM_TABLE * SystemTable) Line 2588 C
回答1:
Found my answer, sharing here for others:
I based my original mempath off of the grub source:http://git.savannah.gnu.org/cgit/grub.git/tree/grub-core/loader/arm64/linux.c?id=7a210304ebfd6d704b4fc08fe496a0c417441879#n249
I changed the type of end point to instance, the size field of the header. I properly exit the loop now. My original header had the size of the entire structure, so I believe when trying to iterate to the next endpoint it was winding up with an invalid one, instead of going to my correct second element. Here is what I used:
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);
来源:https://stackoverflow.com/questions/31317566/uefi-loadimage-hangs