系统中的每个设备都有一个唯一的路径。例如,每次进入shell时,都会打印出系统中的硬盘设备以及设备路径。针对硬盘和文件系统,将在BIOS学习实战中通过获取U盘路径,读取BIOS文件,然后进行更新的具体操作,本文主要说的是一些基础的内容
基础知识
设备路径中的节点称为设备节点,设备路径由设备节点组成的列表构成,列表由结束设备节点结束。
每个设备节点都以EFI_DEVICE_PATH_PROTOCOL开始,结束设备节点是一个特设的设备节点,它的类型为0x7F,次类型为0xFF或0x01,节点长度为2字节
说下重点:
UEFI提供了EFI_DEVICE_PATH_TO_TEXT_PROTOCOL用于将设备路径转换为字符串,其中的成员函数ConvertDevicePathToText用于将设备路径DevicePath转换为字符串。
IsDevicePathEnd(CONST VOID *Node)用于判断设备节点Node是否为设备路径的设备结束节点。
NextDevicePathNode(CONST VOID *Node)用于返回设备节点Node的下一个设备节点。
以打印找到的硬盘设备路径为例,步骤如下:
1、首先要用gBS->LocateHandleBuffer服务找出所有支持DiskIo的设备
2、然后找到DiskIo设备的设备路径
3、调用ConvertDevicePathToText,得到设备路径字符串
4、遍历设备路径的各个节点
代码如下:
#include <DevicePath.h>
EFI_STATUS
PrintNode(EFI_DEVICE_PATH_PROTOCOL *Node){
Print(L"(%d %d)/",Node->Type,Node->SubType);
return 0;
}
EFI_DEVICE_PATH_PROTOCOL*
WalkthroughDevicePath(
EFI_DEVICE_PATH_PROTOCOL* DevPath,
EFI_STATUS (*Callbk)(EFI_DEVICE_PATH_PROTOCOL*)
)
{
EFI_DEVICE_PATH_PROTOCOL* pDevPath=DevPath;
while(!IsDevicePathEnd(pDevPath)){
Callbk(pDevPath);
pDevPath= NextDevicePathNode(pDevPath);
}
return pDevPath;
}
EFI_STATUS
EFIAPI
ShellAppMain (
IN UINTN Argc,
IN CHAR16 **Argv
)
{
EFI_STATUS Status ;
UINTN HandleIndex,NumHandles;
EFI_HANDLE *ControllerHandle =NULL;
EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *Device2TextProtocol = 0;
EFI_DEVICE_PATH_PROTOCOL *DiskDevicePath;
CHAR16 *TextDevicePath;
//第一步,打开EFI_DEVICE_PATH_TO_TEXT_PROTOCOL服务
Status = gBS->LocateProtocol(
&gEfiDevicePathToTextProtocolGuid,
NULL,
(VOID**)&Device2TextProtocol);
if (EFI_ERROR(Status)){
Print(L"located DevicePathToTextProtocol fail\n");
return Status;
}
//第二步,找出所有支持DiskIo的设备
Status = gBS->LocateHandleBuffer(ByProtocol,
&gEfiDiskIoProtocolGuid,
NULL,
&NumHandles,
&ControllerHandle);
if (EFI_ERROR(Status)){
Print(L"No Disk\n");
return Status;
}
第三步,遍历每个DiskIo设备,并打开设备上的DevicePathprotocol
for(HandleIndex=0;HandleIndex<NumHandles;HandleIndex++){
Status = gBS->OpenProtocol(ControllerHandle[HandleIndex],
&gEfiDevicePathProtocolGuid,
(VOID**)&DiskDevicePath,
gImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(Status)){
continue;
}
{
TextDevicePath = Device2TextProtocol->
ConvertDevicePathToText(DiskDevicePath,TRUE,TRUE);
Print(L"%s\n",TextDevicePath);
if(TextDevicePath)
{
gBS->FreePool(TextDevicePath);
}
//遍历设备路径DiskDevicePath里的各个设备节点
}
WalkthroughDevicePath(DiskDevicePath,PrintNode);
Print(L"\n\n");
}
return Status;
}
输出显示: