UEFI原理与编程实践--Device Path

系统中的每个设备都有一个唯一的路径。例如,每次进入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;

}

 输出显示:

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值