加载 UEFI 协议的正确方法是什么?
What is the correct way to load a UEFI protocol?
如果这不符合 Whosebug 格式,我们深表歉意。我目前正在学习编写 UEFI 应用程序。我一直在阅读 UEFI 标准以及大量在线教程,但我似乎无法弄清楚加载 UEFI 协议的正确方法是什么。所有教程似乎都在使用方法上有所不同。
在很多情况下,教程都是按照定位句柄然后遍历句柄缓冲区来打开协议的方法。示例如下:
EFI_HANDLE *handle_buffer;
UINTN handle_count;
EFI_GRAPHICS_OUTPUT_PROTOCOL *protocol;
// GNU-EFI wrapper.
status = uefi_call_wrapper(gBS->LocateHandleBuffer,
5,
ByProtocol,
&gEfiGraphicsOutputProtocolGuid,
NULL,
&handle_count,
&handle_buffer);
UINTN i = 0;
for(i = 0; i < handle_count; i++) {
status = uefi_call_wrapper(gBS->OpenProtocol, 6,
handle_buffer[i],
&gEfiGraphicsOutputProtocolGuid,
(VOID **)&protocol,
ImageHandle, // from `efi_main`
NULL,
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
if(status == EFI_SUCCESS) {
break;
}
}
或者,您似乎可以直接使用 LocateProtocol
函数加载协议。示例:
status = uefi_call_wrapper(gBS->LocateProtocol,
3,
&gEfiGraphicsOutputProtocolGuid,
NULL,
&graphics_service.protocol);
以上两个例子都有效。
我不确定我是否理解在加载协议之前获取句柄缓冲区的重要性,如某些教程和在线 material 所示。通过搜索 Github 上的示例,看起来两者可以互换使用,到目前为止我发现它们同样有效。我知道在前一种方法中我需要释放缓冲区,因为它是从池中分配的,而在后一种方法中对此没有任何责任。
谁能指出加载 UEFI 协议的理想方法是什么?这两种方法有什么问题吗?
如有任何帮助,我们将不胜感激。
对于这个具体情况(试图找到"EFI_GRAPHICS_OUTPUT_PROTOCOL")如果只有一个,或者你只想要一个而不关心哪个;那么 gBS->LocateProtocol
更容易(并且可能更快?)但是如果你愿意,你也可以使用 gBS->LocateHandleBuffer
。
但是;如果有 5 个显卡,每个显卡有 2 个显示器,并且有 10 个不同的 "EFI_GRAPHICS_OUTPUT_PROTOCOL" 实例怎么办?在这种情况下,您可能想要所有这些(这样您就可以在所有 10 个显示器上设置一个不错的视频模式),并且您可能想搜索正确的一个(例如,可能确实是用户右侧的那个) ) 和 skip/avoid 其他 9 个错误的。为此,您必须使用 gBS->LocateHandleBuffer
.
如果这不符合 Whosebug 格式,我们深表歉意。我目前正在学习编写 UEFI 应用程序。我一直在阅读 UEFI 标准以及大量在线教程,但我似乎无法弄清楚加载 UEFI 协议的正确方法是什么。所有教程似乎都在使用方法上有所不同。
在很多情况下,教程都是按照定位句柄然后遍历句柄缓冲区来打开协议的方法。示例如下:
EFI_HANDLE *handle_buffer;
UINTN handle_count;
EFI_GRAPHICS_OUTPUT_PROTOCOL *protocol;
// GNU-EFI wrapper.
status = uefi_call_wrapper(gBS->LocateHandleBuffer,
5,
ByProtocol,
&gEfiGraphicsOutputProtocolGuid,
NULL,
&handle_count,
&handle_buffer);
UINTN i = 0;
for(i = 0; i < handle_count; i++) {
status = uefi_call_wrapper(gBS->OpenProtocol, 6,
handle_buffer[i],
&gEfiGraphicsOutputProtocolGuid,
(VOID **)&protocol,
ImageHandle, // from `efi_main`
NULL,
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
if(status == EFI_SUCCESS) {
break;
}
}
或者,您似乎可以直接使用 LocateProtocol
函数加载协议。示例:
status = uefi_call_wrapper(gBS->LocateProtocol,
3,
&gEfiGraphicsOutputProtocolGuid,
NULL,
&graphics_service.protocol);
以上两个例子都有效。 我不确定我是否理解在加载协议之前获取句柄缓冲区的重要性,如某些教程和在线 material 所示。通过搜索 Github 上的示例,看起来两者可以互换使用,到目前为止我发现它们同样有效。我知道在前一种方法中我需要释放缓冲区,因为它是从池中分配的,而在后一种方法中对此没有任何责任。
谁能指出加载 UEFI 协议的理想方法是什么?这两种方法有什么问题吗? 如有任何帮助,我们将不胜感激。
对于这个具体情况(试图找到"EFI_GRAPHICS_OUTPUT_PROTOCOL")如果只有一个,或者你只想要一个而不关心哪个;那么 gBS->LocateProtocol
更容易(并且可能更快?)但是如果你愿意,你也可以使用 gBS->LocateHandleBuffer
。
但是;如果有 5 个显卡,每个显卡有 2 个显示器,并且有 10 个不同的 "EFI_GRAPHICS_OUTPUT_PROTOCOL" 实例怎么办?在这种情况下,您可能想要所有这些(这样您就可以在所有 10 个显示器上设置一个不错的视频模式),并且您可能想搜索正确的一个(例如,可能确实是用户右侧的那个) ) 和 skip/avoid 其他 9 个错误的。为此,您必须使用 gBS->LocateHandleBuffer
.