diff options
| author | Arseney300 <Arseney300@gmail.com> | 2026-03-29 02:07:17 +0700 |
|---|---|---|
| committer | Arseney300 <Arseney300@gmail.com> | 2026-04-08 01:19:07 +0700 |
| commit | 4912796d2e88c6eb5d02fbf0fb9c39f8c9f7cd4c (patch) | |
| tree | 9ee8110e2c090c888f23797cda56c7e2df531695 /include | |
bastion: initial implementation
ready project skeleton
dual-arch build system with Linux-config style configuration
UEFI EFI stub loader (PE32+) for x86_64 and AArch64
ELF64 kernel parser
Temporary framebuffer console
freestanding string and c++ abi stubs
For now, kernel boots, prints banner, memory map and go halt
Diffstat (limited to 'include')
| -rw-r--r-- | include/boot/boot_info.h | 76 | ||||
| -rw-r--r-- | include/boot/efi.h | 365 | ||||
| -rw-r--r-- | include/elf/elf.h | 331 |
3 files changed, 772 insertions, 0 deletions
diff --git a/include/boot/boot_info.h b/include/boot/boot_info.h new file mode 100644 index 0000000..cc02ae8 --- /dev/null +++ b/include/boot/boot_info.h @@ -0,0 +1,76 @@ +#pragma once +// ============================================================================ +// boot_info.h - Boot handoff struct +// Shared between the UEFI loader and the kernel. +// The loader fills it, the kernel consumes it. Simple. +// In future i will expand this struct +// ============================================================================ + +#include <stdint.h> + +// ── Boot Magic Number─────────────────────────────────────────────────────── +inline constexpr uint64_t BOOT_INFO_MAGIC = 0xDEADDEADDEADDEADULL; + +// ── Framebuffer (GOP) ─────────────────────────────────────────────────────── +// TODO: remove Framebuffer to driver +enum class PixelFormat : uint32_t { + RGB = 0, // PixelRedGreenBlueReserved8BitPerColor + BGR = 1, // PixelBlueGreenRedReserved8BitPerColor + Mask = 2, // PixelBitMask — need to check masks +}; + +struct FramebufferInfo { + uint64_t base; // Physical address of framebuffer + uint32_t width; // Horizontal resolution in pixels + uint32_t height; // Vertical resolution in pixels + uint32_t pitch; // Bytes per scanline (>= width * 4) + PixelFormat format; +}; + +// ── Memory map ───────────────────────────────────────────────────────────── +//TODO: remove FrameBuffer +enum class MemoryRegionType : uint32_t { + Usable = 0, // Free RAM - kernel can use + Reserved = 1, // Firmware/hardware reserved + AcpiReclaimable = 2, // ACPI tables - free after parsing + AcpiNvs = 3, // ACPI non-volatile storage + BootloaderReclaimable = 4, // Loader code/data - free after kernel init + KernelAndModules = 5, // Kernel image + any loaded modules + Framebuffer = 6, // Framebuffer memory - do not use as RAM +}; + +struct MemoryRegion { + uint64_t base; + uint64_t length; + MemoryRegionType type; + uint32_t _reserved; // Padding to 24 bytes +}; + +// ── Boot info structure ──────────────────────────────────────────────────── + +struct BootInfo { + uint64_t magic; // Must be BOOT_INFO_MAGIC + + // Framebuffer + // Todo: remove + FramebufferInfo framebuffer; + + // Memory map (array of MemoryRegion) + MemoryRegion* memory_map; + uint64_t memory_map_count; + + // Platform-specific firmware tables (both always present to keep layout uniform) + uint64_t rsdp_address; // ACPI RSDP (x86_64), 0 if absent + uint64_t fdt_address; // Flattened Device Tree (aarch64), 0 if absent + + // Kernel load info + uint64_t kernel_phys_base; // Where the kernel was loaded physically + uint64_t kernel_virt_base; // Kernel's virtual base (from ELF) + uint64_t kernel_size; // Total size of kernel in memory + + // Kernel entry point (virtual address from ELF e_entry) + uint64_t kernel_entry_point; + + // Higher-half direct map base (if set up by loader) + uint64_t hhdm_base; // e.g., 0xFFFF800000000000 +}; diff --git a/include/boot/efi.h b/include/boot/efi.h new file mode 100644 index 0000000..bcb8854 --- /dev/null +++ b/include/boot/efi.h @@ -0,0 +1,365 @@ +#pragma once +// ============================================================================ +// efi.h - Minimal UEFI type and protocol definitions +// +// Only what we need for our boot loader. No external dependencies (like gnu-efi). +// Reference: UEFI Specification 2.10, https://uefi.org/specs/UEFI/2.10/ +// I generate it with Cloude, because i don't want to manually rewrite whole spec +// ============================================================================ + +#include <stdint.h> +#include <stddef.h> + +// ── Base types ───────────────────────────────────────────────────────────── + +typedef uint64_t UINTN; +typedef int64_t INTN; +typedef uint64_t EFI_STATUS; +typedef void* EFI_HANDLE; +typedef void* EFI_EVENT; +typedef uint64_t EFI_PHYSICAL_ADDRESS; +typedef uint64_t EFI_VIRTUAL_ADDRESS; +typedef wchar_t CHAR16; // With -fshort-wchar, wchar_t is 16-bit +typedef uint8_t BOOLEAN; + +#define TRUE 1 +#define FALSE 0 +#define IN +#define OUT +#define OPTIONAL +#define EFIAPI + +// ── Status codes ─────────────────────────────────────────────────────────── + +#define EFI_SUCCESS 0ULL +#define EFI_ERROR_BIT (1ULL << 63) +#define EFI_LOAD_ERROR (EFI_ERROR_BIT | 1) +#define EFI_INVALID_PARAMETER (EFI_ERROR_BIT | 2) +#define EFI_UNSUPPORTED (EFI_ERROR_BIT | 3) +#define EFI_BAD_BUFFER_SIZE (EFI_ERROR_BIT | 4) +#define EFI_BUFFER_TOO_SMALL (EFI_ERROR_BIT | 5) +#define EFI_NOT_FOUND (EFI_ERROR_BIT | 14) + +#define EFI_ERROR(status) ((status) & EFI_ERROR_BIT) + +// ── GUIDs ────────────────────────────────────────────────────────────────── + +struct EFI_GUID { + uint32_t Data1; + uint16_t Data2; + uint16_t Data3; + uint8_t Data4[8]; +}; + +#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_ID \ + { 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 } } + +#define EFI_DTB_TABLE_GUID \ + { 0xB1B621D5, 0xF19C, 0x41A5, { 0x83, 0x0B, 0xD9, 0x15, 0x2C, 0x69, 0xAA, 0xE0 } } + +// ── Memory types ─────────────────────────────────────────────────────────── + +typedef uint32_t EFI_MEMORY_TYPE; +#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 +#define EfiMaxMemoryType 15 + +typedef uint32_t EFI_ALLOCATE_TYPE; +#define AllocateAnyPages 0 +#define AllocateMaxAddress 1 +#define AllocateAddress 2 + +struct EFI_MEMORY_DESCRIPTOR { + uint32_t Type; + EFI_PHYSICAL_ADDRESS PhysicalStart; + EFI_VIRTUAL_ADDRESS VirtualStart; + uint64_t NumberOfPages; + uint64_t Attribute; +}; + +// ── Simple Text Output Protocol ──────────────────────────────────────────── + +struct EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL { + void* Reset; + EFI_STATUS (EFIAPI *OutputString)( + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL* This, + CHAR16* String + ); + void* TestString; + void* QueryMode; + void* SetMode; + void* SetAttribute; + EFI_STATUS (EFIAPI *ClearScreen)( + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL* This + ); + void* SetCursorPosition; + void* EnableCursor; + void* Mode; +}; + +// ── Graphics Output Protocol ─────────────────────────────────────────────── + +typedef uint32_t EFI_GRAPHICS_PIXEL_FORMAT; +#define PixelRedGreenBlueReserved8BitPerColor 0 +#define PixelBlueGreenRedReserved8BitPerColor 1 +#define PixelBitMask 2 +#define PixelBltOnly 3 + +struct EFI_PIXEL_BITMASK { + uint32_t RedMask; + uint32_t GreenMask; + uint32_t BlueMask; + uint32_t ReservedMask; +}; + +struct EFI_GRAPHICS_OUTPUT_MODE_INFORMATION { + uint32_t Version; + uint32_t HorizontalResolution; + uint32_t VerticalResolution; + EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; + EFI_PIXEL_BITMASK PixelInformation; + uint32_t PixelsPerScanLine; +}; + +struct EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE { + uint32_t MaxMode; + uint32_t Mode; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* Info; + UINTN SizeOfInfo; + EFI_PHYSICAL_ADDRESS FrameBufferBase; + UINTN FrameBufferSize; +}; + +struct EFI_GRAPHICS_OUTPUT_PROTOCOL { + void* QueryMode; + void* SetMode; + void* Blt; + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE* Mode; +}; + +// ── File Protocol ────────────────────────────────────────────────────────── + +#define EFI_FILE_MODE_READ 0x0000000000000001ULL +#define EFI_FILE_READ_ONLY 0x0000000000000001ULL + +struct EFI_FILE_PROTOCOL { + uint64_t Revision; + EFI_STATUS (EFIAPI *Open)( + EFI_FILE_PROTOCOL* This, + EFI_FILE_PROTOCOL** NewHandle, + CHAR16* FileName, + uint64_t OpenMode, + uint64_t Attributes + ); + EFI_STATUS (EFIAPI *Close)( + EFI_FILE_PROTOCOL* This + ); + void* Delete; + EFI_STATUS (EFIAPI *Read)( + EFI_FILE_PROTOCOL* This, + UINTN* BufferSize, + void* Buffer + ); + void* Write; + void* GetPosition; + void* SetPosition; + EFI_STATUS (EFIAPI *GetInfo)( + EFI_FILE_PROTOCOL* This, + EFI_GUID* InformationType, + UINTN* BufferSize, + void* Buffer + ); +}; + +struct EFI_FILE_INFO { + uint64_t Size; + uint64_t FileSize; + uint64_t PhysicalSize; + uint8_t _time_padding[48]; // Skip EFI_TIME fields + uint64_t Attribute; + CHAR16 FileName[1]; // Variable length +}; + +// ── Simple File System Protocol ──────────────────────────────────────────── + +struct EFI_SIMPLE_FILE_SYSTEM_PROTOCOL { + uint64_t Revision; + EFI_STATUS (EFIAPI *OpenVolume)( + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* This, + EFI_FILE_PROTOCOL** Root + ); +}; + +// ── Loaded Image Protocol ────────────────────────────────────────────────── + +struct EFI_LOADED_IMAGE_PROTOCOL { + uint32_t Revision; + EFI_HANDLE ParentHandle; + void* SystemTable; + EFI_HANDLE DeviceHandle; + void* FilePath; + void* Reserved; + uint32_t LoadOptionsSize; + void* LoadOptions; + void* ImageBase; + uint64_t ImageSize; + EFI_MEMORY_TYPE ImageCodeType; + EFI_MEMORY_TYPE ImageDataType; + void* Unload; +}; + +// ── Boot Services ────────────────────────────────────────────────────────── + +struct EFI_BOOT_SERVICES { + char _hdr[24]; + + // Task Priority (2) + void* RaiseTPL; + void* RestoreTPL; + + // Memory Services + EFI_STATUS (EFIAPI *AllocatePages)( + EFI_ALLOCATE_TYPE Type, + EFI_MEMORY_TYPE MemoryType, + UINTN Pages, + EFI_PHYSICAL_ADDRESS* Memory + ); + EFI_STATUS (EFIAPI *FreePages)( + EFI_PHYSICAL_ADDRESS Memory, + UINTN Pages + ); + EFI_STATUS (EFIAPI *GetMemoryMap)( + UINTN* MemoryMapSize, + EFI_MEMORY_DESCRIPTOR* MemoryMap, + UINTN* MapKey, + UINTN* DescriptorSize, + uint32_t* DescriptorVersion + ); + EFI_STATUS (EFIAPI *AllocatePool)( + EFI_MEMORY_TYPE PoolType, + UINTN Size, + void** Buffer + ); + EFI_STATUS (EFIAPI *FreePool)( + void* Buffer + ); + + // Event & Timer (6) + void* CreateEvent; + void* SetTimer; + void* WaitForEvent; + void* SignalEvent; + void* CloseEvent; + void* CheckEvent; + + // Protocol Handler (6 + 3) + void* InstallProtocolInterface; + void* ReinstallProtocolInterface; + void* UninstallProtocolInterface; + EFI_STATUS (EFIAPI *HandleProtocol)( + EFI_HANDLE Handle, + EFI_GUID* Protocol, + void** Interface + ); + void* Reserved; + void* RegisterProtocolNotify; + void* LocateHandle; + void* LocateDevicePath; + void* InstallConfigurationTable; + + // Image Services (5) + void* LoadImage; + void* StartImage; + void* Exit; + void* UnloadImage; + EFI_STATUS (EFIAPI *ExitBootServices)( + EFI_HANDLE ImageHandle, + UINTN MapKey + ); + + // Misc (3) + void* GetNextMonotonicCount; + void* Stall; + void* SetWatchdogTimer; + + // DriverSupport (2) + void* ConnectController; + void* DisconnectController; + + // Open/Close Protocol (3) + void* OpenProtocol; + void* CloseProtocol; + void* OpenProtocolInformation; + + // Library (3) + void* ProtocolsPerHandle; + void* LocateHandleBuffer; + EFI_STATUS (EFIAPI *LocateProtocol)( + EFI_GUID* Protocol, + void* Registration, + void** Interface + ); +}; + +// ── Configuration Table ──────────────────────────────────────────────────── + +struct EFI_CONFIGURATION_TABLE { + EFI_GUID VendorGuid; + void* VendorTable; +}; + +// ── System Table ─────────────────────────────────────────────────────────── + +struct EFI_SYSTEM_TABLE { + char _hdr[24]; + + CHAR16* FirmwareVendor; + uint32_t FirmwareRevision; + uint32_t _pad; + + EFI_HANDLE ConsoleInHandle; + void* ConIn; + EFI_HANDLE ConsoleOutHandle; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL* ConOut; + EFI_HANDLE StandardErrorHandle; + void* StdErr; + void* RuntimeServices; + EFI_BOOT_SERVICES* BootServices; + UINTN NumberOfTableEntries; + EFI_CONFIGURATION_TABLE* ConfigurationTable; +}; + +// ── Utility ──────────────────────────────────────────────────────────────── + +inline bool guid_equal(const EFI_GUID& a, const EFI_GUID& b) { + return a.Data1 == b.Data1 && a.Data2 == b.Data2 && a.Data3 == b.Data3 && + a.Data4[0] == b.Data4[0] && a.Data4[1] == b.Data4[1] && + a.Data4[2] == b.Data4[2] && a.Data4[3] == b.Data4[3] && + a.Data4[4] == b.Data4[4] && a.Data4[5] == b.Data4[5] && + a.Data4[6] == b.Data4[6] && a.Data4[7] == b.Data4[7]; +} diff --git a/include/elf/elf.h b/include/elf/elf.h new file mode 100644 index 0000000..512ba14 --- /dev/null +++ b/include/elf/elf.h @@ -0,0 +1,331 @@ +#pragma once + +// ============================================================================ +// elf.h - ELF format definitions +// https://refspecs.linuxbase.org/elf/elf.pdf +// https://gist.github.com/x0nu11byt3/bcb35c3de461e5fb66173071a2379779 +// https://docs.oracle.com/cd/E19683-01/816-1386/6m7qcoblh/index.html +// ============================================================================ + +#include <stdint.h> + +/* ELF Types */ +#pragma message("TODO: describe ELF types from specification") + +// ============================================================================ +// =================================== ELF Header ============================= +// ============================================================================ +#define EI_NIDENT (16) + +/* e_ident offset (https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#ELF_header) */ +#define EI_MAG0 0 +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_OSABI 7 +#define EI_ABIVERSION 8 +#define EI_PAD 9 + +/* ELF Magic value */ +#define ELF_MAGIC 0x464C457F // "\x7FELF" little-endian + +/* ELF Class */ +#define ELFCLASS32 0x1 +#define ELFCLASS64 0x2 + +/* Data format: or LSB(Least Significant Bit, little-endian) or MSB(Most Significant Bit, big-endian) */ +#define ELFDATA2LSB 0x1 +#define ELFDATA2MSB 0x2 + +/* ELF version */ +#define ELFVERSION 0x1 + +/* Target ABI */ +#define ELFABISYSTEMV 0x00 +#define ELFABIHPUX 0x01 +#define ELFABINETBSD 0x02 +#define ELFABILINUX 0x03 +#define ELFABIGNUHURD 0x04 +#define ELFABISOLARIS 0x06 +#define ELFABIAIX 0x07 +#define ELFABIIRIX 0x08 +#define ELFABIFREEBSD 0x09 +#define ELFABITRU64 0x0A +#define ELFABINM 0x0B +#define ELFABIOPENBSD 0x0C +#define ELFABIOPENVMS 0x0D +#define ELFABINSKERNEL 0x0E +#define ELFABIAROS 0x0F +#define ELFABIFENIXOS 0x10 +#define ELFABICLOUDABI 0x11 +#define ELFABISTOPENVOS 0x12 + +/* ABI version */ +#pragma message("TODO: do something with ABI version") +/* Currently i don't use ABI version */ + +/* Object File Types, e_type field */ +#define ET_NONE 0x0 /* Unknown */ +#define ET_REL 0x1 /* Relocatable. (output of gcc -c). Contains sections + symbol tables + relocations. No program header */ +#define ET_EXEC 0x2 /* Executable. Statically-linked executable with fixed virtual addresses. Has program headers. */ +#define ET_DYN 0x3 /* Shared object. Shared library or PIE executable. Postitoin-independent, relocated at load time. */ +#define ET_CORE 0x4 /* Core dump. Process memory image for post-mortem debugging */ +#define ET_LOOS 0xFE00 /* Reserved inclusive range. Operating system specific */ +#define ET_HIOS 0xFEFF /* Reserved inclusive range. Operating system specific */ +#define ET_LOPROC 0xFF00 /* Reserved inclusive range. Processor specific */ +#define ET_HIPROC 0xFFFF /* Reserved inclusive range. Processor specific */ + +/* Arch types, e_machine field */ +#pragma message("TODO: add other architecture defines, copy from github") +#define EM_X86 0x03 +#define EM_X86_64 0x3E +#define EM_ARM 0x28 /* up to Armv7/AArch32 */ +#define EM_AARCH64 0xB7 /* Armv8/AArch64 */ + +/* Version value, e_version field */ +#define EV_NONE 0x00 +#define EV_CURRENT 0x01 +#define EV_NUM 0x02 + +/* Other header fields: + e_entry: Memory address of the entry point. + e_phoff: Pointer to the start of the program header table. + e_shoff: Pointer to the start of section header table. + e_flags: Interpretation of this field depends on the target arch. + e_ehsize: Contains the size of header (normally 64 bytes for 64-bit and 52 Bytes for 32-bit) + e_phentsize: Contains the size of program header table entry. Or 0x20 (for 32-bit) or 0x38 (for 64-bit). + e_phnum: Contains the number of entries in the program header table. + e_shentsize: Contains the size of a section header table entry. Or 0x28 (for 32-bit) or 0x40 (for 64-bit) + e_shnum: Contains the number of entries in the section header table. + e_shstrndx: Contains index of the section header table entry, that contains the section names. +*/ + +/* ELF header (atm only for 64 bit) */ +#pragma message("TODO: add elf header for 32 bit") +struct Elf64_Ehdr { + uint8_t e_ident[EI_NIDENT]; + uint16_t e_type; + uint16_t e_machine; + uint32_t e_version; + uint64_t e_entry; + uint64_t e_phoff; + uint64_t e_shoff; + uint32_t e_flags; + uint16_t e_ehsize; + uint16_t e_phentsize; + uint16_t e_phnum; + uint16_t e_shentsize; + uint16_t e_shnum; + uint16_t e_shstrndx; +}; + +// ============================================================================ +// =================================== Program Header ========================= +// ============================================================================ + +/* Type, p_type field */ +#define PT_NULL 0x00000000 /* Program header table entry unused */ +#define PT_LOAD 0x00000001 /* Loadable segment */ +#define PT_DYNAMIC 0x00000002 /* Dynamic linking information */ +#define PT_INTERP 0x00000003 /* Interpreter information */ +#define PT_NOTE 0x00000004 /* Auxiliary information */ +#define PT_SHLIB 0x00000005 /* Reserved */ +#define PT_PHDR 0x00000006 /* Segment containing program header table itself */ +#define PT_TLS 0x00000007 /* Thread-Local Storage template */ +#define PT_NUM 0x00000008 /* Number of defined types */ +#define PT_LOOS 0x60000000 /* Reserved inclusive range. Operating system specific: */ +#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ +#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ +#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6FFFFFFF /* Reserved inclusive range. Operating system specific end*/ +#define PT_LOPROC 0x70000000 /* Reserved inclusive range. Processor specific */ +#define PT_HIPROC 0x7FFFFFFF /* Reserved inclusive range. Processor specific */ + +/* Flags, p_flags 64-bit field */ +#define PF_X 0x1 /* Executable segment */ +#define PF_W 0x2 /* Writeable segment */ +#define PF_R 0x4 /* Readable segment */ +#define PF_MASKOS 0x0FF00000 /* OS-specific */ +#define PF_MASKPROC 0xF0000000 /* Processor-specific */ + +/* Other Program Header fields: + p_offset: Offset of the segment in the file image. + p_vaddr: Virtual address of the segment in memory. + p_paddr: On systems where physical address is relevant, reserved for segment's physical address. + p_filesz: Size in bytes of the segment in the file image. May be 0. + p_memsz: Size in bytes of the segment in memory. May be 0. + p_flags: 32-bit flags (don't exist on 64 bit header) + p_align: 0 and 1 specify no alignment. Otherwise should be a positive, integral power of 2, with p_vaddr equating p_offset modules p_align +*/ + +/* Elf64 Program Header */ +struct Elf64_Phdr { + uint32_t p_type; + uint32_t p_flags; + uint64_t p_offset; + uint64_t p_vaddr; + uint64_t p_paddr; + uint64_t p_filesz; + uint64_t p_memsz; + uint64_t p_align; +}; + +// ============================================================================ +// =================================== Section Header ============================= +// ============================================================================ + +/* Section Header Type, sh_type field */ +#define SHT_NULL 0x0 /* Section header table entry unused. First entry in the section table must be SHT_NULL according the stanard */ +#define SHT_PROGBITS 0x1 /* Program data */ +#define SHT_SYMTAB 0x2 /* Symbol table */ +#define SHT_STRTAB 0x3 /* String table */ +#define SHT_RELA 0x4 /* Relocation entries with addends */ +#define SHT_HASH 0x5 /* Symbol hash table */ +#define SHT_DYNAMIC 0x6 /* Dynamic linking information */ +#define SHT_NOTE 0x7 /* Notes */ +#define SHT_NOBITS 0x8 /* Program space with no data (bss) */ +#define SHT_REL 0x9 /* Relocation entries, no addends */ +#define SHT_SHLIB 0x0A /* Reserved */ +#define SHT_DYNSYM 0x0B /* Dynamic linker symbol table */ +#define SHT_INIT_ARRAY 0x0E /* Array of constructors */ +#define SHT_FINI_ARRAY 0x0F /* Array of destructors */ +#define SHT_PREINIT_ARRAY 0x10 /* Array of pre-constructors */ +#define SHT_GROUP 0x11 /* Section group */ +#define SHT_SYMTAB_SHNDX 0x12 /* Extended section indices */ +#define SHT_NUM 0x13 /* Number of defined types */ +#define SHT_LOOS 0x60000000 /* Start OS-specific */ +#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */ +#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */ +#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ +#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ +#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ +#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ +#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ +#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ +#define SHT_HIOS 0x6fffffff /* End OS-specific type */ +#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ +#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ +#define SHT_LOUSER 0x80000000 /* Start of application-specific */ +#define SHT_HIUSER 0x8fffffff /* End of application-specific */ + +/* Section Header flags, sh_flags field */ +#define SHF_WRITE 0x1 /*Writable*/ +#define SHF_ALLOC 0x2 /*Occupies memory during execution*/ +#define SHF_EXECINSTR 0x4 /*Executable*/ +#define SHF_MERGE 0x10 /*Might be merged*/ +#define SHF_STRINGS 0x20 /*Contains null-terminated strings*/ +#define SHF_INFO_LINK 0x40 /*'sh_info' contains SHT index*/ +#define SHF_LINK_ORDER 0x80 /*Preserve order after combining*/ +#define SHF_OS_NONCONFORMING 0x100 /*Non-standard OS specific handling required*/ +#define SHF_GROUP 0x200 /*Section is member of a group*/ +#define SHF_TLS 0x400 /*Section hold thread-local data*/ +#define SHF_COMPRESSED 0x800 /*Section with compressed data*/ +#define SHF_MASKOS 0x0FF00000 /*OS-specific*/ +#define SHF_MASKPROC 0xF0000000 /*Processor-specific*/ +#define SHF_ORDERED 0x4000000 /*Special ordering requirement (Solaris)*/ +#define SHF_EXCLUDE 0x8000000 /*Section is excluded unless referenced or allocated (Solaris)*/ + +/* Other Section Header fields: + sh_name: An offset to a string in the .shstrab section that represents the name of this section. Zero means no name. + sh_addr: Virtual address of the section in memory, for sections that are loaded. + sh_offset: Offset of the section in the file image. + sh_size: Size in bytes of the section. May be 0. + sh_link: Contains the section index of an associated section. This field is used for several purposes, depending on the type of section. + sh_info: Contains extra information about the section. This field is used for several purposes, depending on the type of section. + sh_addralign: Contains the required alignment of the section. This field must be a power of two. + sh_entsize: Contains the size, in bytes, of each entry, for sections that contain fixed-size entries. Otherwise, this field contains zero. +*/ +/* + The most common ELF sections: + .text - contains executable code. Packed with Read and Execute flags. Load only one times. Can't be changed. + .data - initalized data. Read and Write flags. + .rodata - initalized read only data. Read flag. + .bss - unititlized data. Read and Write flags. + other sections you can see here: https://gist.github.com/x0nu11byt3/bcb35c3de461e5fb66173071a2379779#sections + + Also, there is something like "group of sections" (readelf -g), but it's very rare. +*/ + +/* Elf64 Section Header */ +struct Elf64_Shdr { + uint32_t sh_name; + uint32_t sh_type; + uint64_t sh_flags; + uint64_t sh_addr; + uint64_t sh_offset; + uint64_t sh_size; + uint32_t sh_link; + uint32_t sh_info; + uint64_t sh_addralign; + uint64_t sh_entsize; +}; + +// ============================================================================ +// =================================== Symbols ================================ +// ============================================================================ +// https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-79797/index.html +#pragma message("TODO: do") + +/* Symbol fields: + st_name: Symbol name + st_info: Symbol type and binding. It is calculated using macros + st_other: Symbol visibility. + st_shndx: Section index. + st_value: Symbol value. + st_size: Symbol size; +*/ + +/* Symbol struct */ +struct Elf64_Sym { + uint32_t st_name; + uint8_t st_info; + uint8_t st_other; + uint16_t st_shndx; + uint64_t st_value; + uint64_t st_size; +}; + + +// ============================================================================ +// =================================== ELF Page size ========================== +// ============================================================================ +#define ELF_PAGE_SIZE 0x1000 +#define ELF_PAGE_MASK (ELF_PAGE_SIZE - 1) + +// ============================================================================ +// =================================== ELF Load Result ======================== +// ============================================================================ +// ATM it uses in efi_elf_parser.cpp + +/* Error codes for ElfLoadResult.error */ +#define ELF_ERR_NONE 0 /* success */ +#define ELF_ERR_FILE_TOO_SMALL 1 /* file smaller than ELF header */ +#define ELF_ERR_INVALID_MAGIC 2 /* bad magic */ +#define ELF_ERR_INVALID_CLASS 3 /* bad class */ +#define ELF_ERR_INVALID_IDENT 4 /* bad ident */ +#define ELF_ERR_INVALID_ARCH 5 /* bad machine */ +#define ELF_ERR_INVALID_TYPE 6 /* bad type */ +#define ELF_ERR_NO_LOAD_SEGS 7 /* no PT_LOAD segments found */ +#define ELF_ERR_ALLOC_FAILED 8 /* AllocatePages failed (check efi_alloc_status) */ + +/* Elf Load Result object */ +struct ElfLoadResult { + uint64_t entry_point; + uint64_t phys_base; + uint64_t virt_base; + uint64_t total_size; + uint64_t efi_alloc_status; /* EFI_STATUS from AllocatePages, valid when error == ELF_ERR_ALLOC_FAILED */ + uint8_t error; /* ELF_ERR_* code above */ + bool success; +}; |
