EDK2获取Protocol总结
时间轴
2025-02-25
- 添加了OpenProtocol,HandleProtocol,LocateProtocol,OpenProtocolInfomation,CloseProtocol
UefiSpec.h 中定义了Protocol相关的接口:
EFI_HANDLE_PROTOCOL HandleProtocol;
EFI_REGISTER_PROTOCOL_NOTIFY RegisterProtocolNotify;
EFI_LOCATE_HANDLE LocateHandle;
EFI_LOCATE_DEVICE_PATH LocateDevicePath;
EFI_OPEN_PROTOCOL OpenProtocol;
EFI_CLOSE_PROTOCOL CloseProtocol;
EFI_OPEN_PROTOCOL_INFORMATION OpenProtocolInformation;
EFI_PROTOCOLS_PER_HANDLE ProtocolsPerHandle;
EFI_LOCATE_HANDLE_BUFFER LocateHandleBuffer;
EFI_LOCATE_PROTOCOL LocateProtocol;
EFI_INSTALL_PROTOCOL_INTERFACE InstallProtocolInterface;
EFI_REINSTALL_PROTOCOL_INTERFACE ReinstallProtocolInterface;
EFI_UNINSTALL_PROTOCOL_INTERFACE UninstallProtocolInterface;
EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES InstallMultipleProtocolInterfaces;
EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInterfaces;
1 | /// |
OpenProtocol
1 | // MdePkg/Include/Uefi/UefiSpec.h |
示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
EFI_STATUS
ReadFileByName(IN CHAR16 *FileName, OUT UINT8 **FileData, OUT UINTN *FileSize) {
EFI_FILE_INFO *FileInfo;
UINTN FileInfoSize;
EFI_FILE_PROTOCOL *FileHandle = NULL;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem;
EFI_FILE_PROTOCOL *Root;
EFI_STATUS Status;
UINTN HandleCount = 0;
UINTN HandleIndex = 0;
EFI_HANDLE *HandleBuffer = NULL;
// find all handles of SimpleFileSystemProtocol
Status =
gBS->LocateHandleBuffer(ByProtocol, &gEfiSimpleFileSystemProtocolGuid,
NULL, &HandleCount, &HandleBuffer);
if (EFI_ERROR(Status) || HandleCount == 0) {
Print(L"Locate SimpleFileSystemProtocolHandle Buffer error");
return Status;
}
for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
Status = gBS->OpenProtocol(HandleBuffer[HandleIndex],
&gEfiSimpleFileSystemProtocolGuid,
(VOID **)&SimpleFileSystem, gImageHandle, NULL,
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
if (EFI_ERROR(Status)) {
Print(L"Open SimpleFileSystemProtocol error,at HandleIndex %d",
HandleIndex);
continue;
}
Status = SimpleFileSystem->OpenVolume(SimpleFileSystem, &Root);
if (EFI_ERROR(Status)) {
Print(L"Open Root Volume error at HandleIndex%d", HandleIndex);
gBS->CloseProtocol(HandleBuffer[HandleIndex],
&gEfiSimpleFileSystemProtocolGuid, gImageHandle, NULL);
continue;
}
// 1.打开文件,获取文件句柄FileHandle
Status = Root->Open(Root, &FileHandle, FileName, EFI_FILE_MODE_READ, 0);
if ((FileHandle == NULL) || (EFI_ERROR(Status))) {
Print(L"Open file %s failed at HandleIndex%d\n", FileName, HandleIndex);
Root->Close(Root);
gBS->CloseProtocol(HandleBuffer[HandleIndex],
&gEfiSimpleFileSystemProtocolGuid, gImageHandle, NULL);
continue;
}
// else find the target handle
Print(L"FileHandle: 0x%p at HandleIndex%d\n", FileHandle, HandleIndex);
// 2.分配文件信息大小
FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
FileInfo = AllocateZeroPool(FileInfoSize);
if (FileInfo == NULL) {
Print(L"can not allocate %d size for FineInfo at HandleIndex%d\n",
FileInfoSize, HandleIndex);
FileHandle->Close(FileHandle);
Root->Close(Root);
gBS->CloseProtocol(HandleBuffer[HandleIndex],
&gEfiSimpleFileSystemProtocolGuid, gImageHandle, NULL);
continue;
}
// 3.打开文件信息
Status = FileHandle->GetInfo(FileHandle, &gEfiFileInfoGuid, &FileInfoSize,
FileInfo);
if (EFI_ERROR(Status)) {
Print(L"Get FileInfo failed at HandleIndex%d\n", HandleIndex);
FileHandle->Close(FileHandle);
Root->Close(Root);
gBS->CloseProtocol(HandleBuffer[HandleIndex],
&gEfiSimpleFileSystemProtocolGuid, gImageHandle, NULL);
continue;
}
Print(L"FileInfo: 0x%p\n", FileInfo);
// 4.预先分配文件大小
*FileSize = (UINTN)FileInfo->FileSize + sizeof(CHAR16);
*FileData = AllocateZeroPool(*FileSize);
if (*FileData == NULL) {
Print(L"locate file data size %d failed at HandleIndex%d\n", *FileSize,
HandleIndex);
FileHandle->Close(FileHandle);
gBS->FreePool(FileInfo); // 释放FileInfo
Root->Close(Root);
gBS->CloseProtocol(HandleBuffer[HandleIndex],
&gEfiSimpleFileSystemProtocolGuid, gImageHandle, NULL);
continue;
} else {
Print(L"size of %s is %d\n", FileName, *FileSize);
Print(L"FileData: 0x%p\n", *FileData);
}
// 5.读取文件
Status = FileHandle->Read(FileHandle, FileSize, (VOID *)*FileData);
if (EFI_ERROR(Status)) {
Print(L"open %s file failed at HandleIndex%d\n", FileName, HandleIndex);
FileHandle->Close(FileHandle);
gBS->FreePool(FileInfo); // 释放FileInfo
Root->Close(Root);
gBS->CloseProtocol(HandleBuffer[HandleIndex],
&gEfiSimpleFileSystemProtocolGuid, gImageHandle, NULL);
// gBS->FreePool((VOID *)FileData);
continue;
} else {
Print(L"open %s file success at HandleIndex%d\n", FileName, HandleIndex);
}
FileHandle->Close(FileHandle);
Print(L"FileHandle is freed normally at HandleIndex%d\n", HandleIndex);
gBS->FreePool(FileInfo); // 释放FileInfo
Print(L"FileInfo is freed normally at HandleIndex%d\n", HandleIndex);
Root->Close(Root);
gBS->CloseProtocol(HandleBuffer[HandleIndex],
&gEfiSimpleFileSystemProtocolGuid, gImageHandle, NULL);
Print(L"Operation Success at HandleIndex%d\n", HandleIndex);
break;
}
if (HandleBuffer != NULL) {
gBS->FreePool(HandleBuffer);
}
return Status;
}
HandleProtocol
UEFI_Spec_2.8
相比于OpenProtocol,不需要指定参数AgentHandle,ControllerHandle和Attributes
1 | /** |
例子:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
EFI_STATUS EFIAPI UefiMain(IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable) {
EFI_STATUS Status;
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
Status = gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid,
(VOID **)&LoadedImage);
if (Status == EFI_SUCCESS) {
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
Status =
gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageDevicePathProtocolGuid,
(VOID **)&DevicePath);
if(Status == EFI_SUCCESS){
Print(L"Image device: %s\n",ConvertDevicePathToText(DevicePath,FALSE,TRUE));
Print(L"Image file: %s\n", ConvertDevicePathToText(LoadedImage->FilePath,FALSE,TRUE));
Print(L"Image Base: %X\n",LoadedImage->ImageBase);
Print(L"Image Size: %X\n",LoadedImage->ImageSize);
}else{
Print(L"Can't get EFI_LOADED_IMAGE_PROTOCOL, Status=%r\n",Status);
}
}else{
Print(L"Can't get EFI_DEVICE_PATH_PROTOCOL, Status=%r\n",Status);
}
return EFI_SUCCESS;
}
ProtocolsPerHandle
UEFI_Spec_2.8
通过Protocol GUID检索安装在设备句柄上的接口1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29/**
Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
from pool.
@param[in] Handle The handle from which to retrieve the list of protocol interface
GUIDs.
@param[out] ProtocolBuffer A pointer to the list of protocol interface GUID pointers that are
installed on Handle.
@param[out] ProtocolBufferCount A pointer to the number of GUID pointers present in
ProtocolBuffer.
@retval EFI_SUCCESS The list of protocol interface GUIDs installed on Handle was returned in
ProtocolBuffer. The number of protocol interface GUIDs was
returned in ProtocolBufferCount.
@retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the results.
@retval EFI_INVALID_PARAMETER Handle is NULL.
@retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.
@retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.
**/
typedef
EFI_STATUS
(EFIAPI *EFI_PROTOCOLS_PER_HANDLE)(
IN EFI_HANDLE Handle,
OUT EFI_GUID ***ProtocolBuffer,
OUT UINTN *ProtocolBufferCount
);
例子:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
EFI_STATUS
EFIAPI
UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) {
Print(L"_______________\n");
EFI_GUID **ProtocolGuidArray;
UINTN ArrayCount;
EFI_STATUS Status = gBS->ProtocolsPerHandle(ImageHandle,&ProtocolGuidArray,&ArrayCount);
if(Status==EFI_SUCCESS){
for(UINTN i =0;i<ArrayCount;i++){
Print(L"%g\n",ProtocolGuidArray[i]);
}
FreePool(ProtocolGuidArray);
}else{
Print(L"ProtocolsPerHandle error: %r\n",Status);//%r打印EFI_STATUS错误码
}
return EFI_SUCCESS;
}
LocateProtocol
UEFI_Spec_2.8
与HandleProtocol和OpenProtocol不同,LocateProtocol不关心Protocol在哪个设备上,它会在系统中顺序寻找句柄列表,返回找到的第一个Protocol实例
1 | /** |
例子:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95EFI_STATUS
LoadFileByName(
IN CHAR16 *FileName,
OUT UINT8 **FileData,
OUT UINTN *FileSize)
{
EFI_STATUS Status;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem;
EFI_FILE_PROTOCOL *Root;
EFI_FILE_PROTOCOL *FileHandle = NULL;
EFI_FILE_INFO *FileInfo;
UINTN FileInfoSize;
UINTN TempBufferSize;
VOID *TempBuffer;
Status = gBS->LocateProtocol(&gEfiSimpleFileSystemProtocolGuid,
NULL, (VOID **)&SimpleFileSystem);
if (EFI_ERROR(Status))
{
return Status;
}
//
// Open the root directory
//
Status = SimpleFileSystem->OpenVolume(SimpleFileSystem, &Root);
if (EFI_ERROR(Status))
{
return Status;
}
//
// Open the file
//
Status = Root->Open(Root, &FileHandle, FileName,
EFI_FILE_MODE_READ, 0);
if ((FileHandle == NULL) || (EFI_ERROR(Status)))
{
Print(L"Open file %s failed !!\n", FileName);
Root->Close(Root);
return Status;
}
//
// Get the file information
//
FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
FileInfo = AllocateZeroPool(FileInfoSize);
if (FileInfo == NULL)
{
FileHandle->Close(FileHandle);
return Status;
}
Status = FileHandle->GetInfo(FileHandle, &gEfiFileInfoGuid,
&FileInfoSize,
FileInfo);
if (EFI_ERROR(Status))
{
FileHandle->Close(FileHandle);
gBS->FreePool(FileInfo);
return Status;
}
//
// Allocate buffer for the file data. The last CHAR16 is for L'\0'
//
TempBufferSize = (UINTN)FileInfo->FileSize + sizeof(CHAR16);
TempBuffer = AllocateZeroPool(TempBufferSize);
if (TempBuffer == NULL)
{
FileHandle->Close(FileHandle);
gBS->FreePool(FileInfo);
return Status;
}
gBS->FreePool(FileInfo);
//
// Read the file data to the buffer
//
Status = FileHandle->Read(FileHandle, &TempBufferSize, TempBuffer);
if (EFI_ERROR(Status))
{
FileHandle->Close(FileHandle);
gBS->FreePool(TempBuffer);
return Status;
}
FileHandle->Close(FileHandle);
*FileSize = TempBufferSize;
*FileData = TempBuffer;
return Status;
}
OpenProtocolInformation
UEFI_Spec_2.8
1 | /// |
例子:1
CloseProtocol
UEFI_Spec_2.8
1 | /** |
例子:
1 |