我正在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
...
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
可以返回EFI_INVALID_PARAMETER
的多种原因,但我看不到它们中的任何一个在代码中如何发生。任何指针或问题将不胜感激。
最佳答案
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
...
关于assembly - UEFI引导服务CreateEvent()返回状态EFI_INVALID_PARAMETER,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60582920/