为什么我的 hello world EFI 程序无法正确构建?

问题描述 投票:0回答:1

我似乎无法取得进步;我的程序无法运行,并且错误消息毫无意义。十六进制转储显示一个错误的 PE 二进制文件,没有明显的原因:

我从本教程开始

我的

Makefile

ARCH=x86_64

OBJS=hello.o
TARGET=hello.efi

EFIINC=/usr/include/efi
EFIINCS=-I$(EFIINC) -I$(EIFFINC)/$(ARCH) -I$(EFIINC)/protocol
LIB=/usr/lib64
EFILIB=/usr/lib
EFI_CRT_OJBS=$(EFILIB)/crt0-efi-$(ARCH).o
EFI_LDS=$(EFILIB)/elf_$(ARCH)_efi.lds

CFLAGS=$(EFIINCS) -fno-stack-protector -fpic -fshort-wchar -mno-red-zone -Wall -DEFI_FUNCION_WRAPPER

LDFLAGS =-nostdlib -znocombreloc -T $(EFI_LDS) -shared -Bsymbolic -L $(EFILIB) -L $(LIB) $(EFI_CRT_OBJS)

all: $(TARGET)

hello.so: $(OBJS)
    ld $(LDFLAGS) $(OBJS) -o $@ -lefi -lgnuefi

%.efi: %.so
    objcopy -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j rel -j rela -j reloc --target=efi-app-$(ARCH) $^ $@

我的

hello.c

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

EFI_STATUS EFIAPI efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
    InitializeLib(ImageHandle, SystemTable);
    Print(L"Hello, World\n");
    return EFI_SUCCESS;
}

我构建,将 hello.efi 复制到磁盘映像上,然后使用以下命令启动 qemu:

qemu-system-x86_64 -enable-kvm -bios /usr/share/qemu/OVMF.fd -nodefaults -display gtk -vga std -hda target

但是在尝试运行它时:

FS0:\> dir
Directory of: FS0:\
12/31/2023    48,181  exit.efi
12/31/2023    41,494  hello.efi
FS0:\> hello.efi
Command Error Status: Unsupported

exit.efi
是 efi 库中的一个库存演示应用程序;它启动了。我不确定它是否应该挂起 qemu,但它确实做了一些事情。我的申请是
hello.efi
。它无法启动。

运行

objdump
以确保文件格式正确:

$ objdump -f -h hello.efi 

hello.efi:     file format pei-x86-64
architecture: i386:x86-64, flags 0x00000030:
HAS_SYMS, HAS_LOCALS
start address 0x0000000000000000

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         00005bf0  0000000000003000  0000000000003000  00000138  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00001d00  0000000000009000  0000000000009000  00005d38  2**5
                  CONTENTS, ALLOC, LOAD, DATA
  2 .dynamic      00000110  000000000000b000  000000000000b000  00007b38  2**3
                  CONTENTS, ALLOC, LOAD, DATA
  3 .dynsym       000000d8  000000000000d000  000000000000d000  00007d38  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA

构建和宿主环境是 debian 12.4 x86_64。

编译过程出了问题。二进制文件顶部的十六进制转储给出:

$ hexdump -C hello.efi | head -n 16
00000000  4d 5a 90 00 03 00 00 00  04 00 00 00 ff ff 00 00  |MZ..........ÿÿ..|
00000010  b8 00 00 00 00 00 00 00  40 00 00 00 00 00 00 00  |¸.......@.......|
00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 80 00 00 00  |................|
00000040  0e 1f ba 0e 00 b4 09 cd  21 b8 01 4c cd 21 54 68  |..º..´.Í!¸.LÍ!Th|
00000050  69 73 20 70 72 6f 67 72  61 6d 20 63 61 6e 6e 6f  |is program canno|
00000060  74 20 62 65 20 72 75 6e  20 69 6e 20 44 4f 53 20  |t be run in DOS |
00000070  6d 6f 64 65 2e 0d 0d 0a  24 00 00 00 00 00 00 00  |mode....$.......|
00000080  50 45 00 00 64 86 04 00  00 00 00 00 38 7f 00 00  |PE..d.......8...|
00000090  12 01 00 00 00 00 05 02  2e 74 65 78 74 00 00 00  |.........text...|
000000a0  f0 5b 00 00 00 30 00 00  00 5c 00 00 38 01 00 00  |ð[...0...\..8...|
000000b0  00 00 00 00 00 00 00 00  00 00 00 00 20 00 50 60  |............ .P`|
000000c0  2e 64 61 74 61 00 00 00  00 1d 00 00 00 90 00 00  |.data...........|
000000d0  00 1e 00 00 38 5d 00 00  00 00 00 00 00 00 00 00  |....8]..........|
000000e0  00 00 00 00 40 00 60 c0  2e 64 79 6e 61 6d 69 63  |....@.`À.dynamic|
000000f0  10 01 00 00 00 b0 00 00  00 02 00 00 38 7b 00 00  |.....°......8{..|

节标题的开头距离 PE 签名太近。该二进制文件将无法加载。

c uefi
1个回答
0
投票

您的 Makefile 中有一些拼写错误:

  • EFIINCS=-I$(EFIINC) -I$(EIFFINC)/$(ARCH) -I$(EFIINC)/协议

  • EFI_CRT_OJBS=$(EFILIB)/crt0-efi-$(ARCH).o

  • objcopy -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j rel -j rela -j reloc --target=efi-app-$(ARCH) $^ $@

我用这个 Makefile 运行了你的代码:

ARCH=x86_64

OBJS=hello.o
TARGET=hello.efi

EFIINC=/usr/include/efi
EFIINCS=-I$(EFIINC) -I$(EFIINC)/$(ARCH) -I$(EFIINC)/protocol
LIB=/usr/lib64
EFILIB=/usr/lib
EFI_CRT_OBJS=$(EFILIB)/crt0-efi-$(ARCH).o
EFI_LDS=$(EFILIB)/elf_$(ARCH)_efi.lds

CFLAGS=$(EFIINCS) -fpic -ffreestanding -fno-stack-protector -fno-stack-check -fshort-wchar -mno-red-zone -maccumulate-outgoing-args 

LDFLAGS=-shared -Bsymbolic -T $(EFI_LDS) -L $(EFILIB) -L $(LIB) $(EFI_CRT_OBJS)

all: $(TARGET)

%.o: %.c
    cc $(CFLAGS) -c $^ -o $@

hello.so: $(OBJS)
    ld $(LDFLAGS) $(OBJS) -o $@ -lgnuefi -lefi

%.efi: %.so
    objcopy -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j .rel.* -j .rela.* -j .reloc --target=efi-app-$(ARCH) --subsystem=10 $^ $@
© www.soinside.com 2019 - 2024. All rights reserved.