UEFI LocateHandleBuffer всегда возвращает недопустимый параметр

Очень простая программа UEFI как таковая:

LocateHandleBuffer() всегда возвращает 8000000000000002, который является «Недопустимым параметром». В документах EFI говорится, что единственная причина этого должна заключаться в том, что один из двух указателей, которые я передаю, равен NULL, что явно не так.

Это не может быть намного проще, чем это. Первоначально я пытался использовать ByProtocol с определенным GUID, но всегда терпел неудачу с той же ошибкой.

Есть идеи, в чем может быть проблема?

#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);
}

person Brad    schedule 25.10.2017    source источник
comment
В спецификации NoHandles помечен как IN OUT. Я не уверен, почему - спецификация не говорит - но я предлагаю инициализировать его до 0 (или до максимального количества дескрипторов, которые вы хотите вернуть).   -  person prl    schedule 25.10.2017
comment
В моем коде я не инициализирую NoHandles, но я инициализирую Buffer значением NULL, потому что я проверяю это перед вызовом FreePool.   -  person prl    schedule 25.10.2017
comment
Поскольку с кодом, похоже, нет ничего плохого, возможно, посмотрите на среду - шаги сборки, связывание библиотек, ... Можете ли вы успешно вызвать какие-либо другие функции службы загрузки? Я думаю, вы успешно вызываете Print.   -  person prl    schedule 25.10.2017
comment
Пробовал их инициализировать - безрезультатно. Я собираюсь копнуть еще немного, так как мне интересно, есть ли что-то сломанное в самой среде EFI (система, в которой я работаю, является прототипом). Спасибо!   -  person Brad    schedule 26.10.2017
comment
Пожалуйста, дайте мне знать, если разберетесь. Мне любопытно.   -  person prl    schedule 27.10.2017
comment
Я строю с GNU EFI - и на 99% уверен, что это проблема...   -  person Brad    schedule 30.10.2017
comment
@prl: Брэд: Я думаю, вы, вероятно, сами это поняли (или просто перешли на TianoCode), но я публикую решение ниже для всех, кому это может понадобиться.   -  person m4tx    schedule 22.07.2018


Ответы (1)


Поскольку GCC использует cdecl/SysV ABI в качестве соглашения о вызовах по умолчанию, а x86_64 UEFI требует использования соглашения о вызовах Microsoft x64, в GNU EFI есть утилита-преобразователь, которая называется uefi_call_wrapper. По сути, он берет указатель на вызываемую функцию, количество аргументов и параметры и вызывает эту функцию, используя соответствующее соглашение. Итак, в основном, вместо того, чтобы писать такой код:

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

вы должны написать что-то вроде этого:

Status = uefi_call_wrapper(
    gBS->LocateHandleBuffer, 5,
    AllHandles, NULL, NULL,
    &HandleCount, &HandleBuffer);
person m4tx    schedule 22.07.2018
comment
Я так и не понял - и уже давно ушел - но спасибо за ответ - это действительно похоже на решение! - person Brad; 23.07.2018