I can't seem to make progress; my program won't run and the error message is nonseniscal. A hexdump shows a bad PE binary for no apparent reason:
I started from this tutorial
My 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) $^ $@
My 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;
}
I build, copy hello.efi onto disk image, and start qemu with:
qemu-system-x86_64 -enable-kvm -bios /usr/share/qemu/OVMF.fd -nodefaults -display gtk -vga std -hda target
But on trying to run it:
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
is a stock demo application from efi library; it launches. I'm not sure if it's supposed to hang up qemu or not, but it does something. My application is hello.efi
. It does not start.
Running objdump
to make sure the file format is right:
$ 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
Build and host environment is debian 12.4 x86_64.
Something is very wrong with the compilation process. A hexdump of the top of the binary gives:
$ 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{..|
The section headers start too close to the PE signature. That binary will be unloadable.
You have some typos in your Makefile:
EFIINCS=-I$(EFIINC) -I$(EIFFINC)/$(ARCH) -I$(EFIINC)/protocol
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) $^ $@
I got your code running with this 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 -Wall -DEFI_FUNCION_WRAPPER
LDFLAGS=-shared -Bsymbolic -T $(EFI_LDS) -L $(EFILIB) -L $(LIB) $(EFI_CRT_OBJS)
all: $(TARGET)
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 $^ $@