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
...
我正在 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
...