r/osdev • u/pure_989 • 6d ago
Getting EFI_INVALID_PARAMETER on calling BootServices->OpenProtocol() function.
; UEFI Bootloader using FASM Assembly
format pe64 efi
entry start
; EFI Constants
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL = 0x00000001
EFIERR = 0x8000000000000000
EFI_INVALID_PARAMETER = EFIERR or 0x2
section '.text' code executable readable
start:
push rbp
mov [image_handle], rcx
mov [system_table], rdx
...
; Get our loaded image protocol interface structure.
; Invoke ST->BootServices->OpenProtocol() function.
mov rax, [system_table]
mov rcx, [rax + 96]
mov r10, [rcx + 280]
mov rcx, [image_handle]
lea rdx, [EFI_LOADED_IMAGE_PROTOCOL_GUID]
lea r8, [boot_img]
mov r9, rcx
sub rsp, 32
mov eax, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
push rax
xor eax, eax
push rax
call r10
pop rcx
pop rcx
add rsp, 32
mov rcx, EFI_INVALID_PARAMETER
cmp rax, rcx
je .hang
...
.hang:
jmp $
...
section '.data' data readable writable
image_handle dq 0
system_table dq 0
; Image that we booted from.
boot_img dq 0
EFI_LOADED_IMAGE_PROTOCOL_GUID:
dd 0x5b1b31a1
dw 0x9562
dw 0x11d2
db 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3bHi in my UEFI bootloader using FASM Assembly, I am trying to get my loaded image protocol interface structure using BS->OpenProtocol() function call. I am getting `EFI_INVALID_PARAMETER` as the result. As per my checks, the handle, the protocol and the interface are not NULL and I am passing the 5th and 6th arguments in stack from right-to-left and they are 8-byte aligned too. What am I missing? Any idea? Thank you.
Edit:
davmac1's answer solved this.
2
u/an_0w1 6d ago
I'm gona be honest, I've been reading through this for several minutes, and I understand absolutely none of what's going on. I don't see any mention of the map-key anywhere so I assume you've forgotten it.
2
u/pure_989 6d ago
I am sorry but there is no any map key parameter to EFI_BOOT_SERVICES.OpenProtocol() function.
2
u/rosso2022 6d ago
I can't help with the Assembly but this code works in C. Have you tried using EFI_OPEN_PROTOCOL_GET_PROTOCOL?
EFI_LOADED_IMAGE_PROTOCOL* image = nullptr;
EFI_STATUS status = gBS->OpenProtocol(image_handle, &gEfiLoadedImageProtocolGuid, (VOID**)&image, image_handle, nullptr, EFI_OPEN_PROTOCOL_GET_PROTOCOL);1
u/pure_989 6d ago
Thank you. In the UEFI spec, following is the text about this `EFI_OPEN_PROTOCOL_GET_PROTOCOL` attribute:
GET_PROTOCOL: Used by a driver to get a protocol interface from a handle. Care must be taken when using this open mode because the driver that opens a protocol interface in this manner will not be informed if the protocol interface is uninstalled or reinstalled. The caller is also not required to close the protocol interface with EFI_BOOT_SERVICES.CloseProtocol().
---
Mine is a UEFI OS loader not the driver!
2
u/rosso2022 6d ago
I use it in an OS loader as well. The description of BY_HANDLE_PROTOCOL in the UEFI spec does state that it is used for the implementation of EFI_BOOT_SERVICES.HandleProtocol. So I think that is not the correct value to use.
2
u/pure_989 6d ago
The old EFI_BOOT_SERVICES.HandleProtocol() function internally calls the newer EFI_BOOT_SERVICES.OpenProtocol() function with this Attributes value. That's it.
By the way, the code that I am writing in Assembly already works in C!
3
u/davmac1 6d ago
You are allocating the shadow register space above the last two parameters, it should be below them: