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

Pet*_*ost 5 x86 assembly x86-64 nasm uefi

我正在 NASM 程序集中编写一个简单的 UEFI 应用程序,并且我正在尝试为一个自由运行的计时器创建一个事件,但是CreateEvent总是返回调用,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
...
Run Code Online (Sandbox Code Playgroud)
section .data    
    ptrSystemTable  dq  0          
    ptrTimerEvent   dq  0
Run Code Online (Sandbox Code Playgroud)
; 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

Run Code Online (Sandbox Code Playgroud)

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

整数值在 Rcx、Rdx、R8 和 R9 寄存器中从左到右传递。调用者将参数 5 及以上传递到堆栈上。

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

 Type --> EVT_TIMER
 NotifyTpl --> TPL_APPLICATION
 NotifyFunction --> 0
 *NotifyContext --> 0
 *Event --> &ptrTimerEvent  
Run Code Online (Sandbox Code Playgroud)

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

prl*_*prl 6

UEFI 的调用约定在调用之前始终在堆栈顶部有 0x20 字节的可用空间。第五个及后续参数(如果存在)从堆栈上的偏移量 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
...
Run Code Online (Sandbox Code Playgroud)