Das Projekt Bootloader geht in die zweite Runde. Ziel der Reise ist das Hauptverzeichnis…

Zugriff auf Boot-Medium und Hauptverzeichnis:

#include <stdint.h>

// ===================================================================
// 1. BASISTYPEN & DEFINITIONEN
// ===================================================================
typedef unsigned long long UINTN;
typedef long long INTN;
typedef void *EFI_HANDLE;
typedef INTN EFI_STATUS;

#define EFI_SUCCESS 0

typedef struct {
    uint32_t Data1;
    uint16_t Data2;
    uint16_t Data3;
    uint8_t  Data4[8];
} EFI_GUID;

// Die "Ausweise" für die UEFI-Dienste, die wir suchen
static EFI_GUID LoadedImageProtocolGuid = {0x5B1B31A1, 0x9562, 0x11D2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B}};
static EFI_GUID SimpleFileSystemProtocolGuid = {0x0964E5B2, 0x82F1, 0x11D2, {0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B}};

// ====================================================================
// 2. UEFI PROTOKOLLE & FUNKTIONSZEIGER
// ====================================================================

// --- VORAB-DEKLARATIONEN (Damit der Compiler die Typen kennt) ---
struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL;
struct _EFI_FILE_PROTOCOL;

// --- Textausgabe (Kapitel 1) ---
typedef EFI_STATUS (__attribute__((ms_abi)) *EFI_TEXT_STR)(struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, const uint16_t *String);
typedef EFI_STATUS (__attribute__((ms_abi)) *EFI_TEXT_CLR)(struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This);

typedef struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
    void *Reset;
    EFI_TEXT_STR OutputString;
    void *TestString;
    void *QueryMode;
    void *SetMode;
    void *SetAttribute;
    EFI_TEXT_CLR ClearScreen;
} EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;

// --- Dateisystem (Kapitel 2) ---
typedef EFI_STATUS (__attribute__((ms_abi)) *EFI_VOLUME_OPEN)(struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, struct _EFI_FILE_PROTOCOL **Root);

typedef struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL {
    uint64_t Revision;
    EFI_VOLUME_OPEN OpenVolume;
} EFI_SIMPLE_FILE_SYSTEM_PROTOCOL;

typedef struct {
    uint32_t Revision;
    EFI_HANDLE ParentHandle;
    void *SystemTable;
    EFI_HANDLE DeviceHandle; // Zeigt auf das Laufwerk, von dem wir gebootet haben
} EFI_LOADED_IMAGE_PROTOCOL;

// ====================================================================
// 3. UEFI SYSTEM-TABELLEN (Die Infrastruktur)
// ====================================================================

// Boot Services (Wichtig: HandleProtocol muss an der exakten Stelle sitzen!)
typedef EFI_STATUS (__attribute__((ms_abi)) *EFI_HANDLE_PROTOCOL)(EFI_HANDLE Handle, EFI_GUID *Protocol, void **Interface);

typedef struct {
    char Header[24];
    void *RaiseTPL; void *RestoreTPL; void *AllocatePages; void *FreePages;
    void *GetMemoryMap; void *AllocatePool; void *FreePool; void *CreateEvent;
    void *SetTimer; void *WaitForEvent; void *SignalEvent; void *CloseEvent;
    void *CheckEvent; void *InstallProtocolInterface; void *ReinstallProtocolInterface;
    void *UninstallProtocolInterface;
    EFI_HANDLE_PROTOCOL HandleProtocol; // Unsere Suchfunktion
} EFI_BOOT_SERVICES;

// Haupttabelle (Erweitert um StandardError und BootServices am Ende)
typedef struct {
    char Header[24];
    void *FirmwareVendor;
    uint32_t FirmwareRevision;
    EFI_HANDLE ConsoleInHandle;
    void *ConIn;
    EFI_HANDLE ConsoleOutHandle;
    EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
    void *StandardError;       // Platzhalter, um die richtige Reihenfolge zu wahren
    EFI_BOOT_SERVICES *BootServices; // <--- WICHTIG: Hier angedockt!
} EFI_SYSTEM_TABLE;

// ============================================================================
// 4. EINSTIEGSPUNKT (Die Logik)
// ============================================================================
__attribute__((ms_abi))
EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
    
    // 1. Start-Meldung ausgeben
    SystemTable->ConOut->ClearScreen(SystemTable->ConOut);
    SystemTable->ConOut->OutputString(SystemTable->ConOut, (const uint16_t *)L"UEFI-Bootloader \r\n");

    // Variablen für die Protokolle
    EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
    EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem;
    void *RootDirectory = 0; 
    EFI_STATUS status;

    // 2. Welches Laufwerk hat uns gestartet?
    status = SystemTable->BootServices->HandleProtocol(ImageHandle, &LoadedImageProtocolGuid, (void **)&LoadedImage);
    if (status == EFI_SUCCESS) {
        SystemTable->ConOut->OutputString(SystemTable->ConOut, (const uint16_t *)L"[OK] Boot-Medium lokalisiert.\r\n");
        
        // 3. Dateisystem dieses Laufwerks ansprechen
        status = SystemTable->BootServices->HandleProtocol(LoadedImage->DeviceHandle, &SimpleFileSystemProtocolGuid, (void **)&FileSystem);
        if (status == EFI_SUCCESS) {
            SystemTable->ConOut->OutputString(SystemTable->ConOut, (const uint16_t *)L"[OK] FAT-Dateisystem geoeffnet.\r\n");
            
            // 4. Das Hauptverzeichnis (Root) öffnen
            status = FileSystem->OpenVolume(FileSystem, (struct _EFI_FILE_PROTOCOL **)&RootDirectory);
            if (status == EFI_SUCCESS) {
                SystemTable->ConOut->OutputString(SystemTable->ConOut, (const uint16_t *)L"[OK] Hauptverzeichnis (/) erfolgreich geoeffnet!\r\n");
            }
        }
    }

    // Fehlerprüfung, falls irgendwo auf dem Weg etwas schiefging
    if (status != EFI_SUCCESS) {
        SystemTable->ConOut->OutputString(SystemTable->ConOut, (const uint16_t *)L"[FEHLER] Dateisystem-Zugriff fehlgeschlagen!\r\n");
    }

    // Endlosschleife zum Lesen der Ausgaben
    while(1) { 
        __asm__("hlt"); 
    }

    return EFI_SUCCESS;
}

Terminalbefehl für den Ming-Compiler:

  • x86_64-w64-mingw32-gcc -shared -nostdlib -fno-builtin -fshort-wchar -mno-red-zone -Wl,-entry=efi_main -Wl,–subsystem,10 -o BOOTX64.EFI bootloader.c

Praxistest und Statusmeldung:

Der aktuelle Bootloader zeigt jetzt einige neue Textmeldungen. Das Boot-Medium wird bereits erfolgreich lokalisiert und auch das FAT-Dateisystem wird geöffnet. Nur das Hauptverzeichnis wird noch nicht geöffnet und damit geht es im nächsten Artikel weiter…

Von Torsten

Schreibe einen Kommentar

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