1

Very simple UEFI program as such:

LocateHandleBuffer() always returns 8000000000000002 which is "Invalid Parameter. EFI docs say that the only reason for that should be if one of the two pointers I am passing are NULL, which they are clearly not.

It can't get much simpler than this. I originally tried with ByProtocol with a speicifc GUID - but it always fails with the same error.

Any idea what the issue could be?

#include <efi.h>
#include <efilib.h>

EFI_STATUS EFIAPI efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {

  EFI_STATUS Status;
  UINTN HandleCount;
  EFI_HANDLE *HandleBuffer;

  EFI_BOOT_SERVICES *gBS = SystemTable-> BootServices;

  InitializeLib(ImageHandle, SystemTable);
  Print(L"test2  built on " __DATE__ " at " __TIME__ "\n");
  Status = gBS->LocateHandleBuffer (
     AllHandles, NULL, NULL,
     &HandleCount, &HandleBuffer);
  Print(L"Test AllHandles returned status  %llx count %d\n",Status,HandleCount);
  return (Status);
}
m4tx
  • 4,139
  • 5
  • 37
  • 61
Brad
  • 11,262
  • 8
  • 55
  • 74
  • 1
    In the spec, NoHandles is tagged as "IN OUT". I'm not sure why--the spec doesn't say--but I suggest initializing it to 0 (or to the maximum number of handles you want returned). – prl Oct 25 '17 at 20:03
  • 1
    In my code, I don't initialize NoHandles, but I do initialize Buffer to NULL, because I check for that before calling FreePool. – prl Oct 25 '17 at 20:07
  • 1
    Since there doesn't seem to be anything wrong with the code, perhaps look at environment--build steps, library linkage, ... Can you successfully call any other boot services functions? I guess you call Print successfully. – prl Oct 25 '17 at 20:18
  • I tried initializing those - no luck. I am going to dig in some more as I am wondering if there is something broken in the EFI environment itself (system I am running on is a prototype). Thanks! – Brad Oct 26 '17 at 14:59
  • 1
    Please let me know if you figure it out. I'm curious. – prl Oct 26 '17 at 22:19
  • I am building with GNU EFI - and am 99% sure it's a problem with that... – Brad Oct 30 '17 at 13:21
  • @prl: Brad: I guess you probably figured it out yourself (or just switched to TianoCode), but I'm posting the solution below for anyone who possibly needs this. – m4tx Jul 22 '18 at 20:17

1 Answers1

1

Because GCC uses cdecl/SysV ABI as its default calling convention, and x86_64 UEFI requires Microsoft x64 calling convention to be used, there is a utility thunk in GNU EFI called uefi_call_wrapper. Basically what it does is that it takes a pointer to the function to be called, number of arguments and the parameters, and it calls this function using the proper convention. So, basically, instead of writing code like this:

Status = gBS->LocateHandleBuffer(
    AllHandles, NULL, NULL,
    &HandleCount, &HandleBuffer);

you should write something like this:

Status = uefi_call_wrapper(
    gBS->LocateHandleBuffer, 5,
    AllHandles, NULL, NULL,
    &HandleCount, &HandleBuffer);
m4tx
  • 4,139
  • 5
  • 37
  • 61
  • I never figured it out - and have long moved on - but thanks for the reply - it indeed sounds like "the solution"! – Brad Jul 23 '18 at 13:09