Timeline
Timeline
2025-02-25
- Added OpenProtocol, HandleProtocol, LocateProtocol, OpenProtocolInformation, CloseProtocol
This article introduces several commonly used interfaces for obtaining Protocols in EDK2, including OpenProtocol, HandleProtocol, LocateProtocol, OpenProtocolInformation, and CloseProtocol. OpenProtocol requires specifying AgentHandle, ControllerHandle, and Attributes; HandleProtocol is similar to OpenProtocol but does not require these parameters; ProtocolsPerHandle is used to retrieve all Protocol interface GUIDs installed on a device handle; LocateProtocol does not care about which specific device the Protocol resides on, but instead searches the system sequentially and returns the first matching Protocol instance; OpenProtocolInformation and CloseProtocol are used to query information about opened protocols and close protocols, respectively.
Protocol-related interfaces 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;
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 | ////// EFI Boot Services Table.///typedef struct { /// /// The table header for the EFI Boot Services Table. /// EFI_TABLE_HEADER Hdr; // // Task Priority Services // EFI_RAISE_TPL RaiseTPL; EFI_RESTORE_TPL RestoreTPL; // // Memory Services // EFI_ALLOCATE_PAGES AllocatePages; EFI_FREE_PAGES FreePages; EFI_GET_MEMORY_MAP GetMemoryMap; EFI_ALLOCATE_POOL AllocatePool; EFI_FREE_POOL FreePool; // // Event & Timer Services // EFI_CREATE_EVENT CreateEvent; EFI_SET_TIMER SetTimer; EFI_WAIT_FOR_EVENT WaitForEvent; EFI_SIGNAL_EVENT SignalEvent; EFI_CLOSE_EVENT CloseEvent; EFI_CHECK_EVENT CheckEvent; // // Protocol Handler Services // EFI_INSTALL_PROTOCOL_INTERFACE InstallProtocolInterface; EFI_REINSTALL_PROTOCOL_INTERFACE ReinstallProtocolInterface; EFI_UNINSTALL_PROTOCOL_INTERFACE UninstallProtocolInterface; EFI_HANDLE_PROTOCOL HandleProtocol; VOID *Reserved; EFI_REGISTER_PROTOCOL_NOTIFY RegisterProtocolNotify; EFI_LOCATE_HANDLE LocateHandle; EFI_LOCATE_DEVICE_PATH LocateDevicePath; EFI_INSTALL_CONFIGURATION_TABLE InstallConfigurationTable; // // Image Services // EFI_IMAGE_LOAD LoadImage; EFI_IMAGE_START StartImage; EFI_EXIT Exit; EFI_IMAGE_UNLOAD UnloadImage; EFI_EXIT_BOOT_SERVICES ExitBootServices; // // Miscellaneous Services // EFI_GET_NEXT_MONOTONIC_COUNT GetNextMonotonicCount; EFI_STALL Stall; EFI_SET_WATCHDOG_TIMER SetWatchdogTimer; // // DriverSupport Services // EFI_CONNECT_CONTROLLER ConnectController; EFI_DISCONNECT_CONTROLLER DisconnectController; // // Open and Close Protocol Services // EFI_OPEN_PROTOCOL OpenProtocol; EFI_CLOSE_PROTOCOL CloseProtocol; EFI_OPEN_PROTOCOL_INFORMATION OpenProtocolInformation; // // Library Services // EFI_PROTOCOLS_PER_HANDLE ProtocolsPerHandle; EFI_LOCATE_HANDLE_BUFFER LocateHandleBuffer; EFI_LOCATE_PROTOCOL LocateProtocol; EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES InstallMultipleProtocolInterfaces; EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInterfaces; // // 32-bit CRC Services // EFI_CALCULATE_CRC32 CalculateCrc32; // // Miscellaneous Services // EFI_COPY_MEM CopyMem; EFI_SET_MEM SetMem; EFI_CREATE_EVENT_EX CreateEventEx;} EFI_BOOT_SERVICES; |
OpenProtocol






