Issues compiling UEFI application (undefined references)
Posted: Mon Aug 28, 2023 5:49 am
Hey all,
I'm getting started with UEFI applications for a kernel project I'm working on and running into some issues with the first compilation. I've generally followed the UEFI app bare bones guide to a T, but I'm consistently hitting my head on some undefined reference errors in the final of three compilation steps (the linking of the UEFI main executable and data.o). The UEFI application I'm attempting to compile is a basic "Hello, world!" consisting of the following:
Build environment is a rather new install of Ubuntu 23.04, gcc-mingw-w64 version 12.2.0, binutils-mingw-w64 version 2.39.90. I've successfully installed GNU-EFI as well as made the prescribed modifications to gnuefi/lib/data.c. The error occurs on the final leg of the three-part compilation:
First order of business was to check to ensure I got the paths right - GNU-EFI apparently installs to /usr/lib on Ubuntu, as confirmed by dpkg:
At this point, I'm a bit stumped. I can obviously tell something's going on with the linking (not including or correctly binding an EFI lib), but I'm lost on how to address the matter further. I found this thread which has a similar issue, although I'm uncertain what the resolution ultimately was or whether or not it applies to this particular route (using the MinGW cross-compiler). I tried my hand at cobbling a Makefile for the process, although this gives me a different series of errors and I'm almost certain I messed something up somewhere. I'm by no means a novice to C/C++, but I have virtually zero experience with make - I've always gotten by using built-in IDE build systems.
Any ideas? As is the case 90% of the time, I'm sure it boils down to some simple oversight of mine somewhere.
I'm getting started with UEFI applications for a kernel project I'm working on and running into some issues with the first compilation. I've generally followed the UEFI app bare bones guide to a T, but I'm consistently hitting my head on some undefined reference errors in the final of three compilation steps (the linking of the UEFI main executable and data.o). The UEFI application I'm attempting to compile is a basic "Hello, world!" consisting of the following:
Code: Select all
#include <efi.h>
#include <efilib.h>
EFI_STATUS EFIAPI efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
EFI_STATUS Status;
EFI_INPUT_KEY Key;
EFI_SYSTEM_TABLE *ST = SystemTable;
InitializeLib(ImageHandle, SystemTable);
Print(L"Hello, world!\r\n");
Status = ST->ConIn->Reset(ST->ConIn, FALSE);
if (EFI_ERROR(Status))
return Status;
while ((Status = ST->ConIn->ReadKeyStroke(ST->ConIn, &Key)) == EFI_NOT_READY);
return Status;
}
Code: Select all
$ x86_64-w64-mingw32-gcc -ffreestanding -I/usr/include/efi -I/usr/include/efi/x86_64 -I/usr/include/efi/protocol -c -o uefiboot.o uefiboot.c
$ x86_64-w64-mingw32-gcc -ffreestanding -I/usr/include/efi -I/usr/include/efi/x86_64 -I/usr/include/efi/protocol -c -o data.o /usr/lib/data.c
$ x86_64-w64-mingw32-gcc -nostdlib -Wl,-dll -shared -Wl,--subsystem,10 -e efi_main -o BOOTX64.EFI uefiboot.o data.o
# ---> /usr/bin/x86_64-w64-mingw32-ld: uefiboot.o:uefiboot.c:(.text+0x24): undefined reference to `InitializeLib'
# ---> /usr/bin/x86_64-w64-mingw32-ld: uefiboot.o:uefiboot.c:(.text+0x33): undefined reference to `Print'
# ---> collect2: error: ld returned 1 exit status
Code: Select all
$ dpkg -L gnu-efi
/.
/usr
/usr/include
/usr/include/efi
/usr/include/efi/efi.h
/usr/include/efi/efi_nii.h
/usr/include/efi/efi_pxe.h
/usr/include/efi/efiapi.h
# ...
/usr/include/efi/efiui.h
/usr/include/efi/ia32
# ...
/usr/include/efi/lib.h
/usr/include/efi/libsmbios.h
/usr/include/efi/pci22.h
/usr/include/efi/protocol
/usr/include/efi/protocol/adapterdebug.h
# ...
/usr/include/efi/protocol/vgaclass.h
/usr/include/efi/romload.h
/usr/include/efi/x86_64
# ...
/usr/include/efi/x86_64/pe.h
/usr/lib
/usr/lib/crt0-efi-x86_64.o
/usr/lib/elf_x86_64_efi.lds
/usr/lib/libefi.a
/usr/lib/libgnuefi.a
/usr/lib32
# ...
Code: Select all
SHELL = /usr/bin/env zsh
.PHONY: clean
ARCH = $(shell uname -m)
CC = x86_64-w64-mingw32-gcc
CCFLAGS = -fpic -ffreestanding -fno-stack-protector -fno-stack-check -fshort-wchar \
-mno-red-zone -maccumulate-outgoing-args
LDFLAGS = -nostdlib -Wl,-dll -shared -Wl,--subsystem,10 -e efi_main
EFIINC = /usr/include/efi
EFIINCS = -I$(EFIINC) -I$(EFIINC)/$(ARCH) -I$(EFIINC)/protocol
LIB = /usr/lib
EFILIB = $(LIB)
EFI_CRT_OBJS = $(EFI_LIB)/crt0-efi-$(ARCH).o
EFI_LDS = $(EFI_LIB)/elf_$(ARCH)_efi.lds
DATALOC = $(LIB)/data.c
all: uefiboot data bootx64
uefiboot: uefiboot.c
$(CC) $(CCFLAGS) $(EFIINCS) -c -o uefiboot.o uefiboot.c
data: data.c
$(CC) $(CCFLAGS) $(EFIINCS) -c -o data.o $(DATALOC)
bootx64: uefiboot.o data.o
$(CC) $(LDFLAGS) -o BOOTX64.EFI uefiboot.o data.o
clean:
rm -f uefiboot.o data.o BOOTX64.EFI
# Errors:
# x86_64-w64-mingw32-gcc -fpic -ffreestanding -fno-stack-protector -fno-stack-check -fshort-wchar -mno-red-zone -maccumulate-outgoing-args -I/usr/include/efi -I/usr/include/efi/x86_64 -I/usr/include/efi/protocol -c -o uefiboot.o uefiboot.c
# make: *** No rule to make target 'data.c', needed by 'data'. Stop.