Summary of EDK2 Protocol Retrieval
Timeline
2025-02-25
- Added OpenProtocol, HandleProtocol, LocateProtocol, OpenProtocolInformation, CloseProtocol
The interfaces related to Protocol are defined in UefiSpec.h.
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 |
Example: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
128
129
130
131
132
133
134
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. Open the file and get the file handle (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, found the target handle
Print(L"FileHandle: 0x%p at HandleIndex %d\n", FileHandle, HandleIndex);
// 2. Allocate memory for file info size
FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
FileInfo = AllocateZeroPool(FileInfoSize);
if (FileInfo == NULL) {
Print(L"Cannot allocate %d size for FileInfo at HandleIndex %d\n",
FileInfoSize, HandleIndex);
FileHandle->Close(FileHandle);
Root->Close(Root);
gBS->CloseProtocol(HandleBuffer[HandleIndex],
&gEfiSimpleFileSystemProtocolGuid, gImageHandle, NULL);
continue;
}
// 3. Retrieve file information
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. Pre-allocate memory for file size
*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); // Free 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. Read the file
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); // Free 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); // Free 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 | /** |
Example: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
Retrieve the interface installed on a device handle by using the 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
);
Example: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 Print EFI_STATUS error code
}
return EFI_SUCCESS;
}
LocateProtocol
UEFI_Spec_2.8
Unlike HandleProtocol and OpenProtocol, LocateProtocol does not care which device the protocol is on. It sequentially searches through the system’s handle list and returns the first instance of the protocol it finds.
1 | /** |
Example: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 | /// |
Example:1
CloseProtocol
UEFI_Spec_2.8
1 | /** |
Example:
1 |