1

我想了解有关固件开发的更多信息。我已经知道如何为旧的 BIOS 编写汇编程序,现在我想从 UEFI 开始。我设法编译并模拟了一个Hello World程序,现在我正在尝试编写一个程序,该程序使用运行时服务 GetTime() 在屏幕上显示当前时间。但是,当我使用此功能时,程序会挂起,就好像它没有在 PI 期间安装一样。这是代码:

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

//gBS: SystemTable->BootServices;
//gRS: SystemTable->RuntimeServices;

EFI_STATUS
efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE* systab)
{
    EFI_TIME* time;

    InitializeLib(image, systab);
    RT->GetTime(time, NULL);

    Print(L"Time %u\n", time->Hour);
    return EFI_SUCCESS;
}

你知道我做错了什么吗?

这是我用来编译和模拟的代码,以备不时之需:

gcc -I/usr/include/efi -I/usr/include/efi/x86_64/  -fpic -ffreestanding -fno-stack-protector -fno-stack-check -fshort-wchar -mno-red-zone -maccumulate-outgoing-args -c main.c -o main.o

ld -shared -Bsymbolic -L/usr/lib -T/usr/lib/elf_x86_64_efi.lds /usr/lib/crt0-efi-x86_64.o main.o -o main.so -lgnuefi -lefi

objcopy -j .text -j .sdata -j .data -j .dynamic -j .dynsym  -j .rel -j .rela -j .rel.* -j .rela.* -j .reloc --target efi-app-x86_64 --subsystem=10 main.so main.efi

uefi-run -b /usr/share/edk2-ovmf/x64/OVMF.fd -q /usr/bin/qemu-system-x86_64 main.efi
4

2 回答 2

2

如果您使用的是 gnu-efi,请使用uefi_call_wrapper()来调用 UEFI 函数。

RT->GetTime(time, NULL);  // Program hangs
uefi_call_wrapper(RT->GetTime, 2, time, NULL);  // Okay

原因是 UEFI(使用 Microsoft x64 调用约定)和 Linux(使用 System V amd64 ABI)之间的调用约定不同。默认情况下,gcc 会生成 Linux 格式的代码,所以我们需要明确告诉它生成 UEFI 格式的代码。

您可以通过执行objdump.

于 2020-12-13T05:15:56.267 回答
0

我认为您错过了初始化 RT。

RT = SystemTable->RuntimeServices;

您的代码与统一可扩展固件接口规范 2.6 的示例之一(第 4.7.1 节中的示例)非常相似。我怀疑你没有读过它,但以防万一。

https://www.uefi.org/sites/default/files/resources/UEFI%20Spec%202_6.pdf

于 2020-12-12T14:54:21.577 回答