Why is load image returning EFI_NOT_FOUND?

64 Views Asked by At

I am creating a UEFI application in NASM assembly. I want to be able to give it an absolute file path to a secondary EFI file, and to use the loadImage boot service to launch that image.

The problem is that it is returning EFI_NOT_FOUND (on multiple UEFI systems that I have tried), even though my device path variable in the function call is not null. When I set it to null, I get an invalid parameter. But the specification only mentions returning EFI_NOT_FOUND when both device path and source buffer are null (and I know that device path is not null because of my test earlier).

Why is it returning EFI_NOT_FOUND, and how do I resolve it?

I have attached some of my code below.

This is the function:

;******************************************************************
;*** loadImage [BOOT FUNCTION ONLY]                             ***
;*** Definition: Load an EFI boot driver from a file            ***
;*** Input: rcx is a pointer to a device path protocol to load  ***
;*** Output: rcx is the EFI handle                              ***
;******************************************************************
loadImage:
    ;Save registers
    push rdx
    push r8
    push r9
    push r10
    push r11
    
    ;Call the function
    mov r8, rcx
    mov rcx, 0
    mov rdx, [EFI_HANDLE]
    mov r8, turtleDevicePathProtocol    
    mov r9, 0
    mov r10, 0
    mov r11, BUFFER_LOAD_IMAGE
    push r11
    push r10
    
    sub rsp, 0x20
    call [ADDRESS_BOOT_SERVICES_LOAD_IMAGE]
    
    ;Restore registers
    add rsp, 0x30   
    pop r11
    pop r10
    pop r9
    pop r8
    pop rdx
    
    ;Return
    mov rcx, [BUFFER_LOAD_IMAGE]
    ret

This is where the function is called. It returns with the EFI_NOT_FOUND error:

;Load turtle image
loadTurtleImage:
mov rcx, turtleDevicePathProtocol
call loadImage
cmp rax, [RETURN_SUCCESS]
jne exitWithError

And this is the device path protocol. I have confirmed that is in the same format as the device protocol from EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL for my loaded image:

;****************************************
;*** Bootloader device path protocols ***
;****************************************
turtleDevicePathProtocol    db 4 ;This is the image I am trying to load
                db 4
                dw 36
                db __utf16__ `\\EFI\\turtle.efi\0`
                db 0x7f
                db 0xff
                dw 4                
bootloaderDevicePathProtocol    db 4 ;This is the loaded image protocol, for reference
                db 4
                dw 48
                db __utf16__ `\\EFI\\BOOT\\BOOTX64.efi\0`
                db 0x7f
                db 0xff
                dw 4

Edit Through @prl's comment, looking at other SO questions and the EDK2 source code, I discovered that I needed to append my filepath to the device path of the device handle. But even when I do that, I still get the same error.

Here is my code to call my functions:

; We need to append two device paths together to load the second image
; First, we need the device path linked to the parent EFI handle
; Second, we need the absolute file path of the image to load
; Third, we append them together
; Finally, we load and start the image at the appended device path

; So, step 1:
mov rcx, [ADDRESS_LOADED_IMAGE_DEVICE_HANDLE]
mov rdx, GUID_EFI_DEVICE_PATH_PROTOCOL
call getProtocolFromHandle
cmp rax, [RETURN_SUCCESS]
jne exitWithError
mov [ADDRESS_DEVICE_PATH], rcx

; Step 2
mov rdx, turtleDevicePathProtocol

; Step 3
call appendDevicePath
cmp rax, [RETURN_SUCCESS]
jne exitWithError

loadDevicePath:
mov [ADDRESS_DEVICE_PATH], rcx

; Print the device path if we can. Note that this function uses the optional
; DEVICE_PATH_TO_TEXT_PROTOCOL, so we will just skip this step if we can't find it

mov rcx, GUID_EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
call locateProtocol
cmp rax, [RETURN_SUCCESS]
je printImagePath
cmp rax, [RETURN_NOT_FOUND]
jne exitWithError
call warnWithError
jmp noPrintDevicePath

printImagePath:
; Get the print device path function
mov [ADDRESS_DEVICE_PATH_TO_TEXT_PROTOCOL], rcx
;mov rcx, [ADDRESS_DEVICE_PATH_TO_TEXT_PROTOCOL] ;Obviously line is not needed right?
add rcx, [OFFSET_DEVICE_PATH_TO_TEXT_CONVERT_PATH]
mov rcx, [rcx]
mov [ADDRESS_DEVICE_PATH_TO_TEXT_PROTOCOL_CONVERT_PATH_TO_TEXT], rcx

;Print the device path
mov rcx, [ADDRESS_DEVICE_PATH]
mov rdx, [ADDRESS_CONOUT]
call printDevicePath
mov rcx, rdx
mov rdx, newLine
call printString

noPrintDevicePath:
;Load turtle image
mov rcx, [ADDRESS_DEVICE_PATH]
call loadImage
cmp rax, [RETURN_SUCCESS]
jne exitWithError

And this is the output that I get:

Fv(7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1)/\EFI\turtle.efi
Instruction failed with exit code 14. Turtle is stopping!

I definitely have a file in \EFI\turtle.efi. What else could be wrong?

0

There are 0 best solutions below