UEFI中LocateProtocol与HandleProtocol返回Invalid Parameter异常排查
UEFI应用开发:访问Simple Text Output Protocol时的Invalid Parameter错误问题
问题背景
近期开始学习UEFI应用开发,使用GNU-EFI与QEMU作为开发平台,实践UEFI开发教程。在尝试访问Simple Text Output Protocol时遇到两个异常:
- 调用
LocateProtocol查找支持该协议的句柄时,返回Invalid Parameter错误; - 通过
LocateHandleBuffer获取到4个对应句柄后,每个句柄调用HandleProtocol均返回相同错误。
根据UEFI规范,Invalid Parameter仅在Interface或Protocol为NULL时返回,但已确认两者均不为空,疑惑是否OVMF未正确实现规范,或是遗漏了必要操作(如加载驱动)。
相关代码
#include <efi.h> #include <efilib.h> #define CHK_EFI_ERROR(status) \ do { \ if (EFI_ERROR(status)) { \ Print(L"CHK_EFI_ERROR at %d failed with %r\n", __LINE__, status); \ } \ } while(0) EFI_STATUS EFIAPI efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) { InitializeLib(ImageHandle, SystemTable); Print(L"Hello, world!\n"); /* EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID */ EFI_GUID *Protocol = &gEfiSimpleTextOutProtocolGuid; /* Use LocateProtocol */ { EFI_STATUS status; EFI_SERIAL_IO_PROTOCOL *Interface = NULL; status = uefi_call_wrapper(ST->BootServices->LocateProtocol, 3 Protocol, NULL, (void **)&Interface); CHK_EFI_ERROR(status); } /* Use HandleProtocol */ { EFI_STATUS status; UINTN NoHandles; EFI_HANDLE *Buffer; status = uefi_call_wrapper(ST->BootServices->LocateHandleBuffer, 4, ByProtocol, Protocol, NULL, &NoHandles, &Buffer); CHK_EFI_ERROR(status); Print(L"NoHandles: %ld\n", NoHandles); Print(L"Buffer: %p\n", Buffer); for (UINTN i = 0; i < NoHandles; i++) { Print(L"Buffer[%ld]: %p\n", i, Buffer[i]); { EFI_STATUS status; EFI_SERIAL_IO_PROTOCOL *Interface = NULL; status = uefi_call_wrapper(ST->BootServices->HandleProtocol, 3 Buffer[i], Protocol, (void **)&Interface); CHK_EFI_ERROR(status); } } } return EFI_SUCCESS; }
程序运行输出
Hello, world! CHK_EFI_ERROR at 27 failed with Invalid Parameter NoHandles: 4 Buffer: 0x6A33C98 Buffer[0]: 0x6EB6798 CHK_EFI_ERROR at 50 failed with Invalid Parameter Buffer[1]: 0x6EB5F18 CHK_EFI_ERROR at 50 failed with Invalid Parameter Buffer[2]: 0x6AF2F98 CHK_EFI_ERROR at 50 failed with Invalid Parameter Buffer[3]: 0x6A95C98 CHK_EFI_ERROR at 50 failed with Invalid Parameter
问题根源与解决思路
根源
代码存在协议接口类型不匹配的关键错误:
你要获取的是EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL,但代码中却错误地使用EFI_SERIAL_IO_PROTOCOL *Interface作为输出参数传递给LocateProtocol和HandleProtocol。UEFI实现会校验输出指针对应的协议类型与查找的GUID是否匹配,类型不匹配时就会返回Invalid Parameter错误——这是规范未明确但主流实现(包括OVMF)都会执行的校验逻辑。
修复方法
将代码中所有的EFI_SERIAL_IO_PROTOCOL *Interface替换为EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Interface,重新编译运行即可解决错误。
额外优化提示
实际上无需手动调用LocateProtocol获取文本输出协议,GNU-EFI的InitializeLib执行完成后,ST->ConOut已经直接提供了可用的EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL实例,直接使用该实例即可完成文本输出操作。
内容的提问来源于stack exchange,提问作者Eric Stdlib
相关产品推荐
相关产品推荐

