krishnaLee(sssky307)为我们提供了一个解析DevicePath 的例子:
#include <Uefi.h>
#include <Library/UefiApplicationEntryPoint.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h> //global gST gBS gImageHandle
#include <Protocol/LoadedImage.h> //EFI_LOADED_IMAGE_PROTOCOL
#include <Protocol/DevicePath.h> //EFI_DEVICE_PATH_PROTOCOL
#include <Protocol/DevicePathToText.h> //EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
#include <Library/DevicePathLib.h> //link
//reference:http://www.cppblog.com/djxzh/archive/2012/03/06/167106.aspx
//reference:http://www.lab-z.com/getcurd/
//My custom struct defined by UEFI 2.6 Spec
typedef struct
{
UINT8 Type;
UINT8 SubType;
UINT16 Length;
UINT32 PartitionNumber;
UINT64 PartitionStart;
UINT64 PartitionSize;
GUID PartitionSig;
UINT8 PartitionFormat;
UINT8 SignatureType;
} HardDriveMediaDevicePath;
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath=NULL;
UINT8 *path;
EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *Device2TextProtocol;
CHAR16 *TextDevicePath;
Print(L"Print Nodes:\n");
//open the Loaded image protocol,which is binded on the imageHandle,to get the device handle.
Status = gBS->OpenProtocol (
gImageHandle,
&gEfiLoadedImageProtocolGuid,
(VOID**)&LoadedImage,
gImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
//get the device path protocol for the device handle.
if (!EFI_ERROR (Status))
{
Status = gBS->OpenProtocol (
LoadedImage->DeviceHandle,
&gEfiDevicePathProtocolGuid,
(VOID**)&ImageDevicePath, //get the path protocol
gImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
}
//parse the device path
path=(UINT8 *)ImageDevicePath;
while(1)
{
if(((EFI_DEVICE_PATH_PROTOCOL *)path)->Type==0x7F||((EFI_DEVICE_PATH_PROTOCOL *)path)->SubType==0xFF)
{
//if it is end node:
Print(L"type:%d,subType:%d,length:%d\n",\
((EFI_DEVICE_PATH_PROTOCOL *)path)->Type,\
((EFI_DEVICE_PATH_PROTOCOL *)path)->SubType,\
((EFI_DEVICE_PATH_PROTOCOL *)path)->Length[0]+((EFI_DEVICE_PATH_PROTOCOL *)path)->Length[1]*0xff);
break;
}
else
{
UINT16 len=((EFI_DEVICE_PATH_PROTOCOL *)path)->Length[0]+((EFI_DEVICE_PATH_PROTOCOL *)path)->Length[1]*0xff;
Print(L"type:%d,subType:%d,length:%d\n",\
((EFI_DEVICE_PATH_PROTOCOL *)path)->Type,\
((EFI_DEVICE_PATH_PROTOCOL *)path)->SubType,\
((EFI_DEVICE_PATH_PROTOCOL *)path)->Length[0]+((EFI_DEVICE_PATH_PROTOCOL *)path)->Length[1]*0xff);
//print my concern node
if(((EFI_DEVICE_PATH_PROTOCOL *)path)->Type==0x4&&((EFI_DEVICE_PATH_PROTOCOL *)path)->SubType==0x1)
{
HardDriveMediaDevicePath *path2=(HardDriveMediaDevicePath *)path;
Print(L" PartitionNumber:%d \n PartitionStart:0x%lx \n PartitionSize:0x%lx \n PartitionSig:%g \n PartitionFormat:%d \n SignatureType:%d \n",\
path2->PartitionNumber,path2->PartitionStart,path2->PartitionSize,path2->PartitionSig,path2->PartitionFormat,path2->SignatureType);
}
//go to next node;
path+=len;
}
}//while end
//get a converter.
Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid,
NULL,
(VOID**)&Device2TextProtocol
);
//convert device path to text.
if (!EFI_ERROR (Status))
{
TextDevicePath= Device2TextProtocol->ConvertDevicePathToText(ImageDevicePath, 1, 1);
Print(L"%s\n",TextDevicePath);
gBS->FreePool(TextDevicePath);
}
//clear
gBS->CloseProtocol(
LoadedImage->DeviceHandle,
&gEfiDevicePathProtocolGuid,
gImageHandle,
NULL);
gBS->CloseProtocol(
gImageHandle,
&gEfiLoadedImageProtocolGuid,
gImageHandle,
NULL);
return EFI_SUCCESS;
}
运行结果如下:
X64 的 EFI: mytestpathX64
完整的代码下载: mytestpath

Hi Sir, 請問您是參考哪一份Uefi SPEC. 去解析出這些type and information.我想多了解detail ..感謝!
Best Regards,
Tim
有说明是2.6
博主请问你用的是什么模拟器?或者虚拟机
我基本上用 NT32 模拟器而已。再复杂的只能用实体机了。
还有一个小问题是,我之前练习一直用的QEMU,现在看VirtualBOX也挺好用。博主有用过么?用过的话能请教下将编译好的.efi放到什么位置并进行设置才能让虚拟机在shell里读到呢。在VirtualBOX里不太会。
VirtualBox 的话,我还没有找到好办法直接把外面的东西 copy 到里面去。理论上你可以创建一个虚拟硬盘,然后把外面东西copy到这个硬盘上就可以在 fs0: 下面运行。 可行的接口有:串口, USB ,网卡…….但是目前我还没有找到方便易行的方案。如果你有空不妨研究一下。