mirror of
https://github.com/johndoe6345789/MetalOS.git
synced 2026-04-24 13:45:02 +00:00
Implement UEFI bootloader with all core functionality
Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com>
This commit is contained in:
@@ -13,8 +13,8 @@
|
|||||||
#define MAX_KERNEL_SIZE 0x1000000 // 16MB max
|
#define MAX_KERNEL_SIZE 0x1000000 // 16MB max
|
||||||
|
|
||||||
// Function declarations
|
// Function declarations
|
||||||
EFI_STATUS initialize_graphics(EFI_HANDLE ImageHandle);
|
EFI_STATUS initialize_graphics(EFI_HANDLE ImageHandle, BootInfo* boot_info);
|
||||||
EFI_STATUS load_kernel(EFI_HANDLE ImageHandle);
|
EFI_STATUS load_kernel(EFI_HANDLE ImageHandle, BootInfo* boot_info);
|
||||||
void* get_rsdp(void);
|
void* get_rsdp(void);
|
||||||
void print_string(const CHAR16* str);
|
void print_string(const CHAR16* str);
|
||||||
void print_status(const CHAR16* operation, EFI_STATUS status);
|
void print_status(const CHAR16* operation, EFI_STATUS status);
|
||||||
|
|||||||
@@ -2,12 +2,31 @@
|
|||||||
#define METALOS_BOOTLOADER_EFI_H
|
#define METALOS_BOOTLOADER_EFI_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
// Basic UEFI types
|
// Basic UEFI types
|
||||||
typedef uint64_t EFI_STATUS;
|
typedef uint64_t EFI_STATUS;
|
||||||
typedef void* EFI_HANDLE;
|
typedef void* EFI_HANDLE;
|
||||||
typedef uint64_t UINTN;
|
typedef uint64_t UINTN;
|
||||||
|
typedef uint64_t UINT64;
|
||||||
|
typedef uint32_t UINT32;
|
||||||
|
typedef uint16_t UINT16;
|
||||||
|
typedef uint8_t UINT8;
|
||||||
|
typedef int64_t INTN;
|
||||||
typedef uint16_t CHAR16;
|
typedef uint16_t CHAR16;
|
||||||
|
typedef uint8_t BOOLEAN;
|
||||||
|
typedef void VOID;
|
||||||
|
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
|
||||||
|
// EFI GUID structure
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Data1;
|
||||||
|
UINT16 Data2;
|
||||||
|
UINT16 Data3;
|
||||||
|
UINT8 Data4[8];
|
||||||
|
} EFI_GUID;
|
||||||
|
|
||||||
// EFI Status codes
|
// EFI Status codes
|
||||||
#define EFI_SUCCESS 0
|
#define EFI_SUCCESS 0
|
||||||
@@ -19,36 +38,48 @@ typedef uint16_t CHAR16;
|
|||||||
#define EFI_NOT_FOUND 14
|
#define EFI_NOT_FOUND 14
|
||||||
|
|
||||||
// EFI Memory types
|
// EFI Memory types
|
||||||
#define EfiReservedMemoryType 0
|
typedef enum {
|
||||||
#define EfiLoaderCode 1
|
EfiReservedMemoryType,
|
||||||
#define EfiLoaderData 2
|
EfiLoaderCode,
|
||||||
#define EfiBootServicesCode 3
|
EfiLoaderData,
|
||||||
#define EfiBootServicesData 4
|
EfiBootServicesCode,
|
||||||
#define EfiRuntimeServicesCode 5
|
EfiBootServicesData,
|
||||||
#define EfiRuntimeServicesData 6
|
EfiRuntimeServicesCode,
|
||||||
#define EfiConventionalMemory 7
|
EfiRuntimeServicesData,
|
||||||
#define EfiUnusableMemory 8
|
EfiConventionalMemory,
|
||||||
#define EfiACPIReclaimMemory 9
|
EfiUnusableMemory,
|
||||||
#define EfiACPIMemoryNVS 10
|
EfiACPIReclaimMemory,
|
||||||
#define EfiMemoryMappedIO 11
|
EfiACPIMemoryNVS,
|
||||||
#define EfiMemoryMappedIOPortSpace 12
|
EfiMemoryMappedIO,
|
||||||
#define EfiPalCode 13
|
EfiMemoryMappedIOPortSpace,
|
||||||
#define EfiPersistentMemory 14
|
EfiPalCode,
|
||||||
|
EfiPersistentMemory,
|
||||||
|
EfiMaxMemoryType
|
||||||
|
} EFI_MEMORY_TYPE;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t Type;
|
UINT32 Type;
|
||||||
uint64_t PhysicalStart;
|
UINT64 PhysicalStart;
|
||||||
uint64_t VirtualStart;
|
UINT64 VirtualStart;
|
||||||
uint64_t NumberOfPages;
|
UINT64 NumberOfPages;
|
||||||
uint64_t Attribute;
|
UINT64 Attribute;
|
||||||
} EFI_MEMORY_DESCRIPTOR;
|
} EFI_MEMORY_DESCRIPTOR;
|
||||||
|
|
||||||
|
// EFI Table Header
|
||||||
|
typedef struct {
|
||||||
|
UINT64 Signature;
|
||||||
|
UINT32 Revision;
|
||||||
|
UINT32 HeaderSize;
|
||||||
|
UINT32 CRC32;
|
||||||
|
UINT32 Reserved;
|
||||||
|
} EFI_TABLE_HEADER;
|
||||||
|
|
||||||
// Graphics Output Protocol structures
|
// Graphics Output Protocol structures
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t RedMask;
|
UINT32 RedMask;
|
||||||
uint32_t GreenMask;
|
UINT32 GreenMask;
|
||||||
uint32_t BlueMask;
|
UINT32 BlueMask;
|
||||||
uint32_t ReservedMask;
|
UINT32 ReservedMask;
|
||||||
} EFI_PIXEL_BITMASK;
|
} EFI_PIXEL_BITMASK;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -60,39 +91,323 @@ typedef enum {
|
|||||||
} EFI_GRAPHICS_PIXEL_FORMAT;
|
} EFI_GRAPHICS_PIXEL_FORMAT;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t Version;
|
UINT32 Version;
|
||||||
uint32_t HorizontalResolution;
|
UINT32 HorizontalResolution;
|
||||||
uint32_t VerticalResolution;
|
UINT32 VerticalResolution;
|
||||||
EFI_GRAPHICS_PIXEL_FORMAT PixelFormat;
|
EFI_GRAPHICS_PIXEL_FORMAT PixelFormat;
|
||||||
EFI_PIXEL_BITMASK PixelInformation;
|
EFI_PIXEL_BITMASK PixelInformation;
|
||||||
uint32_t PixelsPerScanLine;
|
UINT32 PixelsPerScanLine;
|
||||||
} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION;
|
} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t MaxMode;
|
UINT32 MaxMode;
|
||||||
uint32_t Mode;
|
UINT32 Mode;
|
||||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* Info;
|
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* Info;
|
||||||
UINTN SizeOfInfo;
|
UINTN SizeOfInfo;
|
||||||
uint64_t FrameBufferBase;
|
UINT64 FrameBufferBase;
|
||||||
UINTN FrameBufferSize;
|
UINTN FrameBufferSize;
|
||||||
} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE;
|
} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE;
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
struct _EFI_GRAPHICS_OUTPUT_PROTOCOL;
|
||||||
|
struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
|
||||||
|
struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL;
|
||||||
|
struct _EFI_FILE_PROTOCOL;
|
||||||
|
|
||||||
|
// Graphics Output Protocol
|
||||||
|
typedef EFI_STATUS (*EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE)(
|
||||||
|
struct _EFI_GRAPHICS_OUTPUT_PROTOCOL* This,
|
||||||
|
UINT32 ModeNumber,
|
||||||
|
UINTN* SizeOfInfo,
|
||||||
|
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION** Info
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef EFI_STATUS (*EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE)(
|
||||||
|
struct _EFI_GRAPHICS_OUTPUT_PROTOCOL* This,
|
||||||
|
UINT32 ModeNumber
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef struct _EFI_GRAPHICS_OUTPUT_PROTOCOL {
|
||||||
|
EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE QueryMode;
|
||||||
|
EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE SetMode;
|
||||||
|
VOID* Blt; // We don't need this
|
||||||
|
EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE* Mode;
|
||||||
|
} EFI_GRAPHICS_OUTPUT_PROTOCOL;
|
||||||
|
|
||||||
|
// Simple Text Output Protocol
|
||||||
|
typedef EFI_STATUS (*EFI_TEXT_STRING)(
|
||||||
|
struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL* This,
|
||||||
|
CHAR16* String
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef EFI_STATUS (*EFI_TEXT_RESET)(
|
||||||
|
struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL* This,
|
||||||
|
BOOLEAN ExtendedVerification
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL {
|
||||||
|
EFI_TEXT_RESET Reset;
|
||||||
|
EFI_TEXT_STRING OutputString;
|
||||||
|
VOID* TestString;
|
||||||
|
VOID* QueryMode;
|
||||||
|
VOID* SetMode;
|
||||||
|
VOID* SetAttribute;
|
||||||
|
VOID* ClearScreen;
|
||||||
|
VOID* SetCursorPosition;
|
||||||
|
VOID* EnableCursor;
|
||||||
|
VOID* Mode;
|
||||||
|
} EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
|
||||||
|
|
||||||
|
// File Protocol
|
||||||
|
#define EFI_FILE_MODE_READ 0x0000000000000001
|
||||||
|
#define EFI_FILE_MODE_WRITE 0x0000000000000002
|
||||||
|
#define EFI_FILE_MODE_CREATE 0x8000000000000000
|
||||||
|
|
||||||
|
typedef EFI_STATUS (*EFI_FILE_OPEN)(
|
||||||
|
struct _EFI_FILE_PROTOCOL* This,
|
||||||
|
struct _EFI_FILE_PROTOCOL** NewHandle,
|
||||||
|
CHAR16* FileName,
|
||||||
|
UINT64 OpenMode,
|
||||||
|
UINT64 Attributes
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef EFI_STATUS (*EFI_FILE_CLOSE)(
|
||||||
|
struct _EFI_FILE_PROTOCOL* This
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef EFI_STATUS (*EFI_FILE_READ)(
|
||||||
|
struct _EFI_FILE_PROTOCOL* This,
|
||||||
|
UINTN* BufferSize,
|
||||||
|
VOID* Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef EFI_STATUS (*EFI_FILE_GET_INFO)(
|
||||||
|
struct _EFI_FILE_PROTOCOL* This,
|
||||||
|
EFI_GUID* InformationType,
|
||||||
|
UINTN* BufferSize,
|
||||||
|
VOID* Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef struct _EFI_FILE_PROTOCOL {
|
||||||
|
UINT64 Revision;
|
||||||
|
EFI_FILE_OPEN Open;
|
||||||
|
EFI_FILE_CLOSE Close;
|
||||||
|
VOID* Delete;
|
||||||
|
EFI_FILE_READ Read;
|
||||||
|
VOID* Write;
|
||||||
|
VOID* GetPosition;
|
||||||
|
VOID* SetPosition;
|
||||||
|
EFI_FILE_GET_INFO GetInfo;
|
||||||
|
VOID* SetInfo;
|
||||||
|
VOID* Flush;
|
||||||
|
} EFI_FILE_PROTOCOL;
|
||||||
|
|
||||||
|
// Simple File System Protocol
|
||||||
|
typedef EFI_STATUS (*EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME)(
|
||||||
|
struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* This,
|
||||||
|
EFI_FILE_PROTOCOL** Root
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL {
|
||||||
|
UINT64 Revision;
|
||||||
|
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume;
|
||||||
|
} EFI_SIMPLE_FILE_SYSTEM_PROTOCOL;
|
||||||
|
|
||||||
|
// Loaded Image Protocol
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Revision;
|
||||||
|
EFI_HANDLE ParentHandle;
|
||||||
|
VOID* SystemTable;
|
||||||
|
EFI_HANDLE DeviceHandle;
|
||||||
|
VOID* FilePath;
|
||||||
|
VOID* Reserved;
|
||||||
|
UINT32 LoadOptionsSize;
|
||||||
|
VOID* LoadOptions;
|
||||||
|
VOID* ImageBase;
|
||||||
|
UINT64 ImageSize;
|
||||||
|
EFI_MEMORY_TYPE ImageCodeType;
|
||||||
|
EFI_MEMORY_TYPE ImageDataType;
|
||||||
|
VOID* Unload;
|
||||||
|
} EFI_LOADED_IMAGE_PROTOCOL;
|
||||||
|
|
||||||
|
// Protocol GUIDs
|
||||||
|
#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \
|
||||||
|
{ 0x9042a9de, 0x23dc, 0x4a38, {0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a} }
|
||||||
|
|
||||||
|
#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \
|
||||||
|
{ 0x964e5b22, 0x6459, 0x11d2, {0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b} }
|
||||||
|
|
||||||
|
#define EFI_LOADED_IMAGE_PROTOCOL_GUID \
|
||||||
|
{ 0x5b1b31a1, 0x9562, 0x11d2, {0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b} }
|
||||||
|
|
||||||
|
#define EFI_FILE_INFO_GUID \
|
||||||
|
{ 0x09576e92, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b} }
|
||||||
|
|
||||||
|
#define EFI_ACPI_20_TABLE_GUID \
|
||||||
|
{ 0x8868e871, 0xe4f1, 0x11d3, {0xbc, 0x22, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81} }
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
struct _EFI_BOOT_SERVICES;
|
||||||
|
struct _EFI_SYSTEM_TABLE;
|
||||||
|
|
||||||
|
// Boot Services functions
|
||||||
|
typedef EFI_STATUS (*EFI_LOCATE_PROTOCOL)(
|
||||||
|
EFI_GUID* Protocol,
|
||||||
|
VOID* Registration,
|
||||||
|
VOID** Interface
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef EFI_STATUS (*EFI_HANDLE_PROTOCOL)(
|
||||||
|
EFI_HANDLE Handle,
|
||||||
|
EFI_GUID* Protocol,
|
||||||
|
VOID** Interface
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef EFI_STATUS (*EFI_GET_MEMORY_MAP)(
|
||||||
|
UINTN* MemoryMapSize,
|
||||||
|
EFI_MEMORY_DESCRIPTOR* MemoryMap,
|
||||||
|
UINTN* MapKey,
|
||||||
|
UINTN* DescriptorSize,
|
||||||
|
UINT32* DescriptorVersion
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef EFI_STATUS (*EFI_ALLOCATE_POOL)(
|
||||||
|
EFI_MEMORY_TYPE PoolType,
|
||||||
|
UINTN Size,
|
||||||
|
VOID** Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef EFI_STATUS (*EFI_FREE_POOL)(
|
||||||
|
VOID* Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef EFI_STATUS (*EFI_EXIT_BOOT_SERVICES)(
|
||||||
|
EFI_HANDLE ImageHandle,
|
||||||
|
UINTN MapKey
|
||||||
|
);
|
||||||
|
|
||||||
|
// Boot Services Table
|
||||||
|
typedef struct _EFI_BOOT_SERVICES {
|
||||||
|
EFI_TABLE_HEADER Hdr;
|
||||||
|
|
||||||
|
// Task Priority Services (stub pointers)
|
||||||
|
VOID* RaiseTPL;
|
||||||
|
VOID* RestoreTPL;
|
||||||
|
|
||||||
|
// Memory Services (stub pointers for unused)
|
||||||
|
VOID* AllocatePages;
|
||||||
|
VOID* FreePages;
|
||||||
|
EFI_GET_MEMORY_MAP GetMemoryMap;
|
||||||
|
EFI_ALLOCATE_POOL AllocatePool;
|
||||||
|
EFI_FREE_POOL FreePool;
|
||||||
|
|
||||||
|
// Event & Timer Services (stub pointers)
|
||||||
|
VOID* CreateEvent;
|
||||||
|
VOID* SetTimer;
|
||||||
|
VOID* WaitForEvent;
|
||||||
|
VOID* SignalEvent;
|
||||||
|
VOID* CloseEvent;
|
||||||
|
VOID* CheckEvent;
|
||||||
|
|
||||||
|
// Protocol Handler Services (stub pointers for unused)
|
||||||
|
VOID* InstallProtocolInterface;
|
||||||
|
VOID* ReinstallProtocolInterface;
|
||||||
|
VOID* UninstallProtocolInterface;
|
||||||
|
EFI_HANDLE_PROTOCOL HandleProtocol;
|
||||||
|
VOID* Reserved;
|
||||||
|
VOID* RegisterProtocolNotify;
|
||||||
|
VOID* LocateHandle;
|
||||||
|
VOID* LocateDevicePath;
|
||||||
|
VOID* InstallConfigurationTable;
|
||||||
|
|
||||||
|
// Image Services (stub pointers)
|
||||||
|
VOID* LoadImage;
|
||||||
|
VOID* StartImage;
|
||||||
|
VOID* Exit;
|
||||||
|
VOID* UnloadImage;
|
||||||
|
EFI_EXIT_BOOT_SERVICES ExitBootServices;
|
||||||
|
|
||||||
|
// Miscellaneous Services (stub pointers)
|
||||||
|
VOID* GetNextMonotonicCount;
|
||||||
|
VOID* Stall;
|
||||||
|
VOID* SetWatchdogTimer;
|
||||||
|
|
||||||
|
// Driver Support Services (stub pointers)
|
||||||
|
VOID* ConnectController;
|
||||||
|
VOID* DisconnectController;
|
||||||
|
|
||||||
|
// Open and Close Protocol Services (stub pointers)
|
||||||
|
VOID* OpenProtocol;
|
||||||
|
VOID* CloseProtocol;
|
||||||
|
VOID* OpenProtocolInformation;
|
||||||
|
|
||||||
|
// Library Services (stub pointers)
|
||||||
|
VOID* ProtocolsPerHandle;
|
||||||
|
VOID* LocateHandleBuffer;
|
||||||
|
EFI_LOCATE_PROTOCOL LocateProtocol;
|
||||||
|
VOID* InstallMultipleProtocolInterfaces;
|
||||||
|
VOID* UninstallMultipleProtocolInterfaces;
|
||||||
|
|
||||||
|
// CRC Services (stub pointers)
|
||||||
|
VOID* CalculateCrc32;
|
||||||
|
|
||||||
|
// Miscellaneous Services (stub pointers)
|
||||||
|
VOID* CopyMem;
|
||||||
|
VOID* SetMem;
|
||||||
|
VOID* CreateEventEx;
|
||||||
|
} EFI_BOOT_SERVICES;
|
||||||
|
|
||||||
|
// Configuration Table
|
||||||
|
typedef struct {
|
||||||
|
EFI_GUID VendorGuid;
|
||||||
|
VOID* VendorTable;
|
||||||
|
} EFI_CONFIGURATION_TABLE;
|
||||||
|
|
||||||
|
// System Table
|
||||||
|
typedef struct _EFI_SYSTEM_TABLE {
|
||||||
|
EFI_TABLE_HEADER Hdr;
|
||||||
|
CHAR16* FirmwareVendor;
|
||||||
|
UINT32 FirmwareRevision;
|
||||||
|
EFI_HANDLE ConsoleInHandle;
|
||||||
|
VOID* ConIn;
|
||||||
|
EFI_HANDLE ConsoleOutHandle;
|
||||||
|
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL* ConOut;
|
||||||
|
EFI_HANDLE StandardErrorHandle;
|
||||||
|
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL* StdErr;
|
||||||
|
VOID* RuntimeServices;
|
||||||
|
EFI_BOOT_SERVICES* BootServices;
|
||||||
|
UINTN NumberOfTableEntries;
|
||||||
|
EFI_CONFIGURATION_TABLE* ConfigurationTable;
|
||||||
|
} EFI_SYSTEM_TABLE;
|
||||||
|
|
||||||
|
// File Info structure
|
||||||
|
typedef struct {
|
||||||
|
UINT64 Size;
|
||||||
|
UINT64 FileSize;
|
||||||
|
UINT64 PhysicalSize;
|
||||||
|
VOID* CreateTime;
|
||||||
|
VOID* LastAccessTime;
|
||||||
|
VOID* ModificationTime;
|
||||||
|
UINT64 Attribute;
|
||||||
|
CHAR16 FileName[256];
|
||||||
|
} EFI_FILE_INFO;
|
||||||
|
|
||||||
// Boot information passed to kernel
|
// Boot information passed to kernel
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t memory_map_size;
|
UINT64 memory_map_size;
|
||||||
uint64_t memory_map_descriptor_size;
|
UINT64 memory_map_descriptor_size;
|
||||||
EFI_MEMORY_DESCRIPTOR* memory_map;
|
EFI_MEMORY_DESCRIPTOR* memory_map;
|
||||||
|
|
||||||
uint64_t framebuffer_base;
|
UINT64 framebuffer_base;
|
||||||
uint32_t framebuffer_width;
|
UINT32 framebuffer_width;
|
||||||
uint32_t framebuffer_height;
|
UINT32 framebuffer_height;
|
||||||
uint32_t framebuffer_pitch;
|
UINT32 framebuffer_pitch;
|
||||||
uint32_t framebuffer_bpp;
|
UINT32 framebuffer_bpp;
|
||||||
|
|
||||||
uint64_t kernel_base;
|
UINT64 kernel_base;
|
||||||
uint64_t kernel_size;
|
UINT64 kernel_size;
|
||||||
|
|
||||||
void* rsdp; // ACPI RSDP pointer
|
VOID* rsdp; // ACPI RSDP pointer
|
||||||
} BootInfo;
|
} BootInfo;
|
||||||
|
|
||||||
#endif // METALOS_BOOTLOADER_EFI_H
|
#endif // METALOS_BOOTLOADER_EFI_H
|
||||||
|
|||||||
@@ -14,50 +14,42 @@
|
|||||||
#include "bootloader.h"
|
#include "bootloader.h"
|
||||||
#include "efi.h"
|
#include "efi.h"
|
||||||
|
|
||||||
// Simplified UEFI System Table structures (bare minimum)
|
|
||||||
// In a real implementation, we'd use gnu-efi or full UEFI headers
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint64_t Signature;
|
|
||||||
uint32_t Revision;
|
|
||||||
uint32_t HeaderSize;
|
|
||||||
uint32_t CRC32;
|
|
||||||
uint32_t Reserved;
|
|
||||||
} EFI_TABLE_HEADER;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
EFI_TABLE_HEADER Hdr;
|
|
||||||
// Simplified - real implementation would have all console I/O functions
|
|
||||||
void* pad[10];
|
|
||||||
} EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
EFI_TABLE_HEADER Hdr;
|
|
||||||
CHAR16* FirmwareVendor;
|
|
||||||
uint32_t FirmwareRevision;
|
|
||||||
EFI_HANDLE ConsoleInHandle;
|
|
||||||
void* ConIn;
|
|
||||||
EFI_HANDLE ConsoleOutHandle;
|
|
||||||
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL* ConOut;
|
|
||||||
EFI_HANDLE StandardErrorHandle;
|
|
||||||
void* StdErr;
|
|
||||||
void* RuntimeServices;
|
|
||||||
void* BootServices;
|
|
||||||
UINTN NumberOfTableEntries;
|
|
||||||
void* ConfigurationTable;
|
|
||||||
} EFI_SYSTEM_TABLE;
|
|
||||||
|
|
||||||
// Global system table
|
// Global system table
|
||||||
static EFI_SYSTEM_TABLE* gST = NULL;
|
static EFI_SYSTEM_TABLE* gST = NULL;
|
||||||
|
static EFI_BOOT_SERVICES* gBS = NULL;
|
||||||
|
|
||||||
|
// Helper: Compare GUIDs
|
||||||
|
static int guid_compare(const EFI_GUID* a, const EFI_GUID* b) {
|
||||||
|
if (a->Data1 != b->Data1) return 0;
|
||||||
|
if (a->Data2 != b->Data2) return 0;
|
||||||
|
if (a->Data3 != b->Data3) return 0;
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
if (a->Data4[i] != b->Data4[i]) return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper: Memory set
|
||||||
|
static void* memset(void* s, int c, size_t n) {
|
||||||
|
unsigned char* p = s;
|
||||||
|
while (n--) *p++ = (unsigned char)c;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper: Memory copy
|
||||||
|
static void* memcpy(void* dest, const void* src, size_t n) {
|
||||||
|
unsigned char* d = dest;
|
||||||
|
const unsigned char* s = src;
|
||||||
|
while (n--) *d++ = *s++;
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Print a string to the UEFI console
|
* Print a string to the UEFI console
|
||||||
*/
|
*/
|
||||||
void print_string(const CHAR16* str) {
|
void print_string(const CHAR16* str) {
|
||||||
(void)str;
|
|
||||||
if (gST && gST->ConOut) {
|
if (gST && gST->ConOut) {
|
||||||
// In real implementation: gST->ConOut->OutputString(gST->ConOut, (CHAR16*)str);
|
gST->ConOut->OutputString(gST->ConOut, (CHAR16*)str);
|
||||||
// For now, this is a stub
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,23 +57,38 @@ void print_string(const CHAR16* str) {
|
|||||||
* Print operation status
|
* Print operation status
|
||||||
*/
|
*/
|
||||||
void print_status(const CHAR16* operation, EFI_STATUS status) {
|
void print_status(const CHAR16* operation, EFI_STATUS status) {
|
||||||
// Stub for status reporting
|
print_string(operation);
|
||||||
(void)operation;
|
if (status == EFI_SUCCESS) {
|
||||||
(void)status;
|
print_string(u" [OK]\r\n");
|
||||||
|
} else {
|
||||||
|
print_string(u" [FAILED]\r\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize graphics output protocol
|
* Initialize graphics output protocol
|
||||||
*/
|
*/
|
||||||
EFI_STATUS initialize_graphics(EFI_HANDLE ImageHandle) {
|
EFI_STATUS initialize_graphics(EFI_HANDLE ImageHandle, BootInfo* boot_info) {
|
||||||
(void)ImageHandle;
|
(void)ImageHandle;
|
||||||
|
EFI_STATUS status;
|
||||||
|
EFI_GRAPHICS_OUTPUT_PROTOCOL* gop = NULL;
|
||||||
|
|
||||||
// TODO: Implement graphics initialization
|
// Locate Graphics Output Protocol
|
||||||
// 1. Locate Graphics Output Protocol
|
EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
||||||
// 2. Query available modes
|
status = gBS->LocateProtocol(&gop_guid, NULL, (void**)&gop);
|
||||||
// 3. Select appropriate resolution (prefer 1920x1080 or 1280x720)
|
|
||||||
// 4. Set mode
|
if (status != EFI_SUCCESS || gop == NULL) {
|
||||||
// 5. Clear screen
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use current mode (don't try to change it - keep it simple)
|
||||||
|
if (gop->Mode && gop->Mode->Info) {
|
||||||
|
boot_info->framebuffer_base = gop->Mode->FrameBufferBase;
|
||||||
|
boot_info->framebuffer_width = gop->Mode->Info->HorizontalResolution;
|
||||||
|
boot_info->framebuffer_height = gop->Mode->Info->VerticalResolution;
|
||||||
|
boot_info->framebuffer_pitch = gop->Mode->Info->PixelsPerScanLine * 4; // Assume 32-bit
|
||||||
|
boot_info->framebuffer_bpp = 32; // Assume 32-bit color
|
||||||
|
}
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -89,14 +96,84 @@ EFI_STATUS initialize_graphics(EFI_HANDLE ImageHandle) {
|
|||||||
/*
|
/*
|
||||||
* Load kernel from disk
|
* Load kernel from disk
|
||||||
*/
|
*/
|
||||||
EFI_STATUS load_kernel(EFI_HANDLE ImageHandle) {
|
EFI_STATUS load_kernel(EFI_HANDLE ImageHandle, BootInfo* boot_info) {
|
||||||
(void)ImageHandle;
|
EFI_STATUS status;
|
||||||
|
EFI_LOADED_IMAGE_PROTOCOL* loaded_image = NULL;
|
||||||
|
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* fs = NULL;
|
||||||
|
EFI_FILE_PROTOCOL* root = NULL;
|
||||||
|
EFI_FILE_PROTOCOL* kernel_file = NULL;
|
||||||
|
|
||||||
// TODO: Implement kernel loading
|
// Get loaded image protocol to find our boot device
|
||||||
// 1. Open volume protocol
|
EFI_GUID loaded_image_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
|
||||||
// 2. Open kernel file (metalos.bin)
|
status = gBS->HandleProtocol(ImageHandle, &loaded_image_guid, (void**)&loaded_image);
|
||||||
// 3. Read kernel into memory at KERNEL_LOAD_ADDRESS
|
if (status != EFI_SUCCESS) {
|
||||||
// 4. Verify kernel signature/checksum
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open file system protocol on boot device
|
||||||
|
EFI_GUID fs_guid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
|
||||||
|
status = gBS->HandleProtocol(loaded_image->DeviceHandle, &fs_guid, (void**)&fs);
|
||||||
|
if (status != EFI_SUCCESS) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open root directory
|
||||||
|
status = fs->OpenVolume(fs, &root);
|
||||||
|
if (status != EFI_SUCCESS) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open kernel file
|
||||||
|
status = root->Open(root, &kernel_file, u"metalos.bin", EFI_FILE_MODE_READ, 0);
|
||||||
|
if (status != EFI_SUCCESS) {
|
||||||
|
root->Close(root);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get file size
|
||||||
|
EFI_GUID file_info_guid = EFI_FILE_INFO_GUID;
|
||||||
|
EFI_FILE_INFO file_info;
|
||||||
|
UINTN info_size = sizeof(EFI_FILE_INFO);
|
||||||
|
status = kernel_file->GetInfo(kernel_file, &file_info_guid, &info_size, &file_info);
|
||||||
|
if (status != EFI_SUCCESS) {
|
||||||
|
kernel_file->Close(kernel_file);
|
||||||
|
root->Close(root);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT64 kernel_size = file_info.FileSize;
|
||||||
|
|
||||||
|
// Allocate memory for kernel at KERNEL_LOAD_ADDRESS
|
||||||
|
// We'll just use AllocatePool for simplicity
|
||||||
|
VOID* kernel_buffer = NULL;
|
||||||
|
status = gBS->AllocatePool(EfiLoaderData, kernel_size, &kernel_buffer);
|
||||||
|
if (status != EFI_SUCCESS) {
|
||||||
|
kernel_file->Close(kernel_file);
|
||||||
|
root->Close(root);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read kernel into memory
|
||||||
|
UINTN read_size = kernel_size;
|
||||||
|
status = kernel_file->Read(kernel_file, &read_size, kernel_buffer);
|
||||||
|
if (status != EFI_SUCCESS || read_size != kernel_size) {
|
||||||
|
gBS->FreePool(kernel_buffer);
|
||||||
|
kernel_file->Close(kernel_file);
|
||||||
|
root->Close(root);
|
||||||
|
return EFI_LOAD_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy kernel to final location
|
||||||
|
memcpy((void*)KERNEL_LOAD_ADDRESS, kernel_buffer, kernel_size);
|
||||||
|
|
||||||
|
// Store kernel info
|
||||||
|
boot_info->kernel_base = KERNEL_LOAD_ADDRESS;
|
||||||
|
boot_info->kernel_size = kernel_size;
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
gBS->FreePool(kernel_buffer);
|
||||||
|
kernel_file->Close(kernel_file);
|
||||||
|
root->Close(root);
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -105,7 +182,15 @@ EFI_STATUS load_kernel(EFI_HANDLE ImageHandle) {
|
|||||||
* Get ACPI RSDP (Root System Description Pointer)
|
* Get ACPI RSDP (Root System Description Pointer)
|
||||||
*/
|
*/
|
||||||
void* get_rsdp(void) {
|
void* get_rsdp(void) {
|
||||||
// TODO: Search configuration tables for ACPI RSDP
|
EFI_GUID acpi_20_guid = EFI_ACPI_20_TABLE_GUID;
|
||||||
|
|
||||||
|
// Search configuration tables for ACPI 2.0 table
|
||||||
|
for (UINTN i = 0; i < gST->NumberOfTableEntries; i++) {
|
||||||
|
if (guid_compare(&gST->ConfigurationTable[i].VendorGuid, &acpi_20_guid)) {
|
||||||
|
return gST->ConfigurationTable[i].VendorTable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,40 +199,103 @@ void* get_rsdp(void) {
|
|||||||
*/
|
*/
|
||||||
EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) {
|
EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) {
|
||||||
EFI_STATUS status;
|
EFI_STATUS status;
|
||||||
BootInfo boot_info = {0};
|
BootInfo boot_info;
|
||||||
(void)boot_info;
|
UINTN map_key;
|
||||||
|
UINT32 descriptor_version;
|
||||||
|
|
||||||
|
// Initialize
|
||||||
gST = SystemTable;
|
gST = SystemTable;
|
||||||
|
gBS = SystemTable->BootServices;
|
||||||
|
memset(&boot_info, 0, sizeof(BootInfo));
|
||||||
|
|
||||||
// Print banner
|
// Print banner
|
||||||
print_string(u"MetalOS v0.1 - MINIMAL BOOTLOADER\r\n");
|
print_string(u"MetalOS v0.1 - MINIMAL BOOTLOADER\r\n");
|
||||||
print_string(u"==================================\r\n\r\n");
|
print_string(u"==================================\r\n\r\n");
|
||||||
|
|
||||||
// Get framebuffer (don't care about resolution, take what UEFI gives us)
|
// Get framebuffer (don't care about resolution, take what UEFI gives us)
|
||||||
print_string(u"Getting framebuffer...\r\n");
|
print_string(u"Getting framebuffer...");
|
||||||
status = initialize_graphics(ImageHandle);
|
status = initialize_graphics(ImageHandle, &boot_info);
|
||||||
|
print_status(u"", status);
|
||||||
if (status != EFI_SUCCESS) {
|
if (status != EFI_SUCCESS) {
|
||||||
print_string(u"WARNING: No graphics, continuing anyway...\r\n");
|
print_string(u"WARNING: No graphics, continuing anyway...\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load kernel (just read metalos.bin, don't overthink it)
|
// Load kernel (just read metalos.bin, don't overthink it)
|
||||||
print_string(u"Loading kernel...\r\n");
|
print_string(u"Loading kernel...");
|
||||||
status = load_kernel(ImageHandle);
|
status = load_kernel(ImageHandle, &boot_info);
|
||||||
|
print_status(u"", status);
|
||||||
if (status != EFI_SUCCESS) {
|
if (status != EFI_SUCCESS) {
|
||||||
print_string(u"ERROR: Can't load kernel\r\n");
|
print_string(u"ERROR: Can't load kernel\r\n");
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get RSDP for ACPI
|
||||||
|
print_string(u"Getting ACPI RSDP...");
|
||||||
|
boot_info.rsdp = get_rsdp();
|
||||||
|
if (boot_info.rsdp) {
|
||||||
|
print_string(u" [OK]\r\n");
|
||||||
|
} else {
|
||||||
|
print_string(u" [NOT FOUND]\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
// Get memory map (minimal info)
|
// Get memory map (minimal info)
|
||||||
print_string(u"Getting memory map...\r\n");
|
print_string(u"Getting memory map...");
|
||||||
// TODO: GetMemoryMap
|
|
||||||
|
// First call to get size
|
||||||
|
UINTN memory_map_size = 0;
|
||||||
|
UINTN descriptor_size = 0;
|
||||||
|
status = gBS->GetMemoryMap(&memory_map_size, NULL, &map_key, &descriptor_size, &descriptor_version);
|
||||||
|
|
||||||
|
// Allocate buffer (add extra space for potential allocations)
|
||||||
|
memory_map_size += 2 * descriptor_size;
|
||||||
|
EFI_MEMORY_DESCRIPTOR* memory_map = NULL;
|
||||||
|
status = gBS->AllocatePool(EfiLoaderData, memory_map_size, (void**)&memory_map);
|
||||||
|
if (status != EFI_SUCCESS) {
|
||||||
|
print_string(u" [FAILED]\r\n");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second call to get actual memory map
|
||||||
|
status = gBS->GetMemoryMap(&memory_map_size, memory_map, &map_key, &descriptor_size, &descriptor_version);
|
||||||
|
if (status != EFI_SUCCESS) {
|
||||||
|
print_string(u" [FAILED]\r\n");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
print_string(u" [OK]\r\n");
|
||||||
|
|
||||||
|
// Store memory map info
|
||||||
|
boot_info.memory_map = memory_map;
|
||||||
|
boot_info.memory_map_size = memory_map_size;
|
||||||
|
boot_info.memory_map_descriptor_size = descriptor_size;
|
||||||
|
|
||||||
// Exit boot services (point of no return)
|
// Exit boot services (point of no return)
|
||||||
print_string(u"Exiting UEFI boot services...\r\n");
|
print_string(u"Exiting UEFI boot services...");
|
||||||
// TODO: ExitBootServices
|
status = gBS->ExitBootServices(ImageHandle, map_key);
|
||||||
|
if (status != EFI_SUCCESS) {
|
||||||
|
// If this fails, memory map changed - try one more time
|
||||||
|
gBS->FreePool(memory_map);
|
||||||
|
|
||||||
|
memory_map_size = 0;
|
||||||
|
gBS->GetMemoryMap(&memory_map_size, NULL, &map_key, &descriptor_size, &descriptor_version);
|
||||||
|
memory_map_size += 2 * descriptor_size;
|
||||||
|
gBS->AllocatePool(EfiLoaderData, memory_map_size, (void**)&memory_map);
|
||||||
|
gBS->GetMemoryMap(&memory_map_size, memory_map, &map_key, &descriptor_size, &descriptor_version);
|
||||||
|
|
||||||
|
boot_info.memory_map = memory_map;
|
||||||
|
boot_info.memory_map_size = memory_map_size;
|
||||||
|
|
||||||
|
status = gBS->ExitBootServices(ImageHandle, map_key);
|
||||||
|
if (status != EFI_SUCCESS) {
|
||||||
|
// Can't print after this point if it fails
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Jump to kernel
|
// Jump to kernel
|
||||||
// TODO: ((void(*)(BootInfo*))KERNEL_LOAD_ADDRESS)(&boot_info);
|
// Cast KERNEL_LOAD_ADDRESS to function pointer and call with boot_info
|
||||||
|
typedef void (*kernel_entry_t)(BootInfo*);
|
||||||
|
kernel_entry_t kernel_entry = (kernel_entry_t)KERNEL_LOAD_ADDRESS;
|
||||||
|
kernel_entry(&boot_info);
|
||||||
|
|
||||||
// Should never get here
|
// Should never get here
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
|
|||||||
Reference in New Issue
Block a user