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 条评论