Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UEFI boot services CreateEvent() returning status EFI_INVALID_PARAMETER

I'm writing a simple UEFI application in NASM assembly, and I'm trying to make an event for a free-running timer, but the call to CreateEvent always returns EFI_INVALID_PARAMETER and I'm not sure why.

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

According to 2.3.4.2 Detailed Calling Conventions in the UEFI spec:

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.

So the arguments I'm passing should be:

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

The spec gives multiple reasons why CreateEvent could return EFI_INVALID_PARAMETER, but I can't see how any of them are occurring in my code. Any pointers or questions would be greatly appreciated.

like image 407
Peter Frost Avatar asked Mar 07 '20 22:03

Peter Frost


Video Answer


1 Answers

The calling convention for UEFI always has 0x20 bytes of free space at the top of the stack before the call. The fifth and subsequent parameters, if present, start at offset 0x20 on the stack.

It's the same as the Windows / Microsoft x64 calling convention.

Also, the stack must be aligned to a multiple of 0x10 before the call. The stack is aligned to an odd multiple of 8 when the function is entered, so you must adjust the stack pointer by an odd multiple of 8 within the function.

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
...
like image 50
prl Avatar answered Oct 10 '22 01:10

prl