UEFI开发学习15 – Device Path
前言
最近在写小功能,其中需要把信息以文件的形式保存在U盘上。U盘是一个存储设备,可以用 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL 把找出来,但是如果有其它的存储设备,如硬盘(fat32分区),也会被列出来。那怎么来区分这两种设备呢?进入efi shell的时候,可以通过观察设备路径(Device Path)就很容易分辨出哪个是USB,哪个是SATA了,所以程序上也可据此判断。
Device Path Protocol
此Protocol可以在任何Device Handle上都可以使用,用以获得与物理设备或逻辑设备有关的通用路径/位置信息, 定义如下:
//******************************************************* // EFI_DEVICE_PATH_PROTOCOL //******************************************************* typedef struct _EFI_DEVICE_PATH_PROTOCOL { UINT8 Type; UINT8 SubType; UINT8 Length[2]; } EFI_DEVICE_PATH_PROTOCOL;
其中,Type为主类型,SubType为子类型,Length为结构体的长度。要注意一下的是,这个定义不是一个完整的设备路径,这只相当于设备路径中的一个Header,通用的设备路径(Generic Device Path)定义如下:
最后一部分的数据是跟随设备类型变化的,所以才有一个Length,它的长度是Length=n+4。
一个完整的Device Path是由多个部分组成的,每个部分被称为Node,每个Node由一个通用设备路径和设备数据组成。UEFI中支持6种主类型,如上图。每种主类型下可能还有几种子类型,如Type1 Hardware Device Path下就有PCI、PCCARD、Memory Mapped、Vendor、Controller、BMC这6种Sub-Type。
下面通过实例来认识设备路径。
实例1:打印设备路径
思路:
1.找到一个Device Path
2.使用EFI_DEVICE_PATH_TO_TEXT_PROTOCOL 将得到的设备路径转换为字符串
程序实现如下:
#include <Uefi.h> #include <Library/UefiLib.h> #include <Library/ShellLib.h> #include <Library/UefiBootServicesTableLib.h> #include <Protocol/DevicePath.h> #include <Protocol/DevicePathToText.h> int main(int argc, char **argv) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL * DevPath; EFI_DEVICE_PATH_TO_TEXT_PROTOCOL * DevPath2Text; CHAR16 * DevPathText; Status = gBS->LocateProtocol(&gEfiDevicePathProtocolGuid, NULL, (VOID *) &DevPath); if (EFI_ERROR(Status)) { Print(L"Error %r\n\r", Status); return Status; } Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID *) &DevPath2Text); if (EFI_ERROR(Status)) { Print(L"Error %r\n\r", Status); return Status; } DevPathText = DevPath2Text->ConvertDevicePathToText(DevPath, TRUE, FALSE); Print(L"Device path: %s\n\r", DevPathText); return 0; }
实例2:找到所有USB存储设备
思路:
1.找到所有的文件系统设备
2.在找到的设备中逐个判断其设备路径,直到找到USB Node的设备
程序如下:
#include <Uefi.h> #include <Library/UefiLib.h> #include <Library/ShellLib.h> #include <Library/DevicePathLib.h> #include <Library/UefiBootServicesTableLib.h> #include <Protocol/DevicePath.h> #include <Protocol/DevicePathToText.h> int main(int argc, char **argv) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL * DevPath; EFI_DEVICE_PATH_TO_TEXT_PROTOCOL * DevPath2Text; EFI_HANDLE * HandleBuffer; UINTN HandleCount; UINTN Index; Status = gBS->LocateHandleBuffer( ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &HandleCount, &HandleBuffer ); if (EFI_ERROR(Status)) { Print(L"Error %r\n\r", Status); return Status; } for (Index = 0; Index < HandleCount; Index ++) { Status = gBS->HandleProtocol(HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID *)&DevPath); if (EFI_ERROR(Status)) continue; while (1) { if (DevPath->Type == MESSAGING_DEVICE_PATH && DevPath->SubType == MSG_USB_DP ) { Print (L"Usb storage found:%s\n\r", DevPath2Text->ConvertDevicePathToText(DevPath, TRUE, FALSE)); break; } if (IsDevicePathEnd (DevPath)) { break; } DevPath = NextDevicePathNode(DevPath); } } return 0; }
代码
以后代码都会传到Gitee,避免链接失效。
版权声明:
作者:bin
链接:https://ay123.net/mystudy/uefi/1107/
来源:爱影博客
文章版权归作者所有,未经允许请勿转载。
共有 0 条评论