UEFI Protocol使用
啟動服務提供了豐富的服務供開發者操作Protocol,我們可以使用Protocol也可以開發Protocol。本文主要介紹如何使用Protocol。
使用Protocol一般分為下面三個步驟:
1. 通過啟動服務找出Protocol對象;
2. 使用這個Protocol提供的服務;
3. 關閉打開的Protocol
可以使用OpenProtocolInformation服務查看打開某個Protocol的所有設備。
啟動服務,有四種,分別為:OpenProtocol、HandleProtocol、LocateProtocol和LocalHandleBuffer。下面分別介紹它們
一、OpenProtocol 服務
OpenProtocol 用于查詢指定的Handle中是否支持指定的Protocol,如果支持,則打開該Protocol,否則返回錯誤代碼。
BS(啟動時服務)中的OpenProtocol函數原型:
typedef
EFI_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
);
Handle:查詢次Handle提供的Protocol
Protocol:要打開的Protocol(指向次Protocol GUID的指針)**Interface:返回打開的Protocol的對象AgentHandle:打開此Protocol的ImageControllerHandle:打開此Protocol的控制器Attributes:打開此Protocol的方式 Handle是Protocol的提供者,如果Handle的Protocols鏈表中有該Protocol,則Protocol對象的指針寫到Interface,并返回EFI_SUCCESS,否則返回EFI_UNSUPPORTED。
如果在驅動中調用OpenProtocol,則ControllerHandle是擁有該驅動的控制器,也就是請求使用這個Protocol的控制器;AgentHandle是擁有該EFI_DRIVER_BINDING_PROTOCOL對象的Handle。EFI_DRIVER_BINDING_PROTOCOL是UEFI驅動開發一定會用到的一個Protocol,它負責驅動的安裝與卸載。
如果調用OpenProtocol的是應用程序,那么AgentHandle是該用用程序的Handle,也就是UefiMain的第一個參數,ControllerHandle此時可以忽略。
二、HandleProtocol 服務
OpenProtocol功能比較強大,但是使用比較復雜,需要提供Handle和Protocol的GUID,還要提供AgentHandle、ControllerHandle和Attributes。但是開發者大多時候只是想通過Protocol的GUID得到Protocol對象,并不關心打開方式細節。為了方便開發者使用Protocol,啟動服務提供了HandleProtocol以簡化打開Protocol。
HandleProtocol服務的函數原型:
typedef
EFI_STATUS
(EFIAPI *EFI_HANDLE_PROTOCOL) (
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
OUT VOID **Interface
);
HandleProtocol 是OpenProtocol的簡化版,在調用HandleProtocol時不必再傳入AgentHandle、ControllerHandle和Attribute。它的內部其實仍是調用了OpenProtocol。
三、LocateProtocol 服務
OpenProtocol和HandleProtocol用于打開指定設備上的某個Protocol,要使用這兩個函數,首先要得到這個設備的句柄 。有時開發者并不關心Protocol在哪個設備上,尤其是系統僅有一個該Protocol的實例時。啟動服務提供了LocateProtocol(…)服務,它可以從UEFI內核中找到指定Protocol的第一個實例。
LocateProtocol服務函數原型:
typedef
EFI_STATUS
(EFIAPI *EFI_LOCATE_PROTOCOL) (
IN EFI_GUID *Protocol,
IN VOID *Registration,OPTIONAL
OUT VOID **Interface
);
UEFI內核中某個Protocol的實例可能不止一個,例如,每個硬盤及每個分區都有一個EFI_DISK_IO_PROTOCOL實例。LocateProtocol順序搜索HANDLE鏈表,返回找到的第一個該Protocol的實例。
四、LocateProtocolBuffer服務
前面三種是從設備上找出Protocol的方法。有時候開發者需要找出支持某個Protocol的所有設備,例如找出系統中所有安裝了BlockIo的設備。LocateHandle和LocateProtocolBuffer提供這個服務。
typedef
EFI_STATUS
(EFIAPI *EFI_LOCATE_HANDLE_BUFFER) (
IN EFI_LOCATE_SEARCH_TYPE SearchType, //查找方式
IN EFI_GUID *Protocol OPTIONAL, //指定的Protocol
IN VOID *SearchKey OPTIONAL, //PROTOCOL_NOTIFY的類型
IN OUT UINTN *NoHandles, //返回找到的HANDLE數量
OUT EFI_HANDLE **Buffer //分配Handle數組并返回
);
五、其它Protocol 服務
除了Protocol和根據Protocol找出設備這些常用服務,啟動服務關于使用Protocol的服務還有ProtocolsPerHandle和OpenProtocolInformation。
六、CloseProtocol 服務
Protocol使用完畢之后需要通過CloseProtocol關閉打開的Protocol。
CloseProtocol函數原型:
typedef
EFI_STATUS
(EFIAPI *EFI_CLOSE_PROTOCOL) (
IN EFI_HANDLE Handle,
IN EFI_GUID *Protocol,
IN EFI_HANDLE AgentHandle,
IN EFI_HANDLE ControllerHandle
);
七、總結
本部分,不住要講解了Protocol的使用方法。Protocol提供了一種在UEFI應用程序以及UEFI驅動之間的通信方式。通過Protocol,用戶可以使用驅動提供的服務,以及系統提供的其他服務。要熟悉自己使用的Protocol的數據結構。
一 、dec dsc inf文件
https://blog.csdn.net/yg2496194392/article/details/112199105
1 .inf文件
以下面 .inf文件為例
[Defines] # 塊用于定義模塊的屬性和其他變量,塊內定義的變量可被其他塊引用
INF_VERSION = 0x00010006 #INF 標準的版本號, 前半部分主版本號,后半次版本號
BASE_NAME = Main #模塊名字字符串,不能包含空格。它通常也是輸出文件的名字 Main.efi
FILE_GUID = 4ea97c46-7491-4dfd-b442-747010f3ce5f#每個工程文件必須有一個8-4-4-4-12格式的GUID,用于生成固件
MODULE_TYPE = UEFI_APPLICATION # 定義模塊的模塊類型
VERSION_STRING = 0.1 # 模塊的版本號字符串
ENTRY_POINT = ShellCEntryLib # 定義模塊的入口函數
[Sources] # 用于列出模塊的所有源文件和資源文件。 可選項體系結構相關塊
Main.c # 塊內每一行表示一個文件,根路徑是工程文件所在的目錄
[Packages] # 列出本模塊引用到的所有包的包聲明文件(.dec 文件)。
StdLib/StdLib.dec
MdePkg/MdePkg.dec
ShellPkg/ShellPkg.dec # 文件使用相對路徑,相對路徑的根路徑為EDK2的根目錄
[LibraryClasses] #塊列出本模塊要鏈接的庫模塊
LibC
LibStdio # 塊內每一行聲明一個要鏈接的庫(庫定義在包的.dsc 文件中,定義方法將在下文講述
inf文件是模塊的工程文件,其作用相當于Makefile 文件或Visual Studio 的.proj 文件,用于指導EDK2 編譯工具自動編譯模塊;
工程文件分為多個塊,每個塊以“[ 塊名]”開頭,“[ 塊名]”必須單獨占一行。塊又分為 工程文件必需塊 和 工程文件非必需塊
2 .dsc文件
.inf 用于編譯一個模塊, 而.dsc 文件用于編譯一個Package, 它包含了[Defines]、
[LibraryClasses]、[Components] 幾個必需部分以及[PCD]、[BuildOptions] 等幾個可選部分。
3 .dec 文件
.dec 文件定義了公開的數據和接口,供其他模塊使用。它包含了必需區塊[Defines] 以及可選區塊[Includes]、[LibraryClasses]、[Guids]、[Protocols]、[Ppis] 和[PCD] 幾個部分。
.dec文件需要被調用模塊.inf文件所包含。
實例:
vendor\qcom\nonhlos\BOOT.XF.4.2\boot_images\QcomPkg\SocPkg\StraitPkg\Library\MDPPlatformLib\MDPPlatformLibPanelCommon.c
調用了 TLLM中的 configgpio 接口
1、利用 LocateProtocol 接口,根據 gEfiTLMMProtocolGuid 查找 TLMMProtocol
gBS->LocateProtocol(&gEfiTLMMProtocolGuid, NULL, (void **)&TLMMProtocol)
2、然后利用 TLMMProtocol 的 ConfigGpio 接口,配置GPIO
TLMMDxe.c 中定義 protocol 的接口,其他模塊想要調用里面的接口,只需在對應的 INF 文件中包含 TLLM 的 GUID 就可以
vendor/qcom/nonhlos/BOOT.XF.4.2/boot_images/QcomPkg/SocPkg/StraitPkg/Library/MDPPlatformLib/MDPPlatformLib.inf
vendor/qcom/nonhlos/BOOT.XF.4.2/boot_images/QcomPkg/Drivers/TLMMDxe$ ls
TLMMDxe.c TLMMDxe.inf
接口在如下定義
EFITLlmm.h 頭文件定義GUID
QcomPkg.dec 中定義別名為 gEfiTLMMProtocolGuid,實質上和 .h頭文件中定義的GUID值一樣
參考了如下兩篇:
https://blog.csdn.net/yg2496194392/article/details/112199105
UEFI原理與編程(九):UEFI中的Protocol使用方法_kaliopensourcextu的博客-CSDN博客_locateprotocol
總結
以上是生活随笔為你收集整理的UEFI Protocol使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中英文字符的映射(TRANSLATE函数
- 下一篇: 【声明】本人博客已经迁移到博客园,欢迎访