123456789101112131415161718192021222324252627282930313233343536373839404142434445 | // MdePkg/Include/Uefi/UefiSpec.h/* Queries a handle to determine if it supports a specified protocol. If the protocol is supported by the handle, it opens the protocol on behalf of the calling agent. @param[in] Handle The handle for the protocol interface that is being opened. @param[in] Protocol The published unique identifier of the protocol. @param[out] Interface Supplies the address where a pointer to the corresponding Protocol Interface is returned. @param[in] AgentHandle The handle of the agent that is opening the protocol interface specified by Protocol and Interface. @param[in] ControllerHandle If the agent that is opening a protocol is a driver that follows the UEFI Driver Model, then this parameter is the controller handle that requires the protocol interface. If the agent does not follow the UEFI Driver Model, then this parameter is optional and may be NULL. @param[in] Attributes The open mode of the protocol interface specified by Handle and Protocol. @retval EFI_SUCCESS An item was added to the open list for the protocol interface, and the protocol interface was returned in Interface. @retval EFI_UNSUPPORTED Handle does not support Protocol. @retval EFI_INVALID_PARAMETER One or more parameters are invalid. @retval EFI_ACCESS_DENIED Required attributes can't be supported in current environment. @retval EFI_ALREADY_STARTED Item on the open list already has required attributes whose agent handle is the same as AgentHandle.*/typedefEFI_STATUS(EFIAPI *EFI_OPEN_PROTOCOL)( IN EFI_HANDLE Handle, IN EFI_GUID *Protocol, OUT VOID **Interface OPTIONAL, IN EFI_HANDLE AgentHandle, IN EFI_HANDLE ControllerHandle, IN UINT32 Attributes ); |
Example:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 | EFI_STATUSReadFileByName(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 find the target handle Print(L"FileHandle: 0x%p at HandleIndex%d\n", FileHandle, HandleIndex); // 2. Allocate file information size FileInfoSize = sizeof(EFI_FILE_INFO) + 1024; FileInfo = AllocateZeroPool(FileInfoSize); if (FileInfo == NULL) { Print(L"can not 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. Open 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 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); // Release 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 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); // Release 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); // Release 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

Compared to OpenProtocol, there is no need to specify the parameters AgentHandle, ControllerHandle, and Attributes.
12345678910111213141516171819202122 | /** Queries a handle to determine if it supports a specified protocol. @param[in] Handle The handle being queried. @param[in] Protocol The published unique identifier of the protocol. @param[out] Interface Supplies the address where a pointer to the corresponding Protocol Interface is returned. @retval EFI_SUCCESS The interface information for the specified protocol was returned. @retval EFI_UNSUPPORTED The device does not support the specified protocol. @retval EFI_INVALID_PARAMETER Handle is NULL. @retval EFI_INVALID_PARAMETER Protocol is NULL. @retval EFI_INVALID_PARAMETER Interface is NULL.**/typedefEFI_STATUS(EFIAPI *EFI_HANDLE_PROTOCOL)( IN EFI_HANDLE Handle, IN EFI_GUID *Protocol, OUT VOID **Interface ); |
Example:
12345678910111213141516171819202122232425262728293031 | 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 all Protocol interface GUIDs installed on the device via the device handle.
1234567891011121314151617181920212223242526272829 | /** 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.**/typedefEFI_STATUS(EFIAPI *EFI_PROTOCOLS_PER_HANDLE)( IN EFI_HANDLE Handle, OUT EFI_GUID ***ProtocolBuffer, OUT UINTN *ProtocolBufferCount ); |
Example:
1234567891011121314151617181920212223 | EFI_STATUSEFIAPIUefiMain(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 prints 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 the handle list in the system and returns the first found Protocol instance
123456789101112131415161718192021222324 | /** Returns the first protocol instance that matches the given protocol. @param[in] Protocol Provides the protocol to search for. @param[in] Registration Optional registration key returned from RegisterProtocolNotify(). @param[out] Interface On return, a pointer to the first interface that matches Protocol and Registration. @retval EFI_SUCCESS A protocol instance matching Protocol was found and returned in Interface. @retval EFI_NOT_FOUND No protocol instances were found that match Protocol and Registration. @retval EFI_INVALID_PARAMETER Interface is NULL. Protocol is NULL.**/typedefEFI_STATUS(EFIAPI *EFI_LOCATE_PROTOCOL)( IN EFI_GUID *Protocol, IN VOID *Registration OPTIONAL, OUT VOID **Interface ); |
Example:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 | EFI_STATUSLoadFileByName( 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

12345678910111213141516171819202122232425262728293031323334 | ////// EFI Open Protocol Information Entry///typedef struct { EFI_HANDLE AgentHandle; EFI_HANDLE ControllerHandle; UINT32 Attributes; UINT32 OpenCount;} EFI_OPEN_PROTOCOL_INFORMATION_ENTRY;/** Retrieves the list of agents that currently have a protocol interface opened. @param[in] Handle The handle for the protocol interface that is being queried. @param[in] Protocol The published unique identifier of the protocol. @param[out] EntryBuffer A pointer to a buffer of open protocol information in the form of EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures. @param[out] EntryCount A pointer to the number of entries in EntryBuffer. @retval EFI_SUCCESS The open protocol information was returned in EntryBuffer, and the number of entries was returned EntryCount. @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate EntryBuffer. @retval EFI_NOT_FOUND Handle does not support the protocol specified by Protocol.**/typedefEFI_STATUS(EFIAPI *EFI_OPEN_PROTOCOL_INFORMATION)( IN EFI_HANDLE Handle, IN EFI_GUID *Protocol, OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer, OUT UINTN *EntryCount ); |
CloseProtocol
UEFI_Spec_2.8


1234567891011121314151617181920212223242526272829 | /** Closes a protocol on a handle that was opened using OpenProtocol(). @param[in] Handle The handle for the protocol interface that was previously opened with OpenProtocol(), and is now being closed. @param[in] Protocol The published unique identifier of the protocol. @param[in] AgentHandle The handle of the agent that is closing the protocol interface. @param[in] ControllerHandle If the agent that opened a protocol is a driver that follows the UEFI Driver Model, then this parameter is the controller handle that required the protocol interface. @retval EFI_SUCCESS The protocol instance was closed. @retval EFI_INVALID_PARAMETER 1) Handle is NULL. 2) AgentHandle is NULL. 3) ControllerHandle is not NULL and ControllerHandle is not a valid EFI_HANDLE. 4) Protocol is NULL. @retval EFI_NOT_FOUND 1) Handle does not support the protocol specified by Protocol. 2) The protocol interface specified by Handle and Protocol is not currently open by AgentHandle and ControllerHandle.**/typedefEFI_STATUS(EFIAPI *EFI_CLOSE_PROTOCOL)( IN EFI_HANDLE Handle, IN EFI_GUID *Protocol, IN EFI_HANDLE AgentHandle, IN EFI_HANDLE ControllerHandle ); |
