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?