Die Fehlersuche überspringen wir elegant und nutzen ab jetzt “gnu-efi“ für unseren Bootloader…

Quellcodes und Troubleshooting:

Die Fehlersuche führte nach dem letzten Quellcode aus dem vorherigen Artikel zu dutzenden weiteren Versuchen mit angepasstem Quellcode. Da alle diese Versuche leider erfolglos geblieben sind, geht es heute mit einer anderen Strategie weiter.

Wir wechseln jetzt auf “gnu-efi“ und damit soll es viel einfacher werden. Außerdem installieren wir mit Qemu einen Emulator für schnellere Tests unseres Bootloaders.

Installation von “gnu-efi“ und Qemu:

  • sudo apt install -y gnu-efi qemu-system-x86 qemu-utils ovmf build-essential

Quellcode für den Bootloader Version 3:

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

EFI_STATUS
EFIAPI
efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
    InitializeLib(ImageHandle, SystemTable);

    // Begrüßung auf dem Bildschirm
    Print(L"Bootloader erfolgreich geladen!\n");
    Print(L"Versuche OpenVolume() via gnu-efi Wrapper...\n");

    EFI_LOADED_IMAGE *LoadedImage;
    EFI_STATUS Status;

    // 1. Hole das LoadedImage-Protokoll für unseren eigenen Bootloader
    Status = uefi_call_wrapper(SystemTable->BootServices->HandleProtocol, 3, 
                               ImageHandle, &LoadedImageProtocol, (void **)&LoadedImage);
    
    if (EFI_ERROR(Status)) {
        Print(L"Fehler beim Laden des LoadedImage-Protokolls.\n");
        return Status;
    }

    // 2. Hole das SimpleFileSystem-Protokoll vom Quell-Laufwerk
    EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;
    Status = uefi_call_wrapper(SystemTable->BootServices->HandleProtocol, 3, 
                               LoadedImage->DeviceHandle, &FileSystemProtocol, (void **)&Volume);

    if (EFI_ERROR(Status)) {
        Print(L"Fehler: Dateisystem konnte nicht geoeffnet werden.\n");
        return Status;
    }

    // 3. Das magische OpenVolume() ohne Register-Mischmasch!
    EFI_FILE_HANDLE Root;
    Status = uefi_call_wrapper(Volume->OpenVolume, 2, Volume, &Root);

    if (EFI_ERROR(Status)) {
        Print(L"OpenVolume() fehlgeschlagen!\n");
    } else {
        Print(L"Erfolg! OpenVolume() hat fehlerfrei funktioniert.\n");
        // Hier schließt man das Handle im echten Leben wieder, aber für den Test reicht es
    }

    // Kurz warten, damit wir die Ausgabe im Emulator auch sehen
    uefi_call_wrapper(SystemTable->BootServices->Stall, 1, 5000000); // 5 Sekunden

    return EFI_SUCCESS;
}

Quellcode für Makefile:

Wir erstellen jetzt noch eine Datei mit dem Namen “Makefile“ mit folgendem Inhalt:

ARCH            = x86_64
TARGET          = bootloader.efi

CC              = gcc
LD              = ld
OBJCOPY         = objcopy

# Pfade für gnu-efi (Standard unter Ubuntu/Debian)
EFI_INC         = /usr/include/efi
EFI_INCS        = -I$(EFI_INC) -I$(EFI_INC)/$(ARCH) -I$(EFI_INC)/protocol
EFI_LIB         = /usr/lib

CFLAGS          = $(EFI_INCS) -fno-stack-protector -fpic -fshort-wchar \
                  -mno-red-zone -Wall -DEFI_FUNCTION_WRAPPER
ifeq ($(ARCH),x86_64)
  CFLAGS += -m64
endif

LDFLAGS         = -nostdlib -znocombreloc -T $(EFI_LIB)/elf_$(ARCH)_efi.lds \
                  -shared -Bsymbolic $(EFI_LIB)/crt0-efi-$(ARCH).o

LIBS            = $(EFI_LIB)/libefi.a $(EFI_LIB)/libgnuefi.a

all: $(TARGET)

main.o: main.c
	$(CC) $(CFLAGS) -c $< -o $@

bootloader.so: main.o
	$(LD) $(LDFLAGS) $< -o $@ $(LIBS)

$(TARGET): bootloader.so
	$(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym \
	           -j .rel -j .rela -j .reloc --target=efi-app-$(ARCH) $< $@

run: all
	# Virtuelles Verzeichnis für QEMU bauen, das den UEFI-Pfad simuliert
	mkdir -p iso/EFI/BOOT
	cp $(TARGET) iso/EFI/BOOT/BOOTX64.EFI
	# QEMU starten mit OVMF-Bios (Pfad ggf. anpassen falls Arch Linux: /usr/share/edk2/x64/OVMF.fd)
	qemu-system-x86_64 -bios /usr/share/ovmf/OVMF.fd -drive file=fat:rw:iso,format=raw -display gtk

clean:
	rm -rf *.o *.so *.efi iso


Die Datei für den Bootloader nennen wir also “main.c“ und im Terminal starten wir den Compiler mit dem Befehl “make run“. Am Ende sollten wir unsere Datei “bootloader.efi“ erhalten haben und Qemu sollte sich öffnen und jetzt sollte es auch mit dem Hauptverzeichnis klappen…

Von Torsten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert