// SPDX-License-Identifier: Apache-2.0 #pragma once #ifndef SCHOS_EFI_H #define SCHOS_EFI_H // The parts of UEFI this loader actually uses, written from the // specification. // // Not gnu-efi and not EDK II. Both are large dependencies for something this // small, and both raise a licensing question the project does not need to // answer -- see docs/licensing.md. What is here is the handful of structures // and function pointers needed to read a file, ask for the framebuffer, take // the memory map and leave: perhaps two hundred lines against tens of // thousands. // // Everything is called through function pointers in tables the firmware hands // us, using the Microsoft x64 calling convention. clang's // --target=x86_64-unknown-windows produces that natively, which is why no // __attribute__((ms_abi)) appears anywhere below. // // Fields this loader never touches are left as `void *` padding rather than // spelled out. The offsets are what matter and they are preserved exactly; // naming a field we do not use would only invite it to drift. typedef unsigned char UINT8; typedef unsigned short UINT16; typedef unsigned int UINT32; typedef unsigned long long UINT64; typedef long long INTN; typedef unsigned long long UINTN; typedef UINT16 CHAR16; typedef UINT8 BOOLEAN; typedef void *EFI_HANDLE; typedef UINTN EFI_STATUS; typedef UINT64 EFI_PHYSICAL_ADDRESS; typedef UINT64 EFI_VIRTUAL_ADDRESS; #define EFI_SUCCESS 0 #define EFI_BUFFER_TOO_SMALL ((EFI_STATUS)(0x8000000000000000ULL | 5)) #define EFI_ERROR(s) (((INTN)(s)) < 0) typedef struct { UINT32 Data1; UINT16 Data2; UINT16 Data3; UINT8 Data4[8]; } EFI_GUID; // --- memory --------------------------------------------------------------- typedef enum { AllocateAnyPages, AllocateMaxAddress, AllocateAddress } EFI_ALLOCATE_TYPE; // Only the types this loader has to reason about are named. The rule it // applies is simply which of them are free for the kernel to use. #define EfiReservedMemoryType 0 #define EfiLoaderCode 1 #define EfiLoaderData 2 #define EfiBootServicesCode 3 #define EfiBootServicesData 4 #define EfiRuntimeServicesCode 5 #define EfiRuntimeServicesData 6 #define EfiConventionalMemory 7 #define EfiUnusableMemory 8 #define EfiACPIReclaimMemory 9 #define EfiACPIMemoryNVS 10 #define EfiMemoryMappedIO 11 #define EfiMemoryMappedIOPortSpace 12 #define EfiPalCode 13 #define EfiPersistentMemory 14 typedef struct { UINT32 Type; UINT32 Pad; EFI_PHYSICAL_ADDRESS PhysicalStart; EFI_VIRTUAL_ADDRESS VirtualStart; UINT64 NumberOfPages; UINT64 Attribute; } EFI_MEMORY_DESCRIPTOR; // --- simple text output --------------------------------------------------- typedef struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL { void *Reset; EFI_STATUS (*OutputString)(struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, CHAR16 *String); void *TestString; void *QueryMode; void *SetMode; void *SetAttribute; EFI_STATUS (*ClearScreen)(struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This); void *SetCursorPosition; void *EnableCursor; void *Mode; } EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; // --- boot services -------------------------------------------------------- typedef struct { char Hdr[24]; void *RaiseTPL; void *RestoreTPL; EFI_STATUS (*AllocatePages)(EFI_ALLOCATE_TYPE Type, UINTN MemoryType, UINTN Pages, EFI_PHYSICAL_ADDRESS *Memory); EFI_STATUS (*FreePages)(EFI_PHYSICAL_ADDRESS Memory, UINTN Pages); EFI_STATUS (*GetMemoryMap)(UINTN *MemoryMapSize, EFI_MEMORY_DESCRIPTOR *MemoryMap, UINTN *MapKey, UINTN *DescriptorSize, UINT32 *DescriptorVersion); EFI_STATUS (*AllocatePool)(UINTN PoolType, UINTN Size, void **Buffer); EFI_STATUS (*FreePool)(void *Buffer); void *CreateEvent; void *SetTimer; void *WaitForEvent; void *SignalEvent; void *CloseEvent; void *CheckEvent; void *InstallProtocolInterface; void *ReinstallProtocolInterface; void *UninstallProtocolInterface; EFI_STATUS (*HandleProtocol)(EFI_HANDLE Handle, EFI_GUID *Protocol, void **Interface); void *Reserved; void *RegisterProtocolNotify; void *LocateHandle; void *LocateDevicePath; void *InstallConfigurationTable; void *LoadImage; void *StartImage; void *Exit; void *UnloadImage; EFI_STATUS (*ExitBootServices)(EFI_HANDLE ImageHandle, UINTN MapKey); void *GetNextMonotonicCount; EFI_STATUS (*Stall)(UINTN Microseconds); void *SetWatchdogTimer; void *ConnectController; void *DisconnectController; void *OpenProtocol; void *CloseProtocol; void *OpenProtocolInformation; void *ProtocolsPerHandle; void *LocateHandleBuffer; EFI_STATUS (*LocateProtocol)(EFI_GUID *Protocol, void *Registration, void **Interface); } EFI_BOOT_SERVICES; typedef struct { char Hdr[24]; 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; void *ConfigurationTable; } EFI_SYSTEM_TABLE; // --- configuration tables ------------------------------------------------- // // Where UEFI publishes things a BIOS left lying in low memory. The ACPI RSDP is // the one that matters here: the kernel finds it by scanning the EBDA and // 0xE0000-0x100000, which is a BIOS convention that firmware is under no // obligation to honour -- and OVMF does not. #define EFI_ACPI_20_TABLE_GUID \ { 0x8868E871, 0xE4F1, 0x11D3, { 0xBC, 0x22, 0x00, 0x80, 0xC7, 0x3C, 0x88, 0x81 } } #define EFI_ACPI_10_TABLE_GUID \ { 0xEB9D2D30, 0x2D88, 0x11D3, { 0x9A, 0x16, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } } typedef struct { EFI_GUID VendorGuid; void *VendorTable; } EFI_CONFIGURATION_TABLE; // --- loaded image --------------------------------------------------------- #define EFI_LOADED_IMAGE_PROTOCOL_GUID \ { 0x5B1B31A1, 0x9562, 0x11D2, { 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } } typedef struct { UINT32 Revision; EFI_HANDLE ParentHandle; void *SystemTable; EFI_HANDLE DeviceHandle; // the volume this image was loaded from void *FilePath; void *Reserved; UINT32 LoadOptionsSize; void *LoadOptions; void *ImageBase; UINT64 ImageSize; UINTN ImageCodeType; UINTN ImageDataType; void *Unload; } EFI_LOADED_IMAGE_PROTOCOL; // --- file system ---------------------------------------------------------- #define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \ { 0x0964E5B22, 0x6459, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } } #define EFI_FILE_MODE_READ 0x0000000000000001ULL typedef struct EFI_FILE_PROTOCOL { UINT64 Revision; EFI_STATUS (*Open)(struct EFI_FILE_PROTOCOL *This, struct EFI_FILE_PROTOCOL **NewHandle, CHAR16 *FileName, UINT64 OpenMode, UINT64 Attributes); EFI_STATUS (*Close)(struct EFI_FILE_PROTOCOL *This); void *Delete; EFI_STATUS (*Read)(struct EFI_FILE_PROTOCOL *This, UINTN *BufferSize, void *Buffer); void *Write; EFI_STATUS (*GetPosition)(struct EFI_FILE_PROTOCOL *This, UINT64 *Position); EFI_STATUS (*SetPosition)(struct EFI_FILE_PROTOCOL *This, UINT64 Position); void *GetInfo; void *SetInfo; void *Flush; } EFI_FILE_PROTOCOL; typedef struct EFI_SIMPLE_FILE_SYSTEM_PROTOCOL { UINT64 Revision; EFI_STATUS (*OpenVolume)(struct EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, EFI_FILE_PROTOCOL **Root); } EFI_SIMPLE_FILE_SYSTEM_PROTOCOL; // --- graphics output ------------------------------------------------------ #define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \ { 0x9042A9DE, 0x23DC, 0x4A38, { 0x96, 0xFB, 0x7A, 0xDE, 0xD0, 0x80, 0x51, 0x6A } } #define PixelRedGreenBlueReserved8BitPerColor 0 #define PixelBlueGreenRedReserved8BitPerColor 1 #define PixelBitMask 2 #define PixelBltOnly 3 typedef struct { UINT32 Version; UINT32 HorizontalResolution; UINT32 VerticalResolution; UINT32 PixelFormat; UINT32 PixelInformation[4]; UINT32 PixelsPerScanLine; } EFI_GRAPHICS_OUTPUT_MODE_INFORMATION; typedef struct { UINT32 Mode; UINT32 MaxMode; EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; UINTN SizeOfInfo; EFI_PHYSICAL_ADDRESS FrameBufferBase; UINTN FrameBufferSize; } EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE; typedef struct EFI_GRAPHICS_OUTPUT_PROTOCOL { void *QueryMode; void *SetMode; void *Blt; EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode; } EFI_GRAPHICS_OUTPUT_PROTOCOL; #endif /* SCHOS_EFI_H */