UEFI 引导服务 CreateEvent() 返回状态 EFI_INVALID_PARAMETER

UEFI boot services CreateEvent() returning status EFI_INVALID_PARAMETER

我正在 NASM 程序集中编写一个简单的 UEFI 应用程序,我正在尝试为一个免费的 运行 计时器创建一个事件,但是对 CreateEvent 的调用总是 returns EFI_INVALID_PARAMETER 我不知道为什么。

section .text

_start:
    mov [ptrSystemTable], rdx
...
    mov rcx, EVT_TIMER
    mov rdx, TPL_APPLICATION
    mov r8, 0
    mov r9, 0
    lea rbx, [ptrTimerEvent]
    push rbx

    mov rax, [ptrSystemTable]
    mov rax, [rax + EFI_SYSTEM_TABLE.BootServices]
    call [rax + EFI_BOOT_SERVICES.CreateEvent]

    cmp rax, EFI_SUCCESS
    jne errorCode
...
section .data    
    ptrSystemTable  dq  0          
    ptrTimerEvent   dq  0
; Include file with a bunch of definitions and structures

EVT_TIMER               equ 0x80000000
TPL_APPLICATION         equ 4

%macro POINTER 0
    RESQ 1
    alignb 8
%endmacro

struc EFI_SYSTEM_TABLE
...
    .BootServices       POINTER
...
endstruc

struc EFI_BOOT_SERVICES
...
    .CheckEvent         POINTER
...
endstruc

根据UEFI规范中的2.3.4.2详细调用约定:

The integer values are passed from left to right in Rcx, Rdx, R8, and R9 registers. The caller passes arguments five and above onto the stack.

所以我传递的参数应该是:

 Type --> EVT_TIMER
 NotifyTpl --> TPL_APPLICATION
 NotifyFunction --> 0
 *NotifyContext --> 0
 *Event --> &ptrTimerEvent  

规范给出了 CreateEvent 可以 return EFI_INVALID_PARAMETER 的多种原因,但我看不出它们是如何出现在我的代码中的。如有任何指点或问题,我们将不胜感激。

UEFI 的调用约定在调用之前总是在堆栈顶部有 0x20 字节的空闲 space。第五个和后续参数(如果存在)从堆栈的偏移量 0x20 开始。

这与 Windows / Microsoft x64 调用约定相同。

此外,堆栈必须在调用前对齐到 0x10 的倍数。进入函数时,堆栈对齐到8的奇数倍,所以必须在函数内部将堆栈指针调整为8的奇数倍。

default rel          ; Use RIP-relative symbol addressing, not absolute

section .text

_start:
    sub rsp, 0x28              ; 0x20 bytes of shadow space + 8 to align the stack
    mov [ptrSystemTable], rdx
...
    mov rcx, EVT_TIMER
    mov rdx, TPL_APPLICATION
    mov r8, 0
    mov r9, 0
    lea rax, [ptrTimerEvent]
    mov [rsp+0x20], rax         ; 5th arg on the stack above the shadow space

    mov rax, [ptrSystemTable]
    mov rax, [rax + EFI_SYSTEM_TABLE.BootServices]
    call [rax + EFI_BOOT_SERVICES.CreateEvent]

    cmp rax, EFI_SUCCESS
    jne errorCode
...