lately i have been trying to develop my own “operating system” along with a fairly basic UEFI Bootloader.
I have been following the GNU-EFI guide on OSDev and apparently i have been running into some problems.
Whenever i call a function present in the SystemTable, be it something like SystemTable->ConIn->ReadKeyStroke()
or SystemTable->BootServices->HandleProtocol()
, i either get the application to freeze (the case of calling ReadKeyStroke) or i get the EFI_INVALID_PARAMETERS (0x02) error.
I have tried using the uefi_call_wrapper()
method insted of calling the functions directly but to no avail, as that made the application hang too
Here is my boot.c file:
#include <efi.h>
#include <efierr.h>
#include <efilib.h>
EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
InitializeLib(ImageHandle, SystemTable);
Print(L"Loading kernel...n");
EFI_INPUT_KEY Key;
SystemTable->ConIn->ReadKeyStroke(SystemTable->ConIn, &Key);
Print(L"Pressed key...n");
return EFI_SUCCESS;
}
What i see as the output, even after pressing several keys:
BdsDxe: loading Boot0001 "UEFI EMU HARDDISK QM00001 * from PciRoot (0x0)/Pci (0x1,0x1) /Ata Primary.Ma ster,0x0)
BasDxe: starting Boot0001 "UEFI EMU HARDDISK QM00001 * from PciRoot (0x0) /Pcs (0x1.0x1) /Ata (Primary.M aster,0x0)
Loading kernel...
If i try to call another function instead, like HandleProtocol, i get this:
boot.c:
#include <efi.h>
#include <efierr.h>
#include <efilib.h>
EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
InitializeLib(ImageHandle, SystemTable);
Print(L"Loading kernel...n");
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
EFI_STATUS s = 0;
s = SystemTable->BootServices->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (void**)&LoadedImage);
Print(L"ERROR... %d n", s);
EFI_INPUT_KEY Key;
SystemTable->ConIn->ReadKeyStroke(SystemTable->ConIn, &Key);
Print(L"Pressed key...n");
return EFI_SUCCESS;
}
Output:
BdsDxe: loading Boot0001 "UEFI EMU HARDDISK QM00001 * from PciRoot (0x0)/Pci (0x1,0x1) /Ata Primary.Ma ster,0x0)
BasDxe: starting Boot0001 "UEFI EMU HARDDISK QM00001 * from PciRoot (0x0) /Pcs (0x1.0x1) /Ata (Primary.M aster,0x0)
Loading kernel...
ERROR... 2
Here the makefile that i am using to build the bootloader:
Makefile
SRCDIR = src
OUTDIR = bin
CC = gcc
BOOTLOADER_CFLAGS = -I/usr/include/efi -fpic -ffreestanding -fno-stack-protector -fno-stack-check -fshort-wchar -mno-red-zone -maccumulate-outgoing-args -DEFI_FUNCTION_WRAPPER
KERNEL_CFLAGS = -ffreestanding -fshort-wchar
LD = ld
BOOTLOADER_LDFLAGS = -shared -Bsymbolic -Lgnu-efi/ -Tgnu-efi/elf_x86_64_efi.lds gnu-efi/crt0-efi-x86_64.o -lgnuefi -lefi -nostdlib
KERNEL_LDFLAGS = -T src/kernel/kernel.ld -shared -Bsymbolic -nostdlib
OBJCOPY = objcopy
BOOT = bootx64
KERNEL = kernel
OSNAME = tinyos
KSRCS := $(wildcard $(SRCDIR)/kernel/*.c)
OBJS = $(patsubst $(SRCDIR)/kernel/%.c, $(OUTDIR)/kernel/%.o, $(KSRCS))
# Build the kernel source files
$(OUTDIR)/kernel/%.o: $(SRCDIR)/kernel/%.c
@mkdir -p $(dir $@)
$(CC) $(KERNEL_CFLAGS) -c $^ -o $@
# Link the kernel obj files into one elf executable
$(KERNEL).elf: $(OBJS)
$(LD) $(KERNEL_LDFLAGS) -o $(OUTDIR)/kernel/$(KERNEL).elf $^
# Create the efi application
$(BOOT): $(SRCDIR)/boot/*.c
$(CC) $(BOOTLOADER_CFLAGS) -c $^ -o $(OUTDIR)/boot/$(BOOT).o
$(LD) $(BOOTLOADER_LDFLAGS) $(OUTDIR)/boot/$(BOOT).o -o $(OUTDIR)/boot/$(BOOT).so
$(OBJCOPY) -j .text -j .sdata -j .data -j .rodata -j .dynamic -j .dynsym -j .rel -j .rela -j .rel.* -j .rela.* -j .reloc --target efi-app-x86_64 --subsystem=10 $(OUTDIR)/boot/$(BOOT).so $(OUTDIR)/boot/$(BOOT).efi
# Create the image file and copy the efi application (bootloader) to the efi partition of the image
buildimg: $(BOOT) $(KERNEL).elf
dd if=/dev/zero of=$(OUTDIR)/$(OSNAME).img bs=512 count=93750
mformat -i $(OUTDIR)/$(OSNAME).img ::
mmd -i $(OUTDIR)/$(OSNAME).img ::/efi
mmd -i $(OUTDIR)/$(OSNAME).img ::/efi/boot
mcopy -i $(OUTDIR)/$(OSNAME).img $(OUTDIR)/boot/$(BOOT).efi ::/efi/boot
mcopy -i $(OUTDIR)/$(OSNAME).img $(OUTDIR)/kernel/$(KERNEL).elf ::
run:
qemu-system-x86_64 -cpu qemu64 -bios /usr/share/edk2-ovmf/x64/OVMF.fd -drive file=$(OUTDIR)/$(OSNAME).img,if=ide
I would also like to say that i am using the latest qemu binaries, OVMF firmware, and gnu-efi available on pacman, as i am developing on Arch linux.
If i have forgot to mention or to add something important please tell me as i will be updating this question with all the information needed.
Thank you for your attention