时间轴
时间轴
2025-02-25
- 添加了 OpenProtocol,HandleProtocol,LocateProtocol,OpenProtocolInformation,CloseProtocol
本文介绍了EDK2中获取Protocol的几种常用接口,包括OpenProtocol、HandleProtocol、LocateProtocol、OpenProtocolInformation和CloseProtocol。OpenProtocol需要指定AgentHandle、ControllerHandle和Attributes;HandleProtocol与OpenProtocol类似,但无需指定这些参数;ProtocolsPerHandle用于通过设备句柄检索其上安装的所有Protocol接口GUID;LocateProtocol不关心Protocol具体所在设备,而是在系统中顺序查找并返回第一个匹配的Protocol实例;OpenProtocolInformation和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;
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 ); |
示例:
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.打开文件,获取文件句柄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 FileInfo 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
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 ); |
例子:
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

通过设备句柄检索其上安装的所有 Protocol 接口 GUID
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 ); |
例子:
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打印EFI_STATUS错误码 } return EFI_SUCCESS;} |
LocateProtocol
UEFI_Spec_2.8


与 HandleProtocol 和 OpenProtocol 不同,LocateProtocol 不关心 Protocol 在哪个设备上,它会在系统中顺序寻找句柄列表,返回找到的第一个 Protocol 实例
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 ); |
例子:
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 ); |
