You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 02:57:55