Сервисы загрузки UEFI CreateEvent () возвращают статус EFI_INVALID_PARAMETER - PullRequest
5 голосов
/ 08 марта 2020

Я пишу простое приложение UEFI в сборке NASM и пытаюсь создать событие для автономного таймера, но вызов 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

В соответствии с 2.3.4.2 Подробные соглашения о вызовах в спецификации UEFI c:

Целочисленные значения передаются слева направо в регистрах Rcx, Rdx, R8 и R9. Вызывающая сторона передает аргументы пять и выше в стек.

Таким образом, аргументы, которые я передаю, должны быть:

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

Spe c дает несколько причин, почему CreateEvent может вернуть EFI_INVALID_PARAMETER, но я не вижу, как это происходит в моем коде. Любые указатели или вопросы будут с благодарностью.

1 Ответ

6 голосов
/ 08 марта 2020

Соглашение о вызовах для 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
...
...