commit 0e1479b16809f7cda68672c18c27ee5ad808bdfb Author: Maksymilian Wilczynski Date: Thu Apr 30 23:48:36 2026 +0200 i think it works diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..64f1707 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +vc140.pdb +bin/ +obj/ diff --git a/KERNEL_DESIGN.md b/KERNEL_DESIGN.md new file mode 100644 index 0000000..41171a4 --- /dev/null +++ b/KERNEL_DESIGN.md @@ -0,0 +1,1182 @@ +# Hybrid Kernel Architecture Design Specification + +--- + +## 1. Overview & Philosophy + +The kernel manages memory, schedules threads, routes interrupts, and brokers messages. +No filesystem, no network stack, no GUI. Everything else lives in user-mode code or +drivers loaded at boot. + +Three governing rules: + +- **Kernel is unreachable from ring 3.** Supervisor pages, full stop. +- **User space is one flat shared heap.** There is no per-process address space. + All user code lives in the same virtual range and can reach any of it. + No code signing certificates, no TPM, just the checksum already in the format. + +Key influences: + +- Executive objects - typed, reference-counted kernel objects for everything the + kernel tracks. +- A HAL sitting between the kernel and hardware so drivers never touch ports directly. +- A clean separation between the object manager, the scheduler, and the memory manager. + +Key influences rejected: + +- UNIX naming (no `pmm_alloc_frame`, no `ke_spin_lock`, no snake_case in kernel code). +- UTF-16 anywhere. The kernel is UTF-8/ASCII. `char *` throughout. +- SYSCALL/SYSRET complexity. Interrupts are simpler and sufficient: `INT 0x2E`. +- GCC-isms. This is MSVC. + +--- + +## 2. Component Map + +``` +bootx64.efi +│ +├── reads boot.ini (debug flag, future knobs) +├── reads drivers/drivers.ini +├── loads: +│ kernel.exe +│ hal.dll +│ syscall.dll +│ win32.dll +│ drivers/*.sys +│ +├── converts EFI memory map -> MEMORY_MAP +└── jumps to kernel entry point in ring 0 + + ┌──────────────────────────────────┐ +ring 0 │ kernel.exe │ +(upper half) │ Mm │ Ke │ Ob │ Io │ scheduler │ + ├──────────────────────────────────┤ + │ hal.dll │ + │ APIC │ HPET │ GOP │ PS/2 │ + │ PCI │ disk dispatch │ + │ DbgPrint │ + └──────────────────────────────────┘ + ┌──────────────────────────────────┐ +ring 0 (loadable) │ ide.sys ahci.sys │ + └──────────────────────────────────┘ + ┌──────────────────────────────────┐ +ring 3 │ win32.dll │ +(lower half) │ kernel32 │ user32 │ ole32 │ + ├──────────────────────────────────┤ + │ syscall.dll │ + │ INT 0x2E stubs │ + └──────────────────────────────────┘ +``` + +--- + +## 3. Naming Convention + +All kernel-visible identifiers follow **PrefixActionObject**: + +``` + +``` + +### Subsystem prefixes + +| Prefix | Subsystem | +|--------|------------------------------------| +| `Mm` | Memory manager | +| `Ke` | Kernel executive (sched, sync) | +| `Ob` | Object manager | +| `Io` | I/O manager / driver interface | +| `Hal` | Hardware abstraction layer | +| `Ldr` | Loader (PE image loading) | +| `Dbg` | Debug | + +### Examples + +```c +MmAllocatePool(size) +MmFreePool(ptr) +MmMapPage(virt, phys, flags) + +KeAcquireMutex(mutex) +KeReleaseMutex(mutex) +KeSignalEvent(event) +KeWaitForObject(object) +KeYield() + +ObReferenceObject(object) +ObDereferenceObject(object) +ObAllocateObject(type, size) + +IoRegisterDisk(index, driver) +IoReadSectors(drive, lba, count, buf) + +HalQueryTicks() +HalStall(us) +HalInitialize(bootInfo) + +LdrLoadImage(buffer, size, baseOut) +LdrResolveImport(dllName, functionName) + +DbgPrint(Format, ...) +``` + +### Types and structs + +Structs are named `NOUN` in all-caps with no prefix. The prefix appears only on functions +and global variables, not on type names: + +```c +typedef struct PROCESS PROCESS; +typedef struct THREAD THREAD; +typedef struct MUTEX MUTEX; +typedef struct SEMAPHORE SEMAPHORE; +typedef struct EVENT EVENT; +typedef struct QUEUE QUEUE; +typedef struct OBJECT OBJECT; +``` + +### Return type + +All fallible kernel functions return `KSTATUS`. Infallible helpers (queries, ref bumps) may +return their value directly. + +--- + +## 4. Memory Architecture + +### 4.1 Virtual Address Space + +``` +0x0000000000000000 ┌──────────────────────────────────┐ + │ │ + │ User Space (lower half) │ + │ │ + │ One flat shared heap. │ + │ All processes and all their │ + │ allocations live here. │ + │ Ring 3 readable and writable. │ + │ │ +0x00007FFFFFFFFFFF └──────────────────────────────────┘ + ... (non-canonical hole) +0xFFFF800000000000 ┌──────────────────────────────────┐ + │ kernel.exe [+0 MB .. +128 MB]│ + ├──────────────────────────────────┤ + │ hal.dll, syscall.dll, │ + │ win32.dll, *.sys │ + │ (packed above kernel.exe) │ + ├──────────────────────────────────┤ + │ Direct physical window │ + │ 0xFFFF880000000000 + │ + ├──────────────────────────────────┤ + │ Kernel pool (kmalloc) │ + │ 0xFFFFC00000000000 + │ + └──────────────────────────────────┘ +``` + +**Invariant:** Every PML4 entry covering the upper half has U/S = 0. A ring-3 access to any +upper-half address is always a hard fault. No fixups, no guard pages, no recovery. + +There is one PML4 shared by all processes. The lower-half entries point to the shared user +heap pages. The upper-half entries are identical in every CR3. + +### 4.2 Custom Memory Map + +The bootloader converts the EFI memory map into a `MEMORY_MAP` before calling `ExitBootServices`. +The kernel never sees EFI types. + +```c +// memory_map.h - shared between bootx64.efi and kernel.exe + +#pragma once +#include + +#define MEMORY_MAP_MAGIC 0x4D454D4D41500000ULL /* 'MEMMAP\0\0' */ +#define MEMORY_MAX_REGIONS 256 + +typedef enum MEMORY_TYPE { + MemoryUsable = 0, /* free RAM, available to the PMM */ + MemoryReserved = 1, /* firmware-reserved, do not touch */ + MemoryMappedIO = 2, /* device MMIO regions */ + MemoryFramebuffer = 3, /* GOP framebuffer */ + MemoryBootloader = 4, /* bootloader code/data (reclaimable) */ + MemoryKernel = 5, /* kernel + HAL + drivers image pages */ +} MEMORY_TYPE; + +typedef struct MEMORY_REGION { + uint64_t Base; + uint64_t Length; /* in bytes, always page-aligned */ + MEMORY_TYPE Type; + uint32_t _pad; +} MEMORY_REGION; + +typedef struct MEMORY_MAP { + uint64_t Magic; + uint32_t RegionCount; + uint32_t _pad; + MEMORY_REGION Regions[MEMORY_MAX_REGIONS]; +} MEMORY_MAP; +``` + +### 4.3 Physical Memory Manager + +Stack allocator over 4 KB frames, seeded from all `MemoryUsable` regions in `MEMORY_MAP`. + +```c +// mm_phys.h + +#pragma once +#include +#include + +#define PAGE_SIZE 4096ULL + +typedef uint64_t PHYSICAL_ADDRESS; + +void MmInitializePhysical(const MEMORY_MAP* map); +PHYSICAL_ADDRESS MmAllocateFrame(void); +PHYSICAL_ADDRESS MmAllocateContiguous(size_t count); +void MmFreeFrame(PHYSICAL_ADDRESS frame); +size_t MmFreeFrameCount(void); +size_t MmTotalFrameCount(void); +``` + +Internals: a stack of free `PHYSICAL_ADDRESS` values in a region carved out before any +allocation is served. Lock is a spinlock; the stack is trivially O(1) for both push and pop. + +### 4.4 Virtual Memory Manager + +```c +// mm_virt.h + +#pragma once +#include +#include + +/* Page flags */ +#define PAGE_PRESENT (1ULL << 0) +#define PAGE_WRITE (1ULL << 1) +#define PAGE_USER (1ULL << 2) +#define PAGE_NOCACHE (1ULL << 4) +#define PAGE_NX (1ULL << 63) + +KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags); +KSTATUS MmUnmapPage(uintptr_t virt); + +/* Kernel pool - ring 0 only, never PAGE_USER. */ +void* MmAllocatePool(size_t size); +void MmFreePool(void* ptr); + +/* User heap - shared flat space, ring 3 accessible. */ +void* MmAllocateUserMemory(size_t size); +void MmFreeUserMemory(void* ptr, size_t size); + +/* Load the shared PML4 into CR3. Called once at boot. */ +void MmActivate(void); +``` + +Kernel pool uses a best-fit free list allocator. + +User memory is a single global best-fit free list allocator backed by the PMM. All user allocations are +mapped `PAGE_PRESENT | PAGE_WRITE | PAGE_USER`. There are no per-process heaps, no virtual +address descriptors, no separate regions per process - one heap, everyone shares it. + +--- + +## 5. Boot Sequence - bootx64.efi + +### 5.1 boot.ini + +Sits at the root of the ESP. Read by the bootloader before anything else. + +```ini +[kernel] +debug = 1 +``` + +The `debug` value is passed through `BOOT_INFO` to the kernel, which hands it to +`HalInitialize`. The HAL sets an internal `HalDebugEnabled` flag from it. No other mechanism +controls `DbgPrint` output at this time. + +Future knobs (serial port, memory cap, etc.) belong here, not in `drivers.ini`. + +### 5.2 Responsibilities + +1. Parse `boot.ini`. +2. Read `drivers/drivers.ini` to build the driver load list. +3. Load each PE image (`kernel.exe`, `hal.dll`, `syscall.dll`, `win32.dll`, all listed `.sys` + files) from the ESP using UEFI file protocol. +4. Validate each image: the PE32+ loader computes the PE checksum and compares it to + `IMAGE_OPTIONAL_HEADER64.CheckSum`. Mismatch → print error via `ConOut` → halt. +5. Map kernel images into the upper half of a freshly constructed PML4. Map all physical RAM + as a direct window at `0xFFFF880000000000`. +6. Convert the EFI memory map to `MEMORY_MAP`. +7. Call `ExitBootServices`. +8. Set up a minimal GDT (ring 0 code/data, ring 3 code/data), a minimal IDT (fault stubs + + `INT 0x2E` handler vector), enable NXE in EFER, set CR3. +9. Fill `BOOT_INFO` and jump to `kernel.exe` entry point. + +### 5.3 PE Checksum Validation + +The checksum algorithm is the standard PE checksum (16-bit word accumulation with carry folding, +then the file size is added). The bootloader rejects any image whose computed checksum does not +match the value stored in the optional header. This is enforced on every image, every boot. +There is no override, no skip flag. + +### 5.4 Boot Information Block + +```c +// boot_info.h - shared between bootx64.efi and kernel.exe + +#pragma once +#include +#include "memory_map.h" + +#define BOOT_INFO_MAGIC 0x424F4F54494E464FULL /* 'BOOTINFO' */ +#define MAX_BOOT_MODULES 32 + +typedef struct BOOT_MODULE { + char Name[32]; /* e.g. "hal.dll", "ide.sys" */ + uintptr_t VirtBase; /* where it was mapped */ + size_t ImageSize; +} BOOT_MODULE; + +typedef struct BOOT_INFO { + uint64_t Magic; + + /* Physical memory (our format, not EFI's). */ + MEMORY_MAP MemoryMap; + + /* GOP framebuffer. */ + uintptr_t FramebufferBase; + uint32_t FramebufferWidth; + uint32_t FramebufferHeight; + uint32_t FramebufferStride; /* pixels per row */ + + /* Loaded modules. */ + BOOT_MODULE Modules[MAX_BOOT_MODULES]; + uint32_t ModuleCount; + + /* ACPI RSDP physical address (for APIC, HPET). */ + uintptr_t RsdpPhysical; + + /* Direct physical window base. */ + uintptr_t PhysicalMapBase; /* = 0xFFFF880000000000 */ + + /* From boot.ini */ + uint32_t DebugEnabled; +} BOOT_INFO; +``` + +--- + +## 6. Kernel - kernel.exe + +### 6.1 Status Codes - KSTATUS + +All fallible kernel functions return `KSTATUS`. Success is always zero. Failures are positive +named constants. No errno negatives, no HRESULT sign games. + +```c +// ke_status.h + +#pragma once +#include + +typedef uint32_t KSTATUS; + +#define STATUS_SUCCESS ((KSTATUS)0x00000000) +#define STATUS_FAILURE ((KSTATUS)0x00000001) +#define STATUS_INVALID_PARAMETER ((KSTATUS)0x00000002) +#define STATUS_NO_MEMORY ((KSTATUS)0x00000003) +#define STATUS_NOT_FOUND ((KSTATUS)0x00000004) +#define STATUS_ACCESS_DENIED ((KSTATUS)0x00000005) +#define STATUS_ALREADY_EXISTS ((KSTATUS)0x00000006) +#define STATUS_NOT_SUPPORTED ((KSTATUS)0x00000007) +#define STATUS_TIMEOUT ((KSTATUS)0x00000008) +#define STATUS_BUFFER_TOO_SMALL ((KSTATUS)0x00000009) +#define STATUS_DEVICE_ERROR ((KSTATUS)0x0000000A) +#define STATUS_OBJECT_DEAD ((KSTATUS)0x0000000B) +#define STATUS_QUEUE_FULL ((KSTATUS)0x0000000C) +#define STATUS_QUEUE_EMPTY ((KSTATUS)0x0000000D) +#define STATUS_CHECKSUM_MISMATCH ((KSTATUS)0x0000000E) + +#define KSUCCESS(s) ((s) == STATUS_SUCCESS) +``` + +### 6.2 Object Model + +Every resource the kernel tracks is an **executive object**: a typed, reference-counted blob +allocated from the kernel pool. The object header is always the first member of any object +struct - this allows the object manager to operate on any object through a pointer to `OBJECT`. + +```c +// ob_object.h + +#pragma once +#include +#include "ke_status.h" + +typedef enum OBJECT_TYPE { + ObjectTypeProcess = 1, + ObjectTypeThread = 2, + ObjectTypeMutex = 3, + ObjectTypeSemaphore = 4, + ObjectTypeEvent = 5, + ObjectTypeQueue = 6, +} OBJECT_TYPE; + +typedef struct OBJECT { + OBJECT_TYPE Type; + volatile long RefCount; /* interlocked */ + void (*Destroy)(struct OBJECT* self); +} OBJECT; + +/* Increment the reference count. Call whenever ownership is shared. */ +void ObReferenceObject(OBJECT* object); + +/* Decrement. Calls Destroy() and frees the object when count reaches zero. */ +void ObDereferenceObject(OBJECT* object); + +/* Allocate a zeroed object of the given size from kernel pool. + Caller fills Type and Destroy before publishing the pointer. */ +OBJECT* ObAllocateObject(OBJECT_TYPE type, size_t size); +``` + +### 6.3 Process Model + +A process owns a handle table and a list of threads. It does not own an address space - +there is one shared address space and it belongs to everyone. + +```c +// ke_process.h + +#pragma once +#include "ob_object.h" +#include "ke_list.h" +#include "ke_spinlock.h" + +#define PROCESS_NAME_MAX 64 +#define HANDLE_TABLE_SIZE 256 + +typedef struct PROCESS { + OBJECT Header; /* must be first */ + + uint32_t ProcessId; + char Name[PROCESS_NAME_MAX]; /* UTF-8 */ + + /* Thread list. */ + LIST_ENTRY ThreadList; /* links THREAD.ProcessLink */ + uint32_t ThreadCount; + + /* Handle table. + Index 0 is always NULL (the invalid handle). + Entries are OBJECT pointers, each holding a reference. */ + OBJECT* Handles[HANDLE_TABLE_SIZE]; + SPINLOCK HandleLock; + + int ExitCode; + LIST_ENTRY GlobalLink; /* node in the global process list */ +} PROCESS; + +KSTATUS KeCreateProcess(const char* name, PROCESS **out); +void KeExitProcess(PROCESS* process, int exitCode); +KSTATUS KeAllocateHandle(PROCESS* process, OBJECT* object, uint32_t* handleOut); +void KeCloseHandle(PROCESS* process, uint32_t handle); +OBJECT* KeLookupHandle(PROCESS* process, uint32_t handle); +``` + +### 6.4 Thread Model + +A thread is the unit of scheduling. Every thread belongs to exactly one process. + +```c +// ke_thread.h + +#pragma once +#include "ob_object.h" +#include "ke_list.h" +#include + +#define KSTACK_SIZE (64 * 1024) /* 64 KB kernel stack */ +#define USTACK_SIZE (512 * 1024) /* 512 KB user stack */ + +typedef enum THREAD_PRIORITY { + PriorityLow = 0, + PriorityNormal = 1, + PriorityHigh = 2, +} THREAD_PRIORITY; + +typedef enum THREAD_STATE { + ThreadReady = 0, + ThreadRunning = 1, + ThreadWaiting = 2, + ThreadDead = 3, +} THREAD_STATE; + +/* + * Saved register context - matches the layout pushed by KeSwitchContext + * in ke_switch.asm. The saved RSP points to this structure on the + * kernel stack; restoring RSP and popping is the entire switch. + */ +typedef struct KCONTEXT { + uint64_t R15, R14, R13, R12; + uint64_t Rbp, Rbx; + uint64_t Rip; /* return address within KeSwitchContext */ +} KCONTEXT; + +typedef struct THREAD { + OBJECT Header; + + uint32_t ThreadId; + THREAD_STATE State; + THREAD_PRIORITY Priority; + + /* Scheduler feedback: quanta consumed without blocking. + Used by the MLFQ to decide demotion. */ + uint32_t QuantaConsumed; + + struct PROCESS* Owner; + LIST_ENTRY ProcessLink; /* node in Owner->ThreadList */ + LIST_ENTRY SchedulerLink; /* node in run queue or wait list */ + + /* Kernel stack - never PAGE_USER. */ + void* KernelStackBase; + uintptr_t KernelStackTop; + + /* Saved context pointer (set by KeSwitchContext). */ + KCONTEXT* SavedContext; + + /* Non-NULL when State == ThreadWaiting. */ + OBJECT* WaitObject; + + /* TSS RSP0 value for this thread, updated on every context switch. */ + uintptr_t TssRsp0; + + /* Ring-3 entry point and argument for new threads. */ + uintptr_t UserEntry; + uintptr_t UserArg; +} THREAD; + +KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, uintptr_t arg, + THREAD_PRIORITY priority, THREAD **out); +void KeExitThread(THREAD* thread, int code); +``` + +**Kernel vs. user stacks:** +The kernel stack is allocated from kernel pool, mapped without `PAGE_USER`, and pointed to by +`TssRsp0`. On `INT 0x2E` or any hardware interrupt the CPU automatically loads this address +from the TSS, so ring-3 code never touches the kernel stack. The user stack lives in the shared +user heap, allocated by `MmAllocateUserMemory` when the thread is created. + +### 6.5 Scheduler - Multi-Level Feedback Queue + +Three run queues, one per priority level. A thread starts at `PriorityNormal` unless specified +otherwise. The scheduler moves threads between levels based on behaviour: + +- **Demotion:** a thread that exhausts its full quantum without blocking is moved down one + level (floor: `PriorityLow`). +- **Promotion:** a thread that blocks voluntarily before its quantum expires is moved up one + level (ceiling: `PriorityHigh`). +- **Dispatch:** always pick from the highest non-empty queue. Within a queue, round-robin. + +This rewards I/O-bound and interactive threads (which block often) with higher priority, and +keeps CPU-bound threads from starving other work without dropping them entirely. + +```c +// ke_sched.h + +#pragma once +#include "ke_thread.h" + +#define QUANTUM_MS 10 /* base time slice in milliseconds */ + +void KeInitializeScheduler(void); +void KeReadyThread(THREAD* thread); +void KeUnreadyThread(THREAD* thread); +void KeSchedulerTick(void); /* called from timer ISR every QUANTUM_MS */ +void KeYield(void); +THREAD* KeCurrentThread(void); +``` + +**`KeSchedulerTick` logic:** + +1. Increment `CurrentThread->QuantaConsumed`. +2. If the thread has blocked since last tick, promote it (already off the run queue - apply + the priority change before it is re-readied). +3. If `QuantaConsumed` exceeds the threshold for the current priority level, demote and reset. +4. Find the highest non-empty queue. If it is higher priority than the current thread, + preempt immediately; otherwise let the current thread finish its quantum. +5. Call `KeSwitchContext(current, next)`. + +**Context switch - `ke_switch.asm` (MASM64):** + +```asm +; void KeSwitchContext(THREAD* from, THREAD* to) +; RCX = from, RDX = to (Microsoft x64 ABI) + +KeSwitchContext PROC + push rbx + push rbp + push r12 + push r13 + push r14 + push r15 + mov [rcx + THREAD_SavedContext], rsp ; from->SavedContext = rsp + mov rsp, [rdx + THREAD_SavedContext] ; rsp = to->SavedContext + ; Update TSS.RSP0 so the next interrupt uses the incoming thread's kernel stack + mov rax, [rdx + THREAD_TssRsp0] + mov qword ptr [tss + TSS_RSP0_OFFSET], rax + pop r15 + pop r14 + pop r13 + pop r12 + pop rbp + pop rbx + ret +KeSwitchContext ENDP +``` + +`THREAD_SavedContext`, `THREAD_TssRsp0`, and `TSS_RSP0_OFFSET` are numeric offsets defined in +a shared `offsets.inc` generated by the build system from the C struct definitions. + +`KeCurrentThread()` reads from `gs:[0]`, a per-CPU slot written by the bootstrap code. +Single-core for now; SMP is a matter of setting up per-core GS bases. + +### 6.6 Synchronization Primitives + +#### Spinlock + +Not an executive object. Used inside the kernel for short critical sections that must not +sleep and may run in interrupt context. Never hold a spinlock across a scheduling boundary. + +Implemented in `ke_spinlock.h` as an inline interlocked CAS loop using MSVC intrinsics +(`_InterlockedCompareExchange`) with a `_mm_pause()` spin body. No assembly file needed. + +```c +// ke_spinlock.h + +#pragma once +#include +#include + +typedef struct SPINLOCK { + volatile long Locked; +} SPINLOCK; + +#define SPINLOCK_INIT { 0 } + +static __forceinline void KeAcquireSpinlock(SPINLOCK* sl) { + while (_InterlockedCompareExchange(&sl->Locked, 1, 0) != 0) + _mm_pause(); +} + +static __forceinline void KeReleaseSpinlock(SPINLOCK* sl) { + _InterlockedExchange(&sl->Locked, 0); +} +``` + +#### Mutex + +Binary, ownership-based. Only the acquiring thread may release it. +Blocking threads sleep on a wait list; the scheduler wakes exactly one on release. + +```c +typedef struct MUTEX { + OBJECT Header; + SPINLOCK Lock; + THREAD* Owner; /* NULL if unowned */ + LIST_ENTRY WaitList; +} MUTEX; + +KSTATUS MutexCreate(MUTEX **out); +KSTATUS KeAcquireMutex(MUTEX* mutex); +KSTATUS KeTryAcquireMutex(MUTEX* mutex); +void KeReleaseMutex(MUTEX* mutex); +``` + +#### Semaphore + +Counter-based. `KeWaitSemaphore` decrements (blocks at zero); +`KeSignalSemaphore` increments and wakes one waiter per call. + +```c +typedef struct SEMAPHORE { + OBJECT Header; + SPINLOCK Lock; + int32_t Count; + int32_t MaxCount; + LIST_ENTRY WaitList; +} SEMAPHORE; + +KSTATUS SemaphoreCreate(int32_t initial, int32_t max, SEMAPHORE **out); +KSTATUS KeWaitSemaphore(SEMAPHORE* semaphore); +KSTATUS KeTrySemaphore(SEMAPHORE* semaphore); +void KeSignalSemaphore(SEMAPHORE* semaphore); +``` + +#### Event + +Two modes: auto-reset and manual-reset. + +```c +typedef enum EVENT_TYPE { EventAutoReset, EventManualReset } EVENT_TYPE; + +typedef struct EVENT { + OBJECT Header; + SPINLOCK Lock; + EVENT_TYPE Type; + uint32_t Signaled; + LIST_ENTRY WaitList; +} EVENT; + +KSTATUS KeEventCreate(EVENT_TYPE type, uint32_t initialState, EVENT **out); +void KeSignalEvent(EVENT* event); +void KeClearEvent(EVENT* event); +KSTATUS KeWaitForEvent(EVENT* event); +``` + +**Common wait mechanism:** +`KeBlockThread(thread, object)` - marks the thread `ThreadWaiting`, records `WaitObject`, +removes it from the run queue, and calls `KeYield()`. The waking side calls +`KeUnblockThread(thread)` which clears `WaitObject`, promotes the thread, and calls +`KeReadyThread`. This path is shared by all three blocking primitives. + +### 6.7 IPC - Message Queues + +Processes share memory, so queues are a synchronization and ordering mechanism, not a +data-transfer one. A pointer in the payload is valid on both sides. + +```c +// ke_queue.h + +#pragma once +#include "ob_object.h" +#include "ke_spinlock.h" +#include +#include + +#define QUEUE_MESSAGE_SIZE 64 /* bytes, fixed */ +#define QUEUE_DEPTH 256 + +typedef struct QUEUE_MESSAGE { + uint32_t Type; /* caller-defined message class */ + uint32_t Flags; + uint64_t Param[6]; /* 48 bytes of payload */ +} QUEUE_MESSAGE; /* total: 64 bytes */ + +typedef struct QUEUE { + OBJECT Header; + SPINLOCK Lock; + QUEUE_MESSAGE Ring[QUEUE_DEPTH]; + uint32_t Head, Tail, Count; + LIST_ENTRY SendWaiters; + LIST_ENTRY RecvWaiters; +} QUEUE; + +KSTATUS QueueCreate(QUEUE **out); +KSTATUS KeSendMessage(QUEUE* queue, const QUEUE_MESSAGE* msg, bool blocking); +KSTATUS KeReceiveMessage(QUEUE* queue, QUEUE_MESSAGE* msg, bool blocking); +``` + +--- + +## 7. Hardware Abstraction Layer - hal.dll + +`hal.dll` is loaded into ring 0 alongside the kernel. The kernel retrieves its interface once +at boot via `LdrGetExport("hal.dll", "HalGetApi")`. Drivers receive the same pointer through +their `DriverEntry` call. + +### 7.1 HAL API Table + +```c +// hal_api.h + +#pragma once +#include +#include +#include +#include "ke_status.h" + +/* Screen - GOP framebuffer */ +typedef struct HAL_SCREEN { + void (*Clear)(uint32_t color); + void (*PutPixel)(int x, int y, uint32_t color); + void (*Blit)(int x, int y, int w, int h, const uint32_t* pixels); + void (*GetSize)(int* width, int* height); + void (*Scroll)(int lines); + void (*PutChar)(char c, int x, int y, uint32_t fg, uint32_t bg); +} HAL_SCREEN; + +/* Keyboard - PS/2, interrupt-driven ring buffer */ +typedef struct HAL_KEYBOARD { + bool (*Poll)(void); /* true if a key is available */ + uint8_t (*ReadScancode)(void); + char (*ReadChar)(void); /* 0 if nothing pending */ + void (*SetCallback)(void (*cb)(uint8_t scancode)); +} HAL_KEYBOARD; + +/* Disk - abstract 512-byte sector interface */ +typedef struct HAL_DISK { + KSTATUS (*ReadSectors)(uint8_t drive, uint64_t lba, + uint32_t count, void* buf); + KSTATUS (*WriteSectors)(uint8_t drive, uint64_t lba, + uint32_t count, const void* buf); + bool (*DrivePresent)(uint8_t drive); + uint64_t (*DriveSectorCount)(uint8_t drive); +} HAL_DISK; + +/* Timer - HPET preferred, APIC timer fallback */ +typedef struct HAL_TIMER { + uint64_t (*QueryTicks)(void); /* milliseconds since boot */ + void (*Stall)(uint32_t us); +} HAL_TIMER; + +/* PCI - config space via port I/O */ +typedef struct HAL_PCI { + uint32_t (*ConfigRead32)(uint8_t bus, uint8_t dev, + uint8_t fn, uint8_t reg); + void (*ConfigWrite32)(uint8_t bus, uint8_t dev, + uint8_t fn, uint8_t reg, uint32_t val); + bool (*FindDevice)(uint16_t vendor, uint16_t device, + uint8_t* bus, uint8_t* dev, uint8_t* fn); + bool (*FindClass)(uint8_t classCode, uint8_t subclass, + uint8_t* bus, uint8_t* dev, uint8_t* fn); +} HAL_PCI; + +/* Interrupt controller - local APIC + I/O APIC */ +typedef struct HAL_INTC { + void (*RegisterIrq)(uint8_t irq, void (*handler)(void)); + void (*MaskIrq)(uint8_t irq); + void (*UnmaskIrq)(uint8_t irq); + void (*SendEoi)(void); +} HAL_INTC; + +typedef struct HAL_API { + uint32_t Version; /* HAL_API_VERSION */ + HAL_SCREEN Screen; + HAL_KEYBOARD Keyboard; + HAL_DISK Disk; + HAL_TIMER Timer; + HAL_PCI Pci; + HAL_INTC Intc; +} HAL_API; + +#define HAL_API_VERSION 1 + +/* Exported by hal.dll. */ +const HAL_API* HalGetApi(void); +KSTATUS HalInitialize(const BOOT_INFO* bootInfo); +``` + +### 7.2 DbgPrint + +```c +/* Declared in hal_api.h, implemented in hal.dll, ring 0 only. + Not exported to ring 3. No KSTATUS - void, always. */ + +void DbgPrint(const char* fmt, ...); +``` + +`DbgPrint` is always compiled in. On entry it checks the internal `HalDebugEnabled` flag +(set by `HalInitialize` from `BOOT_INFO.DebugEnabled`) and returns immediately if clear. +When enabled, it formats the string and writes to the console. The implementation is not +specified here - just noted as writing to console output. + +Kernel code, HAL internals, and drivers all call `DbgPrint` freely. There is no ring-3 +equivalent and no syscall wrapper for it. + +### 7.3 HAL Internals Summary + +**Screen:** Direct writes to the GOP framebuffer from `BOOT_INFO`. An embedded 8×16 bitmap font +covers printable ASCII. `DbgPrint` uses this for output. + +**Keyboard:** IRQ 1 via I/O APIC. PS/2 controller on ports `0x60`/`0x64`. Scancodes collected +into a 256-entry ring buffer; `ReadChar` translates set-2 scancodes to ASCII. + +**Disk:** Dispatch table of up to 8 logical drives. Populated by drivers calling +`IoRegisterDisk` during `DriverEntry`. `HAL_DISK` functions index into this table. + +**Timer:** HPET comparator fires every 1 ms, increments a `uint64_t` tick counter. Falls back +to the APIC timer calibrated against the PIT if no HPET is found. + +**PCI:** Mechanism 1 port I/O (`0xCF8`/`0xCFC`). No PCIe extended config space for now. + +**APIC:** Local APIC MMIO base discovered from the MADT. I/O APIC IRQ routing from MADT. +IRQ 0 drives the scheduler tick. IRQ 1 is the keyboard. + +--- + +## 8. System Call Interface - syscall.dll + +### 8.1 Why INT 0x2E + +`SYSCALL`/`SYSRET` requires programming `MSR_STAR`, `MSR_LSTAR`, `MSR_SFMASK`, and careful +handling of the segment registers on return. `INT 0x2E` uses the IDT we already set up for +hardware interrupts - one IDT gate, one handler, done. The performance difference does not +matter at this scale. + +### 8.2 IDT Entry and Kernel Handler + +Vector `0x2E` is installed as an interrupt gate (IF cleared on entry, ring-3 callable - DPL=3 +in the gate descriptor). + +The handler is a MASM64 stub: + +```asm +; ke_syscall_entry in ke_syscall.asm +; On entry: RAX = syscall number, RCX/RDX/R8/R9/R10/R11 = args +; (Microsoft x64 ABI: first four args in RCX, RDX, R8, R9; +; we repurpose R10 and R11 for args 5 and 6) + +KeSyscallEntry PROC + ; The CPU has already pushed SS, RSP, RFLAGS, CS, RIP + ; and switched to the kernel stack via TSS.RSP0. + sub rsp, 8 ; align to 16 bytes + push r11 + push r10 + push r9 + push r8 + push rdx + push rcx + push rax + call KeSyscallDispatch ; C function, args already on stack + add rsp, 7 * 8 ; clean args + iretq +KeSyscallEntry ENDP +``` + +`KeSyscallDispatch` is a plain C function in `ke_syscall.c` that dispatches on `nr` through +a function pointer table indexed by `SYS_*` constants. + +### 8.3 Syscall Numbers + +```c +// syscall_nr.h - shared between kernel and syscall.dll + +#pragma once + +#define SYS_EXIT_THREAD 0 +#define SYS_EXIT_PROCESS 1 +#define SYS_SPAWN 2 +#define SYS_SLEEP 3 +#define SYS_YIELD 4 +#define SYS_ALLOC 5 +#define SYS_FREE 6 +#define SYS_CREATE_THREAD 7 +#define SYS_OPEN_HANDLE 8 +#define SYS_CLOSE_HANDLE 9 +#define SYS_MUTEX_CREATE 10 +#define SYS_MUTEX_ACQUIRE 11 +#define SYS_MUTEX_RELEASE 12 +#define SYS_SEM_CREATE 13 +#define SYS_SEM_WAIT 14 +#define SYS_SEM_SIGNAL 15 +#define SYS_EVENT_CREATE 16 +#define SYS_EVENT_SET 17 +#define SYS_EVENT_WAIT 18 +#define SYS_QUEUE_CREATE 19 +#define SYS_QUEUE_SEND 20 +#define SYS_QUEUE_RECV 21 +#define SYS_SCREEN_BLIT 22 +#define SYS_GET_TICK 23 + +#define SYS_MAX 24 +``` + +### 8.4 User-Side Stubs - syscall.dll + +Each syscall is a MASM64 procedure. `syscall.dll` exports them by name. User code links +against `syscall.dll` and calls them as normal functions. + +```asm +; syscall_stubs.asm +; Microsoft x64 ABI: args in RCX, RDX, R8, R9, then stack. +; We move arg 5 and 6 into R10 and R11 before INT. + +SysYield PROC + mov rax, SYS_YIELD + int 02Eh + ret +SysYield ENDP + +SysAlloc PROC + ; RCX = size (already in place) + mov rax, SYS_ALLOC + int 02Eh + ret +SysAlloc ENDP + +SysFree PROC + ; RCX = ptr, RDX = size + mov rax, SYS_FREE + int 02Eh + ret +SysFree ENDP + +; ... one PROC per SYS_* constant +``` + +--- + +## 9. Driver Model + +### 9.1 drivers/drivers.ini + +```ini +[drivers] +ide.sys +ahci.sys +``` + +All listed drivers are loaded unconditionally. Each one's `DriverEntry` is called after the +HAL is initialised. A driver that finds no matching hardware returns `STATUS_NOT_FOUND` - this +is logged via `DbgPrint` and the kernel continues. Nothing is skipped based on load order. + +### 9.2 Driver Interface + +```c +// io_driver.h + +#pragma once +#include "hal_api.h" +#include "ke_status.h" + +/* + * Every .sys exports these two symbols. + * + * DriverEntry - probe for hardware, register services, return status. + * DriverUnload - cleanup (reserved for future use). + */ +typedef KSTATUS (*DRIVER_ENTRY_FN)(const HAL_API* hal); +typedef void (*DRIVER_UNLOAD_FN)(void); + +/* Disk driver registration - called by a driver inside DriverEntry + when it has found and initialised a disk controller. + Exported by hal.dll. */ +typedef struct DISK_DRIVER { + KSTATUS (*ReadSectors)(uint64_t lba, uint32_t count, void* buf); + KSTATUS (*WriteSectors)(uint64_t lba, uint32_t count, const void* buf); + uint64_t SectorCount; +} DISK_DRIVER; + +KSTATUS IoRegisterDisk(uint8_t driveIndex, const DISK_DRIVER* driver); +``` + +--- + +## 10. Win32 Personality - win32.dll + +The Win32 personality is implemented as a DLL (`win32.dll`) that provides a user-mode API compatible with Windows. It translates Win32 API calls into equivalent system calls to the kernel. +It does not implement the full Win32 API, but provides a subset sufficient for basic applications. +The API includes functions for process and thread management, synchronization primitives, file I/O, and basic GUI operations (stubs for now, no graphics yet). + +--- + +## 11. Data Structures Reference + +### Intrusive Doubly-Linked List + +```c +// ke_list.h + +#pragma once +#include + +typedef struct LIST_ENTRY { + struct LIST_ENTRY* Fwd; + struct LIST_ENTRY* Bwd; +} LIST_ENTRY; + +#define LIST_INIT(head) ((head)->Fwd = (head)->Bwd = (head)) +#define LIST_IS_EMPTY(head) ((head)->Fwd == (head)) + +/* Recover the containing struct pointer from an embedded LIST_ENTRY. */ +#define CONTAINING_RECORD(ptr, type, member) \ + ((type *)((char *)(ptr) - offsetof(type, member))) + +static inline void ListInsertTail(LIST_ENTRY* head, LIST_ENTRY* node) { + node->Bwd = head->Bwd; + node->Fwd = head; + head->Bwd->Fwd = node; + head->Bwd = node; +} + +static inline void ListRemove(LIST_ENTRY* node) { + node->Bwd->Fwd = node->Fwd; + node->Fwd->Bwd = node->Bwd; + node->Fwd = node->Bwd = node; /* self-loop: poison against double-remove */ +} +``` + +--- + +## 12. File Layout + +``` +ESP/ +├── boot.ini +├── bootx64.efi +├── kernel.exe +├── hal.dll +├── syscall.dll +├── win32.dll +└── drivers/ + ├── drivers.ini + ├── ide.sys + └── ahci.sys + └── fat32.sys + +src/ +├── boot/ +│ ├── main.c UefiMain, image loading, PML4 setup, MEMORY_MAP conversion +│ ├── ini_parser.c Minimal boot.ini / drivers.ini reader +│ └── ldr_image.c symlink to kernel's loader. +│ +├── kernel/ +│ ├── kmain.c KernelMain(BOOT_INFO *) +│ ├── boot_info.h BOOT_INFO structure +│ ├── ke_status.h KSTATUS codes +│ ├── ke_list.h LIST_ENTRY, ListInsertTail, ListRemove +│ ├── ke_spinlock.h SPINLOCK, KeAcquireSpinlock, KeReleaseSpinlock +│ ├── ob_object.c/h OBJECT, ObAllocateObject, ObReferenceObject, ObDereferenceObject +│ ├── mm_phys.c/h PMM: MmAllocateFrame, MmFreeFrame +│ ├── mm_virt.c/h VMM: MmMapPage, MmAllocatePool, MmAllocateUserMemory +│ ├── ke_process.c/h PROCESS, KeCreateProcess, KeExitProcess +│ ├── ke_thread.c/h THREAD, KeCreateThread, KeExitThread +│ ├── ke_sched.c/h MLFQ scheduler, KeSchedulerTick, KeYield +│ ├── ke_switch.asm KeSwitchContext (MASM64) +│ ├── ke_mutex.c/h MUTEX, KeAcquireMutex, KeReleaseMutex +│ ├── ke_semaphore.c/h SEMAPHORE, KeWaitSemaphore, KeSignalSemaphore +│ ├── ke_event.c/h EVENT, KeSignalEvent, KeWaitForEvent +│ ├── ke_queue.c/h QUEUE, KeSendMessage, KeReceiveMessage +│ ├── ke_syscall.c KeSyscallDispatch, syscall table +│ ├── ke_syscall.asm KeSyscallEntry INT 0x2E stub (MASM64) +│ ├── ldr_image.c/h LdrLoadImage, LdrResolveImport, LdrGetExport +│ └── memory_map.h MEMORY_MAP, MEMORY_REGION, MEMORY_TYPE +│ +├── hal/ +│ ├── hal_main.c HalInitialize, HalGetApi, HalDebugEnabled +│ ├── hal_debug.c DbgPrint (printf-style, runtime-gated) +│ ├── hal_screen.c GOP framebuffer, 8x16 ASCII font +│ ├── hal_keyboard.c PS/2 + IRQ 1 +│ ├── hal_timer.c HPET / APIC timer fallback +│ ├── hal_pci.c Mechanism-1 config space +│ ├── hal_disk.c Drive registry, IoRegisterDisk +│ └── hal_apic.c Local APIC + I/O APIC, MADT parsing +│ +├── syscall/ +│ └── syscall_stubs.asm SysYield, SysAlloc, SysFree, ... (MASM64) +│ +├── win32/ +│ ├── kernel32.c +│ ├── user32.c +│ ├── ole32.c +│ └── winmm.c +│ +└── drivers/ + ├── ide/ + │ └── ide.c + └── ahci/ + └── ahci.c +``` diff --git a/OVMF/OVMF_CODE_4M.fd b/OVMF/OVMF_CODE_4M.fd new file mode 100644 index 0000000..24fbf1d Binary files /dev/null and b/OVMF/OVMF_CODE_4M.fd differ diff --git a/OVMF/OVMF_CODE_4M.ms.fd b/OVMF/OVMF_CODE_4M.ms.fd new file mode 100644 index 0000000..d1809b4 Binary files /dev/null and b/OVMF/OVMF_CODE_4M.ms.fd differ diff --git a/OVMF/OVMF_CODE_4M.secboot.fd b/OVMF/OVMF_CODE_4M.secboot.fd new file mode 100644 index 0000000..d1809b4 Binary files /dev/null and b/OVMF/OVMF_CODE_4M.secboot.fd differ diff --git a/OVMF/OVMF_CODE_4M.snakeoil.fd b/OVMF/OVMF_CODE_4M.snakeoil.fd new file mode 100644 index 0000000..d1809b4 Binary files /dev/null and b/OVMF/OVMF_CODE_4M.snakeoil.fd differ diff --git a/OVMF/OVMF_VARS_4M.fd b/OVMF/OVMF_VARS_4M.fd new file mode 100644 index 0000000..354f061 Binary files /dev/null and b/OVMF/OVMF_VARS_4M.fd differ diff --git a/OVMF/OVMF_VARS_4M.ms.fd b/OVMF/OVMF_VARS_4M.ms.fd new file mode 100644 index 0000000..be30858 Binary files /dev/null and b/OVMF/OVMF_VARS_4M.ms.fd differ diff --git a/OVMF/OVMF_VARS_4M.snakeoil.fd b/OVMF/OVMF_VARS_4M.snakeoil.fd new file mode 100644 index 0000000..d57cc47 Binary files /dev/null and b/OVMF/OVMF_VARS_4M.snakeoil.fd differ diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..bdb177d --- /dev/null +++ b/build.bat @@ -0,0 +1,157 @@ +@echo off +setlocal enabledelayedexpansion + +set ROOT=%~dp0. +set SRC=%ROOT%\code +set DEST=G:\ + +if exist "obj" rd /s /q "obj" +if exist "bin" rd /s /q "bin" + +mkdir "obj\boot" 2>nul +mkdir "obj\kernel" 2>nul +mkdir "obj\hal" 2>nul +mkdir "obj\syscall" 2>nul +mkdir "obj\win32" 2>nul +mkdir "obj\drivers" 2>nul +mkdir "obj\shell" 2>nul +mkdir "bin" 2>nul + +set CFLAGS=/nologo /W4 /WX /Od /GS- /Gs999999 /Gz /Gy /EHsc- /GR- /Oi /Zi /std:c17 /D_CRT_SECURE_NO_WARNINGS /I"%SRC%\kernel" /I"%SRC%\hal" +set LFLAGS=/nologo /NODEFAULTLIB /DEBUG + +:: ---- Assemble ASM files ---- +echo Assembling... +ml64 /nologo /c /Fo"obj\kernel\ke_switch.obj" "%SRC%\kernel\ke_switch.asm" || exit /b 1 +ml64 /nologo /c /Fo"obj\kernel\ke_syscall_asm.obj" "%SRC%\kernel\ke_syscall.asm" || exit /b 1 +ml64 /nologo /c /Fo"obj\kernel\ke_gdt_reload.obj" "%SRC%\kernel\ke_gdt_reload.asm" || exit /b 1 +ml64 /nologo /c /Fo"obj\syscall\stubs.obj" "%SRC%\syscall\syscall_stubs.asm" || exit /b 1 + +:: ---- Compile libc ---- +cl /nologo /c /Fo"obj\libc.obj" "%SRC%\libc.c" || exit /b 1 +:: ---- Compile printf ---- +cl %CFLAGS% /c /Fo"obj\printf.obj" "%SRC%\printf.c" || exit /b 1 +:: ---- Compile ini parser ---- +cl %CFLAGS% /c /Fo"obj\ini_parser.obj" "%SRC%\ini_parser.c" || exit /b 1 + +:: ---- Compile bootloader ---- +echo Compiling bootloader... +for %%f in (%SRC%\boot\*.c) do ( + cl %CFLAGS% /c /I"%SRC%\boot\include" /Fo"obj\boot\%%~nf.obj" "%%f" || exit /b 1 +) + +:: ---- Link bootloader ---- +echo Linking bootx64.efi... +link %LFLAGS% /SUBSYSTEM:EFI_APPLICATION /ENTRY:UefiMain /OUT:"bin\bootx64.efi" ^ + /PDB:"bin\bootx64.pdb" %SRC%\boot\efilib.lib obj\ini_parser.obj obj\libc.obj obj\boot\*.obj || exit /b 1 + +:: ---- Compile HAL ---- +echo Compiling hal... +for %%f in (%SRC%\hal\*.c) do ( + cl %CFLAGS% /c /Fo"obj\hal\%%~nf.obj" "%%f" || exit /b 1 +) + +:: ---- Link hal.dll ---- +echo Linking hal.dll... +link %LFLAGS% /DLL /OUT:"bin\hal.dll" ^ + /ENTRY:HalInitialize /IGNORE:4216 ^ + /EXPORT:HalInitialize /EXPORT:HalRegisterScheduler /EXPORT:HalGetApi ^ + /EXPORT:IoRegisterDisk ^ + obj\printf.obj obj\libc.obj obj\hal\*.obj || exit /b 1 + +:: ---- Compile kernel ---- +echo Compiling kernel... +for %%f in (%SRC%\kernel\*.c) do ( + cl %CFLAGS% /c /Fo"obj\kernel\%%~nf.obj" "%%f" || exit /b 1 +) + +:: ---- Link kernel.exe ---- +echo Linking kernel.exe... +link %LFLAGS% /SUBSYSTEM:NATIVE /ENTRY:KernelMain /OUT:"bin\kernel.exe" ^ + /PDB:"bin\kernel.pdb" /EXPORT:MmAllocatePool /EXPORT:MmFreePool /EXPORT:IoRegisterFilesystem ^ + /EXPORT:KeSignalEvent /EXPORT:MmAllocateContiguous /EXPORT:ObDereferenceObject /EXPORT:KeEventCreate ^ + /EXPORT:KeWaitForEvent /EXPORT:KeClearEvent /EXPORT:MmGetPhysicalAddress /EXPORT:DbgPrint /EXPORT:KeIrqDispatch ^ + bin\hal.lib obj\ini_parser.obj obj\printf.obj obj\libc.obj obj\kernel\*.obj || exit /b 1 + +:: ---- Compile syscall.dll ---- +echo Compiling syscall.dll... +link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL ^ + /OUT:"bin\syscall.dll" ^ + /EXPORT:SysYield /EXPORT:SysAlloc /EXPORT:SysFree ^ + /EXPORT:SysCreateThread /EXPORT:SysCloseHandle ^ + /EXPORT:SysMutexCreate /EXPORT:SysMutexAcquire /EXPORT:SysMutexRelease ^ + /EXPORT:SysSemCreate /EXPORT:SysSemWait /EXPORT:SysSemSignal ^ + /EXPORT:SysEventCreate /EXPORT:SysEventSet /EXPORT:SysEventWait ^ + /EXPORT:SysQueueCreate /EXPORT:SysQueueSend /EXPORT:SysQueueRecv ^ + /EXPORT:SysScreenBlit /EXPORT:SysGetTick /EXPORT:SysSleep ^ + /EXPORT:SysExitThread /EXPORT:SysExitProcess /EXPORT:SysDbgPrint ^ + obj\syscall\stubs.obj || exit /b 1 + +:: ---- Compile win32.dll ---- +echo Compiling win32.dll... +for %%f in (%SRC%\win32\*.c) do ( + cl %CFLAGS% /c /Fo"obj\win32\%%~nf.obj" "%%f" || exit /b 1 +) +link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL ^ + /OUT:"bin\win32.dll" ^ + /EXPORT:HeapAlloc /EXPORT:HeapFree /EXPORT:HeapReAlloc ^ + /EXPORT:CreateThread /EXPORT:ExitProcess /EXPORT:ExitThread ^ + /EXPORT:Sleep /EXPORT:SwitchToThread ^ + /EXPORT:CreateMutex /EXPORT:ReleaseMutex /EXPORT:WaitForSingleObject ^ + /EXPORT:CreateEvent /EXPORT:SetEvent /EXPORT:CloseHandle ^ + /EXPORT:GetTickCount /EXPORT:GetTickCount64 ^ + /EXPORT:BitBlt /EXPORT:GetMessage /EXPORT:DispatchMessage /EXPORT:OutputDebugStringA ^ + bin\syscall.lib obj\win32\*.obj || exit /b 1 + +:: ---- Compile drivers ---- +echo Compiling drivers... +cl %CFLAGS% /I"%SRC%\hal" /c /Fo"obj\drivers\ide.obj" "%SRC%\drivers\ide\ide.c" || exit /b 1 +link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL ^ + /OUT:"bin\ide.sys" /IGNORE:4216 /ENTRY:DriverEntry /EXPORT:DriverEntry ^ + bin\hal.lib bin\kernel.lib obj\libc.obj obj\drivers\ide.obj || exit /b 1 + +cl %CFLAGS% /I"%SRC%\hal" /c /Fo"obj\drivers\ahci.obj" "%SRC%\drivers\ahci\ahci.c" || exit /b 1 +link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL ^ + /OUT:"bin\ahci.sys" /IGNORE:4216 /ENTRY:DriverEntry /EXPORT:DriverEntry ^ + bin\hal.lib bin\kernel.lib obj\libc.obj obj\drivers\ahci.obj || exit /b 1 + +cl %CFLAGS% /I"%SRC%\fat32" /c /Fo"obj\drivers\fat32.obj" "%SRC%\drivers\fat32\fat32.c" || exit /b 1 +link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL ^ + /OUT:"bin\fat32.sys" /IGNORE:4216 /ENTRY:DriverEntry /EXPORT:DriverEntry ^ + bin\hal.lib bin\kernel.lib obj\libc.obj obj\drivers\fat32.obj || exit /b 1 + +cl %CFLAGS% /I"%SRC%\usb" /c /Fo"obj\drivers\usb.obj" "%SRC%\drivers\usb\usb.c" || exit /b 1 +link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL ^ + /OUT:"bin\usb.sys" /IGNORE:4216 /ENTRY:DriverEntry /EXPORT:DriverEntry ^ + bin\hal.lib bin\kernel.lib obj\libc.obj obj\drivers\usb.obj || exit /b 1 + +:: ---- Compile shell ---- +echo Compiling shell... +for %%f in (%SRC%\shell\*.c) do ( + cl %CFLAGS% /c /Fo"obj\shell\%%~nf.obj" "%%f" || exit /b 1 +) + +:: ---- Link shell.exe ---- +echo Linking shell.exe... +link %LFLAGS% /SUBSYSTEM:NATIVE /ENTRY:main ^ + /OUT:"bin\shell.exe" /PDB:"bin\shell.pdb" bin\win32.lib obj\libc.obj obj\shell\*.obj || exit /b 1 + +:: ---- Copy to ESP layout ---- +echo Assembling ESP... +mkdir "%DEST%\drivers" 2>nul +mkdir "%DEST%\EFI\BOOT" 2>nul +copy /y "bin\bootx64.efi" "%DEST%\EFI\BOOT\" +copy /y "bin\kernel.exe" "%DEST%\" +copy /y "bin\hal.dll" "%DEST%\" +copy /y "bin\syscall.dll" "%DEST%\" +copy /y "bin\win32.dll" "%DEST%\" +copy /y "bin\ide.sys" "%DEST%\drivers\" +copy /y "bin\ahci.sys" "%DEST%\drivers\" +copy /y "bin\fat32.sys" "%DEST%\drivers\" +copy /y "bin\usb.sys" "%DEST%\drivers\" +copy /y "bin\shell.exe" "%DEST%\" +copy /y "%SRC%\boot.ini" "%DEST%\" +copy /y "%SRC%\drivers\drivers.ini" "%DEST%\drivers\" + +echo. +echo Build complete. diff --git a/code/boot.ini b/code/boot.ini new file mode 100644 index 0000000..7c91c2e --- /dev/null +++ b/code/boot.ini @@ -0,0 +1,4 @@ +[kernel] +debug = 1 +[init] +commandline = shell.exe diff --git a/code/boot/efilib.lib b/code/boot/efilib.lib new file mode 100644 index 0000000..8497241 Binary files /dev/null and b/code/boot/efilib.lib differ diff --git a/code/boot/efilib.pdb b/code/boot/efilib.pdb new file mode 100644 index 0000000..d7c86bf Binary files /dev/null and b/code/boot/efilib.pdb differ diff --git a/code/boot/include/Makefile b/code/boot/include/Makefile new file mode 100644 index 0000000..35361eb --- /dev/null +++ b/code/boot/include/Makefile @@ -0,0 +1,24 @@ +SRCDIR = . + +VPATH = $(SRCDIR) +TOPDIR = $(SRCDIR)/.. + +include $(SRCDIR)/../Make.defaults + +all: + +clean: + +install: + mkdir -p $(INSTALLROOT)$(INCLUDEDIR)/efi + mkdir -p $(INSTALLROOT)$(INCLUDEDIR)/efi/protocol + mkdir -p $(INSTALLROOT)$(INCLUDEDIR)/efi/$(ARCH) + $(INSTALL) -m 644 $(SRCDIR)/*.h $(INSTALLROOT)$(INCLUDEDIR)/efi + $(INSTALL) -m 644 $(SRCDIR)/protocol/*.h $(INSTALLROOT)$(INCLUDEDIR)/efi/protocol + $(INSTALL) -m 644 $(SRCDIR)/$(ARCH)/*.h $(INSTALLROOT)$(INCLUDEDIR)/efi/$(ARCH) +ifeq ($(ARCH),ia64) + mkdir -p $(INSTALLROOT)$(INCLUDEDIR)/efi/protocol/ia64 + $(INSTALL) -m 644 $(SRCDIR)/protocol/ia64/*.h $(INSTALLROOT)$(INCLUDEDIR)/efi/protocol/ia64 +endif + +include $(SRCDIR)/../Make.rules diff --git a/code/boot/include/aarch64/efibind.h b/code/boot/include/aarch64/efibind.h new file mode 100644 index 0000000..a15f1b5 --- /dev/null +++ b/code/boot/include/aarch64/efibind.h @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2014 - 2015 Linaro Ltd. + * Author: Ard Biesheuvel + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License as published by the Free Software Foundation; + * either version 2 of the License, or (at your option) any later version. + */ + +#if !defined(_MSC_VER) && (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L )) && !defined(__cplusplus) + +// ANSI C 1999/2000 stdint.h integer width declarations + +typedef unsigned long uint64_t; +typedef long int64_t; +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef signed char int8_t; // unqualified 'char' is unsigned on ARM +typedef uint64_t uintptr_t; +typedef int64_t intptr_t; + +#else +#include +#endif + +// +// Basic EFI types of various widths +// + +#include + +typedef wchar_t CHAR16; +#define WCHAR CHAR16 + +typedef uint64_t UINT64; +typedef int64_t INT64; + +typedef uint32_t UINT32; +typedef int32_t INT32; + +typedef uint16_t UINT16; +typedef int16_t INT16; + +typedef uint8_t UINT8; +typedef char CHAR8; +typedef int8_t INT8; + +#undef VOID +typedef void VOID; + +typedef int64_t INTN; +typedef uint64_t UINTN; + +#define EFIERR(a) (0x8000000000000000 | a) +#define EFI_ERROR_MASK 0x8000000000000000 +#define EFIERR_OEM(a) (0xc000000000000000 | a) + +#define BAD_POINTER 0xFBFBFBFBFBFBFBFB +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF + +#define BREAKPOINT() while (TRUE); // Make it hang on Bios[Dbg]32 + +// +// Pointers must be aligned to these address to function +// + +#define MIN_ALIGNMENT_SIZE 8 + +#define ALIGN_VARIABLE(Value ,Adjustment) \ + (UINTN)Adjustment = 0; \ + if((UINTN)Value % MIN_ALIGNMENT_SIZE) \ + (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \ + Value = (UINTN)Value + (UINTN)Adjustment + + +// +// Define macros to build data structure signatures from characters. +// + +#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8)) +#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16)) +#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32)) + +// +// EFIAPI - prototype calling convention for EFI function pointers +// BOOTSERVICE - prototype for implementation of a boot service interface +// RUNTIMESERVICE - prototype for implementation of a runtime service interface +// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service +// RUNTIME_CODE - pragma macro for declaring runtime code +// + +#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options +#define EFIAPI // Substitute expresion to force C calling convention +#endif + +#define BOOTSERVICE +#define RUNTIMESERVICE +#define RUNTIMEFUNCTION + + +#define RUNTIME_CODE(a) alloc_text("rtcode", a) +#define BEGIN_RUNTIME_DATA() data_seg("rtdata") +#define END_RUNTIME_DATA() data_seg("") + +#define VOLATILE volatile + +#define MEMORY_FENCE __sync_synchronize + +// +// When build similiar to FW, then link everything together as +// one big module. For the MSVC toolchain, we simply tell the +// linker what our driver init function is using /ENTRY. +// +#if defined(_MSC_EXTENSIONS) +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + __pragma(comment(linker, "/ENTRY:" # InitFunction)) +#else +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + UINTN \ + InitializeDriver ( \ + VOID* ImageHandle, \ + VOID* SystemTable \ + ) \ + { \ + return InitFunction(ImageHandle, \ + SystemTable); \ + } \ + \ + EFI_STATUS efi_main( \ + EFI_HANDLE image, \ + EFI_SYSTEM_TABLE* systab \ + ) __attribute__((weak, \ + alias ("InitializeDriver"))); +#endif + +#define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, entry) + + +// +// Some compilers don't support the forward reference construct: +// typedef struct XXXXX +// +// The following macro provide a workaround for such cases. + +#define INTERFACE_DECL(x) struct x + +#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__) +#define EFI_FUNCTION diff --git a/code/boot/include/aarch64/efilibplat.h b/code/boot/include/aarch64/efilibplat.h new file mode 100644 index 0000000..ba280b0 --- /dev/null +++ b/code/boot/include/aarch64/efilibplat.h @@ -0,0 +1,25 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efilibplat.h + +Abstract: + + EFI to compile bindings + + + + +Revision History + +--*/ + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE* SystemTable + ); + diff --git a/code/boot/include/aarch64/efisetjmp_arch.h b/code/boot/include/aarch64/efisetjmp_arch.h new file mode 100644 index 0000000..14be3c8 --- /dev/null +++ b/code/boot/include/aarch64/efisetjmp_arch.h @@ -0,0 +1,34 @@ +#ifndef GNU_EFI_AARCH64_SETJMP_H +#define GNU_EFI_AARCH64_SETJMP_H + +#define JMPBUF_ALIGN 8 + +typedef struct { + /* GP regs */ + UINT64 X19; + UINT64 X20; + UINT64 X21; + UINT64 X22; + UINT64 X23; + UINT64 X24; + UINT64 X25; + UINT64 X26; + UINT64 X27; + UINT64 X28; + UINT64 FP; + UINT64 LR; + UINT64 IP0; + UINT64 _pad1; + + /* FP regs */ + UINT64 D8; + UINT64 D9; + UINT64 D10; + UINT64 D11; + UINT64 D12; + UINT64 D13; + UINT64 D14; + UINT64 D15; +} EFI_ALIGN(JMPBUF_ALIGN) jmp_buf[1]; + +#endif /* GNU_EFI_AARCH64_SETJMP_H */ diff --git a/code/boot/include/arm/efibind.h b/code/boot/include/arm/efibind.h new file mode 100644 index 0000000..52d0e3d --- /dev/null +++ b/code/boot/include/arm/efibind.h @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2014 - 2015 Linaro Ltd. + * Author: Ard Biesheuvel + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License as published by the Free Software Foundation; + * either version 2 of the License, or (at your option) any later version. + */ + +#if !defined(_MSC_VER) && (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L )) && !defined(__cplusplus) + +// ANSI C 1999/2000 stdint.h integer width declarations + +typedef unsigned long long uint64_t; +typedef long long int64_t; +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef signed char int8_t; // unqualified 'char' is unsigned on ARM +typedef uint32_t uintptr_t; +typedef int32_t intptr_t; + +#else +#include +#endif + +/* + * This prevents GCC from emitting GOT based relocations, and use R_ARM_REL32 + * relative relocations instead, which are more suitable for static binaries. + */ +#if defined(__GNUC__) && !__STDC_HOSTED__ +#pragma GCC visibility push (hidden) +#endif + +// +// Basic EFI types of various widths +// + +#include + +typedef wchar_t CHAR16; +#define WCHAR CHAR16 + +typedef uint64_t UINT64; +typedef int64_t INT64; + +typedef uint32_t UINT32; +typedef int32_t INT32; + +typedef uint16_t UINT16; +typedef int16_t INT16; + +typedef uint8_t UINT8; +typedef char CHAR8; +typedef int8_t INT8; + +#undef VOID +typedef void VOID; + +typedef int32_t INTN; +typedef uint32_t UINTN; + +#define EFIERR(a) (0x80000000 | a) +#define EFI_ERROR_MASK 0x80000000 +#define EFIERR_OEM(a) (0xc0000000 | a) + +#define BAD_POINTER 0xFBFBFBFB +#define MAX_ADDRESS 0xFFFFFFFF + +#define BREAKPOINT() while (TRUE); + +// +// Pointers must be aligned to these address to function +// + +#define MIN_ALIGNMENT_SIZE 4 + +#define ALIGN_VARIABLE(Value ,Adjustment) \ + (UINTN)Adjustment = 0; \ + if((UINTN)Value % MIN_ALIGNMENT_SIZE) \ + (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \ + Value = (UINTN)Value + (UINTN)Adjustment + + +// +// Define macros to build data structure signatures from characters. +// + +#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8)) +#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16)) +#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32)) + +// +// EFIAPI - prototype calling convention for EFI function pointers +// BOOTSERVICE - prototype for implementation of a boot service interface +// RUNTIMESERVICE - prototype for implementation of a runtime service interface +// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service +// RUNTIME_CODE - pragma macro for declaring runtime code +// + +#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options +#define EFIAPI // Substitute expresion to force C calling convention +#endif + +#define BOOTSERVICE +#define RUNTIMESERVICE +#define RUNTIMEFUNCTION + + +#define RUNTIME_CODE(a) alloc_text("rtcode", a) +#define BEGIN_RUNTIME_DATA() data_seg("rtdata") +#define END_RUNTIME_DATA() data_seg("") + +#define VOLATILE volatile + +#define MEMORY_FENCE __sync_synchronize + +// +// When build similiar to FW, then link everything together as +// one big module. For the MSVC toolchain, we simply tell the +// linker what our driver init function is using /ENTRY. +// +#if defined(_MSC_EXTENSIONS) +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + __pragma(comment(linker, "/ENTRY:" # InitFunction)) +#else +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + UINTN \ + InitializeDriver ( \ + VOID* ImageHandle, \ + VOID* SystemTable \ + ) \ + { \ + return InitFunction(ImageHandle, \ + SystemTable); \ + } \ + \ + EFI_STATUS efi_main( \ + EFI_HANDLE image, \ + EFI_SYSTEM_TABLE* systab \ + ) __attribute__((weak, \ + alias ("InitializeDriver"))); +#endif + +#define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, entry) + + +// +// Some compilers don't support the forward reference construct: +// typedef struct XXXXX +// +// The following macro provide a workaround for such cases. + +#define INTERFACE_DECL(x) struct x + +#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__) +#define EFI_FUNCTION diff --git a/code/boot/include/arm/efilibplat.h b/code/boot/include/arm/efilibplat.h new file mode 100644 index 0000000..ba280b0 --- /dev/null +++ b/code/boot/include/arm/efilibplat.h @@ -0,0 +1,25 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efilibplat.h + +Abstract: + + EFI to compile bindings + + + + +Revision History + +--*/ + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE* SystemTable + ); + diff --git a/code/boot/include/arm/efisetjmp_arch.h b/code/boot/include/arm/efisetjmp_arch.h new file mode 100644 index 0000000..3c1d48c --- /dev/null +++ b/code/boot/include/arm/efisetjmp_arch.h @@ -0,0 +1,21 @@ +#ifndef GNU_EFI_ARM_SETJMP_H +#define GNU_EFI_ARM_SETJMP_H + +#define JMPBUF_ALIGN 4 + +typedef struct { + UINT32 R3; // A copy of R13 + UINT32 R4; + UINT32 R5; + UINT32 R6; + UINT32 R7; + UINT32 R8; + UINT32 R9; + UINT32 R10; + UINT32 R11; + UINT32 R12; + UINT32 R13; + UINT32 R14; +} EFI_ALIGN(JMPBUF_ALIGN) jmp_buf[1]; + +#endif /* GNU_EFI_ARM_SETJMP_H */ diff --git a/code/boot/include/efi.h b/code/boot/include/efi.h new file mode 100644 index 0000000..7a98455 --- /dev/null +++ b/code/boot/include/efi.h @@ -0,0 +1,91 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efi.h + +Abstract: + + Public EFI header files + + + +Revision History + +--*/ + + +// Add a predefined macro to detect usage of the library +#ifndef _GNU_EFI +#define _GNU_EFI +#endif + +// +// Build flags on input +// EFI32 +// EFI_DEBUG - Enable debugging code +// EFI_NT_EMULATOR - Building for running under NT +// + + +#ifndef _EFI_INCLUDE_ +#define _EFI_INCLUDE_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define EFI_FIRMWARE_VENDOR L"INTEL" +#define EFI_FIRMWARE_MAJOR_REVISION 12 +#define EFI_FIRMWARE_MINOR_REVISION 33 +#define EFI_FIRMWARE_REVISION ((EFI_FIRMWARE_MAJOR_REVISION <<16) | (EFI_FIRMWARE_MINOR_REVISION)) + +#if defined(_M_X64) || defined(__x86_64__) || defined(__amd64__) +#include "x86_64/efibind.h" +#elif defined(_M_IX86) || defined(__i386__) +#include "ia32/efibind.h" +#elif defined(_M_IA64) || defined(__ia64__) +#include "ia64/efibind.h" +#elif defined (_M_ARM64) || defined(__aarch64__) +#include "aarch64/efibind.h" +#elif defined (_M_ARM) || defined(__arm__) +#include "arm/efibind.h" +#elif defined (_M_MIPS64) || defined(__mips64__) || defined(__mips64) +#include "mips64el/efibind.h" +#elif defined (__riscv) && __riscv_xlen == 64 +#include "riscv64/efibind.h" +#elif defined (__loongarch64) +#include "loongarch64/efibind.h" +#else +#error Usupported architecture +#endif + +#include "eficompiler.h" +#include "efidef.h" +#include "legacy.h" +#include "efidevp.h" +#include "efipciio.h" +#include "efiprot.h" +#include "eficon.h" +#include "eficonex.h" +#include "efiser.h" +#include "efi_nii.h" +#include "efipxebc.h" +#include "efinet.h" +#include "efiapi.h" +#include "efifs.h" +#include "efierr.h" +#include "efiui.h" +#include "efiip.h" +#include "efiudp.h" +#include "efitcp.h" +#include "efipoint.h" +#include "efishell.h" + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/code/boot/include/efi_nii.h b/code/boot/include/efi_nii.h new file mode 100644 index 0000000..ccd7d3f --- /dev/null +++ b/code/boot/include/efi_nii.h @@ -0,0 +1,78 @@ +#ifndef _EFI_NII_H +#define _EFI_NII_H + +/*++ +Copyright (c) 2000 Intel Corporation + +Module name: + efi_nii.h + +Abstract: + +Revision history: + 2000-Feb-18 M(f)J GUID updated. + Structure order changed for machine word alignment. + Added StringId[4] to structure. + + 2000-Feb-14 M(f)J Genesis. +--*/ + +#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID \ + { 0xE18541CD, 0xF755, 0x4f73, {0x92, 0x8D, 0x64, 0x3C, 0x8A, 0x79, 0xB2, 0x29} } + +#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION 0x00010000 +#define EFI_NETWORK_INTERFACE_IDENTIFIER_INTERFACE_REVISION EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION + +typedef enum { + EfiNetworkInterfaceUndi = 1 +} EFI_NETWORK_INTERFACE_TYPE; + +typedef struct _EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL { + + UINT64 Revision; + // Revision of the network interface identifier protocol interface. + + UINT64 ID; + // Address of the first byte of the identifying structure for this + // network interface. This is set to zero if there is no structure. + // + // For PXE/UNDI this is the first byte of the !PXE structure. + + UINT64 ImageAddr; + // Address of the UNrelocated driver/ROM image. This is set + // to zero if there is no driver/ROM image. + // + // For 16-bit UNDI, this is the first byte of the option ROM in + // upper memory. + // + // For 32/64-bit S/W UNDI, this is the first byte of the EFI ROM + // image. + // + // For H/W UNDI, this is set to zero. + + UINT32 ImageSize; + // Size of the UNrelocated driver/ROM image of this network interface. + // This is set to zero if there is no driver/ROM image. + + CHAR8 StringId[4]; + // 4 char ASCII string to go in class identifier (option 60) in DHCP + // and Boot Server discover packets. + // For EfiNetworkInterfaceUndi this field is "UNDI". + // For EfiNetworkInterfaceSnp this field is "SNPN". + + UINT8 Type; + UINT8 MajorVer; + UINT8 MinorVer; + // Information to be placed into the PXE DHCP and Discover packets. + // This is the network interface type and version number that will + // be placed into DHCP option 94 (client network interface identifier). + BOOLEAN Ipv6Supported; + UINT8 IfNum; // interface number to be used with pxeid structure +} EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL, EFI_NETWORK_INTERFACE_IDENTIFIER_INTERFACE; + +// Note: Because it conflicted with the EDK2 struct name, the +// 'EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL' GUID definition, +// from older versions of gnu-efi, is now obsoleted. +// Use 'EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID' instead. + +#endif // _EFI_NII_H diff --git a/code/boot/include/efi_pxe.h b/code/boot/include/efi_pxe.h new file mode 100644 index 0000000..86f7f89 --- /dev/null +++ b/code/boot/include/efi_pxe.h @@ -0,0 +1,1743 @@ +#ifndef _EFI_PXE_H +#define _EFI_PXE_H + + +/*++ +Copyright (c) Intel 1999 + +Module name: + efi_pxe.h + +32/64-bit PXE specification: + alpha-4, 99-Dec-17 + +Abstract: + This header file contains all of the PXE type definitions, + structure prototypes, global variables and constants that + are needed for porting PXE to EFI. +--*/ + +#pragma pack(1) + +#define PXE_INTEL_ORDER 1 // Intel order +//#define PXE_NETWORK_ORDER 1 // network order + +#define PXE_UINT64_SUPPORT 1 // UINT64 supported +//#define PXE_NO_UINT64_SUPPORT 1 // UINT64 not supported + +#define PXE_BUSTYPE(a,b,c,d) \ +((((PXE_UINT32)(d) & 0xFF) << 24) | \ +(((PXE_UINT32)(c) & 0xFF) << 16) | \ +(((PXE_UINT32)(b) & 0xFF) << 8) | \ +((PXE_UINT32)(a) & 0xFF)) + +// +// UNDI ROM ID and devive ID signature +// +#define PXE_BUSTYPE_PXE PXE_BUSTYPE('!', 'P', 'X', 'E') + +// +// BUS ROM ID signatures +// +#define PXE_BUSTYPE_PCI PXE_BUSTYPE('P', 'C', 'I', 'R') +#define PXE_BUSTYPE_PC_CARD PXE_BUSTYPE('P', 'C', 'C', 'R') +#define PXE_BUSTYPE_USB PXE_BUSTYPE('U', 'S', 'B', 'R') +#define PXE_BUSTYPE_1394 PXE_BUSTYPE('1', '3', '9', '4') + +#define PXE_SWAP_UINT16(n) \ +((((PXE_UINT16)(n) & 0x00FF) << 8) | \ +(((PXE_UINT16)(n) & 0xFF00) >> 8)) + +#define PXE_SWAP_UINT32(n) \ +((((PXE_UINT32)(n) & 0x000000FF) << 24) | \ +(((PXE_UINT32)(n) & 0x0000FF00) << 8) | \ +(((PXE_UINT32)(n) & 0x00FF0000) >> 8) | \ +(((PXE_UINT32)(n) & 0xFF000000) >> 24)) + +#if PXE_UINT64_SUPPORT != 0 +#define PXE_SWAP_UINT64(n) \ +((((PXE_UINT64)(n) & 0x00000000000000FF) << 56) | \ +(((PXE_UINT64)(n) & 0x000000000000FF00) << 40) | \ +(((PXE_UINT64)(n) & 0x0000000000FF0000) << 24) | \ +(((PXE_UINT64)(n) & 0x00000000FF000000) << 8) | \ +(((PXE_UINT64)(n) & 0x000000FF00000000) >> 8) | \ +(((PXE_UINT64)(n) & 0x0000FF0000000000) >> 24) | \ +(((PXE_UINT64)(n) & 0x00FF000000000000) >> 40) | \ +(((PXE_UINT64)(n) & 0xFF00000000000000) >> 56)) +#endif // PXE_UINT64_SUPPORT + +#if PXE_NO_UINT64_SUPPORT != 0 +#define PXE_SWAP_UINT64(n) \ +{ \ +PXE_UINT32 tmp = (PXE_UINT64)(n)[1]; \ +(PXE_UINT64)(n)[1] = PXE_SWAP_UINT32((PXE_UINT64)(n)[0]); \ +(PXE_UINT64)(n)[0] = tmp; \ +} +#endif // PXE_NO_UINT64_SUPPORT + +#define PXE_CPBSIZE_NOT_USED 0 // zero +#define PXE_DBSIZE_NOT_USED 0 // zero +#define PXE_CPBADDR_NOT_USED (PXE_UINT64)0 // zero +#define PXE_DBADDR_NOT_USED (PXE_UINT64)0 // zero + +#define PXE_CONST const + +#define PXE_VOLATILE volatile + +typedef void PXE_VOID; + +typedef unsigned char PXE_UINT8; + +typedef unsigned short PXE_UINT16; + +typedef unsigned PXE_UINT32; + +#if PXE_UINT64_SUPPORT != 0 +// typedef unsigned long PXE_UINT64; +typedef UINT64 PXE_UINT64; +#endif // PXE_UINT64_SUPPORT + +#if PXE_NO_UINT64_SUPPORT != 0 +typedef PXE_UINT32 PXE_UINT64[2]; +#endif // PXE_NO_UINT64_SUPPORT + +typedef unsigned PXE_UINTN; + +typedef PXE_UINT8 PXE_BOOL; + +#define PXE_FALSE 0 // zero +#define PXE_TRUE (!PXE_FALSE) + +typedef PXE_UINT16 PXE_OPCODE; + +// +// Return UNDI operational state. +// +#define PXE_OPCODE_GET_STATE 0x0000 + +// +// Change UNDI operational state from Stopped to Started. +// +#define PXE_OPCODE_START 0x0001 + +// +// Change UNDI operational state from Started to Stopped. +// +#define PXE_OPCODE_STOP 0x0002 + +// +// Get UNDI initialization information. +// +#define PXE_OPCODE_GET_INIT_INFO 0x0003 + +// +// Get NIC configuration information. +// +#define PXE_OPCODE_GET_CONFIG_INFO 0x0004 + +// +// Changed UNDI operational state from Started to Initialized. +// +#define PXE_OPCODE_INITIALIZE 0x0005 + +// +// Re-initialize the NIC H/W. +// +#define PXE_OPCODE_RESET 0x0006 + +// +// Change the UNDI operational state from Initialized to Started. +// +#define PXE_OPCODE_SHUTDOWN 0x0007 + +// +// Read & change state of external interrupt enables. +// +#define PXE_OPCODE_INTERRUPT_ENABLES 0x0008 + +// +// Read & change state of packet receive filters. +// +#define PXE_OPCODE_RECEIVE_FILTERS 0x0009 + +// +// Read & change station MAC address. +// +#define PXE_OPCODE_STATION_ADDRESS 0x000A + +// +// Read traffic statistics. +// +#define PXE_OPCODE_STATISTICS 0x000B + +// +// Convert multicast IP address to multicast MAC address. +// +#define PXE_OPCODE_MCAST_IP_TO_MAC 0x000C + +// +// Read or change non-volatile storage on the NIC. +// +#define PXE_OPCODE_NVDATA 0x000D + +// +// Get & clear interrupt status. +// +#define PXE_OPCODE_GET_STATUS 0x000E + +// +// Fill media header in packet for transmit. +// +#define PXE_OPCODE_FILL_HEADER 0x000F + +// +// Transmit packet(s). +// +#define PXE_OPCODE_TRANSMIT 0x0010 + +// +// Receive packet. +// +#define PXE_OPCODE_RECEIVE 0x0011 + +// last valid opcode: +#define PXE_OPCODE_VALID_MAX 0x0011 + +// +// Last valid PXE UNDI OpCode number. +// +#define PXE_OPCODE_LAST_VALID 0x0011 + +typedef PXE_UINT16 PXE_OPFLAGS; + +#define PXE_OPFLAGS_NOT_USED 0x0000 + +//////////////////////////////////////// +// UNDI Get State +// + +// No OpFlags + +//////////////////////////////////////// +// UNDI Start +// + +// No OpFlags + +//////////////////////////////////////// +// UNDI Stop +// + +// No OpFlags + +//////////////////////////////////////// +// UNDI Get Init Info +// + +// No Opflags + +//////////////////////////////////////// +// UNDI Get Config Info +// + +// No Opflags + +//////////////////////////////////////// +// UNDI Initialize +// + +#define PXE_OPFLAGS_INITIALIZE_CABLE_DETECT_MASK 0x0001 +#define PXE_OPFLAGS_INITIALIZE_DETECT_CABLE 0x0000 +#define PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE 0x0001 + +//////////////////////////////////////// +// UNDI Reset +// + +#define PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS 0x0001 +#define PXE_OPFLAGS_RESET_DISABLE_FILTERS 0x0002 + +//////////////////////////////////////// +// UNDI Shutdown +// + +// No OpFlags + +//////////////////////////////////////// +// UNDI Interrupt Enables +// + +// +// Select whether to enable or disable external interrupt signals. +// Setting both enable and disable will return PXE_STATCODE_INVALID_OPFLAGS. +// +#define PXE_OPFLAGS_INTERRUPT_OPMASK 0xC000 +#define PXE_OPFLAGS_INTERRUPT_ENABLE 0x8000 +#define PXE_OPFLAGS_INTERRUPT_DISABLE 0x4000 +#define PXE_OPFLAGS_INTERRUPT_READ 0x0000 + +// +// Enable receive interrupts. An external interrupt will be generated +// after a complete non-error packet has been received. +// +#define PXE_OPFLAGS_INTERRUPT_RECEIVE 0x0001 + +// +// Enable transmit interrupts. An external interrupt will be generated +// after a complete non-error packet has been transmitted. +// +#define PXE_OPFLAGS_INTERRUPT_TRANSMIT 0x0002 + +// +// Enable command interrupts. An external interrupt will be generated +// when command execution stops. +// +#define PXE_OPFLAGS_INTERRUPT_COMMAND 0x0004 + +// +// Generate software interrupt. Setting this bit generates an external +// interrupt, if it is supported by the hardware. +// +#define PXE_OPFLAGS_INTERRUPT_SOFTWARE 0x0008 + +//////////////////////////////////////// +// UNDI Receive Filters +// + +// +// Select whether to enable or disable receive filters. +// Setting both enable and disable will return PXE_STATCODE_INVALID_OPCODE. +// +#define PXE_OPFLAGS_RECEIVE_FILTER_OPMASK 0xC000 +#define PXE_OPFLAGS_RECEIVE_FILTER_ENABLE 0x8000 +#define PXE_OPFLAGS_RECEIVE_FILTER_DISABLE 0x4000 +#define PXE_OPFLAGS_RECEIVE_FILTER_READ 0x0000 + +// +// To reset the contents of the multicast MAC address filter list, +// set this OpFlag: +// +#define PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST 0x2000 + +// +// Enable unicast packet receiving. Packets sent to the current station +// MAC address will be received. +// +#define PXE_OPFLAGS_RECEIVE_FILTER_UNICAST 0x0001 + +// +// Enable broadcast packet receiving. Packets sent to the broadcast +// MAC address will be received. +// +#define PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST 0x0002 + +// +// Enable filtered multicast packet receiving. Packets sent to any +// of the multicast MAC addresses in the multicast MAC address filter +// list will be received. If the filter list is empty, no multicast +// +#define PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST 0x0004 + +// +// Enable promiscuous packet receiving. All packets will be received. +// +#define PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS 0x0008 + +// +// Enable promiscuous multicast packet receiving. All multicast +// packets will be received. +// +#define PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST 0x0010 + +//////////////////////////////////////// +// UNDI Station Address +// + +#define PXE_OPFLAGS_STATION_ADDRESS_READ 0x0000 +#define PXE_OPFLAGS_STATION_ADDRESS_RESET 0x0001 + +//////////////////////////////////////// +// UNDI Statistics +// + +#define PXE_OPFLAGS_STATISTICS_READ 0x0000 +#define PXE_OPFLAGS_STATISTICS_RESET 0x0001 + +//////////////////////////////////////// +// UNDI MCast IP to MAC +// + +// +// Identify the type of IP address in the CPB. +// +#define PXE_OPFLAGS_MCAST_IP_TO_MAC_OPMASK 0x0003 +#define PXE_OPFLAGS_MCAST_IPV4_TO_MAC 0x0000 +#define PXE_OPFLAGS_MCAST_IPV6_TO_MAC 0x0001 + +//////////////////////////////////////// +// UNDI NvData +// + +// +// Select the type of non-volatile data operation. +// +#define PXE_OPFLAGS_NVDATA_OPMASK 0x0001 +#define PXE_OPFLAGS_NVDATA_READ 0x0000 +#define PXE_OPFLAGS_NVDATA_WRITE 0x0001 + +//////////////////////////////////////// +// UNDI Get Status +// + +// +// Return current interrupt status. This will also clear any interrupts +// that are currently set. This can be used in a polling routine. The +// interrupt flags are still set and cleared even when the interrupts +// are disabled. +// +#define PXE_OPFLAGS_GET_INTERRUPT_STATUS 0x0001 + +// +// Return list of transmitted buffers for recycling. Transmit buffers +// must not be changed or unallocated until they have recycled. After +// issuing a transmit command, wait for a transmit complete interrupt. +// When a transmit complete interrupt is received, read the transmitted +// buffers. Do not plan on getting one buffer per interrupt. Some +// NICs and UNDIs may transmit multiple buffers per interrupt. +// +#define PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS 0x0002 + +//////////////////////////////////////// +// UNDI Fill Header +// + +#define PXE_OPFLAGS_FILL_HEADER_OPMASK 0x0001 +#define PXE_OPFLAGS_FILL_HEADER_FRAGMENTED 0x0001 +#define PXE_OPFLAGS_FILL_HEADER_WHOLE 0x0000 + +//////////////////////////////////////// +// UNDI Transmit +// + +// +// S/W UNDI only. Return after the packet has been transmitted. A +// transmit complete interrupt will still be generated and the transmit +// buffer will have to be recycled. +// +#define PXE_OPFLAGS_SWUNDI_TRANSMIT_OPMASK 0x0001 +#define PXE_OPFLAGS_TRANSMIT_BLOCK 0x0001 +#define PXE_OPFLAGS_TRANSMIT_DONT_BLOCK 0x0000 + +// +// +// +#define PXE_OPFLAGS_TRANSMIT_OPMASK 0x0002 +#define PXE_OPFLAGS_TRANSMIT_FRAGMENTED 0x0002 +#define PXE_OPFLAGS_TRANSMIT_WHOLE 0x0000 + +//////////////////////////////////////// +// UNDI Receive +// + +// No OpFlags + +typedef PXE_UINT16 PXE_STATFLAGS; + +#define PXE_STATFLAGS_INITIALIZE 0x0000 + +//////////////////////////////////////// +// Common StatFlags that can be returned by all commands. +// + +// +// The COMMAND_COMPLETE and COMMAND_FAILED status flags must be +// implemented by all UNDIs. COMMAND_QUEUED is only needed by UNDIs +// that support command queuing. +// +#define PXE_STATFLAGS_STATUS_MASK 0xC000 +#define PXE_STATFLAGS_COMMAND_COMPLETE 0xC000 +#define PXE_STATFLAGS_COMMAND_FAILED 0x8000 +#define PXE_STATFLAGS_COMMAND_QUEUED 0x4000 +//#define PXE_STATFLAGS_INITIALIZE 0x0000 + +#define PXE_STATFLAGS_DB_WRITE_TRUNCATED 0x2000 + +//////////////////////////////////////// +// UNDI Get State +// + +#define PXE_STATFLAGS_GET_STATE_MASK 0x0003 +#define PXE_STATFLAGS_GET_STATE_INITIALIZED 0x0002 +#define PXE_STATFLAGS_GET_STATE_STARTED 0x0001 +#define PXE_STATFLAGS_GET_STATE_STOPPED 0x0000 + +//////////////////////////////////////// +// UNDI Start +// + +// No additional StatFlags + +//////////////////////////////////////// +// UNDI Get Init Info +// + +#define PXE_STATFLAGS_CABLE_DETECT_MASK 0x0001 +#define PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED 0x0000 +#define PXE_STATFLAGS_CABLE_DETECT_SUPPORTED 0x0001 + + +//////////////////////////////////////// +// UNDI Initialize +// + +#define PXE_STATFLAGS_INITIALIZED_NO_MEDIA 0x0001 + +//////////////////////////////////////// +// UNDI Reset +// + +#define PXE_STATFLAGS_RESET_NO_MEDIA 0x0001 + +//////////////////////////////////////// +// UNDI Shutdown +// + +// No additional StatFlags + +//////////////////////////////////////// +// UNDI Interrupt Enables +// + +// +// If set, receive interrupts are enabled. +// +#define PXE_STATFLAGS_INTERRUPT_RECEIVE 0x0001 + +// +// If set, transmit interrupts are enabled. +// +#define PXE_STATFLAGS_INTERRUPT_TRANSMIT 0x0002 + +// +// If set, command interrupts are enabled. +// +#define PXE_STATFLAGS_INTERRUPT_COMMAND 0x0004 + + +//////////////////////////////////////// +// UNDI Receive Filters +// + +// +// If set, unicast packets will be received. +// +#define PXE_STATFLAGS_RECEIVE_FILTER_UNICAST 0x0001 + +// +// If set, broadcast packets will be received. +// +#define PXE_STATFLAGS_RECEIVE_FILTER_BROADCAST 0x0002 + +// +// If set, multicast packets that match up with the multicast address +// filter list will be received. +// +#define PXE_STATFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST 0x0004 + +// +// If set, all packets will be received. +// +#define PXE_STATFLAGS_RECEIVE_FILTER_PROMISCUOUS 0x0008 + +// +// If set, all multicast packets will be received. +// +#define PXE_STATFLAGS_RECEIVE_FILTER_ALL_MULTICAST 0x0010 + +//////////////////////////////////////// +// UNDI Station Address +// + +// No additional StatFlags + +//////////////////////////////////////// +// UNDI Statistics +// + +// No additional StatFlags + +//////////////////////////////////////// +// UNDI MCast IP to MAC +// + +// No additional StatFlags + +//////////////////////////////////////// +// UNDI NvData +// + +// No additional StatFlags + + +//////////////////////////////////////// +// UNDI Get Status +// + +// +// Use to determine if an interrupt has occurred. +// +#define PXE_STATFLAGS_GET_STATUS_INTERRUPT_MASK 0x000F +#define PXE_STATFLAGS_GET_STATUS_NO_INTERRUPTS 0x0000 + +// +// If set, at least one receive interrupt occurred. +// +#define PXE_STATFLAGS_GET_STATUS_RECEIVE 0x0001 + +// +// If set, at least one transmit interrupt occurred. +// +#define PXE_STATFLAGS_GET_STATUS_TRANSMIT 0x0002 + +// +// If set, at least one command interrupt occurred. +// +#define PXE_STATFLAGS_GET_STATUS_COMMAND 0x0004 + +// +// If set, at least one software interrupt occurred. +// +#define PXE_STATFLAGS_GET_STATUS_SOFTWARE 0x0008 + +// +// This flag is set if the transmitted buffer queue is empty. This flag +// will be set if all transmitted buffer addresses get written into the DB. +// +#define PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY 0x0010 + +// +// This flag is set if no transmitted buffer addresses were written +// into the DB. (This could be because DBsize was too small.) +// +#define PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN 0x0020 + +//////////////////////////////////////// +// UNDI Fill Header +// + +// No additional StatFlags + +//////////////////////////////////////// +// UNDI Transmit +// + +// No additional StatFlags. + +//////////////////////////////////////// +// UNDI Receive +// + +// No additional StatFlags. + +typedef PXE_UINT16 PXE_STATCODE; + +#define PXE_STATCODE_INITIALIZE 0x0000 + +//////////////////////////////////////// +// Common StatCodes returned by all UNDI commands, UNDI protocol functions +// and BC protocol functions. +// + +#define PXE_STATCODE_SUCCESS 0x0000 + +#define PXE_STATCODE_INVALID_CDB 0x0001 +#define PXE_STATCODE_INVALID_CPB 0x0002 +#define PXE_STATCODE_BUSY 0x0003 +#define PXE_STATCODE_QUEUE_FULL 0x0004 +#define PXE_STATCODE_ALREADY_STARTED 0x0005 +#define PXE_STATCODE_NOT_STARTED 0x0006 +#define PXE_STATCODE_NOT_SHUTDOWN 0x0007 +#define PXE_STATCODE_ALREADY_INITIALIZED 0x0008 +#define PXE_STATCODE_NOT_INITIALIZED 0x0009 +#define PXE_STATCODE_DEVICE_FAILURE 0x000A +#define PXE_STATCODE_NVDATA_FAILURE 0x000B +#define PXE_STATCODE_UNSUPPORTED 0x000C +#define PXE_STATCODE_BUFFER_FULL 0x000D +#define PXE_STATCODE_INVALID_PARAMETER 0x000E +#define PXE_STATCODE_INVALID_UNDI 0x000F +#define PXE_STATCODE_IPV4_NOT_SUPPORTED 0x0010 +#define PXE_STATCODE_IPV6_NOT_SUPPORTED 0x0011 +#define PXE_STATCODE_NOT_ENOUGH_MEMORY 0x0012 +#define PXE_STATCODE_NO_DATA 0x0013 + + +typedef PXE_UINT16 PXE_IFNUM; + +// +// This interface number must be passed to the S/W UNDI Start command. +// +#define PXE_IFNUM_START 0x0000 + +// +// This interface number is returned by the S/W UNDI Get State and +// Start commands if information in the CDB, CPB or DB is invalid. +// +#define PXE_IFNUM_INVALID 0x0000 + +typedef PXE_UINT16 PXE_CONTROL; + +// +// Setting this flag directs the UNDI to queue this command for later +// execution if the UNDI is busy and it supports command queuing. +// If queuing is not supported, a PXE_STATCODE_INVALID_CONTROL error +// is returned. If the queue is full, a PXE_STATCODE_CDB_QUEUE_FULL +// error is returned. +// +#define PXE_CONTROL_QUEUE_IF_BUSY 0x0002 + +// +// These two bit values are used to determine if there are more UNDI +// CDB structures following this one. If the link bit is set, there +// must be a CDB structure following this one. Execution will start +// on the next CDB structure as soon as this one completes successfully. +// If an error is generated by this command, execution will stop. +// +#define PXE_CONTROL_LINK 0x0001 +#define PXE_CONTROL_LAST_CDB_IN_LIST 0x0000 + +typedef PXE_UINT8 PXE_FRAME_TYPE; + +#define PXE_FRAME_TYPE_NONE 0x00 +#define PXE_FRAME_TYPE_UNICAST 0x01 +#define PXE_FRAME_TYPE_BROADCAST 0x02 +#define PXE_FRAME_TYPE_MULTICAST 0x03 +#define PXE_FRAME_TYPE_PROMISCUOUS 0x04 + +typedef PXE_UINT32 PXE_IPV4; + +typedef PXE_UINT32 PXE_IPV6[4]; +#define PXE_MAC_LENGTH 32 + +typedef PXE_UINT8 PXE_MAC_ADDR[PXE_MAC_LENGTH]; + +typedef PXE_UINT8 PXE_IFTYPE; +typedef PXE_UINT16 PXE_MEDIA_PROTOCOL; + +// +// This information is from the ARP section of RFC 1700. +// +// 1 Ethernet (10Mb) [JBP] +// 2 Experimental Ethernet (3Mb) [JBP] +// 3 Amateur Radio AX.25 [PXK] +// 4 Proteon ProNET Token Ring [JBP] +// 5 Chaos [GXP] +// 6 IEEE 802 Networks [JBP] +// 7 ARCNET [JBP] +// 8 Hyperchannel [JBP] +// 9 Lanstar [TU] +// 10 Autonet Short Address [MXB1] +// 11 LocalTalk [JKR1] +// 12 LocalNet (IBM PCNet or SYTEK LocalNET) [JXM] +// 13 Ultra link [RXD2] +// 14 SMDS [GXC1] +// 15 Frame Relay [AGM] +// 16 Asynchronous Transmission Mode (ATM) [JXB2] +// 17 HDLC [JBP] +// 18 Fibre Channel [Yakov Rekhter] +// 19 Asynchronous Transmission Mode (ATM) [Mark Laubach] +// 20 Serial Line [JBP] +// 21 Asynchronous Transmission Mode (ATM) [MXB1] +// + +#define PXE_IFTYPE_ETHERNET 0x01 +#define PXE_IFTYPE_TOKENRING 0x04 +#define PXE_IFTYPE_FIBRE_CHANNEL 0x12 + +typedef struct s_pxe_hw_undi { +PXE_UINT32 Signature; // PXE_ROMID_SIGNATURE +PXE_UINT8 Len; // sizeof(PXE_HW_UNDI) +PXE_UINT8 Fudge; // makes 8-bit cksum equal zero +PXE_UINT8 Rev; // PXE_ROMID_REV +PXE_UINT8 IFcnt; // physical connector count +PXE_UINT8 MajorVer; // PXE_ROMID_MAJORVER +PXE_UINT8 MinorVer; // PXE_ROMID_MINORVER +PXE_UINT16 reserved; // zero, not used +PXE_UINT32 Implementation; // implementation flags +// reserved // vendor use +// PXE_UINT32 Status; // status port +// PXE_UINT32 Command; // command port +// PXE_UINT64 CDBaddr; // CDB address port +} PXE_HW_UNDI; + +// +// Status port bit definitions +// + +// +// UNDI operation state +// +#define PXE_HWSTAT_STATE_MASK 0xC0000000 +#define PXE_HWSTAT_BUSY 0xC0000000 +#define PXE_HWSTAT_INITIALIZED 0x80000000 +#define PXE_HWSTAT_STARTED 0x40000000 +#define PXE_HWSTAT_STOPPED 0x00000000 + +// +// If set, last command failed +// +#define PXE_HWSTAT_COMMAND_FAILED 0x20000000 + +// +// If set, identifies enabled receive filters +// +#define PXE_HWSTAT_PROMISCUOUS_MULTICAST_RX_ENABLED 0x00001000 +#define PXE_HWSTAT_PROMISCUOUS_RX_ENABLED 0x00000800 +#define PXE_HWSTAT_BROADCAST_RX_ENABLED 0x00000400 +#define PXE_HWSTAT_MULTICAST_RX_ENABLED 0x00000200 +#define PXE_HWSTAT_UNICAST_RX_ENABLED 0x00000100 + +// +// If set, identifies enabled external interrupts +// +#define PXE_HWSTAT_SOFTWARE_INT_ENABLED 0x00000080 +#define PXE_HWSTAT_TX_COMPLETE_INT_ENABLED 0x00000040 +#define PXE_HWSTAT_PACKET_RX_INT_ENABLED 0x00000020 +#define PXE_HWSTAT_CMD_COMPLETE_INT_ENABLED 0x00000010 + +// +// If set, identifies pending interrupts +// +#define PXE_HWSTAT_SOFTWARE_INT_PENDING 0x00000008 +#define PXE_HWSTAT_TX_COMPLETE_INT_PENDING 0x00000004 +#define PXE_HWSTAT_PACKET_RX_INT_PENDING 0x00000002 +#define PXE_HWSTAT_CMD_COMPLETE_INT_PENDING 0x00000001 + +// +// Command port definitions +// + +// +// If set, CDB identified in CDBaddr port is given to UNDI. +// If not set, other bits in this word will be processed. +// +#define PXE_HWCMD_ISSUE_COMMAND 0x80000000 +#define PXE_HWCMD_INTS_AND_FILTS 0x00000000 + +// +// Use these to enable/disable receive filters. +// +#define PXE_HWCMD_PROMISCUOUS_MULTICAST_RX_ENABLE 0x00001000 +#define PXE_HWCMD_PROMISCUOUS_RX_ENABLE 0x00000800 +#define PXE_HWCMD_BROADCAST_RX_ENABLE 0x00000400 +#define PXE_HWCMD_MULTICAST_RX_ENABLE 0x00000200 +#define PXE_HWCMD_UNICAST_RX_ENABLE 0x00000100 + +// +// Use these to enable/disable external interrupts +// +#define PXE_HWCMD_SOFTWARE_INT_ENABLE 0x00000080 +#define PXE_HWCMD_TX_COMPLETE_INT_ENABLE 0x00000040 +#define PXE_HWCMD_PACKET_RX_INT_ENABLE 0x00000020 +#define PXE_HWCMD_CMD_COMPLETE_INT_ENABLE 0x00000010 + +// +// Use these to clear pending external interrupts +// +#define PXE_HWCMD_CLEAR_SOFTWARE_INT 0x00000008 +#define PXE_HWCMD_CLEAR_TX_COMPLETE_INT 0x00000004 +#define PXE_HWCMD_CLEAR_PACKET_RX_INT 0x00000002 +#define PXE_HWCMD_CLEAR_CMD_COMPLETE_INT 0x00000001 + +typedef struct s_pxe_sw_undi { +PXE_UINT32 Signature; // PXE_ROMID_SIGNATURE +PXE_UINT8 Len; // sizeof(PXE_SW_UNDI) +PXE_UINT8 Fudge; // makes 8-bit cksum zero +PXE_UINT8 Rev; // PXE_ROMID_REV +PXE_UINT8 IFcnt; // physical connector count +PXE_UINT8 MajorVer; // PXE_ROMID_MAJORVER +PXE_UINT8 MinorVer; // PXE_ROMID_MINORVER +PXE_UINT16 reserved1; // zero, not used +PXE_UINT32 Implementation; // Implementation flags +PXE_UINT64 EntryPoint; // API entry point +PXE_UINT8 reserved2[3]; // zero, not used +PXE_UINT8 BusCnt; // number of bustypes supported +PXE_UINT32 BusType[1]; // list of supported bustypes +} PXE_SW_UNDI; + +typedef union u_pxe_undi { +PXE_HW_UNDI hw; +PXE_SW_UNDI sw; +} PXE_UNDI; + +// +// Signature of !PXE structure +// +#define PXE_ROMID_SIGNATURE PXE_BUSTYPE('!', 'P', 'X', 'E') + +// +// !PXE structure format revision +// +#define PXE_ROMID_REV 0x02 + +// +// UNDI command interface revision. These are the values that get sent +// in option 94 (Client Network Interface Identifier) in the DHCP Discover +// and PXE Boot Server Request packets. +// +#define PXE_ROMID_MAJORVER 0x03 +#define PXE_ROMID_MINORVER 0x00 + +// +// Implementation flags +// +#define PXE_ROMID_IMP_HW_UNDI 0x80000000 +#define PXE_ROMID_IMP_SW_VIRT_ADDR 0x40000000 +#define PXE_ROMID_IMP_64BIT_DEVICE 0x00010000 +#define PXE_ROMID_IMP_FRAG_SUPPORTED 0x00008000 +#define PXE_ROMID_IMP_CMD_LINK_SUPPORTED 0x00004000 +#define PXE_ROMID_IMP_CMD_QUEUE_SUPPORTED 0x00002000 +#define PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED 0x00001000 +#define PXE_ROMID_IMP_NVDATA_SUPPORT_MASK 0x00000C00 +#define PXE_ROMID_IMP_NVDATA_BULK_WRITABLE 0x00000C00 +#define PXE_ROMID_IMP_NVDATA_SPARSE_WRITABLE 0x00000800 +#define PXE_ROMID_IMP_NVDATA_READ_ONLY 0x00000400 +#define PXE_ROMID_IMP_NVDATA_NOT_AVAILABLE 0x00000000 +#define PXE_ROMID_IMP_STATISTICS_SUPPORTED 0x00000200 +#define PXE_ROMID_IMP_STATION_ADDR_SETTABLE 0x00000100 +#define PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED 0x00000080 +#define PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED 0x00000040 +#define PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED 0x00000020 +#define PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED 0x00000010 +#define PXE_ROMID_IMP_SOFTWARE_INT_SUPPORTED 0x00000008 +#define PXE_ROMID_IMP_TX_COMPLETE_INT_SUPPORTED 0x00000004 +#define PXE_ROMID_IMP_PACKET_RX_INT_SUPPORTED 0x00000002 +#define PXE_ROMID_IMP_CMD_COMPLETE_INT_SUPPORTED 0x00000001 + + +typedef struct s_pxe_cdb { +PXE_OPCODE OpCode; +PXE_OPFLAGS OpFlags; +PXE_UINT16 CPBsize; +PXE_UINT16 DBsize; +UINT64 CPBaddr; +UINT64 DBaddr; +PXE_STATCODE StatCode; +PXE_STATFLAGS StatFlags; +PXE_UINT16 IFnum; +PXE_CONTROL Control; +} PXE_CDB; + + +typedef union u_pxe_ip_addr { +PXE_IPV6 IPv6; +PXE_IPV4 IPv4; +} PXE_IP_ADDR; + +typedef union pxe_device { +// +// PCI and PC Card NICs are both identified using bus, device +// and function numbers. For PC Card, this may require PC +// Card services to be loaded in the BIOS or preboot +// environment. +// +struct { +// +// See S/W UNDI ROMID structure definition for PCI and +// PCC BusType definitions. +// +PXE_UINT32 BusType; + +// +// Bus, device & function numbers that locate this device. +// +PXE_UINT16 Bus; +PXE_UINT8 Device; +PXE_UINT8 Function; +} PCI, PCC; + +// +// %%TBD - More information is needed about enumerating +// USB and 1394 devices. +// +struct { +PXE_UINT32 BusType; +PXE_UINT32 tdb; +} USB, _1394; +} PXE_DEVICE; + +// cpb and db definitions + +#define MAX_PCI_CONFIG_LEN 64 // # of dwords +#define MAX_EEPROM_LEN 128 // #of dwords +#define MAX_XMIT_BUFFERS 32 // recycling Q length for xmit_done +#define MAX_MCAST_ADDRESS_CNT 8 + +typedef struct s_pxe_cpb_start { + // + // PXE_VOID Delay(PXE_UINT64 microseconds); + // + // UNDI will never request a delay smaller than 10 microseconds + // and will always request delays in increments of 10 microseconds. + // The Delay() CallBack routine must delay between n and n + 10 + // microseconds before returning control to the UNDI. + // + // This field cannot be set to zero. + // + PXE_UINT64 Delay; + + // + // PXE_VOID Block(PXE_UINT32 enable); + // + // UNDI may need to block multi-threaded/multi-processor access to + // critical code sections when programming or accessing the network + // device. To this end, a blocking service is needed by the UNDI. + // When UNDI needs a block, it will call Block() passing a non-zero + // value. When UNDI no longer needs a block, it will call Block() + // with a zero value. When called, if the Block() is already enabled, + // do not return control to the UNDI until the previous Block() is + // disabled. + // + // This field cannot be set to zero. + // + PXE_UINT64 Block; + + // + // PXE_VOID Virt2Phys(PXE_UINT64 virtual, PXE_UINT64 physical_ptr); + // + // UNDI will pass the virtual address of a buffer and the virtual + // address of a 64-bit physical buffer. Convert the virtual address + // to a physical address and write the result to the physical address + // buffer. If virtual and physical addresses are the same, just + // copy the virtual address to the physical address buffer. + // + // This field can be set to zero if virtual and physical addresses + // are equal. + // + PXE_UINT64 Virt2Phys; + // + // PXE_VOID Mem_IO(PXE_UINT8 read_write, PXE_UINT8 len, PXE_UINT64 port, + // PXE_UINT64 buf_addr); + // + // UNDI will read or write the device io space using this call back + // function. It passes the number of bytes as the len parameter and it + // will be either 1,2,4 or 8. + // + // This field can not be set to zero. + // + PXE_UINT64 Mem_IO; +} PXE_CPB_START; + +#define PXE_DELAY_MILLISECOND 1000 +#define PXE_DELAY_SECOND 1000000 +#define PXE_IO_READ 0 +#define PXE_IO_WRITE 1 +#define PXE_MEM_READ 2 +#define PXE_MEM_WRITE 4 + + +typedef struct s_pxe_db_get_init_info { + // + // Minimum length of locked memory buffer that must be given to + // the Initialize command. Giving UNDI more memory will generally + // give better performance. + // + // If MemoryRequired is zero, the UNDI does not need and will not + // use system memory to receive and transmit packets. + // + PXE_UINT32 MemoryRequired; + + // + // Maximum frame data length for Tx/Rx excluding the media header. + // + PXE_UINT32 FrameDataLen; + + // + // Supported link speeds are in units of mega bits. Common ethernet + // values are 10, 100 and 1000. Unused LinkSpeeds[] entries are zero + // filled. + // + PXE_UINT32 LinkSpeeds[4]; + + // + // Number of non-volatile storage items. + // + PXE_UINT32 NvCount; + + // + // Width of non-volatile storage item in bytes. 0, 1, 2 or 4 + // + PXE_UINT16 NvWidth; + + // + // Media header length. This is the typical media header length for + // this UNDI. This information is needed when allocating receive + // and transmit buffers. + // + PXE_UINT16 MediaHeaderLen; + + // + // Number of bytes in the NIC hardware (MAC) address. + // + PXE_UINT16 HWaddrLen; + + // + // Maximum number of multicast MAC addresses in the multicast + // MAC address filter list. + // + PXE_UINT16 MCastFilterCnt; + + // + // Default number and size of transmit and receive buffers that will + // be allocated by the UNDI. If MemoryRequired is non-zero, this + // allocation will come out of the memory buffer given to the Initialize + // command. If MemoryRequired is zero, this allocation will come out of + // memory on the NIC. + // + PXE_UINT16 TxBufCnt; + PXE_UINT16 TxBufSize; + PXE_UINT16 RxBufCnt; + PXE_UINT16 RxBufSize; + + // + // Hardware interface types defined in the Assigned Numbers RFC + // and used in DHCP and ARP packets. + // See the PXE_IFTYPE typedef and PXE_IFTYPE_xxx macros. + // + PXE_UINT8 IFtype; + + // + // Supported duplex. See PXE_DUPLEX_xxxxx #defines below. + // + PXE_UINT8 Duplex; + + // + // Supported loopback options. See PXE_LOOPBACK_xxxxx #defines below. + // + PXE_UINT8 LoopBack; +} PXE_DB_GET_INIT_INFO; + +#define PXE_MAX_TXRX_UNIT_ETHER 1500 + +#define PXE_HWADDR_LEN_ETHER 0x0006 +#define PXE_MAC_HEADER_LEN_ETHER 0x000E + +#define PXE_DUPLEX_ENABLE_FULL_SUPPORTED 1 +#define PXE_DUPLEX_FORCE_FULL_SUPPORTED 2 + +#define PXE_LOOPBACK_INTERNAL_SUPPORTED 1 +#define PXE_LOOPBACK_EXTERNAL_SUPPORTED 2 + + +typedef struct s_pxe_pci_config_info { + // + // This is the flag field for the PXE_DB_GET_CONFIG_INFO union. + // For PCI bus devices, this field is set to PXE_BUSTYPE_PCI. + // + PXE_UINT32 BusType; + + // + // This identifies the PCI network device that this UNDI interface + // is bound to. + // + PXE_UINT16 Bus; + PXE_UINT8 Device; + PXE_UINT8 Function; + + // + // This is a copy of the PCI configuration space for this + // network device. + // + union { + PXE_UINT8 Byte[256]; + PXE_UINT16 Word[128]; + PXE_UINT32 Dword[64]; + } Config; +} PXE_PCI_CONFIG_INFO; + + +typedef struct s_pxe_pcc_config_info { + // + // This is the flag field for the PXE_DB_GET_CONFIG_INFO union. + // For PCC bus devices, this field is set to PXE_BUSTYPE_PCC. + // + PXE_UINT32 BusType; + + // + // This identifies the PCC network device that this UNDI interface + // is bound to. + // + PXE_UINT16 Bus; + PXE_UINT8 Device; + PXE_UINT8 Function; + + // + // This is a copy of the PCC configuration space for this + // network device. + // + union { + PXE_UINT8 Byte[256]; + PXE_UINT16 Word[128]; + PXE_UINT32 Dword[64]; + } Config; +} PXE_PCC_CONFIG_INFO; + + +typedef struct s_pxe_usb_config_info { + PXE_UINT32 BusType; + // %%TBD What should we return here... +} PXE_USB_CONFIG_INFO; + + +typedef struct s_pxe_1394_config_info { + PXE_UINT32 BusType; + // %%TBD What should we return here... +} PXE_1394_CONFIG_INFO; + + +typedef union u_pxe_db_get_config_info { + PXE_PCI_CONFIG_INFO pci; + PXE_PCC_CONFIG_INFO pcc; + PXE_USB_CONFIG_INFO usb; + PXE_1394_CONFIG_INFO _1394; +} PXE_DB_GET_CONFIG_INFO; + + +typedef struct s_pxe_cpb_initialize { + // + // Address of first (lowest) byte of the memory buffer. This buffer must + // be in contiguous physical memory and cannot be swapped out. The UNDI + // will be using this for transmit and receive buffering. + // + PXE_UINT64 MemoryAddr; + + // + // MemoryLength must be greater than or equal to MemoryRequired + // returned by the Get Init Info command. + // + PXE_UINT32 MemoryLength; + + // + // Desired link speed in Mbit/sec. Common ethernet values are 10, 100 + // and 1000. Setting a value of zero will auto-detect and/or use the + // default link speed (operation depends on UNDI/NIC functionality). + // + PXE_UINT32 LinkSpeed; + + // + // Suggested number and size of receive and transmit buffers to + // allocate. If MemoryAddr and MemoryLength are non-zero, this + // allocation comes out of the supplied memory buffer. If MemoryAddr + // and MemoryLength are zero, this allocation comes out of memory + // on the NIC. + // + // If these fields are set to zero, the UNDI will allocate buffer + // counts and sizes as it sees fit. + // + PXE_UINT16 TxBufCnt; + PXE_UINT16 TxBufSize; + PXE_UINT16 RxBufCnt; + PXE_UINT16 RxBufSize; + + // + // The following configuration parameters are optional and must be zero + // to use the default values. + // + PXE_UINT8 Duplex; + + PXE_UINT8 LoopBack; +} PXE_CPB_INITIALIZE; + + +#define PXE_DUPLEX_DEFAULT 0x00 +#define PXE_FORCE_FULL_DUPLEX 0x01 +#define PXE_ENABLE_FULL_DUPLEX 0x02 + +#define LOOPBACK_NORMAL 0 +#define LOOPBACK_INTERNAL 1 +#define LOOPBACK_EXTERNAL 2 + + +typedef struct s_pxe_db_initialize { + // + // Actual amount of memory used from the supplied memory buffer. This + // may be less that the amount of memory suppllied and may be zero if + // the UNDI and network device do not use external memory buffers. + // + // Memory used by the UNDI and network device is allocated from the + // lowest memory buffer address. + // + PXE_UINT32 MemoryUsed; + + // + // Actual number and size of receive and transmit buffers that were + // allocated. + // + PXE_UINT16 TxBufCnt; + PXE_UINT16 TxBufSize; + PXE_UINT16 RxBufCnt; + PXE_UINT16 RxBufSize; +} PXE_DB_INITIALIZE; + + +typedef struct s_pxe_cpb_receive_filters { + // + // List of multicast MAC addresses. This list, if present, will + // replace the existing multicast MAC address filter list. + // + PXE_MAC_ADDR MCastList[MAX_MCAST_ADDRESS_CNT]; +} PXE_CPB_RECEIVE_FILTERS; + + +typedef struct s_pxe_db_receive_filters { + // + // Filtered multicast MAC address list. + // + PXE_MAC_ADDR MCastList[MAX_MCAST_ADDRESS_CNT]; +} PXE_DB_RECEIVE_FILTERS; + + +typedef struct s_pxe_cpb_station_address { + // + // If supplied and supported, the current station MAC address + // will be changed. + // + PXE_MAC_ADDR StationAddr; +} PXE_CPB_STATION_ADDRESS; + + +typedef struct s_pxe_dpb_station_address { + // + // Current station MAC address. + // + PXE_MAC_ADDR StationAddr; + + // + // Station broadcast MAC address. + // + PXE_MAC_ADDR BroadcastAddr; + + // + // Permanent station MAC address. + // + PXE_MAC_ADDR PermanentAddr; +} PXE_DB_STATION_ADDRESS; + + +typedef struct s_pxe_db_statistics { + // + // Bit field identifying what statistic data is collected by the + // UNDI/NIC. + // If bit 0x00 is set, Data[0x00] is collected. + // If bit 0x01 is set, Data[0x01] is collected. + // If bit 0x20 is set, Data[0x20] is collected. + // If bit 0x21 is set, Data[0x21] is collected. + // Etc. + // + PXE_UINT64 Supported; + + // + // Statistic data. + // + PXE_UINT64 Data[64]; +} PXE_DB_STATISTICS; + +// +// Total number of frames received. Includes frames with errors and +// dropped frames. +// +#define PXE_STATISTICS_RX_TOTAL_FRAMES 0x00 + +// +// Number of valid frames received and copied into receive buffers. +// +#define PXE_STATISTICS_RX_GOOD_FRAMES 0x01 + +// +// Number of frames below the minimum length for the media. +// This would be <64 for ethernet. +// +#define PXE_STATISTICS_RX_UNDERSIZE_FRAMES 0x02 + +// +// Number of frames longer than the maxminum length for the +// media. This would be >1500 for ethernet. +// +#define PXE_STATISTICS_RX_OVERSIZE_FRAMES 0x03 + +// +// Valid frames that were dropped because receive buffers were full. +// +#define PXE_STATISTICS_RX_DROPPED_FRAMES 0x04 + +// +// Number of valid unicast frames received and not dropped. +// +#define PXE_STATISTICS_RX_UNICAST_FRAMES 0x05 + +// +// Number of valid broadcast frames received and not dropped. +// +#define PXE_STATISTICS_RX_BROADCAST_FRAMES 0x06 + +// +// Number of valid mutlicast frames received and not dropped. +// +#define PXE_STATISTICS_RX_MULTICAST_FRAMES 0x07 + +// +// Number of frames w/ CRC or alignment errors. +// +#define PXE_STATISTICS_RX_CRC_ERROR_FRAMES 0x08 + +// +// Total number of bytes received. Includes frames with errors +// and dropped frames. +// +#define PXE_STATISTICS_RX_TOTAL_BYTES 0x09 + +// +// Transmit statistics. +// +#define PXE_STATISTICS_TX_TOTAL_FRAMES 0x0A +#define PXE_STATISTICS_TX_GOOD_FRAMES 0x0B +#define PXE_STATISTICS_TX_UNDERSIZE_FRAMES 0x0C +#define PXE_STATISTICS_TX_OVERSIZE_FRAMES 0x0D +#define PXE_STATISTICS_TX_DROPPED_FRAMES 0x0E +#define PXE_STATISTICS_TX_UNICAST_FRAMES 0x0F +#define PXE_STATISTICS_TX_BROADCAST_FRAMES 0x10 +#define PXE_STATISTICS_TX_MULTICAST_FRAMES 0x11 +#define PXE_STATISTICS_TX_CRC_ERROR_FRAMES 0x12 +#define PXE_STATISTICS_TX_TOTAL_BYTES 0x13 + +// +// Number of collisions detection on this subnet. +// +#define PXE_STATISTICS_COLLISIONS 0x14 + +// +// Number of frames destined for unsupported protocol. +// +#define PXE_STATISTICS_UNSUPPORTED_PROTOCOL 0x15 + + +typedef struct s_pxe_cpb_mcast_ip_to_mac { + // + // Multicast IP address to be converted to multicast MAC address. + // + PXE_IP_ADDR IP; +} PXE_CPB_MCAST_IP_TO_MAC; + + +typedef struct s_pxe_db_mcast_ip_to_mac { + // + // Multicast MAC address. + // + PXE_MAC_ADDR MAC; +} PXE_DB_MCAST_IP_TO_MAC; + + +typedef struct s_pxe_cpb_nvdata_sparse { + // + // NvData item list. Only items in this list will be updated. + // + struct { + // Non-volatile storage address to be changed. + PXE_UINT32 Addr; + + // Data item to write into above storage address. + + union { + PXE_UINT8 Byte; + PXE_UINT16 Word; + PXE_UINT32 Dword; + } Data; + } Item[MAX_EEPROM_LEN]; +} PXE_CPB_NVDATA_SPARSE; + + +// +// When using bulk update, the size of the CPB structure must be +// the same size as the non-volatile NIC storage. +// +typedef union u_pxe_cpb_nvdata_bulk { + // + // Array of byte-wide data items. + // + PXE_UINT8 Byte[MAX_EEPROM_LEN << 2]; + + // + // Array of word-wide data items. + // + PXE_UINT16 Word[MAX_EEPROM_LEN << 1]; + + // + // Array of dword-wide data items. + // + PXE_UINT32 Dword[MAX_EEPROM_LEN]; +} PXE_CPB_NVDATA_BULK; + +typedef struct s_pxe_db_nvdata { + + // Arrays of data items from non-volatile storage. + + union { + // + // Array of byte-wide data items. + // + PXE_UINT8 Byte[MAX_EEPROM_LEN << 2]; + + // + // Array of word-wide data items. + // + PXE_UINT16 Word[MAX_EEPROM_LEN << 1]; + + // Array of dword-wide data items. + + PXE_UINT32 Dword[MAX_EEPROM_LEN]; + } Data; +} PXE_DB_NVDATA; + + +typedef struct s_pxe_db_get_status { + // + // Length of next receive frame (header + data). If this is zero, + // there is no next receive frame available. + // + PXE_UINT32 RxFrameLen; + + // + // Reserved, set to zero. + // + PXE_UINT32 reserved; + + // + // Addresses of transmitted buffers that need to be recycled. + // + PXE_UINT64 TxBuffer[MAX_XMIT_BUFFERS]; +} PXE_DB_GET_STATUS; + + + +typedef struct s_pxe_cpb_fill_header { + // + // Source and destination MAC addresses. These will be copied into + // the media header without doing byte swapping. + // + PXE_MAC_ADDR SrcAddr; + PXE_MAC_ADDR DestAddr; + + // + // Address of first byte of media header. The first byte of packet data + // follows the last byte of the media header. + // + PXE_UINT64 MediaHeader; + + // + // Length of packet data in bytes (not including the media header). + // + PXE_UINT32 PacketLen; + + // + // Protocol type. This will be copied into the media header without + // doing byte swapping. Protocol type numbers can be obtained from + // the Assigned Numbers RFC 1700. + // + PXE_UINT16 Protocol; + + // + // Length of the media header in bytes. + // + PXE_UINT16 MediaHeaderLen; +} PXE_CPB_FILL_HEADER; + + +#define PXE_PROTOCOL_ETHERNET_IP 0x0800 +#define PXE_PROTOCOL_ETHERNET_ARP 0x0806 +#define MAX_XMIT_FRAGMENTS 16 + +typedef struct s_pxe_cpb_fill_header_fragmented { + // + // Source and destination MAC addresses. These will be copied into + // the media header without doing byte swapping. + // + PXE_MAC_ADDR SrcAddr; + PXE_MAC_ADDR DestAddr; + + // + // Length of packet data in bytes (not including the media header). + // + PXE_UINT32 PacketLen; + + // + // Protocol type. This will be copied into the media header without + // doing byte swapping. Protocol type numbers can be obtained from + // the Assigned Numbers RFC 1700. + // + PXE_MEDIA_PROTOCOL Protocol; + + // + // Length of the media header in bytes. + // + PXE_UINT16 MediaHeaderLen; + + // + // Number of packet fragment descriptors. + // + PXE_UINT16 FragCnt; + + // + // Reserved, must be set to zero. + // + PXE_UINT16 reserved; + + // + // Array of packet fragment descriptors. The first byte of the media + // header is the first byte of the first fragment. + // + struct { + // + // Address of this packet fragment. + // + PXE_UINT64 FragAddr; + + // + // Length of this packet fragment. + // + PXE_UINT32 FragLen; + + // + // Reserved, must be set to zero. + // + PXE_UINT32 reserved; + } FragDesc[MAX_XMIT_FRAGMENTS]; +} PXE_CPB_FILL_HEADER_FRAGMENTED; + + + +typedef struct s_pxe_cpb_transmit { + // + // Address of first byte of frame buffer. This is also the first byte + // of the media header. + // + PXE_UINT64 FrameAddr; + + // + // Length of the data portion of the frame buffer in bytes. Do not + // include the length of the media header. + // + PXE_UINT32 DataLen; + + // + // Length of the media header in bytes. + // + PXE_UINT16 MediaheaderLen; + + // + // Reserved, must be zero. + // + PXE_UINT16 reserved; +} PXE_CPB_TRANSMIT; + + + +typedef struct s_pxe_cpb_transmit_fragments { + // + // Length of packet data in bytes (not including the media header). + // + PXE_UINT32 FrameLen; + + // + // Length of the media header in bytes. + // + PXE_UINT16 MediaheaderLen; + + // + // Number of packet fragment descriptors. + // + PXE_UINT16 FragCnt; + + // + // Array of frame fragment descriptors. The first byte of the first + // fragment is also the first byte of the media header. + // + struct { + // + // Address of this frame fragment. + // + PXE_UINT64 FragAddr; + + // + // Length of this frame fragment. + // + PXE_UINT32 FragLen; + + // + // Reserved, must be set to zero. + // + PXE_UINT32 reserved; + } FragDesc[MAX_XMIT_FRAGMENTS]; +} PXE_CPB_TRANSMIT_FRAGMENTS; + + +typedef struct s_pxe_cpb_receive { + // + // Address of first byte of receive buffer. This is also the first byte + // of the frame header. + // + PXE_UINT64 BufferAddr; + + // + // Length of receive buffer. This must be large enough to hold the + // received frame (media header + data). If the length of smaller than + // the received frame, data will be lost. + // + PXE_UINT32 BufferLen; + + // + // Reserved, must be set to zero. + // + PXE_UINT32 reserved; +} PXE_CPB_RECEIVE; + + +typedef struct s_pxe_db_receive { + // + // Source and destination MAC addresses from media header. + // + PXE_MAC_ADDR SrcAddr; + PXE_MAC_ADDR DestAddr; + + // + // Length of received frame. May be larger than receive buffer size. + // The receive buffer will not be overwritten. This is how to tell + // if data was lost because the receive buffer was too small. + // + PXE_UINT32 FrameLen; + + // + // Protocol type from media header. + // + PXE_MEDIA_PROTOCOL Protocol; + + // + // Length of media header in received frame. + // + PXE_UINT16 MediaHeaderLen; + + // + // Type of receive frame. + // + PXE_FRAME_TYPE Type; + + // + // Reserved, must be zero. + // + PXE_UINT8 reserved[7]; + +} PXE_DB_RECEIVE; + +#pragma pack() + +/* EOF - efi_pxe.h */ +#endif /* _EFI_PXE_H */ + diff --git a/code/boot/include/efiapi.h b/code/boot/include/efiapi.h new file mode 100644 index 0000000..fe8e1bf --- /dev/null +++ b/code/boot/include/efiapi.h @@ -0,0 +1,1034 @@ +#ifndef _EFI_API_H +#define _EFI_API_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efiapi.h + +Abstract: + + Global EFI runtime & boot service interfaces + + + + +Revision History + +--*/ + +// +// EFI Specification Revision +// + +#define EFI_SPECIFICATION_REVISION_MAJORMINOR(major, minor) ((major<<16) | (minor)) +#define EFI_SPECIFICATION_MAJOR_REVISION 1 +#define EFI_SPECIFICATION_MINOR_REVISION 02 +#define EFI_SPECIFICATION_VERSION EFI_SPECIFICATION_REVISION_MAJORMINOR(EFI_SPECIFICATION_MAJOR_REVISION, EFI_SPECIFICATION_MINOR_REVISION) + +// +// Declare forward referenced data structures +// + +INTERFACE_DECL(_EFI_SYSTEM_TABLE); + +// +// EFI Memory +// + +typedef +EFI_STATUS +(EFIAPI* EFI_ALLOCATE_PAGES) ( + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN NoPages, + OUT EFI_PHYSICAL_ADDRESS* Memory + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_FREE_PAGES) ( + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN NoPages + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_GET_MEMORY_MAP) ( + IN OUT UINTN* MemoryMapSize, + IN OUT EFI_MEMORY_DESCRIPTOR* MemoryMap, + OUT UINTN* MapKey, + OUT UINTN* DescriptorSize, + OUT UINT32* DescriptorVersion + ); + +#define NextMemoryDescriptor(Ptr,Size) ((EFI_MEMORY_DESCRIPTOR *) (((UINT8 *) Ptr) + Size)) + + +typedef +EFI_STATUS +(EFIAPI* EFI_ALLOCATE_POOL) ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN Size, + OUT VOID **Buffer + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_FREE_POOL) ( + IN VOID* Buffer + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SET_VIRTUAL_ADDRESS_MAP) ( + IN UINTN MemoryMapSize, + IN UINTN DescriptorSize, + IN UINT32 DescriptorVersion, + IN EFI_MEMORY_DESCRIPTOR* VirtualMap + ); + + +#define EFI_OPTIONAL_PTR 0x00000001 +#define EFI_INTERNAL_FNC 0x00000002 // Pointer to internal runtime fnc +#define EFI_INTERNAL_PTR 0x00000004 // Pointer to internal runtime data + + +typedef +EFI_STATUS +(EFIAPI* EFI_CONVERT_POINTER) ( + IN UINTN DebugDisposition, + IN OUT VOID **Address + ); + + +// +// EFI Events +// + +#define EVT_TIMER 0x80000000 +#define EVT_RUNTIME 0x40000000 +#define EVT_RUNTIME_CONTEXT 0x20000000 + +#define EVT_NOTIFY_WAIT 0x00000100 +#define EVT_NOTIFY_SIGNAL 0x00000200 + +#define EVT_SIGNAL_EXIT_BOOT_SERVICES 0x00000201 +#define EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 0x60000202 + +#define EVT_EFI_SIGNAL_MASK 0x000000FF +#define EVT_EFI_SIGNAL_MAX 4 + +#define EFI_EVENT_TIMER EVT_TIMER +#define EFI_EVENT_RUNTIME EVT_RUNTIME +#define EFI_EVENT_RUNTIME_CONTEXT EVT_RUNTIME_CONTEXT +#define EFI_EVENT_NOTIFY_WAIT EVT_NOTIFY_WAIT +#define EFI_EVENT_NOTIFY_SIGNAL EVT_NOTIFY_SIGNAL +#define EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES EVT_SIGNAL_EXIT_BOOT_SERVICES +#define EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE +#define EFI_EVENT_EFI_SIGNAL_MASK EVT_EFI_SIGNAL_MASK +#define EFI_EVENT_EFI_SIGNAL_MAX EVT_EFI_SIGNAL_MAX + + +typedef +VOID +(EFIAPI* EFI_EVENT_NOTIFY) ( + IN EFI_EVENT Event, + IN VOID* Context + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_CREATE_EVENT) ( + IN UINT32 Type, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, + IN VOID* NotifyContext, + OUT EFI_EVENT* Event + ); + +typedef enum { + TimerCancel, + TimerPeriodic, + TimerRelative, + TimerTypeMax +} EFI_TIMER_DELAY; + +typedef +EFI_STATUS +(EFIAPI* EFI_SET_TIMER) ( + IN EFI_EVENT Event, + IN EFI_TIMER_DELAY Type, + IN UINT64 TriggerTime + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SIGNAL_EVENT) ( + IN EFI_EVENT Event + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_WAIT_FOR_EVENT) ( + IN UINTN NumberOfEvents, + IN EFI_EVENT* Event, + OUT UINTN* Index + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_CLOSE_EVENT) ( + IN EFI_EVENT Event + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_CHECK_EVENT) ( + IN EFI_EVENT Event + ); + +// +// Task priority level +// + +#define TPL_APPLICATION 4 +#define TPL_CALLBACK 8 +#define TPL_NOTIFY 16 +#define TPL_HIGH_LEVEL 31 +#define EFI_TPL_APPLICATION TPL_APPLICATION +#define EFI_TPL_CALLBACK TPL_CALLBACK +#define EFI_TPL_NOTIFY TPL_NOTIFY +#define EFI_TPL_HIGH_LEVEL TPL_HIGH_LEVEL +typedef +EFI_TPL +(EFIAPI* EFI_RAISE_TPL) ( + IN EFI_TPL NewTpl + ); + +typedef +VOID +(EFIAPI* EFI_RESTORE_TPL) ( + IN EFI_TPL OldTpl + ); + + +// +// EFI platform varibles +// + +#define EFI_GLOBAL_VARIABLE \ + { 0x8BE4DF61, 0x93CA, 0x11d2, {0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C} } + +// Variable attributes +#define EFI_VARIABLE_NON_VOLATILE 0x00000001 +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002 +#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004 +#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x00000008 +#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010 +#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x00000020 +#define EFI_VARIABLE_APPEND_WRITE 0x00000040 +#define EFI_VARIABLE_ENHANCED_AUTHENTICATED_ACCESS 0x00000080 + +// Variable size limitation +#define EFI_MAXIMUM_VARIABLE_SIZE 1024 + +typedef +EFI_STATUS +(EFIAPI* EFI_GET_VARIABLE) ( + IN CHAR16* VariableName, + IN EFI_GUID* VendorGuid, + OUT UINT32* Attributes OPTIONAL, + IN OUT UINTN* DataSize, + OUT VOID* Data + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_GET_NEXT_VARIABLE_NAME) ( + IN OUT UINTN* VariableNameSize, + IN OUT CHAR16* VariableName, + IN OUT EFI_GUID* VendorGuid + ); + + +typedef +EFI_STATUS +(EFIAPI* EFI_SET_VARIABLE) ( + IN CHAR16* VariableName, + IN EFI_GUID* VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID* Data + ); + + +// +// EFI Time +// + +typedef struct { + UINT32 Resolution; // 1e-6 parts per million + UINT32 Accuracy; // hertz + BOOLEAN SetsToZero; // Set clears sub-second time +} EFI_TIME_CAPABILITIES; + + +typedef +EFI_STATUS +(EFIAPI* EFI_GET_TIME) ( + OUT EFI_TIME* Time, + OUT EFI_TIME_CAPABILITIES* Capabilities OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SET_TIME) ( + IN EFI_TIME* Time + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_GET_WAKEUP_TIME) ( + OUT BOOLEAN* Enabled, + OUT BOOLEAN* Pending, + OUT EFI_TIME* Time + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SET_WAKEUP_TIME) ( + IN BOOLEAN Enable, + IN EFI_TIME* Time OPTIONAL + ); + + +// +// Image functions +// + + +// PE32+ Subsystem type for EFI images + +#if !defined(IMAGE_SUBSYSTEM_EFI_APPLICATION) +#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 +#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 +#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 +#endif + +// PE32+ Machine type for EFI images + +#if !defined(EFI_IMAGE_MACHINE_IA32) +#define EFI_IMAGE_MACHINE_IA32 0x014c +#endif + +#if !defined(EFI_IMAGE_MACHINE_IA64) +#define EFI_IMAGE_MACHINE_IA64 0x0200 +#endif + +#if !defined(EFI_IMAGE_MACHINE_EBC) +#define EFI_IMAGE_MACHINE_EBC 0x0EBC +#endif + +#if !defined(EFI_IMAGE_MACHINE_X64) +#define EFI_IMAGE_MACHINE_X64 0x8664 +#endif + +#if !defined(EFI_IMAGE_MACHINE_ARMTHUMB_MIXED) +#define EFI_IMAGE_MACHINE_ARMTHUMB_MIXED 0x01C2 +#endif + +#if !defined(EFI_IMAGE_MACHINE_AARCH64) +#define EFI_IMAGE_MACHINE_AARCH64 0xAA64 +#endif + +#if !defined(EFI_IMAGE_MACHINE_RISCV32) +#define EFI_IMAGE_MACHINE_RISCV32 0x5032 +#endif + +#if !defined(EFI_IMAGE_MACHINE_RISCV64) +#define EFI_IMAGE_MACHINE_RISCV64 0x5064 +#endif + +#if !defined(EFI_IMAGE_MACHINE_RISCV128) +#define EFI_IMAGE_MACHINE_RISCV128 0x5128 +#endif + +#if !defined(EFI_IMAGE_MACHINE_LOONGARCH32) +#define EFI_IMAGE_MACHINE_LOONGARCH32 0x6232 +#endif + +#if !defined(EFI_IMAGE_MACHINE_LOONGARCH64) +#define EFI_IMAGE_MACHINE_LOONGARCH64 0x6264 +#endif + +// Image Entry prototype + +typedef +EFI_STATUS +(EFIAPI* EFI_IMAGE_ENTRY_POINT) ( + IN EFI_HANDLE ImageHandle, + IN struct _EFI_SYSTEM_TABLE* SystemTable + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_IMAGE_LOAD) ( + IN BOOLEAN BootPolicy, + IN EFI_HANDLE ParentImageHandle, + IN EFI_DEVICE_PATH* FilePath, + IN VOID* SourceBuffer OPTIONAL, + IN UINTN SourceSize, + OUT EFI_HANDLE* ImageHandle + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_IMAGE_START) ( + IN EFI_HANDLE ImageHandle, + OUT UINTN* ExitDataSize, + OUT CHAR16 **ExitData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_EXIT) ( + IN EFI_HANDLE ImageHandle, + IN EFI_STATUS ExitStatus, + IN UINTN ExitDataSize, + IN CHAR16* ExitData OPTIONAL + ); + + +// Image handle +/*#define LOADED_IMAGE_PROTOCOL \ + { 0x5B1B31A1, 0x9562, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B} } + +#define EFI_IMAGE_INFORMATION_REVISION 0x1000 +typedef struct { + UINT32 Revision; + EFI_HANDLE ParentHandle; + struct _EFI_SYSTEM_TABLE* SystemTable; + + // Source location of image + EFI_HANDLE DeviceHandle; + EFI_DEVICE_PATH* FilePath; + VOID* Reserved; + + // Images load options + UINT32 LoadOptionsSize; + VOID* LoadOptions; + + // Location of where image was loaded + VOID* ImageBase; + UINT64 ImageSize; + EFI_MEMORY_TYPE ImageCodeType; + EFI_MEMORY_TYPE ImageDataType; + + // If the driver image supports a dynamic unload request + EFI_IMAGE_UNLOAD Unload; + +} EFI_LOADED_IMAGE;*/ + + +typedef +EFI_STATUS +(EFIAPI* EFI_EXIT_BOOT_SERVICES) ( + IN EFI_HANDLE ImageHandle, + IN UINTN MapKey + ); + +// +// Misc +// + + +typedef +EFI_STATUS +(EFIAPI* EFI_STALL) ( + IN UINTN Microseconds + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SET_WATCHDOG_TIMER) ( + IN UINTN Timeout, + IN UINT64 WatchdogCode, + IN UINTN DataSize, + IN CHAR16* WatchdogData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_CONNECT_CONTROLLER) ( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE* DriverImageHandle OPTIONAL, + IN EFI_DEVICE_PATH* RemainingDevicePath OPTIONAL, + IN BOOLEAN Recursive + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_DISCONNECT_CONTROLLER) ( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE DriverImageHandle OPTIONAL, + IN EFI_HANDLE ChildHandle OPTIONAL + ); + +#define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001 +#define EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x00000002 +#define EFI_OPEN_PROTOCOL_TEST_PROTOCOL 0x00000004 +#define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x00000008 +#define EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010 +#define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020 + +typedef +EFI_STATUS +(EFIAPI* EFI_OPEN_PROTOCOL) ( + IN EFI_HANDLE Handle, + IN EFI_GUID* Protocol, + OUT VOID **Interface OPTIONAL, + IN EFI_HANDLE AgentHandle, + IN EFI_HANDLE ControllerHandle, + IN UINT32 Attributes + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_CLOSE_PROTOCOL) ( + IN EFI_HANDLE Handle, + IN EFI_GUID* Protocol, + IN EFI_HANDLE AgentHandle, + IN EFI_HANDLE ControllerHandle + ); + +typedef struct { + EFI_HANDLE AgentHandle; + EFI_HANDLE ControllerHandle; + UINT32 Attributes; + UINT32 OpenCount; +} EFI_OPEN_PROTOCOL_INFORMATION_ENTRY; + +typedef +EFI_STATUS +(EFIAPI* EFI_OPEN_PROTOCOL_INFORMATION) ( + IN EFI_HANDLE Handle, + IN EFI_GUID* Protocol, + OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer, + OUT UINTN* EntryCount + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_PROTOCOLS_PER_HANDLE) ( + IN EFI_HANDLE Handle, + OUT EFI_GUID ***ProtocolBuffer, + OUT UINTN* ProtocolBufferCount + ); + +typedef enum { + AllHandles, + ByRegisterNotify, + ByProtocol +} EFI_LOCATE_SEARCH_TYPE; + +typedef +EFI_STATUS +(EFIAPI* EFI_LOCATE_HANDLE_BUFFER) ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID* Protocol OPTIONAL, + IN VOID* SearchKey OPTIONAL, + IN OUT UINTN* NoHandles, + OUT EFI_HANDLE **Buffer + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_LOCATE_PROTOCOL) ( + IN EFI_GUID* Protocol, + IN VOID* Registration OPTIONAL, + OUT VOID **Interface + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES) ( + IN OUT EFI_HANDLE* Handle, + ... + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES) ( + IN OUT EFI_HANDLE Handle, + ... + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_CALCULATE_CRC32) ( + IN VOID* Data, + IN UINTN DataSize, + OUT UINT32* Crc32 + ); + +typedef +VOID +(EFIAPI* EFI_COPY_MEM) ( + IN VOID* Destination, + IN VOID* Source, + IN UINTN Length + ); + +typedef +VOID +(EFIAPI* EFI_SET_MEM) ( + IN VOID* Buffer, + IN UINTN Size, + IN UINT8 Value + ); + + +typedef +EFI_STATUS +(EFIAPI* EFI_CREATE_EVENT_EX) ( + IN UINT32 Type, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL, + IN const VOID* NotifyContext OPTIONAL, + IN const EFI_GUID* EventGroup OPTIONAL, + OUT EFI_EVENT* Event + ); + +typedef enum { + EfiResetCold, + EfiResetWarm, + EfiResetShutdown +} EFI_RESET_TYPE; + +typedef +EFI_STATUS +(EFIAPI* EFI_RESET_SYSTEM) ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN CHAR16* ResetData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_GET_NEXT_MONOTONIC_COUNT) ( + OUT UINT64* Count + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_GET_NEXT_HIGH_MONO_COUNT) ( + OUT UINT32* HighCount + ); + +typedef struct { + UINT64 Length; + union { + EFI_PHYSICAL_ADDRESS DataBlock; + EFI_PHYSICAL_ADDRESS ContinuationPointer; + } Union; +} EFI_CAPSULE_BLOCK_DESCRIPTOR; + +typedef struct { + EFI_GUID CapsuleGuid; + UINT32 HeaderSize; + UINT32 Flags; + UINT32 CapsuleImageSize; +} EFI_CAPSULE_HEADER; + +#define CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x00010000 +#define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE 0x00020000 +#define CAPSULE_FLAGS_INITIATE_RESET 0x00040000 + +typedef +EFI_STATUS +(EFIAPI* EFI_UPDATE_CAPSULE) ( + IN EFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_QUERY_CAPSULE_CAPABILITIES) ( + IN EFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + OUT UINT64* MaximumCapsuleSize, + OUT EFI_RESET_TYPE* ResetType + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_QUERY_VARIABLE_INFO) ( + IN UINT32 Attributes, + OUT UINT64* MaximumVariableStorageSize, + OUT UINT64* RemainingVariableStorageSize, + OUT UINT64* MaximumVariableSize + ); + +// +// Protocol handler functions +// + +typedef enum { + EFI_NATIVE_INTERFACE, + EFI_PCODE_INTERFACE +} EFI_INTERFACE_TYPE; + +typedef +EFI_STATUS +(EFIAPI* EFI_INSTALL_PROTOCOL_INTERFACE) ( + IN OUT EFI_HANDLE* Handle, + IN EFI_GUID* Protocol, + IN EFI_INTERFACE_TYPE InterfaceType, + IN VOID* Interface + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_REINSTALL_PROTOCOL_INTERFACE) ( + IN EFI_HANDLE Handle, + IN EFI_GUID* Protocol, + IN VOID* OldInterface, + IN VOID* NewInterface + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_UNINSTALL_PROTOCOL_INTERFACE) ( + IN EFI_HANDLE Handle, + IN EFI_GUID* Protocol, + IN VOID* Interface + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_HANDLE_PROTOCOL) ( + IN EFI_HANDLE Handle, + IN EFI_GUID* Protocol, + OUT VOID **Interface + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_REGISTER_PROTOCOL_NOTIFY) ( + IN EFI_GUID* Protocol, + IN EFI_EVENT Event, + OUT VOID **Registration + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_LOCATE_HANDLE) ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID* Protocol OPTIONAL, + IN VOID* SearchKey OPTIONAL, + IN OUT UINTN* BufferSize, + OUT EFI_HANDLE* Buffer + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_LOCATE_DEVICE_PATH) ( + IN EFI_GUID* Protocol, + IN OUT EFI_DEVICE_PATH **DevicePath, + OUT EFI_HANDLE* Device + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_INSTALL_CONFIGURATION_TABLE) ( + IN EFI_GUID* Guid, + IN VOID* Table + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_RESERVED_SERVICE) ( + ); + +// +// Standard EFI table header +// + +typedef struct _EFI_TABLE_HEADER { + UINT64 Signature; + UINT32 Revision; + UINT32 HeaderSize; + UINT32 CRC32; + UINT32 Reserved; +} EFI_TABLE_HEADER; + + +// +// EFI Runtime Serivces Table +// + +#define EFI_RUNTIME_SERVICES_SIGNATURE 0x56524553544e5552 +#define EFI_1_02_RUNTIME_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(1, 02) +#define EFI_1_10_RUNTIME_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(1, 10) +#define EFI_2_00_RUNTIME_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 00) +#define EFI_2_10_RUNTIME_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 10) +#define EFI_2_20_RUNTIME_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 20) +#define EFI_2_30_RUNTIME_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 30) +#define EFI_2_31_RUNTIME_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 31) +#define EFI_2_40_RUNTIME_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 40) +#define EFI_2_50_RUNTIME_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 50) +#define EFI_2_60_RUNTIME_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 60) +#define EFI_2_70_RUNTIME_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 70) +#define EFI_2_80_RUNTIME_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 80) +#define EFI_2_90_RUNTIME_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 90) +#define EFI_2_100_RUNTIME_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 100) +#define EFI_RUNTIME_SERVICES_REVISION EFI_SPECIFICATION_VERSION + +typedef struct { + EFI_TABLE_HEADER Hdr; + + // + // Time services + // + + EFI_GET_TIME GetTime; + EFI_SET_TIME SetTime; + EFI_GET_WAKEUP_TIME GetWakeupTime; + EFI_SET_WAKEUP_TIME SetWakeupTime; + + // + // Virtual memory services + // + + EFI_SET_VIRTUAL_ADDRESS_MAP SetVirtualAddressMap; + EFI_CONVERT_POINTER ConvertPointer; + + // + // Variable serviers + // + + EFI_GET_VARIABLE GetVariable; + EFI_GET_NEXT_VARIABLE_NAME GetNextVariableName; + EFI_SET_VARIABLE SetVariable; + + // + // Misc + // + + EFI_GET_NEXT_HIGH_MONO_COUNT GetNextHighMonotonicCount; + EFI_RESET_SYSTEM ResetSystem; + + EFI_UPDATE_CAPSULE UpdateCapsule; + EFI_QUERY_CAPSULE_CAPABILITIES QueryCapsuleCapabilities; + EFI_QUERY_VARIABLE_INFO QueryVariableInfo; +} EFI_RUNTIME_SERVICES; + + +// +// EFI Boot Services Table +// + +#define EFI_BOOT_SERVICES_SIGNATURE 0x56524553544f4f42 +#define EFI_1_02_BOOT_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(1, 02) +#define EFI_1_10_BOOT_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(1, 10) +#define EFI_2_00_BOOT_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 00) +#define EFI_2_10_BOOT_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 10) +#define EFI_2_20_BOOT_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 20) +#define EFI_2_30_BOOT_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 30) +#define EFI_2_31_BOOT_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 31) +#define EFI_2_40_BOOT_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 40) +#define EFI_2_50_BOOT_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 50) +#define EFI_2_60_BOOT_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 60) +#define EFI_2_70_BOOT_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 70) +#define EFI_2_80_BOOT_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 80) +#define EFI_2_90_BOOT_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 90) +#define EFI_2_100_BOOT_SERVICES_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 100) +#define EFI_BOOT_SERVICES_REVISION EFI_SPECIFICATION_VERSION + +typedef struct _EFI_BOOT_SERVICES { + + EFI_TABLE_HEADER Hdr; + + // + // Task priority functions + // + + EFI_RAISE_TPL RaiseTPL; + EFI_RESTORE_TPL RestoreTPL; + + // + // Memory functions + // + + EFI_ALLOCATE_PAGES AllocatePages; + EFI_FREE_PAGES FreePages; + EFI_GET_MEMORY_MAP GetMemoryMap; + EFI_ALLOCATE_POOL AllocatePool; + EFI_FREE_POOL FreePool; + + // + // Event & timer functions + // + + EFI_CREATE_EVENT CreateEvent; + EFI_SET_TIMER SetTimer; + EFI_WAIT_FOR_EVENT WaitForEvent; + EFI_SIGNAL_EVENT SignalEvent; + EFI_CLOSE_EVENT CloseEvent; + EFI_CHECK_EVENT CheckEvent; + + // + // Protocol handler functions + // + + EFI_INSTALL_PROTOCOL_INTERFACE InstallProtocolInterface; + EFI_REINSTALL_PROTOCOL_INTERFACE ReinstallProtocolInterface; + EFI_UNINSTALL_PROTOCOL_INTERFACE UninstallProtocolInterface; + EFI_HANDLE_PROTOCOL HandleProtocol; + EFI_HANDLE_PROTOCOL PCHandleProtocol; + EFI_REGISTER_PROTOCOL_NOTIFY RegisterProtocolNotify; + EFI_LOCATE_HANDLE LocateHandle; + EFI_LOCATE_DEVICE_PATH LocateDevicePath; + EFI_INSTALL_CONFIGURATION_TABLE InstallConfigurationTable; + + // + // Image functions + // + + EFI_IMAGE_LOAD LoadImage; + EFI_IMAGE_START StartImage; + EFI_EXIT Exit; + EFI_IMAGE_UNLOAD UnloadImage; + EFI_EXIT_BOOT_SERVICES ExitBootServices; + + // + // Misc functions + // + + EFI_GET_NEXT_MONOTONIC_COUNT GetNextMonotonicCount; + EFI_STALL Stall; + EFI_SET_WATCHDOG_TIMER SetWatchdogTimer; + + // + // DriverSupport Services + // + + EFI_CONNECT_CONTROLLER ConnectController; + EFI_DISCONNECT_CONTROLLER DisconnectController; + + // + // Open and Close Protocol Services + // + EFI_OPEN_PROTOCOL OpenProtocol; + EFI_CLOSE_PROTOCOL CloseProtocol; + EFI_OPEN_PROTOCOL_INFORMATION OpenProtocolInformation; + + // + // Library Services + // + EFI_PROTOCOLS_PER_HANDLE ProtocolsPerHandle; + EFI_LOCATE_HANDLE_BUFFER LocateHandleBuffer; + EFI_LOCATE_PROTOCOL LocateProtocol; + EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES InstallMultipleProtocolInterfaces; + EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInterfaces; + + // + // 32-bit CRC Services + // + EFI_CALCULATE_CRC32 CalculateCrc32; + + // + // Misc Services + // + EFI_COPY_MEM CopyMem; + EFI_SET_MEM SetMem; + EFI_CREATE_EVENT_EX CreateEventEx; +} EFI_BOOT_SERVICES; + + +// +// EFI Configuration Table and GUID definitions +// + +#define MPS_TABLE_GUID \ + { 0xeb9d2d2f, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } + +#define ACPI_TABLE_GUID \ + { 0xeb9d2d30, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } + +#define ACPI_20_TABLE_GUID \ + { 0x8868e871, 0xe4f1, 0x11d3, {0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81} } + +#define SMBIOS_TABLE_GUID \ + { 0xeb9d2d31, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } + +#define SMBIOS3_TABLE_GUID \ + { 0xf2fd1544, 0x9794, 0x4a2c, {0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94} } + +#define SAL_SYSTEM_TABLE_GUID \ + { 0xeb9d2d32, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } + +#define EFI_DTB_TABLE_GUID \ + { 0xb1b621d5, 0xf19c, 0x41a5, {0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0} } + +typedef struct _EFI_CONFIGURATION_TABLE { + EFI_GUID VendorGuid; + VOID* VendorTable; +} EFI_CONFIGURATION_TABLE; + + +// +// EFI System Table +// + + + + +#define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249 +#define EFI_1_02_SYSTEM_TABLE_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(1, 02) +#define EFI_1_10_SYSTEM_TABLE_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(1, 10) +#define EFI_2_00_SYSTEM_TABLE_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 00) +#define EFI_2_10_SYSTEM_TABLE_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 10) +#define EFI_2_20_SYSTEM_TABLE_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 20) +#define EFI_2_30_SYSTEM_TABLE_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 30) +#define EFI_2_31_SYSTEM_TABLE_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 31) +#define EFI_2_40_SYSTEM_TABLE_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 40) +#define EFI_2_50_SYSTEM_TABLE_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 50) +#define EFI_2_60_SYSTEM_TABLE_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 60) +#define EFI_2_70_SYSTEM_TABLE_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 70) +#define EFI_2_80_SYSTEM_TABLE_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 80) +#define EFI_2_90_SYSTEM_TABLE_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 90) +#define EFI_2_100_SYSTEM_TABLE_REVISION EFI_SPECIFICATION_REVISION_MAJORMINOR(2, 100) +#define EFI_SYSTEM_TABLE_REVISION EFI_SPECIFICATION_VERSION + +typedef struct _EFI_SYSTEM_TABLE { + EFI_TABLE_HEADER Hdr; + + CHAR16* FirmwareVendor; + UINT32 FirmwareRevision; + + EFI_HANDLE ConsoleInHandle; + SIMPLE_INPUT_INTERFACE* ConIn; + + EFI_HANDLE ConsoleOutHandle; + SIMPLE_TEXT_OUTPUT_INTERFACE* ConOut; + + EFI_HANDLE StandardErrorHandle; + SIMPLE_TEXT_OUTPUT_INTERFACE* StdErr; + + EFI_RUNTIME_SERVICES* RuntimeServices; + EFI_BOOT_SERVICES* BootServices; + + UINTN NumberOfTableEntries; + EFI_CONFIGURATION_TABLE* ConfigurationTable; + +} EFI_SYSTEM_TABLE; + +#endif + diff --git a/code/boot/include/eficompiler.h b/code/boot/include/eficompiler.h new file mode 100644 index 0000000..5301399 --- /dev/null +++ b/code/boot/include/eficompiler.h @@ -0,0 +1,69 @@ +/*++ + +Copyright (c) 2016-2024 Pete Batard + +Module Name: + + eficompiler.h + +Abstract: + + Compiler specific adjustments + +--*/ + +#if defined(__GNUC__) +#define EFI_UNUSED __attribute__((__unused__)) +#else +#define EFI_UNUSED +#endif + +#if defined(__clang__) +#define EFI_NO_TAIL_CALL __attribute__((disable_tail_calls)) +#elif defined(__GNUC__) +#define EFI_NO_TAIL_CALL __attribute__((optimize("no-optimize-sibling-calls"))) +#else +#define EFI_NO_TAIL_CALL +#endif + +#if defined(__clang__) +#define EFI_OPTNONE __attribute__((optnone)) +#elif defined(__GNUC__) +#define EFI_OPTNONE __attribute__((__optimize__("0"))) +#else +#define EFI_OPTNONE +#endif + +#if defined(__GNUC__) +#define EFI_ALIGN(x) __attribute__((__aligned__(x))) +#elif defined(_MSC_VER) +#define EFI_ALIGN(x) __declspec(align(x)) +#else +// Not being able to align is likely to break executables, so report it +#error "No alignement directive is defined for this platform" +#endif + +#if !defined(ALIGN) +#define ALIGN(x) EFI_ALIGN(x) +#endif + +#if defined(__GNUC__) +#define EFI_NORETURN __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define EFI_NORETURN __declspec(noreturn) +#else +#define EFI_NORETURN +#endif + +#if defined(__GNUC__) +#define EFI_NOINLINE __attribute__((noinline)) +#elif defined(_MSC_VER) +#define EFI_NOINLINE __declspec(noinline) +#else +#define EFI_NOINLINE +#endif + +/* Also add a catch-all on __attribute__() for MS compilers */ +#if defined(_MSC_VER) +#define __attribute__(x) +#endif diff --git a/code/boot/include/eficon.h b/code/boot/include/eficon.h new file mode 100644 index 0000000..977300f --- /dev/null +++ b/code/boot/include/eficon.h @@ -0,0 +1,306 @@ +#ifndef _EFI_CON_H +#define _EFI_CON_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + eficon.h + +Abstract: + + EFI console protocols + + + +Revision History + +--*/ + +// +// Text output protocol +// + +#define EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID \ + { 0x387477c2, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } +#define SIMPLE_TEXT_OUTPUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID + +INTERFACE_DECL(_SIMPLE_TEXT_OUTPUT_INTERFACE); + +typedef +EFI_STATUS +(EFIAPI* EFI_TEXT_RESET) ( + IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE* This, + IN BOOLEAN ExtendedVerification + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_TEXT_OUTPUT_STRING) ( + IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE* This, + IN CHAR16* String + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_TEXT_TEST_STRING) ( + IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE* This, + IN CHAR16* String + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_TEXT_QUERY_MODE) ( + IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE* This, + IN UINTN ModeNumber, + OUT UINTN* Columns, + OUT UINTN* Rows + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_TEXT_SET_MODE) ( + IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE* This, + IN UINTN ModeNumber + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_TEXT_SET_ATTRIBUTE) ( + IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE* This, + IN UINTN Attribute + ); + +#define EFI_BLACK 0x00 +#define EFI_BLUE 0x01 +#define EFI_GREEN 0x02 +#define EFI_CYAN (EFI_BLUE | EFI_GREEN) +#define EFI_RED 0x04 +#define EFI_MAGENTA (EFI_BLUE | EFI_RED) +#define EFI_BROWN (EFI_GREEN | EFI_RED) +#define EFI_LIGHTGRAY (EFI_BLUE | EFI_GREEN | EFI_RED) +#define EFI_BRIGHT 0x08 +#define EFI_DARKGRAY (EFI_BRIGHT) +#define EFI_LIGHTBLUE (EFI_BLUE | EFI_BRIGHT) +#define EFI_LIGHTGREEN (EFI_GREEN | EFI_BRIGHT) +#define EFI_LIGHTCYAN (EFI_CYAN | EFI_BRIGHT) +#define EFI_LIGHTRED (EFI_RED | EFI_BRIGHT) +#define EFI_LIGHTMAGENTA (EFI_MAGENTA | EFI_BRIGHT) +#define EFI_YELLOW (EFI_BROWN | EFI_BRIGHT) +#define EFI_WHITE (EFI_BLUE | EFI_GREEN | EFI_RED | EFI_BRIGHT) + +#define EFI_TEXT_ATTR(f,b) ((f) | ((b) << 4)) + +#define EFI_BACKGROUND_BLACK 0x00 +#define EFI_BACKGROUND_BLUE 0x10 +#define EFI_BACKGROUND_GREEN 0x20 +#define EFI_BACKGROUND_CYAN (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN) +#define EFI_BACKGROUND_RED 0x40 +#define EFI_BACKGROUND_MAGENTA (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_RED) +#define EFI_BACKGROUND_BROWN (EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED) +#define EFI_BACKGROUND_LIGHTGRAY (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED) + + +typedef +EFI_STATUS +(EFIAPI* EFI_TEXT_CLEAR_SCREEN) ( + IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE* This + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_TEXT_SET_CURSOR_POSITION) ( + IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE* This, + IN UINTN Column, + IN UINTN Row + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_TEXT_ENABLE_CURSOR) ( + IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE* This, + IN BOOLEAN Enable + ); + +typedef struct { + INT32 MaxMode; + // current settings + INT32 Mode; + INT32 Attribute; + INT32 CursorColumn; + INT32 CursorRow; + BOOLEAN CursorVisible; +} SIMPLE_TEXT_OUTPUT_MODE; + +typedef struct _SIMPLE_TEXT_OUTPUT_INTERFACE { + EFI_TEXT_RESET Reset; + + EFI_TEXT_OUTPUT_STRING OutputString; + EFI_TEXT_TEST_STRING TestString; + + EFI_TEXT_QUERY_MODE QueryMode; + EFI_TEXT_SET_MODE SetMode; + EFI_TEXT_SET_ATTRIBUTE SetAttribute; + + EFI_TEXT_CLEAR_SCREEN ClearScreen; + EFI_TEXT_SET_CURSOR_POSITION SetCursorPosition; + EFI_TEXT_ENABLE_CURSOR EnableCursor; + + // Current mode + SIMPLE_TEXT_OUTPUT_MODE* Mode; +} SIMPLE_TEXT_OUTPUT_INTERFACE, EFI_SIMPLE_TEXT_OUT_PROTOCOL; + +// +// Define's for required EFI Unicode Box Draw character +// + +#define BOXDRAW_HORIZONTAL 0x2500 +#define BOXDRAW_VERTICAL 0x2502 +#define BOXDRAW_DOWN_RIGHT 0x250c +#define BOXDRAW_DOWN_LEFT 0x2510 +#define BOXDRAW_UP_RIGHT 0x2514 +#define BOXDRAW_UP_LEFT 0x2518 +#define BOXDRAW_VERTICAL_RIGHT 0x251c +#define BOXDRAW_VERTICAL_LEFT 0x2524 +#define BOXDRAW_DOWN_HORIZONTAL 0x252c +#define BOXDRAW_UP_HORIZONTAL 0x2534 +#define BOXDRAW_VERTICAL_HORIZONTAL 0x253c + +#define BOXDRAW_DOUBLE_HORIZONTAL 0x2550 +#define BOXDRAW_DOUBLE_VERTICAL 0x2551 +#define BOXDRAW_DOWN_RIGHT_DOUBLE 0x2552 +#define BOXDRAW_DOWN_DOUBLE_RIGHT 0x2553 +#define BOXDRAW_DOUBLE_DOWN_RIGHT 0x2554 + +#define BOXDRAW_DOWN_LEFT_DOUBLE 0x2555 +#define BOXDRAW_DOWN_DOUBLE_LEFT 0x2556 +#define BOXDRAW_DOUBLE_DOWN_LEFT 0x2557 + +#define BOXDRAW_UP_RIGHT_DOUBLE 0x2558 +#define BOXDRAW_UP_DOUBLE_RIGHT 0x2559 +#define BOXDRAW_DOUBLE_UP_RIGHT 0x255a + +#define BOXDRAW_UP_LEFT_DOUBLE 0x255b +#define BOXDRAW_UP_DOUBLE_LEFT 0x255c +#define BOXDRAW_DOUBLE_UP_LEFT 0x255d + +#define BOXDRAW_VERTICAL_RIGHT_DOUBLE 0x255e +#define BOXDRAW_VERTICAL_DOUBLE_RIGHT 0x255f +#define BOXDRAW_DOUBLE_VERTICAL_RIGHT 0x2560 + +#define BOXDRAW_VERTICAL_LEFT_DOUBLE 0x2561 +#define BOXDRAW_VERTICAL_DOUBLE_LEFT 0x2562 +#define BOXDRAW_DOUBLE_VERTICAL_LEFT 0x2563 + +#define BOXDRAW_DOWN_HORIZONTAL_DOUBLE 0x2564 +#define BOXDRAW_DOWN_DOUBLE_HORIZONTAL 0x2565 +#define BOXDRAW_DOUBLE_DOWN_HORIZONTAL 0x2566 + +#define BOXDRAW_UP_HORIZONTAL_DOUBLE 0x2567 +#define BOXDRAW_UP_DOUBLE_HORIZONTAL 0x2568 +#define BOXDRAW_DOUBLE_UP_HORIZONTAL 0x2569 + +#define BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE 0x256a +#define BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL 0x256b +#define BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL 0x256c + +// +// EFI Required Block Elements Code Chart +// + +#define BLOCKELEMENT_FULL_BLOCK 0x2588 +#define BLOCKELEMENT_LIGHT_SHADE 0x2591 +// +// EFI Required Geometric Shapes Code Chart +// + +#define GEOMETRICSHAPE_UP_TRIANGLE 0x25b2 +#define GEOMETRICSHAPE_RIGHT_TRIANGLE 0x25ba +#define GEOMETRICSHAPE_DOWN_TRIANGLE 0x25bc +#define GEOMETRICSHAPE_LEFT_TRIANGLE 0x25c4 + +// +// EFI Required Arrow shapes +// + +#define ARROW_UP 0x2191 +#define ARROW_DOWN 0x2193 + +// +// Text input protocol +// + +#define EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID \ + { 0x387477c1, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } +#define SIMPLE_TEXT_INPUT_PROTOCOL EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID + +INTERFACE_DECL(_SIMPLE_INPUT_INTERFACE); + +typedef struct { + UINT16 ScanCode; + CHAR16 UnicodeChar; +} EFI_INPUT_KEY; + +// +// Baseline unicode control chars +// + +#define CHAR_NULL 0x0000 +#define CHAR_BACKSPACE 0x0008 +#define CHAR_TAB 0x0009 +#define CHAR_LINEFEED 0x000A +#define CHAR_CARRIAGE_RETURN 0x000D + +// +// Scan codes for base line keys +// + +#define SCAN_NULL 0x0000 +#define SCAN_UP 0x0001 +#define SCAN_DOWN 0x0002 +#define SCAN_RIGHT 0x0003 +#define SCAN_LEFT 0x0004 +#define SCAN_HOME 0x0005 +#define SCAN_END 0x0006 +#define SCAN_INSERT 0x0007 +#define SCAN_DELETE 0x0008 +#define SCAN_PAGE_UP 0x0009 +#define SCAN_PAGE_DOWN 0x000A +#define SCAN_F1 0x000B +#define SCAN_F2 0x000C +#define SCAN_F3 0x000D +#define SCAN_F4 0x000E +#define SCAN_F5 0x000F +#define SCAN_F6 0x0010 +#define SCAN_F7 0x0011 +#define SCAN_F8 0x0012 +#define SCAN_F9 0x0013 +#define SCAN_F10 0x0014 +#define SCAN_F11 0x0015 +#define SCAN_F12 0x0016 +#define SCAN_ESC 0x0017 + +typedef +EFI_STATUS +(EFIAPI* EFI_INPUT_RESET) ( + IN struct _SIMPLE_INPUT_INTERFACE* This, + IN BOOLEAN ExtendedVerification + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_INPUT_READ_KEY) ( + IN struct _SIMPLE_INPUT_INTERFACE* This, + OUT EFI_INPUT_KEY* Key + ); + +typedef struct _SIMPLE_INPUT_INTERFACE { + EFI_INPUT_RESET Reset; + EFI_INPUT_READ_KEY ReadKeyStroke; + EFI_EVENT WaitForKey; +} SIMPLE_INPUT_INTERFACE, EFI_SIMPLE_TEXT_IN_PROTOCOL; + +#endif + diff --git a/code/boot/include/eficonex.h b/code/boot/include/eficonex.h new file mode 100644 index 0000000..170ea26 --- /dev/null +++ b/code/boot/include/eficonex.h @@ -0,0 +1,111 @@ +#ifndef _EFI_CONEX_H +#define _EFI_CONEX_H + +/*++ + +Copyright (c) 2020 Kagurazaka Kotori + +Module Name: + + eficonex.h + +Abstract: + + EFI console extension protocols + +--*/ + +// +// Simple Text Input Ex Protocol +// + +#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \ + { 0xdd9e7534, 0x7762, 0x4698, {0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa} } + +INTERFACE_DECL(_EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL); + +typedef UINT8 EFI_KEY_TOGGLE_STATE; + +typedef struct EFI_KEY_STATE { + UINT32 KeyShiftState; + EFI_KEY_TOGGLE_STATE KeyToggleState; +} EFI_KEY_STATE; + +typedef struct { + EFI_INPUT_KEY Key; + EFI_KEY_STATE KeyState; +} EFI_KEY_DATA; + +// Shift states +#define EFI_SHIFT_STATE_VALID 0x80000000 +#define EFI_RIGHT_SHIFT_PRESSED 0x00000001 +#define EFI_LEFT_SHIFT_PRESSED 0x00000002 +#define EFI_RIGHT_CONTROL_PRESSED 0x00000004 +#define EFI_LEFT_CONTROL_PRESSED 0x00000008 +#define EFI_RIGHT_ALT_PRESSED 0x00000010 +#define EFI_LEFT_ALT_PRESSED 0x00000020 +#define EFI_RIGHT_LOGO_PRESSED 0x00000040 +#define EFI_LEFT_LOGO_PRESSED 0x00000080 +#define EFI_MENU_KEY_PRESSED 0x00000100 +#define EFI_SYS_REQ_PRESSED 0x00000200 + +// Toggle states +#define EFI_TOGGLE_STATE_VALID 0x80 +#define EFI_KEY_STATE_EXPOSED 0x40 +#define EFI_SCROLL_LOCK_ACTIVE 0x01 +#define EFI_NUM_LOCK_ACTIVE 0x02 +#define EFI_CAPS_LOCK_ACTIVE 0x04 + +typedef +EFI_STATUS +(EFIAPI* EFI_INPUT_RESET_EX) ( + IN struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL* This, + IN BOOLEAN ExtendedVerification + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_INPUT_READ_KEY_EX) ( + IN struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL* This, + OUT EFI_KEY_DATA* KeyData + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SET_STATE) ( + IN struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL* This, + IN EFI_KEY_TOGGLE_STATE* KeyToggleState + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_KEY_NOTIFY_FUNCTION) ( + IN EFI_KEY_DATA* KeyData + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_REGISTER_KEYSTROKE_NOTIFY) ( + IN struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL* This, + IN EFI_KEY_DATA* KeyData, + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, + OUT VOID **NotifyHandle + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_UNREGISTER_KEYSTROKE_NOTIFY) ( + IN struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL* This, + IN VOID* NotificationHandle + ); + +typedef struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL{ + EFI_INPUT_RESET_EX Reset; + EFI_INPUT_READ_KEY_EX ReadKeyStrokeEx; + EFI_EVENT WaitForKeyEx; + EFI_SET_STATE SetState; + EFI_REGISTER_KEYSTROKE_NOTIFY RegisterKeyNotify; + EFI_UNREGISTER_KEYSTROKE_NOTIFY UnregisterKeyNotify; +} EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL; + +#endif diff --git a/code/boot/include/efidebug.h b/code/boot/include/efidebug.h new file mode 100644 index 0000000..6a5c532 --- /dev/null +++ b/code/boot/include/efidebug.h @@ -0,0 +1,620 @@ +#ifndef _EFI_DEBUG_H +#define _EFI_DEBUG_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efidebug.h + +Abstract: + + EFI library debug functions + + + +Revision History + +--*/ + +extern UINTN EFIDebug; + +#if EFI_DEBUG + + #define DBGASSERT(a) DbgAssert(__FILE__, __LINE__, #a) + #define DEBUG(a) DbgPrint a + +#else + + #define DBGASSERT(a) + #define DEBUG(a) + +#endif + +#if EFI_DEBUG_CLEAR_MEMORY + + #define DBGSETMEM(a,l) SetMem(a,l,(CHAR8)BAD_POINTER) + +#else + + #define DBGSETMEM(a,l) + +#endif + +#define D_INIT 0x00000001 // Initialization style messages +#define D_WARN 0x00000002 // Warnings +#define D_LOAD 0x00000004 // Load events +#define D_FS 0x00000008 // EFI File system +#define D_POOL 0x00000010 // Alloc & Free's +#define D_PAGE 0x00000020 // Alloc & Free's +#define D_INFO 0x00000040 // Verbose +#define D_VAR 0x00000100 // Variable +#define D_PARSE 0x00000200 // Command parsing +#define D_BM 0x00000400 // Boot manager +#define D_BLKIO 0x00001000 // BlkIo Driver +#define D_BLKIO_ULTRA 0x00002000 // BlkIo Driver +#define D_NET 0x00004000 // SNI Driver +#define D_NET_ULTRA 0x00008000 // SNI Driver +#define D_TXTIN 0x00010000 // Simple Input Driver +#define D_TXTOUT 0x00020000 // Simple Text Output Driver +#define D_ERROR_ATA 0x00040000 // ATA error messages +#define D_ERROR 0x80000000 // Error + +#define D_RESERVED 0x7fffC880 // Bits not reserved above + +// +// Current Debug level of the system, value of EFIDebug +// +//#define EFI_DBUG_MASK (D_ERROR | D_WARN | D_LOAD | D_BLKIO | D_INIT) +#define EFI_DBUG_MASK (D_ERROR) + +// +// +// + +#if EFI_DEBUG + + #define ASSERT(a) if(!(a)) DBGASSERT(a) + #define ASSERT_LOCKED(l) if(!(l)->Lock) DBGASSERT(l not locked) + #define ASSERT_STRUCT(p,t) DBGASSERT(t not structure), p + +#else + + #define ASSERT(a) + #define ASSERT_LOCKED(l) + #define ASSERT_STRUCT(p,t) + +#endif + +// +// Prototypes +// + +INTN +DbgAssert ( + CONST CHAR8* file, + INTN lineno, + CONST CHAR8* string + ); + +INTN +DbgPrint ( + INTN mask, + CONST CHAR8* format, + ... + ); + +// +// Instruction Set Architectures definitions for debuggers +// + +typedef INTN EFI_EXCEPTION_TYPE; + +// IA32 +#define EXCEPT_IA32_DIVIDE_ERROR 0 +#define EXCEPT_IA32_DEBUG 1 +#define EXCEPT_IA32_NMI 2 +#define EXCEPT_IA32_BREAKPOINT 3 +#define EXCEPT_IA32_OVERFLOW 4 +#define EXCEPT_IA32_BOUND 5 +#define EXCEPT_IA32_INVALID_OPCODE 6 +#define EXCEPT_IA32_DOUBLE_FAULT 8 +#define EXCEPT_IA32_INVALID_TSS 10 +#define EXCEPT_IA32_SEG_NOT_PRESENT 11 +#define EXCEPT_IA32_STACK_FAULT 12 +#define EXCEPT_IA32_GP_FAULT 13 +#define EXCEPT_IA32_PAGE_FAULT 14 +#define EXCEPT_IA32_FP_ERROR 16 +#define EXCEPT_IA32_ALIGNMENT_CHECK 17 +#define EXCEPT_IA32_MACHINE_CHECK 18 +#define EXCEPT_IA32_SIMD 19 + +typedef struct { + UINT16 Fcw; + UINT16 Fsw; + UINT16 Ftw; + UINT16 Opcode; + UINT32 Eip; + UINT16 Cs; + UINT16 Reserved1; + UINT32 DataOffset; + UINT16 Ds; + UINT8 Reserved2[10]; + UINT8 St0Mm0[10], Reserved3[6]; + UINT8 St1Mm1[10], Reserved4[6]; + UINT8 St2Mm2[10], Reserved5[6]; + UINT8 St3Mm3[10], Reserved6[6]; + UINT8 St4Mm4[10], Reserved7[6]; + UINT8 St5Mm5[10], Reserved8[6]; + UINT8 St6Mm6[10], Reserved9[6]; + UINT8 St7Mm7[10], Reserved10[6]; + UINT8 Xmm0[16]; + UINT8 Xmm1[16]; + UINT8 Xmm2[16]; + UINT8 Xmm3[16]; + UINT8 Xmm4[16]; + UINT8 Xmm5[16]; + UINT8 Xmm6[16]; + UINT8 Xmm7[16]; + UINT8 Reserved11[14 * 16]; +} EFI_FX_SAVE_STATE_IA32; + +typedef struct { + UINT32 ExceptionData; + EFI_FX_SAVE_STATE_IA32 FxSaveState; + UINT32 Dr0; + UINT32 Dr1; + UINT32 Dr2; + UINT32 Dr3; + UINT32 Dr6; + UINT32 Dr7; + UINT32 Cr0; + UINT32 Cr1; + UINT32 Cr2; + UINT32 Cr3; + UINT32 Cr4; + UINT32 Eflags; + UINT32 Ldtr; + UINT32 Tr; + UINT32 Gdtr[2]; + UINT32 Idtr[2]; + UINT32 Eip; + UINT32 Gs; + UINT32 Fs; + UINT32 Es; + UINT32 Ds; + UINT32 Cs; + UINT32 Ss; + UINT32 Edi; + UINT32 Esi; + UINT32 Ebp; + UINT32 Esp; + UINT32 Ebx; + UINT32 Edx; + UINT32 Ecx; + UINT32 Eax; +} EFI_SYSTEM_CONTEXT_IA32; + +// X64 +#define EXCEPT_X64_DIVIDE_ERROR 0 +#define EXCEPT_X64_DEBUG 1 +#define EXCEPT_X64_NMI 2 +#define EXCEPT_X64_BREAKPOINT 3 +#define EXCEPT_X64_OVERFLOW 4 +#define EXCEPT_X64_BOUND 5 +#define EXCEPT_X64_INVALID_OPCODE 6 +#define EXCEPT_X64_DOUBLE_FAULT 8 +#define EXCEPT_X64_INVALID_TSS 10 +#define EXCEPT_X64_SEG_NOT_PRESENT 11 +#define EXCEPT_X64_STACK_FAULT 12 +#define EXCEPT_X64_GP_FAULT 13 +#define EXCEPT_X64_PAGE_FAULT 14 +#define EXCEPT_X64_FP_ERROR 16 +#define EXCEPT_X64_ALIGNMENT_CHECK 17 +#define EXCEPT_X64_MACHINE_CHECK 18 +#define EXCEPT_X64_SIMD 19 + +typedef struct { + UINT16 Fcw; + UINT16 Fsw; + UINT16 Ftw; + UINT16 Opcode; + UINT64 Rip; + UINT64 DataOffset; + UINT8 Reserved1[8]; + UINT8 St0Mm0[10], Reserved2[6]; + UINT8 St1Mm1[10], Reserved3[6]; + UINT8 St2Mm2[10], Reserved4[6]; + UINT8 St3Mm3[10], Reserved5[6]; + UINT8 St4Mm4[10], Reserved6[6]; + UINT8 St5Mm5[10], Reserved7[6]; + UINT8 St6Mm6[10], Reserved8[6]; + UINT8 St7Mm7[10], Reserved9[6]; + UINT8 Xmm0[16]; + UINT8 Xmm1[16]; + UINT8 Xmm2[16]; + UINT8 Xmm3[16]; + UINT8 Xmm4[16]; + UINT8 Xmm5[16]; + UINT8 Xmm6[16]; + UINT8 Xmm7[16]; + UINT8 Reserved11[14 * 16]; +} EFI_FX_SAVE_STATE_X64; + +typedef struct { + UINT64 ExceptionData; + EFI_FX_SAVE_STATE_X64 FxSaveState; + UINT64 Dr0; + UINT64 Dr1; + UINT64 Dr2; + UINT64 Dr3; + UINT64 Dr6; + UINT64 Dr7; + UINT64 Cr0; + UINT64 Cr1; + UINT64 Cr2; + UINT64 Cr3; + UINT64 Cr4; + UINT64 Cr8; + UINT64 Rflags; + UINT64 Ldtr; + UINT64 Tr; + UINT64 Gdtr[2]; + UINT64 Idtr[2]; + UINT64 Rip; + UINT64 Gs; + UINT64 Fs; + UINT64 Es; + UINT64 Ds; + UINT64 Cs; + UINT64 Ss; + UINT64 Rdi; + UINT64 Rsi; + UINT64 Rbp; + UINT64 Rsp; + UINT64 Rbx; + UINT64 Rdx; + UINT64 Rcx; + UINT64 Rax; + UINT64 R8; + UINT64 R9; + UINT64 R10; + UINT64 R11; + UINT64 R12; + UINT64 R13; + UINT64 R14; + UINT64 R15; +} EFI_SYSTEM_CONTEXT_X64; + +/// IA64 +#define EXCEPT_IPF_VHTP_TRANSLATION 0 +#define EXCEPT_IPF_INSTRUCTION_TLB 1 +#define EXCEPT_IPF_DATA_TLB 2 +#define EXCEPT_IPF_ALT_INSTRUCTION_TLB 3 +#define EXCEPT_IPF_ALT_DATA_TLB 4 +#define EXCEPT_IPF_DATA_NESTED_TLB 5 +#define EXCEPT_IPF_INSTRUCTION_KEY_MISSED 6 +#define EXCEPT_IPF_DATA_KEY_MISSED 7 +#define EXCEPT_IPF_DIRTY_BIT 8 +#define EXCEPT_IPF_INSTRUCTION_ACCESS_BIT 9 +#define EXCEPT_IPF_DATA_ACCESS_BIT 10 +#define EXCEPT_IPF_BREAKPOINT 11 +#define EXCEPT_IPF_EXTERNAL_INTERRUPT 12 +#define EXCEPT_IPF_PAGE_NOT_PRESENT 20 +#define EXCEPT_IPF_KEY_PERMISSION 21 +#define EXCEPT_IPF_INSTRUCTION_ACCESS_RIGHTS 22 +#define EXCEPT_IPF_DATA_ACCESS_RIGHTS 23 +#define EXCEPT_IPF_GENERAL_EXCEPTION 24 +#define EXCEPT_IPF_DISABLED_FP_REGISTER 25 +#define EXCEPT_IPF_NAT_CONSUMPTION 26 +#define EXCEPT_IPF_SPECULATION 27 +#define EXCEPT_IPF_DEBUG 29 +#define EXCEPT_IPF_UNALIGNED_REFERENCE 30 +#define EXCEPT_IPF_UNSUPPORTED_DATA_REFERENCE 31 +#define EXCEPT_IPF_FP_FAULT 32 +#define EXCEPT_IPF_FP_TRAP 33 +#define EXCEPT_IPF_LOWER_PRIVILEGE_TRANSFER_TRAP 34 +#define EXCEPT_IPF_TAKEN_BRANCH 35 +#define EXCEPT_IPF_SINGLE_STEP 36 +#define EXCEPT_IPF_IA32_EXCEPTION 45 +#define EXCEPT_IPF_IA32_INTERCEPT 46 +#define EXCEPT_IPF_IA32_INTERRUPT 47 + +typedef struct { + UINT64 Reserved; + UINT64 R1; + UINT64 R2; + UINT64 R3; + UINT64 R4; + UINT64 R5; + UINT64 R6; + UINT64 R7; + UINT64 R8; + UINT64 R9; + UINT64 R10; + UINT64 R11; + UINT64 R12; + UINT64 R13; + UINT64 R14; + UINT64 R15; + UINT64 R16; + UINT64 R17; + UINT64 R18; + UINT64 R19; + UINT64 R20; + UINT64 R21; + UINT64 R22; + UINT64 R23; + UINT64 R24; + UINT64 R25; + UINT64 R26; + UINT64 R27; + UINT64 R28; + UINT64 R29; + UINT64 R30; + UINT64 R31; + UINT64 F2[2]; + UINT64 F3[2]; + UINT64 F4[2]; + UINT64 F5[2]; + UINT64 F6[2]; + UINT64 F7[2]; + UINT64 F8[2]; + UINT64 F9[2]; + UINT64 F10[2]; + UINT64 F11[2]; + UINT64 F12[2]; + UINT64 F13[2]; + UINT64 F14[2]; + UINT64 F15[2]; + UINT64 F16[2]; + UINT64 F17[2]; + UINT64 F18[2]; + UINT64 F19[2]; + UINT64 F20[2]; + UINT64 F21[2]; + UINT64 F22[2]; + UINT64 F23[2]; + UINT64 F24[2]; + UINT64 F25[2]; + UINT64 F26[2]; + UINT64 F27[2]; + UINT64 F28[2]; + UINT64 F29[2]; + UINT64 F30[2]; + UINT64 F31[2]; + UINT64 Pr; + UINT64 B0; + UINT64 B1; + UINT64 B2; + UINT64 B3; + UINT64 B4; + UINT64 B5; + UINT64 B6; + UINT64 B7; + UINT64 ArRsc; + UINT64 ArBsp; + UINT64 ArBspstore; + UINT64 ArRnat; + UINT64 ArFcr; + UINT64 ArEflag; + UINT64 ArCsd; + UINT64 ArSsd; + UINT64 ArCflg; + UINT64 ArFsr; + UINT64 ArFir; + UINT64 ArFdr; + UINT64 ArCcv; + UINT64 ArUnat; + UINT64 ArFpsr; + UINT64 ArPfs; + UINT64 ArLc; + UINT64 ArEc; + UINT64 CrDcr; + UINT64 CrItm; + UINT64 CrIva; + UINT64 CrPta; + UINT64 CrIpsr; + UINT64 CrIsr; + UINT64 CrIip; + UINT64 CrIfa; + UINT64 CrItir; + UINT64 CrIipa; + UINT64 CrIfs; + UINT64 CrIim; + UINT64 CrIha; + UINT64 Dbr0; + UINT64 Dbr1; + UINT64 Dbr2; + UINT64 Dbr3; + UINT64 Dbr4; + UINT64 Dbr5; + UINT64 Dbr6; + UINT64 Dbr7; + UINT64 Ibr0; + UINT64 Ibr1; + UINT64 Ibr2; + UINT64 Ibr3; + UINT64 Ibr4; + UINT64 Ibr5; + UINT64 Ibr6; + UINT64 Ibr7; + UINT64 IntNat; +} EFI_SYSTEM_CONTEXT_IPF; + +// EBC +#define EXCEPT_EBC_UNDEFINED 0 +#define EXCEPT_EBC_DIVIDE_ERROR 1 +#define EXCEPT_EBC_DEBUG 2 +#define EXCEPT_EBC_BREAKPOINT 3 +#define EXCEPT_EBC_OVERFLOW 4 +#define EXCEPT_EBC_INVALID_OPCODE 5 +#define EXCEPT_EBC_STACK_FAULT 6 +#define EXCEPT_EBC_ALIGNMENT_CHECK 7 +#define EXCEPT_EBC_INSTRUCTION_ENCODING 8 +#define EXCEPT_EBC_BAD_BREAK 9 +#define EXCEPT_EBC_STEP 10 +#define MAX_EBC_EXCEPTION EXCEPT_EBC_STEP + +typedef struct { + UINT64 R0; + UINT64 R1; + UINT64 R2; + UINT64 R3; + UINT64 R4; + UINT64 R5; + UINT64 R6; + UINT64 R7; + UINT64 Flags; + UINT64 ControlFlags; + UINT64 Ip; +} EFI_SYSTEM_CONTEXT_EBC; + +// ARM +#define EXCEPT_ARM_RESET 0 +#define EXCEPT_ARM_UNDEFINED_INSTRUCTION 1 +#define EXCEPT_ARM_SOFTWARE_INTERRUPT 2 +#define EXCEPT_ARM_PREFETCH_ABORT 3 +#define EXCEPT_ARM_DATA_ABORT 4 +#define EXCEPT_ARM_RESERVED 5 +#define EXCEPT_ARM_IRQ 6 +#define EXCEPT_ARM_FIQ 7 +#define MAX_ARM_EXCEPTION EXCEPT_ARM_FIQ + +typedef struct { + UINT32 R0; + UINT32 R1; + UINT32 R2; + UINT32 R3; + UINT32 R4; + UINT32 R5; + UINT32 R6; + UINT32 R7; + UINT32 R8; + UINT32 R9; + UINT32 R10; + UINT32 R11; + UINT32 R12; + UINT32 SP; + UINT32 LR; + UINT32 PC; + UINT32 CPSR; + UINT32 DFSR; + UINT32 DFAR; + UINT32 IFSR; + UINT32 IFAR; +} EFI_SYSTEM_CONTEXT_ARM; + + +typedef union { + EFI_SYSTEM_CONTEXT_EBC* SystemContextEbc; + EFI_SYSTEM_CONTEXT_IA32* SystemContextIa32; + EFI_SYSTEM_CONTEXT_X64* SystemContextX64; + EFI_SYSTEM_CONTEXT_IPF* SystemContextIpf; + EFI_SYSTEM_CONTEXT_ARM* SystemContextArm; +} EFI_SYSTEM_CONTEXT; + +typedef +VOID +(EFIAPI* EFI_EXCEPTION_CALLBACK)( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext); + +typedef +VOID +(EFIAPI* EFI_PERIODIC_CALLBACK)( + IN OUT EFI_SYSTEM_CONTEXT SystemContext); + +typedef enum { + IsaIa32 = EFI_IMAGE_MACHINE_IA32, + IsaX64 = EFI_IMAGE_MACHINE_X64, + IsaIpf = EFI_IMAGE_MACHINE_IA64, + IsaEbc = EFI_IMAGE_MACHINE_EBC, + IsaArm = EFI_IMAGE_MACHINE_ARMTHUMB_MIXED, +// IsaArm64 = EFI_IMAGE_MACHINE_AARCH64 +} EFI_INSTRUCTION_SET_ARCHITECTURE; + +// +// DEBUG_IMAGE_INFO +// + +#define EFI_DEBUG_IMAGE_INFO_TABLE_GUID \ + { 0x49152e77, 0x1ada, 0x4764, {0xb7, 0xa2, 0x7a, 0xfe, 0xfe, 0xd9, 0x5e, 0x8b} } + +#define EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS 0x01 +#define EFI_DEBUG_IMAGE_INFO_TABLE_MODIFIED 0x02 +#define EFI_DEBUG_IMAGE_INFO_INITIAL_SIZE (EFI_PAGE_SIZE / sizeof (UINTN)) +#define EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL 0x01 + +typedef struct { +UINT64 Signature; +EFI_PHYSICAL_ADDRESS EfiSystemTableBase; +UINT32 Crc32; +} EFI_SYSTEM_TABLE_POINTER; + +typedef struct { +UINT32 ImageInfoType; +EFI_LOADED_IMAGE_PROTOCOL* LoadedImageProtocolInstance; +EFI_HANDLE* ImageHandle; +} EFI_DEBUG_IMAGE_INFO_NORMAL; + +typedef union { +UINT32* ImageInfoType; +EFI_DEBUG_IMAGE_INFO_NORMAL* NormalImage; +} EFI_DEBUG_IMAGE_INFO; + +typedef struct { +volatile UINT32 UpdateStatus; +UINT32 TableSize; +EFI_DEBUG_IMAGE_INFO* EfiDebugImageInfoTable; +} EFI_DEBUG_IMAGE_INFO_TABLE_HEADER; + +// +// EFI_DEBUGGER_PROTOCOL +// + +#define EFI_DEBUG_SUPPORT_PROTOCOL_GUID \ + { 0x2755590c, 0x6f3c, 0x42fa, {0x9e, 0xa4, 0xa3, 0xba, 0x54, 0x3c, 0xda, 0x25} } + +INTERFACE_DECL(_EFI_DEBUG_SUPPORT_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI* EFI_GET_MAXIMUM_PROCESSOR_INDEX)( + IN struct _EFI_DEBUG_SUPPORT_PROTOCOL* This, + OUT UINTN* MaxProcessorIndex); + +typedef +EFI_STATUS +(EFIAPI* EFI_REGISTER_PERIODIC_CALLBACK)( + IN struct _EFI_DEBUG_SUPPORT_PROTOCOL* This, + IN UINTN ProcessorIndex, + IN EFI_PERIODIC_CALLBACK PeriodicCallback); + +typedef +EFI_STATUS +(EFIAPI* EFI_REGISTER_EXCEPTION_CALLBACK)( + IN struct _EFI_DEBUG_SUPPORT_PROTOCOL* This, + IN UINTN ProcessorIndex, + IN EFI_EXCEPTION_CALLBACK ExceptionCallback, + IN EFI_EXCEPTION_TYPE ExceptionType); + +typedef +EFI_STATUS +(EFIAPI* EFI_INVALIDATE_INSTRUCTION_CACHE)( + IN struct _EFI_DEBUG_SUPPORT_PROTOCOL* This, + IN UINTN ProcessorIndex, + IN VOID* Start, + IN UINT64 Length); + +typedef struct _EFI_DEBUG_SUPPORT_PROTOCOL { + EFI_INSTRUCTION_SET_ARCHITECTURE Isa; + EFI_GET_MAXIMUM_PROCESSOR_INDEX GetMaximumProcessorIndex; + EFI_REGISTER_PERIODIC_CALLBACK RegisterPeriodicCallback; + EFI_REGISTER_EXCEPTION_CALLBACK RegisterExceptionCallback; + EFI_INVALIDATE_INSTRUCTION_CACHE InvalidateInstructionCache; +} EFI_DEBUG_SUPPORT_PROTOCOL; + +#endif diff --git a/code/boot/include/efidef.h b/code/boot/include/efidef.h new file mode 100644 index 0000000..d188595 --- /dev/null +++ b/code/boot/include/efidef.h @@ -0,0 +1,258 @@ +#ifndef _EFI_DEF_H +#define _EFI_DEF_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efidef.h + +Abstract: + + EFI definitions + + + + +Revision History + +--*/ + +#if !defined(__cplusplus) +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +typedef _Bool BOOLEAN; +#else +typedef unsigned char BOOLEAN; +#endif +#else +typedef bool BOOLEAN; +#endif + +#ifndef CONST + #define CONST const +#endif +#ifndef TRUE +#if defined(__cplusplus) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) + #define TRUE true + #define FALSE false +#else + #define TRUE ((BOOLEAN) 1) + #define FALSE ((BOOLEAN) 0) +#endif +#endif + +#ifndef NULL +#if (defined(__cplusplus) && __cplusplus >= 201103L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) + #define NULL nullptr +#else +#if !defined(__cplusplus) + #define NULL ((VOID *) 0) +#else + #define NULL 0 +#endif +#endif +#endif + +typedef UINTN EFI_STATUS; +typedef UINT64 EFI_LBA; +typedef UINTN EFI_TPL; +typedef VOID* EFI_HANDLE; +typedef VOID* EFI_EVENT; + + +// +// Prototype argument decoration for EFI parameters to indicate +// their direction +// +// IN - argument is passed into the function +// OUT - argument (pointer) is returned from the function +// OPTIONAL - argument is optional +// + +#ifndef IN + #define IN + #define OUT + #define OPTIONAL +#endif + + +// +// A GUID +// + +typedef struct { + UINT32 Data1; + UINT16 Data2; + UINT16 Data3; + UINT8 Data4[8]; +} EFI_GUID; + + +// +// Time +// + +typedef struct { + UINT16 Year; // 1998 - 20XX + UINT8 Month; // 1 - 12 + UINT8 Day; // 1 - 31 + UINT8 Hour; // 0 - 23 + UINT8 Minute; // 0 - 59 + UINT8 Second; // 0 - 59 + UINT8 Pad1; + UINT32 Nanosecond; // 0 - 999,999,999 + INT16 TimeZone; // -1440 to 1440 or 2047 + UINT8 Daylight; + UINT8 Pad2; +} EFI_TIME; + +// Bit definitions for EFI_TIME.Daylight +#define EFI_TIME_ADJUST_DAYLIGHT 0x01 +#define EFI_TIME_IN_DAYLIGHT 0x02 + +// Value definition for EFI_TIME.TimeZone +#define EFI_UNSPECIFIED_TIMEZONE 0x07FF + + + +// +// Networking +// + +typedef struct { + UINT8 Addr[4]; +} EFI_IPv4_ADDRESS; + +typedef struct { + UINT8 Addr[16]; +} EFI_IPv6_ADDRESS; + +typedef struct { + UINT8 Addr[32]; +} EFI_MAC_ADDRESS; + +typedef struct { + UINT32 ReceivedQueueTimeoutValue; + UINT32 TransmitQueueTimeoutValue; + UINT16 ProtocolTypeFilter; + BOOLEAN EnableUnicastReceive; + BOOLEAN EnableMulticastReceive; + BOOLEAN EnableBroadcastReceive; + BOOLEAN EnablePromiscuousReceive; + BOOLEAN FlushQueuesOnReset; + BOOLEAN EnableReceiveTimestamps; + BOOLEAN DisableBackgroundPolling; +} EFI_MANAGED_NETWORK_CONFIG_DATA; + +// +// Memory +// + +typedef UINT64 EFI_PHYSICAL_ADDRESS; +typedef UINT64 EFI_VIRTUAL_ADDRESS; + +typedef enum { + AllocateAnyPages, + AllocateMaxAddress, + AllocateAddress, + MaxAllocateType +} EFI_ALLOCATE_TYPE; + +//Preseve the attr on any range supplied. +//ConventialMemory must have WB,SR,SW when supplied. +//When allocating from ConventialMemory always make it WB,SR,SW +//When returning to ConventialMemory always make it WB,SR,SW +//When getting the memory map, or on RT for runtime types + + +typedef enum { + EfiReservedMemoryType, + EfiLoaderCode, + EfiLoaderData, + EfiBootServicesCode, + EfiBootServicesData, + EfiRuntimeServicesCode, + EfiRuntimeServicesData, + EfiConventionalMemory, + EfiUnusableMemory, + EfiACPIReclaimMemory, + EfiACPIMemoryNVS, + EfiMemoryMappedIO, + EfiMemoryMappedIOPortSpace, + EfiPalCode, + EfiPersistentMemory, + EfiUnacceptedMemoryType, + EfiMaxMemoryType +} EFI_MEMORY_TYPE; + + +// Memory cacheability attribute +#define EFI_MEMORY_UC 0x0000000000000001 +#define EFI_MEMORY_WC 0x0000000000000002 +#define EFI_MEMORY_WT 0x0000000000000004 +#define EFI_MEMORY_WB 0x0000000000000008 +#define EFI_MEMORY_UCE 0x0000000000000010 + +// Physical memory protection attribute +#define EFI_MEMORY_WP 0x0000000000001000 +#define EFI_MEMORY_RP 0x0000000000002000 +#define EFI_MEMORY_XP 0x0000000000004000 +#define EFI_MEMORY_RO 0x0000000000020000 + +// Runtime memory attribute +#define EFI_MEMORY_NV 0x0000000000008000 +#define EFI_MEMORY_RUNTIME 0x8000000000000000 + +// Other memory attribute +#define EFI_MEMORY_MORE_RELIABLE 0x0000000000010000 +#define EFI_MEMORY_SP 0x0000000000040000 +#define EFI_MEMORY_CPU_CRYPTO 0x0000000000080000 +#define EFI_MEMORY_ISA_VALID 0x4000000000000000 +#define EFI_MEMORY_ISA_MASK 0x0FFFF00000000000 + + +#define EFI_MEMORY_DESCRIPTOR_VERSION 1 +typedef struct { + UINT32 Type; // Field size is 32 bits followed by 32 bit pad + UINT32 Pad; + EFI_PHYSICAL_ADDRESS PhysicalStart; // Field size is 64 bits + EFI_VIRTUAL_ADDRESS VirtualStart; // Field size is 64 bits + UINT64 NumberOfPages; // Field size is 64 bits + UINT64 Attribute; // Field size is 64 bits +} EFI_MEMORY_DESCRIPTOR; + +// +// International Language +// + +typedef CHAR8 ISO_639_2; +#define ISO_639_2_ENTRY_SIZE 3 + +// +// +// + +#define EFI_PAGE_SIZE 4096 +#define EFI_PAGE_MASK 0xFFF +#define EFI_PAGE_SHIFT 12 + +#define EFI_SIZE_TO_PAGES(a) \ + ( ((a) >> EFI_PAGE_SHIFT) + ((a) & EFI_PAGE_MASK ? 1 : 0) ) + +#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001 +#define EFI_OS_INDICATIONS_TIMESTAMP_REVOCATION 0x0000000000000002 +#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED \ + 0x0000000000000004 +#define EFI_OS_INDICATIONS_FMP_CAPSULE_SUPPORTED \ + 0x0000000000000008 +#define EFI_OS_INDICATIONS_CAPSULE_RESULT_VAR_SUPPORTED \ + 0x0000000000000010 +#define EFI_OS_INDICATIONS_START_OS_RECOVERY 0x0000000000000020 +#define EFI_OS_INDICATIONS_START_PLATFORM_RECOVERY \ + 0x0000000000000040 +#define EFI_OS_INDICATIONS_JSON_CONFIG_DATA_REFRESH \ + 0x0000000000000080 + +#endif diff --git a/code/boot/include/efidevp.h b/code/boot/include/efidevp.h new file mode 100644 index 0000000..ef62b32 --- /dev/null +++ b/code/boot/include/efidevp.h @@ -0,0 +1,650 @@ +#ifndef _DEVPATH_H +#define _DEVPATH_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + devpath.h + +Abstract: + + Defines for parsing the EFI Device Path structures + + + +Revision History + +--*/ + +// +// Device Path structures - Section C +// + +typedef struct _EFI_DEVICE_PATH_PROTOCOL { + UINT8 Type; + UINT8 SubType; + UINT8 Length[2]; +} EFI_DEVICE_PATH_PROTOCOL; + +typedef struct _EFI_DEVICE_PATH_PROTOCOL _EFI_DEVICE_PATH; +typedef EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH; + +#define EFI_DP_TYPE_MASK 0x7F +#define EFI_DP_TYPE_UNPACKED 0x80 + +//#define END_DEVICE_PATH_TYPE 0xff +#define END_DEVICE_PATH_TYPE 0x7f +//#define END_DEVICE_PATH_TYPE_UNPACKED 0x7f + +#define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff +#define END_INSTANCE_DEVICE_PATH_SUBTYPE 0x01 +#define END_DEVICE_PATH_LENGTH (sizeof(EFI_DEVICE_PATH_PROTOCOL)) + + +#define DP_IS_END_TYPE(a) +#define DP_IS_END_SUBTYPE(a) ( ((a)->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE ) + +#define DevicePathType(a) ( ((a)->Type) & EFI_DP_TYPE_MASK ) +#define DevicePathSubType(a) ( (a)->SubType ) +#define DevicePathNodeLength(a) ( ((a)->Length[0]) | ((a)->Length[1] << 8) ) +#define NextDevicePathNode(a) ( (EFI_DEVICE_PATH_PROTOCOL *) ( ((UINT8 *) (a)) + DevicePathNodeLength(a))) +//#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE_UNPACKED ) +#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE ) +#define IsDevicePathEndSubType(a) ( (a)->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE ) +#define IsDevicePathEnd(a) ( IsDevicePathEndType(a) && IsDevicePathEndSubType(a) ) +#define IsDevicePathUnpacked(a) ( (a)->Type & EFI_DP_TYPE_UNPACKED ) + + +#define SetDevicePathNodeLength(a,l) { \ + (a)->Length[0] = (UINT8) (l); \ + (a)->Length[1] = (UINT8) ((l) >> 8); \ + } + +#define SetDevicePathEndNode(a) { \ + (a)->Type = END_DEVICE_PATH_TYPE; \ + (a)->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; \ + (a)->Length[0] = sizeof(EFI_DEVICE_PATH_PROTOCOL); \ + (a)->Length[1] = 0; \ + } + + +/* + * Hardware Device Path (UEFI 2.4 specification, version 2.4 § 9.3.2.) + */ + +#define HARDWARE_DEVICE_PATH 0x01 + +#define HW_PCI_DP 0x01 +typedef struct _PCI_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 Function; + UINT8 Device; +} PCI_DEVICE_PATH; + +#define HW_PCCARD_DP 0x02 +typedef struct _PCCARD_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 FunctionNumber ; +} PCCARD_DEVICE_PATH; + +#define HW_MEMMAP_DP 0x03 +typedef struct _MEMMAP_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 MemoryType; + EFI_PHYSICAL_ADDRESS StartingAddress; + EFI_PHYSICAL_ADDRESS EndingAddress; +} MEMMAP_DEVICE_PATH; + +#define HW_VENDOR_DP 0x04 +typedef struct _VENDOR_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; +} VENDOR_DEVICE_PATH; + +#define UNKNOWN_DEVICE_GUID \ + { 0xcf31fac5, 0xc24e, 0x11d2, {0x85, 0xf3, 0x0, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b} } + +typedef struct _UKNOWN_DEVICE_VENDOR_DP { + VENDOR_DEVICE_PATH DevicePath; + UINT8 LegacyDriveLetter; +} UNKNOWN_DEVICE_VENDOR_DEVICE_PATH; + +#define HW_CONTROLLER_DP 0x05 +typedef struct _CONTROLLER_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Controller; +} CONTROLLER_DEVICE_PATH; + + +/* + * ACPI Device Path (UEFI 2.4 specification, version 2.4 § 9.3.3 and 9.3.4.) + */ +#define ACPI_DEVICE_PATH 0x02 + +#define ACPI_DP 0x01 +typedef struct _ACPI_HID_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 HID; + UINT32 UID; +} ACPI_HID_DEVICE_PATH; + +#define EXPANDED_ACPI_DP 0x02 +typedef struct _EXPANDED_ACPI_HID_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 HID; + UINT32 UID; + UINT32 CID; + UINT8 HidStr[1]; +} EXPANDED_ACPI_HID_DEVICE_PATH; + +#define ACPI_ADR_DP 3 +typedef struct _ACPI_ADR_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header ; + UINT32 ADR ; +} ACPI_ADR_DEVICE_PATH ; + +// +// EISA ID Macro +// EISA ID Definition 32-bits +// bits[15:0] - three character compressed ASCII EISA ID. +// bits[31:16] - binary number +// Compressed ASCII is 5 bits per character 0b00001 = 'A' 0b11010 = 'Z' +// +#define PNP_EISA_ID_CONST 0x41d0 +#define EISA_ID(_Name, _Num) ((UINT32) ((_Name) | (_Num) << 16)) +#define EISA_PNP_ID(_PNPId) (EISA_ID(PNP_EISA_ID_CONST, (_PNPId))) + +#define PNP_EISA_ID_MASK 0xffff +#define EISA_ID_TO_NUM(_Id) ((_Id) >> 16) + + +/* + * Messaging Device Path (UEFI 2.4 specification, version 2.4 § 9.3.5.) + */ +#define MESSAGING_DEVICE_PATH 0x03 + +#define MSG_ATAPI_DP 0x01 +typedef struct _ATAPI_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 PrimarySecondary; + UINT8 SlaveMaster; + UINT16 Lun; +} ATAPI_DEVICE_PATH; + +#define MSG_SCSI_DP 0x02 +typedef struct _SCSI_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 Pun; + UINT16 Lun; +} SCSI_DEVICE_PATH; + +#define MSG_FIBRECHANNEL_DP 0x03 +typedef struct _FIBRECHANNEL_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Reserved; + UINT64 WWN; + UINT64 Lun; +} FIBRECHANNEL_DEVICE_PATH; + +/** + * Fibre Channel Ex SubType. + * UEFI 2.0 specification version 2.4 § 9.3.5.6. + */ +#define MSG_FIBRECHANNELEX_DP 21 +typedef struct _FIBRECHANNELEX_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header ; + UINT32 Reserved ; + UINT8 WWN[ 8 ] ; /* World Wide Name */ + UINT8 Lun[ 8 ] ; /* Logical unit, T-10 SCSI Architecture Model 4 specification */ +} FIBRECHANNELEX_DEVICE_PATH ; + +#define MSG_1394_DP 0x04 +typedef struct _F1394_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Reserved; + UINT64 Guid; +} F1394_DEVICE_PATH; + +#define MSG_USB_DP 0x05 +typedef struct _USB_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 Port; + UINT8 Endpoint; +} USB_DEVICE_PATH; + +/** + * SATA Device Path SubType. + * UEFI 2.0 specification version 2.4 § 9.3.5.6. + */ +#define MSG_SATA_DP 18 +typedef struct _SATA_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header ; + UINT16 HBAPortNumber ; + UINT16 PortMultiplierPortNumber ; + UINT16 Lun ; /* Logical Unit Number */ +} SATA_DEVICE_PATH ; + +/** + * USB WWID Device Path SubType. + * UEFI 2.0 specification version 2.4 § 9.3.5.7. + */ +#define MSG_USB_WWID_DP 16 +typedef struct _USB_WWID_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header ; + UINT16 InterfaceNumber ; + UINT16 VendorId ; + UINT16 ProductId ; + CHAR16 SerialNumber[ 1 ] ; /* UTF-16 characters of the USB serial number */ +} USB_WWID_DEVICE_PATH ; + +/** + * Device Logical Unit SubType. + * UEFI 2.0 specification version 2.4 § 9.3.5.8. + */ +#define MSG_DEVICE_LOGICAL_UNIT_DP 17 +typedef struct _DEVICE_LOGICAL_UNIT_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header ; + UINT8 Lun ; /* Logical Unit Number */ +} DEVICE_LOGICAL_UNIT_DEVICE_PATH ; + +#define MSG_USB_CLASS_DP 0x0F +typedef struct _USB_CLASS_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 VendorId; + UINT16 ProductId; + UINT8 DeviceClass; + UINT8 DeviceSubclass; + UINT8 DeviceProtocol; +} USB_CLASS_DEVICE_PATH; + +#define MSG_I2O_DP 0x06 +typedef struct _I2O_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Tid; +} I2O_DEVICE_PATH; + +#define MSG_MAC_ADDR_DP 0x0b +typedef struct _MAC_ADDR_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_MAC_ADDRESS MacAddress; + UINT8 IfType; +} MAC_ADDR_DEVICE_PATH; + +#define MSG_IPv4_DP 0x0c +typedef struct _IPv4_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_IPv4_ADDRESS LocalIpAddress; + EFI_IPv4_ADDRESS RemoteIpAddress; + UINT16 LocalPort; + UINT16 RemotePort; + UINT16 Protocol; + BOOLEAN StaticIpAddress; + /* new from UEFI version 2, code must check Length field in Header */ + EFI_IPv4_ADDRESS GatewayIpAddress ; + EFI_IPv4_ADDRESS SubnetMask ; +} IPv4_DEVICE_PATH; + +#define MSG_IPv6_DP 0x0d +typedef struct _IPv6_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_IPv6_ADDRESS LocalIpAddress; + EFI_IPv6_ADDRESS RemoteIpAddress; + UINT16 LocalPort; + UINT16 RemotePort; + UINT16 Protocol; + BOOLEAN IPAddressOrigin ; + /* new from UEFI version 2, code must check Length field in Header */ + UINT8 PrefixLength ; + EFI_IPv6_ADDRESS GatewayIpAddress ; +} IPv6_DEVICE_PATH; + + +/** + * Uniform Resource Identifiers SubType. + * UEFI 2.0 specification version 2.4C § 9.3.5.23. + */ +#define MSG_URI_DP 24 +typedef struct _URI_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + CHAR8 Uri[1]; +} URI_DEVICE_PATH; + +/** + * Device Logical Unit SubType. + * UEFI 2.0 specification version 2.4 § 9.3.5.8. + */ +#define MSG_VLAN_DP 20 +typedef struct _VLAN_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header ; + UINT16 VlanId ; +} VLAN_DEVICE_PATH; + +#define MSG_INFINIBAND_DP 0x09 +typedef struct _INFINIBAND_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 ResourceFlags; + UINT8 PortGid[16]; + UINT64 ServiceId; + UINT64 TargetPortId; + UINT64 DeviceId; +} INFINIBAND_DEVICE_PATH; + +#define MSG_UART_DP 0x0e +typedef struct _UART_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Reserved; + UINT64 BaudRate; + UINT8 DataBits; + UINT8 Parity; + UINT8 StopBits; +} UART_DEVICE_PATH; + +#define MSG_VENDOR_DP 0x0A +/* Use VENDOR_DEVICE_PATH struct */ + +#define EFI_PC_ANSI_GUID \ + { 0xe0c14753, 0xf9be, 0x11d2, {0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } +#define DEVICE_PATH_MESSAGING_PC_ANSI EFI_PC_ANSI_GUID + +#define EFI_VT_100_GUID \ + { 0xdfa66065, 0xb419, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } +#define DEVICE_PATH_MESSAGING_VT_100 EFI_VT_100_GUID + +#define EFI_VT_100_PLUS_GUID \ + { 0x7baec70b, 0x57e0, 0x4c76, {0x8e, 0x87, 0x2f, 0x9e, 0x28, 0x08, 0x83, 0x43} } +#define DEVICE_PATH_MESSAGING_VT_100_PLUS EFI_VT_100_PLUS_GUID + +#define EFI_VT_UTF8_GUID \ + { 0xad15a0d6, 0x8bec, 0x4acf, {0xa0, 0x73, 0xd0, 0x1d, 0xe7, 0x7e, 0x2d, 0x88} } +#define DEVICE_PATH_MESSAGING_VT_UTF8 EFI_VT_UTF8_GUID + + +/* + * Media Device Path (UEFI 2.4 specification, version 2.4 § 9.3.6.) + */ +#define MEDIA_DEVICE_PATH 0x04 + +#define MEDIA_HARDDRIVE_DP 0x01 +typedef struct _HARDDRIVE_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 PartitionNumber; + UINT64 PartitionStart; + UINT64 PartitionSize; + UINT8 Signature[16]; + UINT8 MBRType; + UINT8 SignatureType; +} HARDDRIVE_DEVICE_PATH; + +#define MBR_TYPE_PCAT 0x01 +#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02 + +#define SIGNATURE_TYPE_MBR 0x01 +#define SIGNATURE_TYPE_GUID 0x02 + +#define MEDIA_CDROM_DP 0x02 +typedef struct _CDROM_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 BootEntry; + UINT64 PartitionStart; + UINT64 PartitionSize; +} CDROM_DEVICE_PATH; + +#define MEDIA_VENDOR_DP 0x03 +/* Use VENDOR_DEVICE_PATH struct */ + +#define MEDIA_FILEPATH_DP 0x04 +typedef struct _FILEPATH_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + CHAR16 PathName[1]; +} FILEPATH_DEVICE_PATH; + +#define SIZE_OF_FILEPATH_DEVICE_PATH EFI_FIELD_OFFSET(FILEPATH_DEVICE_PATH,PathName) + +#define MEDIA_PROTOCOL_DP 0x05 +typedef struct _MEDIA_PROTOCOL_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Protocol; +} MEDIA_PROTOCOL_DEVICE_PATH; + +/** + * PIWG Firmware File SubType. + * UEFI 2.0 specification version 2.4 § 9.3.6.6. + */ +#define MEDIA_PIWG_FW_FILE_DP 6 +typedef struct _MEDIA_FW_VOL_FILEPATH_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header ; + EFI_GUID FvFileName ; +} MEDIA_FW_VOL_FILEPATH_DEVICE_PATH ; + +/** + * PIWG Firmware Volume Device Path SubType. + * UEFI 2.0 specification version 2.4 § 9.3.6.7. + */ +#define MEDIA_PIWG_FW_VOL_DP 7 +typedef struct _MEDIA_FW_VOL_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header ; + EFI_GUID FvName ; +} MEDIA_FW_VOL_DEVICE_PATH ; + +/** + * Media relative offset range device path. + * UEFI 2.0 specification version 2.4 § 9.3.6.8. + */ +#define MEDIA_RELATIVE_OFFSET_RANGE_DP 8 +typedef struct _MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header ; + UINT32 Reserved ; + UINT64 StartingOffset ; + UINT64 EndingOffset ; +} MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH ; + + +/* + * BIOS Boot Specification Device Path (UEFI 2.4 specification, version 2.4 § 9.3.7.) + */ +#define BBS_DEVICE_PATH 0x05 + +#define BBS_BBS_DP 0x01 +typedef struct _BBS_BBS_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 DeviceType; + UINT16 StatusFlag; + CHAR8 String[1]; +} BBS_BBS_DEVICE_PATH; + +/* DeviceType definitions - from BBS specification */ +#define BBS_TYPE_FLOPPY 0x01 +#define BBS_TYPE_HARDDRIVE 0x02 +#define BBS_TYPE_CDROM 0x03 +#define BBS_TYPE_PCMCIA 0x04 +#define BBS_TYPE_USB 0x05 +#define BBS_TYPE_EMBEDDED_NETWORK 0x06 +#define BBS_TYPE_DEV 0x80 +#define BBS_TYPE_UNKNOWN 0xFF + +typedef union { + EFI_DEVICE_PATH_PROTOCOL DevPath; + PCI_DEVICE_PATH Pci; + PCCARD_DEVICE_PATH PcCard; + MEMMAP_DEVICE_PATH MemMap; + VENDOR_DEVICE_PATH Vendor; + UNKNOWN_DEVICE_VENDOR_DEVICE_PATH UnknownVendor; + CONTROLLER_DEVICE_PATH Controller; + ACPI_HID_DEVICE_PATH Acpi; + + ATAPI_DEVICE_PATH Atapi; + SCSI_DEVICE_PATH Scsi; + FIBRECHANNEL_DEVICE_PATH FibreChannel; + + F1394_DEVICE_PATH F1394; + USB_DEVICE_PATH Usb; + USB_CLASS_DEVICE_PATH UsbClass; + I2O_DEVICE_PATH I2O; + MAC_ADDR_DEVICE_PATH MacAddr; + IPv4_DEVICE_PATH Ipv4; + IPv6_DEVICE_PATH Ipv6; + URI_DEVICE_PATH Uri; + INFINIBAND_DEVICE_PATH InfiniBand; + UART_DEVICE_PATH Uart; + + HARDDRIVE_DEVICE_PATH HardDrive; + CDROM_DEVICE_PATH CD; + + FILEPATH_DEVICE_PATH FilePath; + MEDIA_PROTOCOL_DEVICE_PATH MediaProtocol; + + BBS_BBS_DEVICE_PATH Bbs; + +} EFI_DEV_PATH; + +typedef union { + EFI_DEVICE_PATH_PROTOCOL* DevPath; + PCI_DEVICE_PATH* Pci; + PCCARD_DEVICE_PATH* PcCard; + MEMMAP_DEVICE_PATH* MemMap; + VENDOR_DEVICE_PATH* Vendor; + UNKNOWN_DEVICE_VENDOR_DEVICE_PATH* UnknownVendor; + CONTROLLER_DEVICE_PATH* Controller; + ACPI_HID_DEVICE_PATH* Acpi; + + ATAPI_DEVICE_PATH* Atapi; + SCSI_DEVICE_PATH* Scsi; + FIBRECHANNEL_DEVICE_PATH* FibreChannel; + + F1394_DEVICE_PATH* F1394; + USB_DEVICE_PATH* Usb; + USB_CLASS_DEVICE_PATH* UsbClass; + I2O_DEVICE_PATH* I2O; + MAC_ADDR_DEVICE_PATH* MacAddr; + IPv4_DEVICE_PATH* Ipv4; + IPv6_DEVICE_PATH* Ipv6; + URI_DEVICE_PATH* Uri; + INFINIBAND_DEVICE_PATH* InfiniBand; + UART_DEVICE_PATH* Uart; + + HARDDRIVE_DEVICE_PATH* HardDrive; + + FILEPATH_DEVICE_PATH* FilePath; + MEDIA_PROTOCOL_DEVICE_PATH* MediaProtocol; + + CDROM_DEVICE_PATH* CD; + BBS_BBS_DEVICE_PATH* Bbs; + +} EFI_DEV_PATH_PTR; + +#define EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID \ + { 0x8b843e20, 0x8132, 0x4852, {0x90, 0xcc, 0x55, 0x1a, 0x4e, 0x4a, 0x7f, 0x1c} } + +typedef +CHAR16* +(EFIAPI* EFI_DEVICE_PATH_TO_TEXT_NODE) ( + IN CONST EFI_DEVICE_PATH_PROTOCOL* DeviceNode, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ); + +typedef +CHAR16* +(EFIAPI* EFI_DEVICE_PATH_TO_TEXT_PATH) ( + IN CONST EFI_DEVICE_PATH_PROTOCOL* DevicePath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ); + +typedef struct _EFI_DEVICE_PATH_TO_TEXT_PROTOCOL { + EFI_DEVICE_PATH_TO_TEXT_NODE ConvertDeviceNodeToText; + EFI_DEVICE_PATH_TO_TEXT_PATH ConvertDevicePathToText; +} EFI_DEVICE_PATH_TO_TEXT_PROTOCOL; + +#define EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID \ + { 0x5c99a21, 0xc70f, 0x4ad2, {0x8a, 0x5f, 0x35, 0xdf, 0x33, 0x43, 0xf5, 0x1e} } + +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI* EFI_DEVICE_PATH_FROM_TEXT_NODE) ( + IN CONST CHAR16* TextDeviceNode + ); + +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI* EFI_DEVICE_PATH_FROM_TEXT_PATH) ( + IN CONST CHAR16* TextDevicePath + ); + +typedef struct { + EFI_DEVICE_PATH_FROM_TEXT_NODE ConvertTextToDeviceNode; + EFI_DEVICE_PATH_FROM_TEXT_PATH ConvertTextToDevicePath; +} EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL; + +#define EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID \ + { 0x379be4e, 0xd706, 0x437d, {0xb0, 0x37, 0xed, 0xb8, 0x2f, 0xb7, 0x72, 0xa4} } + +typedef +UINTN +(EFIAPI* EFI_DEVICE_PATH_UTILS_GET_DEVICE_PATH_SIZE) ( + IN CONST EFI_DEVICE_PATH_PROTOCOL* DevicePath + ); + +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI* EFI_DEVICE_PATH_UTILS_DUP_DEVICE_PATH) ( + IN CONST EFI_DEVICE_PATH_PROTOCOL* DevicePath + ); + +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI* EFI_DEVICE_PATH_UTILS_APPEND_PATH) ( + IN CONST EFI_DEVICE_PATH_PROTOCOL* Src1, + IN CONST EFI_DEVICE_PATH_PROTOCOL* Src2 + ); + +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI* EFI_DEVICE_PATH_UTILS_APPEND_NODE) ( + IN CONST EFI_DEVICE_PATH_PROTOCOL* DevicePath, + IN CONST EFI_DEVICE_PATH_PROTOCOL* DeviceNode +); + +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI* EFI_DEVICE_PATH_UTILS_APPEND_INSTANCE) ( + IN CONST EFI_DEVICE_PATH_PROTOCOL* DevicePath, + IN CONST EFI_DEVICE_PATH_PROTOCOL* DevicePathInstance +); + +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI* EFI_DEVICE_PATH_UTILS_GET_NEXT_INSTANCE) ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathInstance, + OUT UINTN* DevicePathInstanceSize OPTIONAL +); + +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI* EFI_DEVICE_PATH_UTILS_CREATE_NODE) ( + IN UINT8 NodeType, + IN UINT8 NodeSubType, + IN UINT16 NodeLength + ); + +typedef +BOOLEAN +(EFIAPI* EFI_DEVICE_PATH_UTILS_IS_MULTI_INSTANCE) ( + IN CONST EFI_DEVICE_PATH_PROTOCOL* DevicePath + ); + +typedef struct _EFI_DEVICE_PATH_UTILITIES_PROTOCOL { + EFI_DEVICE_PATH_UTILS_GET_DEVICE_PATH_SIZE GetDevicePathSize; + EFI_DEVICE_PATH_UTILS_DUP_DEVICE_PATH DuplicateDevicePath; + EFI_DEVICE_PATH_UTILS_APPEND_PATH AppendDevicePath; + EFI_DEVICE_PATH_UTILS_APPEND_NODE AppendDeviceNode; + EFI_DEVICE_PATH_UTILS_APPEND_INSTANCE AppendDevicePathInstance; + EFI_DEVICE_PATH_UTILS_GET_NEXT_INSTANCE GetNextDevicePathInstance; + EFI_DEVICE_PATH_UTILS_IS_MULTI_INSTANCE IsDevicePathMultiInstance; + EFI_DEVICE_PATH_UTILS_CREATE_NODE CreateDeviceNode; +} EFI_DEVICE_PATH_UTILITIES_PROTOCOL; + +#endif diff --git a/code/boot/include/efierr.h b/code/boot/include/efierr.h new file mode 100644 index 0000000..35b3950 --- /dev/null +++ b/code/boot/include/efierr.h @@ -0,0 +1,73 @@ +#ifndef _EFI_ERR_H +#define _EFI_ERR_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efierr.h + +Abstract: + + EFI error codes + + + + +Revision History + +--*/ + + +#define EFIWARN(a) (a) +#define EFI_ERROR(a) (((INTN) a) < 0) + + +#define EFI_SUCCESS 0 +#define EFI_LOAD_ERROR EFIERR(1) +#define EFI_INVALID_PARAMETER EFIERR(2) +#define EFI_UNSUPPORTED EFIERR(3) +#define EFI_BAD_BUFFER_SIZE EFIERR(4) +#define EFI_BUFFER_TOO_SMALL EFIERR(5) +#define EFI_NOT_READY EFIERR(6) +#define EFI_DEVICE_ERROR EFIERR(7) +#define EFI_WRITE_PROTECTED EFIERR(8) +#define EFI_OUT_OF_RESOURCES EFIERR(9) +#define EFI_VOLUME_CORRUPTED EFIERR(10) +#define EFI_VOLUME_FULL EFIERR(11) +#define EFI_NO_MEDIA EFIERR(12) +#define EFI_MEDIA_CHANGED EFIERR(13) +#define EFI_NOT_FOUND EFIERR(14) +#define EFI_ACCESS_DENIED EFIERR(15) +#define EFI_NO_RESPONSE EFIERR(16) +#define EFI_NO_MAPPING EFIERR(17) +#define EFI_TIMEOUT EFIERR(18) +#define EFI_NOT_STARTED EFIERR(19) +#define EFI_ALREADY_STARTED EFIERR(20) +#define EFI_ABORTED EFIERR(21) +#define EFI_ICMP_ERROR EFIERR(22) +#define EFI_TFTP_ERROR EFIERR(23) +#define EFI_PROTOCOL_ERROR EFIERR(24) +#define EFI_INCOMPATIBLE_VERSION EFIERR(25) +#define EFI_SECURITY_VIOLATION EFIERR(26) +#define EFI_CRC_ERROR EFIERR(27) +#define EFI_END_OF_MEDIA EFIERR(28) +#define EFI_END_OF_FILE EFIERR(31) +#define EFI_INVALID_LANGUAGE EFIERR(32) +#define EFI_COMPROMISED_DATA EFIERR(33) +#define EFI_IP_ADDRESS_CONFLICT EFIERR(34) +#define EFI_HTTP_ERROR EFIERR(35) + +#define EFI_WARN_UNKOWN_GLYPH EFIWARN(1) +#define EFI_WARN_UNKNOWN_GLYPH EFIWARN(1) +#define EFI_WARN_DELETE_FAILURE EFIWARN(2) +#define EFI_WARN_WRITE_FAILURE EFIWARN(3) +#define EFI_WARN_BUFFER_TOO_SMALL EFIWARN(4) +#define EFI_WARN_STALE_DATA EFIWARN(5) +#define EFI_WARN_FILE_SYSTEM EFIWARN(6) +#define EFI_WARN_RESET_REQUIRED EFIWARN(7) + +#endif + diff --git a/code/boot/include/efifs.h b/code/boot/include/efifs.h new file mode 100644 index 0000000..48e6cd0 --- /dev/null +++ b/code/boot/include/efifs.h @@ -0,0 +1,116 @@ +#ifndef _EFI_FS_H +#define _EFI_FS_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efifs.h + +Abstract: + + EFI File System structures + + + +Revision History + +--*/ + + +// +// EFI Partition header (normaly starts in LBA 1) +// + +#define EFI_PARTITION_SIGNATURE 0x5053595320494249 +#define EFI_PARTITION_REVISION 0x00010001 +#define MIN_EFI_PARTITION_BLOCK_SIZE 512 +#define EFI_PARTITION_LBA 1 + +typedef struct _EFI_PARTITION_HEADER { + EFI_TABLE_HEADER Hdr; + UINT32 DirectoryAllocationNumber; + UINT32 BlockSize; + EFI_LBA FirstUsableLba; + EFI_LBA LastUsableLba; + EFI_LBA UnusableSpace; + EFI_LBA FreeSpace; + EFI_LBA RootFile; + EFI_LBA SecutiryFile; +} EFI_PARTITION_HEADER; + + +// +// File header +// + +#define EFI_FILE_HEADER_SIGNATURE 0x454c494620494249 +#define EFI_FILE_HEADER_REVISION 0x00010000 +#define EFI_FILE_STRING_SIZE 260 + +typedef struct _EFI_FILE_HEADER { + EFI_TABLE_HEADER Hdr; + UINT32 Class; + UINT32 LBALOffset; + EFI_LBA Parent; + UINT64 FileSize; + UINT64 FileAttributes; + EFI_TIME FileCreateTime; + EFI_TIME FileModificationTime; + EFI_GUID VendorGuid; + CHAR16 FileString[EFI_FILE_STRING_SIZE]; +} EFI_FILE_HEADER; + + +// +// Return the file's first LBAL which is in the same +// logical block as the file header +// + +#define EFI_FILE_LBAL(a) ((EFI_LBAL *) (((CHAR8 *) (a)) + (a)->LBALOffset)) + +#define EFI_FILE_CLASS_FREE_SPACE 1 +#define EFI_FILE_CLASS_EMPTY 2 +#define EFI_FILE_CLASS_NORMAL 3 + + +// +// Logical Block Address List - the fundemental block +// description structure +// + +#define EFI_LBAL_SIGNATURE 0x4c41424c20494249 +#define EFI_LBAL_REVISION 0x00010000 + +typedef struct _EFI_LBAL { + EFI_TABLE_HEADER Hdr; + UINT32 Class; + EFI_LBA Parent; + EFI_LBA Next; + UINT32 ArraySize; + UINT32 ArrayCount; +} EFI_LBAL; + +// Array size +#define EFI_LBAL_ARRAY_SIZE(lbal,offs,blks) \ + (((blks) - (offs) - (lbal)->Hdr.HeaderSize) / sizeof(EFI_RL)) + +// +// Logical Block run-length +// + +typedef struct { + EFI_LBA Start; + UINT64 Length; +} EFI_RL; + +// +// Return the run-length structure from an LBAL header +// + +#define EFI_LBAL_RL(a) ((EFI_RL*) (((CHAR8 *) (a)) + (a)->Hdr.HeaderSize)) + +#endif + diff --git a/code/boot/include/efigpt.h b/code/boot/include/efigpt.h new file mode 100644 index 0000000..31e13e0 --- /dev/null +++ b/code/boot/include/efigpt.h @@ -0,0 +1,68 @@ +#ifndef _EFI_GPT_H +#define _EFI_GPT_H +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + EfiGpt.h + +Abstract: + Include file for EFI partitioning scheme + + + +Revision History + +--*/ + +#define PRIMARY_PART_HEADER_LBA 1 + +typedef struct { + EFI_TABLE_HEADER Header; + EFI_LBA MyLBA; + EFI_LBA AlternateLBA; + EFI_LBA FirstUsableLBA; + EFI_LBA LastUsableLBA; + EFI_GUID DiskGUID; + EFI_LBA PartitionEntryLBA; + UINT32 NumberOfPartitionEntries; + UINT32 SizeOfPartitionEntry; + UINT32 PartitionEntryArrayCRC32; +} EFI_PARTITION_TABLE_HEADER; + +#define EFI_PTAB_HEADER_ID "EFI PART" + +typedef struct { + EFI_GUID PartitionTypeGUID; + EFI_GUID UniquePartitionGUID; + EFI_LBA StartingLBA; + EFI_LBA EndingLBA; + UINT64 Attributes; + CHAR16 PartitionName[36]; +} EFI_PARTITION_ENTRY; + +// +// EFI Partition Attributes +// +#define EFI_PART_USED_BY_EFI 0x0000000000000001 +#define EFI_PART_REQUIRED_TO_FUNCTION 0x0000000000000002 +#define EFI_PART_USED_BY_OS 0x0000000000000004 +#define EFI_PART_REQUIRED_BY_OS 0x0000000000000008 +#define EFI_PART_BACKUP_REQUIRED 0x0000000000000010 +#define EFI_PART_USER_DATA 0x0000000000000020 +#define EFI_PART_CRITICAL_USER_DATA 0x0000000000000040 +#define EFI_PART_REDUNDANT_PARTITION 0x0000000000000080 + +#define EFI_PART_TYPE_UNUSED_GUID \ + { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} } + +#define EFI_PART_TYPE_EFI_SYSTEM_PART_GUID \ + { 0xc12a7328, 0xf81f, 0x11d2, {0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b} } + +#define EFI_PART_TYPE_LEGACY_MBR_GUID \ + { 0x024dee41, 0x33e7, 0x11d3, {0x9d, 0x69, 0x00, 0x08, 0xc7, 0x81, 0xf3, 0x9f} } + +#endif + diff --git a/code/boot/include/efiip.h b/code/boot/include/efiip.h new file mode 100644 index 0000000..f6b89b0 --- /dev/null +++ b/code/boot/include/efiip.h @@ -0,0 +1,459 @@ +#ifndef _EFI_IP_H +#define _EFI_IP_H + +/*++ +Copyright (c) 2013 Intel Corporation + +--*/ + +#define EFI_IP4_SERVICE_BINDING_PROTOCOL \ + {0xc51711e7,0xb4bf,0x404a,{0xbf,0xb8,0x0a,0x04, 0x8e,0xf1,0xff,0xe4}} + +#define EFI_IP4_PROTOCOL \ + {0x41d94cd2,0x35b6,0x455a,{0x82,0x58,0xd4,0xe5,0x13,0x34,0xaa,0xdd}} + +#define EFI_IP6_SERVICE_BINDING_PROTOCOL \ + {0xec835dd3,0xfe0f,0x617b,{0xa6,0x21,0xb3,0x50,0xc3,0xe1,0x33,0x88}} + +#define EFI_IP6_PROTOCOL \ + {0x2c8759d5,0x5c2d,0x66ef,{0x92,0x5f,0xb6,0x6c,0x10,0x19,0x57,0xe2}} + +INTERFACE_DECL(_EFI_IP4); +INTERFACE_DECL(_EFI_IP6); + +typedef struct { + EFI_HANDLE InstanceHandle; + EFI_IPv4_ADDRESS Ip4Address; + EFI_IPv4_ADDRESS SubnetMask; +} EFI_IP4_ADDRESS_PAIR; + +typedef struct { + EFI_HANDLE DriverHandle; + UINT32 AddressCount; + EFI_IP4_ADDRESS_PAIR AddressPairs[1]; +} EFI_IP4_VARIABLE_DATA; + +typedef struct { + UINT8 DefaultProtocol; + BOOLEAN AcceptAnyProtocol; + BOOLEAN AcceptIcmpErrors; + BOOLEAN AcceptBroadcast; + BOOLEAN AcceptPromiscuous; + BOOLEAN UseDefaultAddress; + EFI_IPv4_ADDRESS StationAddress; + EFI_IPv4_ADDRESS SubnetMask; + UINT8 TypeOfService; + UINT8 TimeToLive; + BOOLEAN DoNotFragment; + BOOLEAN RawData; + UINT32 ReceiveTimeout; + UINT32 TransmitTimeout; +} EFI_IP4_CONFIG_DATA; + +typedef struct { + EFI_IPv4_ADDRESS SubnetAddress; + EFI_IPv4_ADDRESS SubnetMask; + EFI_IPv4_ADDRESS GatewayAddress; +} EFI_IP4_ROUTE_TABLE; + +typedef struct { + UINT8 Type; + UINT8 Code; +} EFI_IP4_ICMP_TYPE; + +typedef struct { + BOOLEAN IsStarted; + UINT32 MaxPacketSize; + EFI_IP4_CONFIG_DATA ConfigData; + BOOLEAN IsConfigured; + UINT32 GroupCount; + EFI_IPv4_ADDRESS* GroupTable; + UINT32 RouteCount; + EFI_IP4_ROUTE_TABLE* RouteTable; + UINT32 IcmpTypeCount; + EFI_IP4_ICMP_TYPE* IcmpTypeList; +} EFI_IP4_MODE_DATA; + +typedef +EFI_STATUS +(EFIAPI* EFI_IP4_GET_MODE_DATA) ( + IN struct _EFI_IP4* This, + OUT EFI_IP4_MODE_DATA* Ip4ModeData OPTIONAL, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA* MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE* SnpModeData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_IP4_CONFIGURE) ( + IN struct _EFI_IP4* This, + IN EFI_IP4_CONFIG_DATA* IpConfigData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_IP4_GROUPS) ( + IN struct _EFI_IP4* This, + IN BOOLEAN JoinFlag, + IN EFI_IPv4_ADDRESS* GroupAddress OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_IP4_ROUTES) ( + IN struct _EFI_IP4* This, + IN BOOLEAN DeleteRoute, + IN EFI_IPv4_ADDRESS* SubnetAddress, + IN EFI_IPv4_ADDRESS* SubnetMask, + IN EFI_IPv4_ADDRESS* GatewayAddress + ); + +#pragma pack(1) +typedef struct { + UINT8 HeaderLength:4; + UINT8 Version:4; + UINT8 TypeOfService; + UINT16 TotalLength; + UINT16 Identification; + UINT16 Fragmentation; + UINT8 TimeToLive; + UINT8 Protocol; + UINT16 Checksum; + EFI_IPv4_ADDRESS SourceAddress; + EFI_IPv4_ADDRESS DestinationAddress; +} EFI_IP4_HEADER; +#pragma pack() + +typedef struct { + UINT32 FragmentLength; + VOID* FragmentBuffer; +} EFI_IP4_FRAGMENT_DATA; + +typedef struct { + EFI_TIME TimeStamp; + EFI_EVENT RecycleSignal; + UINT32 HeaderLength; + EFI_IP4_HEADER* Header; + UINT32 OptionsLength; + VOID* Options; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_IP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_IP4_RECEIVE_DATA; + +typedef struct { + EFI_IPv4_ADDRESS SourceAddress; + EFI_IPv4_ADDRESS GatewayAddress; + UINT8 Protocol; + UINT8 TypeOfService; + UINT8 TimeToLive; + BOOLEAN DoNotFragment; +} EFI_IP4_OVERRIDE_DATA; + +typedef struct { + EFI_IPv4_ADDRESS DestinationAddress; + EFI_IP4_OVERRIDE_DATA* OverrideData; + UINT32 OptionsLength; + VOID* OptionsBuffer; + UINT32 TotalDataLength; + UINT32 FragmentCount; + EFI_IP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_IP4_TRANSMIT_DATA; + +typedef struct { + EFI_EVENT Event; + EFI_STATUS Status; + union { + EFI_IP4_RECEIVE_DATA* RxData; + EFI_IP4_TRANSMIT_DATA* TxData; + } Packet; +} EFI_IP4_COMPLETION_TOKEN; + +typedef +EFI_STATUS +(EFIAPI* EFI_IP4_TRANSMIT) ( + IN struct _EFI_IP4* This, + IN EFI_IP4_COMPLETION_TOKEN* Token + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_IP4_RECEIVE) ( + IN struct _EFI_IP4* This, + IN EFI_IP4_COMPLETION_TOKEN* Token + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_IP4_CANCEL)( + IN struct _EFI_IP4* This, + IN EFI_IP4_COMPLETION_TOKEN* Token OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_IP4_POLL) ( + IN struct _EFI_IP4* This + ); + +typedef struct _EFI_IP4 { + EFI_IP4_GET_MODE_DATA GetModeData; + EFI_IP4_CONFIGURE Configure; + EFI_IP4_GROUPS Groups; + EFI_IP4_ROUTES Routes; + EFI_IP4_TRANSMIT Transmit; + EFI_IP4_RECEIVE Receive; + EFI_IP4_CANCEL Cancel; + EFI_IP4_POLL Poll; +} EFI_IP4; + +typedef struct { + UINT8 DefaultProtocol; + BOOLEAN AcceptAnyProtocol; + BOOLEAN AcceptIcmpErrors; + BOOLEAN AcceptPromiscuous; + EFI_IPv6_ADDRESS DestinationAddress; + EFI_IPv6_ADDRESS StationAddress; + UINT8 TrafficClass; + UINT8 HopLimit; + UINT32 FlowLabel; + UINT32 ReceiveTimeout; + UINT32 TransmitTimeout; +} EFI_IP6_CONFIG_DATA; + +typedef struct { + EFI_IPv6_ADDRESS Address; + UINT8 PrefixLength; +} EFI_IP6_ADDRESS_INFO; + +typedef struct { + EFI_IPv6_ADDRESS Gateway; + EFI_IPv6_ADDRESS Destination; + UINT8 PrefixLength; +} EFI_IP6_ROUTE_TABLE; + +typedef enum { + EfiNeighborInComplete, + EfiNeighborReachable, + EfiNeighborStale, + EfiNeighborDelay, + EfiNeighborProbe +} EFI_IP6_NEIGHBOR_STATE; + +typedef struct { + EFI_IPv6_ADDRESS Neighbor; + EFI_MAC_ADDRESS LinkAddress; + EFI_IP6_NEIGHBOR_STATE State; +} EFI_IP6_NEIGHBOR_CACHE; + +typedef struct { + UINT8 Type; + UINT8 Code; +} EFI_IP6_ICMP_TYPE; + +//*********************************************************** +// ICMPv6 type definitions for error messages +//*********************************************************** +#define ICMP_V6_DEST_UNREACHABLE 0x1 +#define ICMP_V6_PACKET_TOO_BIG 0x2 +#define ICMP_V6_TIME_EXCEEDED 0x3 +#define ICMP_V6_PARAMETER_PROBLEM 0x4 + +//*********************************************************** +// ICMPv6 type definition for informational messages +//*********************************************************** +#define ICMP_V6_ECHO_REQUEST 0x80 +#define ICMP_V6_ECHO_REPLY 0x81 +#define ICMP_V6_LISTENER_QUERY 0x82 +#define ICMP_V6_LISTENER_REPORT 0x83 +#define ICMP_V6_LISTENER_DONE 0x84 +#define ICMP_V6_ROUTER_SOLICIT 0x85 +#define ICMP_V6_ROUTER_ADVERTISE 0x86 +#define ICMP_V6_NEIGHBOR_SOLICIT 0x87 +#define ICMP_V6_NEIGHBOR_ADVERTISE 0x88 +#define ICMP_V6_REDIRECT 0x89 +#define ICMP_V6_LISTENER_REPORT_2 0x8F + +//*********************************************************** +// ICMPv6 code definitions for ICMP_V6_DEST_UNREACHABLE +//*********************************************************** +#define ICMP_V6_NO_ROUTE_TO_DEST 0x0 +#define ICMP_V6_COMM_PROHIBITED 0x1 +#define ICMP_V6_BEYOND_SCOPE 0x2 +#define ICMP_V6_ADDR_UNREACHABLE 0x3 +#define ICMP_V6_PORT_UNREACHABLE 0x4 +#define ICMP_V6_SOURCE_ADDR_FAILED 0x5 +#define ICMP_V6_ROUTE_REJECTED 0x6 + +//*********************************************************** +// ICMPv6 code definitions for ICMP_V6_TIME_EXCEEDED +//*********************************************************** +#define ICMP_V6_TIMEOUT_HOP_LIMIT 0x0 +#define ICMP_V6_TIMEOUT_REASSEMBLE 0x1 + +//*********************************************************** +// ICMPv6 code definitions for ICMP_V6_PARAMETER_PROBLEM +//*********************************************************** +#define ICMP_V6_ERRONEOUS_HEADER 0x0 +#define ICMP_V6_UNRECOGNIZE_NEXT_HDR 0x1 +#define ICMP_V6_UNRECOGNIZE_OPTION 0x2 + +typedef struct { + BOOLEAN IsStarted; + UINT32 MaxPacketSize; + EFI_IP6_CONFIG_DATA ConfigData; + BOOLEAN IsConfigured; + UINT32 AddressCount; + EFI_IP6_ADDRESS_INFO* AddressList; + UINT32 GroupCount; + EFI_IPv6_ADDRESS* GroupTable; + UINT32 RouteCount; + EFI_IP6_ROUTE_TABLE* RouteTable; + UINT32 NeighborCount; + EFI_IP6_NEIGHBOR_CACHE* NeighborCache; + UINT32 PrefixCount; + EFI_IP6_ADDRESS_INFO* PrefixTable; + UINT32 IcmpTypeCount; + EFI_IP6_ICMP_TYPE* IcmpTypeList; +} EFI_IP6_MODE_DATA; + +typedef +EFI_STATUS +(EFIAPI* EFI_IP6_GET_MODE_DATA) ( + IN struct _EFI_IP6* This, + OUT EFI_IP6_MODE_DATA* Ip6ModeData OPTIONAL, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA* MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE* SnpModeData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_IP6_CONFIGURE) ( + IN struct _EFI_IP6* This, + IN EFI_IP6_CONFIG_DATA* Ip6ConfigData OPTIONAL + ); +typedef +EFI_STATUS +(EFIAPI* EFI_IP6_GROUPS) ( + IN struct _EFI_IP6* This, + IN BOOLEAN JoinFlag, + IN EFI_IPv6_ADDRESS* GroupAddress OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_IP6_ROUTES) ( + IN struct _EFI_IP6* This, + IN BOOLEAN DeleteRoute, + IN EFI_IPv6_ADDRESS* Destination OPTIONAL, + IN UINT8 PrefixLength, + IN EFI_IPv6_ADDRESS* GatewayAddress OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_IP6_NEIGHBORS) ( + IN struct _EFI_IP6* This, + IN BOOLEAN DeleteFlag, + IN EFI_IPv6_ADDRESS* TargetIp6Address, + IN EFI_MAC_ADDRESS* TargetLinkAddress OPTIONAL, + IN UINT32 Timeout, + IN BOOLEAN Override + ); + +typedef struct _EFI_IP6_FRAGMENT_DATA { + UINT32 FragmentLength; + VOID* FragmentBuffer; +} EFI_IP6_FRAGMENT_DATA; + +typedef struct _EFI_IP6_OVERRIDE_DATA { + UINT8 Protocol; + UINT8 HopLimit; + UINT32 FlowLabel; +} EFI_IP6_OVERRIDE_DATA; + +typedef struct _EFI_IP6_TRANSMIT_DATA { + EFI_IPv6_ADDRESS DestinationAddress; + EFI_IP6_OVERRIDE_DATA* OverrideData; + UINT32 ExtHdrsLength; + VOID* ExtHdrs; + UINT8 NextHeader; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_IP6_FRAGMENT_DATA FragmentTable[1]; +} EFI_IP6_TRANSMIT_DATA; + +#pragma pack(1) +typedef struct _EFI_IP6_HEADER { + UINT8 TrafficClassH:4; + UINT8 Version:4; + UINT8 FlowLabelH:4; + UINT8 TrafficClassL:4; + UINT16 FlowLabelL; + UINT16 PayloadLength; + UINT8 NextHeader; + UINT8 HopLimit; + EFI_IPv6_ADDRESS SourceAddress; + EFI_IPv6_ADDRESS DestinationAddress; +} EFI_IP6_HEADER; +#pragma pack() + +typedef struct _EFI_IP6_RECEIVE_DATA { + EFI_TIME TimeStamp; + EFI_EVENT RecycleSignal; + UINT32 HeaderLength; + EFI_IP6_HEADER* Header; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_IP6_FRAGMENT_DATA FragmentTable[1]; +} EFI_IP6_RECEIVE_DATA; + +typedef struct { + EFI_EVENT Event; + EFI_STATUS Status; + union { + EFI_IP6_RECEIVE_DATA* RxData; + EFI_IP6_TRANSMIT_DATA* TxData; + } Packet; +} EFI_IP6_COMPLETION_TOKEN; + +typedef +EFI_STATUS +(EFIAPI* EFI_IP6_TRANSMIT) ( + IN struct _EFI_IP6* This, + IN EFI_IP6_COMPLETION_TOKEN* Token + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_IP6_RECEIVE) ( + IN struct _EFI_IP6* This, + IN EFI_IP6_COMPLETION_TOKEN* Token + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_IP6_CANCEL)( + IN struct _EFI_IP6* This, + IN EFI_IP6_COMPLETION_TOKEN* Token OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_IP6_POLL) ( + IN struct _EFI_IP6* This + ); + +typedef struct _EFI_IP6 { + EFI_IP6_GET_MODE_DATA GetModeData; + EFI_IP6_CONFIGURE Configure; + EFI_IP6_GROUPS Groups; + EFI_IP6_ROUTES Routes; + EFI_IP6_NEIGHBORS Neighbors; + EFI_IP6_TRANSMIT Transmit; + EFI_IP6_RECEIVE Receive; + EFI_IP6_CANCEL Cancel; + EFI_IP6_POLL Poll; +} EFI_IP6; + +#endif /* _EFI_IP_H */ diff --git a/code/boot/include/efilib.h b/code/boot/include/efilib.h new file mode 100644 index 0000000..2440a64 --- /dev/null +++ b/code/boot/include/efilib.h @@ -0,0 +1,1106 @@ +#ifndef _EFILIB_INCLUDE_ +#define _EFILIB_INCLUDE_ + +/*++ + +Copyright (c) 2000 Intel Corporation + +Module Name: + + efilib.h + +Abstract: + + EFI library functions + + + +Revision History + +--*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "efidebug.h" +#include "efipart.h" +#if defined(_M_X64) || defined(__x86_64__) || defined(__amd64__) +#include "x86_64/efilibplat.h" +#elif defined(_M_IX86) || defined(__i386__) +#include "ia32/efilibplat.h" +#elif defined(_M_IA64) || defined(__ia64__) +#include "ia64/efilibplat.h" +#elif defined (_M_ARM64) || defined(__aarch64__) +#include "aarch64/efilibplat.h" +#elif defined (_M_ARM) || defined(__arm__) +#include "arm/efilibplat.h" +#elif defined (_M_MIPS64) || defined(__mips64__) || defined(__mips64) +#include "mips64el/efilibplat.h" +#elif defined (__riscv) && __riscv_xlen == 64 +#include "riscv64/efilibplat.h" +#elif defined (__loongarch64) +#include "loongarch64/efilibplat.h" +#endif +#include "efilink.h" +#include "efirtlib.h" +#include "efistdarg.h" +#include "pci22.h" +#include "libsmbios.h" + +// +// Public read-only data in the EFI library +// + +extern EFI_SYSTEM_TABLE* ST; +#define gST ST +extern EFI_BOOT_SERVICES* BS; +#define gBS BS +extern EFI_RUNTIME_SERVICES* RT; +#define gRT RT + +extern EFI_GUID gEfiDevicePathProtocolGuid; +#define DevicePathProtocol gEfiDevicePathProtocolGuid +extern EFI_GUID gEfiDevicePathToTextProtocolGuid; +#define DevicePathToTextProtocol gEfiDevicePathToTextProtocolGuid +extern EFI_GUID gEfiDevicePathFromTextProtocolGuid; +#define DevicePathFromTextProtocol gEfiDevicePathFromTextProtocolGuid +extern EFI_GUID gEfiDevicePathUtilitiesProtocolGuid; +#define DevicePathUtilitiesProtocol gEfiDevicePathUtilitiesProtocolGuid +extern EFI_GUID gEfiLoadedImageProtocolGuid; +#define LoadedImageProtocol gEfiLoadedImageProtocolGuid +extern EFI_GUID gEfiSimpleTextInProtocolGuid; +#define TextInProtocol gEfiSimpleTextInProtocolGuid +extern EFI_GUID gEfiSimpleTextOutProtocolGuid; +#define TextOutProtocol gEfiSimpleTextOutProtocolGuid +extern EFI_GUID gEfiGraphicsOutputProtocolGuid; +#define GraphicsOutputProtocol gEfiGraphicsOutputProtocolGuid +extern EFI_GUID gEfiEdidDiscoveredProtocolGuid; +#define EdidDiscoveredProtocol gEfiEdidDiscoveredProtocolGuid +extern EFI_GUID gEfiEdidActiveProtocolGuid; +#define EdidActiveProtocol gEfiEdidActiveProtocolGuid +extern EFI_GUID gEfiEdidOverrideProtocolGuid; +#define EdidOverrideProtocol gEfiEdidOverrideProtocolGuid +extern EFI_GUID gEfiBlockIoProtocolGuid; +#define BlockIoProtocol gEfiBlockIoProtocolGuid +extern EFI_GUID gEfiBlockIo2ProtocolGuid; +#define BlockIo2Protocol gEfiBlockIo2ProtocolGuid +extern EFI_GUID gEfiDiskIoProtocolGuid; +#define DiskIoProtocol gEfiDiskIoProtocolGuid +extern EFI_GUID gEfiDiskIo2ProtocolGuid; +#define DiskIo2Protocol gEfiDiskIo2ProtocolGuid +extern EFI_GUID gEfiSimpleFileSystemProtocolGuid; +#define FileSystemProtocol gEfiSimpleFileSystemProtocolGuid +extern EFI_GUID gEfiLoadFileProtocolGuid; +#define LoadFileProtocol gEfiLoadFileProtocolGuid +extern EFI_GUID gEfiDeviceIoProtocolGuid; +#define DeviceIoProtocol gEfiDeviceIoProtocolGuid +extern EFI_GUID VariableStoreProtocol; +extern EFI_GUID LegacyBootProtocol; +extern EFI_GUID gEfiUnicodeCollationProtocolGuid; +#define UnicodeCollationProtocol gEfiUnicodeCollationProtocolGuid +extern EFI_GUID gEfiSerialIoProtocolGuid; +#define SerialIoProtocol gEfiSerialIoProtocolGuid +extern EFI_GUID VgaClassProtocol; +extern EFI_GUID TextOutSpliterProtocol; +extern EFI_GUID ErrorOutSpliterProtocol; +extern EFI_GUID TextInSpliterProtocol; +extern EFI_GUID gEfiSimpleNetworkProtocolGuid; +#define SimpleNetworkProtocol gEfiSimpleNetworkProtocolGuid +extern EFI_GUID gEfiPxeBaseCodeProtocolGuid; +#define PxeBaseCodeProtocol gEfiPxeBaseCodeProtocolGuid +extern EFI_GUID gEfiPxeBaseCodeCallbackProtocolGuid; +#define PxeCallbackProtocol gEfiPxeBaseCodeCallbackProtocolGuid +extern EFI_GUID gEfiNetworkInterfaceIdentifierProtocolGuid; +#define NetworkInterfaceIdentifierProtocol gEfiNetworkInterfaceIdentifierProtocolGuid +extern EFI_GUID gEFiUiInterfaceProtocolGuid; +#define UiProtocol gEFiUiInterfaceProtocolGuid +extern EFI_GUID InternalShellProtocol; +extern EFI_GUID gEfiPciIoProtocolGuid; +#define PciIoProtocol gEfiPciIoProtocolGuid +extern EFI_GUID gEfiPciRootBridgeIoProtocolGuid; +extern EFI_GUID gEfiDriverBindingProtocolGuid; +#define DriverBindingProtocol gEfiDriverBindingProtocolGuid +extern EFI_GUID gEfiComponentNameProtocolGuid; +#define ComponentNameProtocol gEfiComponentNameProtocolGuid +extern EFI_GUID gEfiComponentName2ProtocolGuid; +#define ComponentName2Protocol gEfiComponentName2ProtocolGuid +extern EFI_GUID gEfiHashProtocolGuid; +#define HashProtocol gEfiHashProtocolGuid +extern EFI_GUID gEfiPlatformDriverOverrideProtocolGuid; +#define PlatformDriverOverrideProtocol gEfiPlatformDriverOverrideProtocolGuid +extern EFI_GUID gEfiBusSpecificDriverOverrideProtocolGuid; +#define BusSpecificDriverOverrideProtocol gEfiBusSpecificDriverOverrideProtocolGuid +extern EFI_GUID gEfiDriverFamilyOverrideProtocolGuid; +#define DriverFamilyOverrideProtocol gEfiDriverFamilyOverrideProtocolGuid +extern EFI_GUID gEfiEbcProtocolGuid; + +extern EFI_GUID gEfiGlobalVariableGuid; +#define EfiGlobalVariable gEfiGlobalVariableGuid +extern EFI_GUID gEfiFileInfoGuid; +#define GenericFileInfo gEfiFileInfoGuid +extern EFI_GUID gEfiFileSystemInfoGuid; +#define FileSystemInfo gEfiFileSystemInfoGuid +extern EFI_GUID gEfiFileSystemVolumeLabelInfoIdGuid; +#define FileSystemVolumeLabelInfo gEfiFileSystemVolumeLabelInfoIdGuid +extern EFI_GUID gEfiPcAnsiGuid; +#define PcAnsiProtocol gEfiPcAnsiGuid +extern EFI_GUID gEfiVT100Guid; +#define Vt100Protocol gEfiVT100Guid +extern EFI_GUID gEfiVT100PlusGuid; +extern EFI_GUID gEfiVTUTF8Guid; + +extern EFI_GUID NullGuid; +extern EFI_GUID UnknownDevice; + +extern EFI_GUID EfiPartTypeSystemPartitionGuid; +extern EFI_GUID EfiPartTypeLegacyMbrGuid; + +extern EFI_GUID MpsTableGuid; +extern EFI_GUID AcpiTableGuid; +extern EFI_GUID gEfiSmbiosTableGuid; +#define SMBIOSTableGuid gEfiSmbiosTableGuid +extern EFI_GUID gEfiSmbios3TableGuid; +#define SMBIOS3TableGuid gEfiSmbios3TableGuid +extern EFI_GUID SalSystemTableGuid; +extern EFI_GUID EfiDtbTableGuid; + +extern EFI_GUID SimplePointerProtocol; +extern EFI_GUID AbsolutePointerProtocol; + +extern EFI_GUID gEfiDebugImageInfoTableGuid; +extern EFI_GUID gEfiDebugSupportProtocolGuid; + +extern EFI_GUID SimpleTextInputExProtocol; + +extern EFI_GUID ShellProtocolGuid; +extern EFI_GUID ShellParametersProtocolGuid; +extern EFI_GUID ShellDynamicCommandProtocolGuid; + +// +// EFI Variable strings +// +#define LOAD_OPTION_ACTIVE 0x00000001 + +#define VarLanguageCodes L"LangCodes" +#define VarLanguage L"Lang" +#define VarTimeout L"Timeout" +#define VarConsoleInp L"ConIn" +#define VarConsoleOut L"ConOut" +#define VarErrorOut L"ErrOut" +#define VarBootOption L"Boot%04x" +#define VarBootOrder L"BootOrder" +#define VarBootNext L"BootNext" +#define VarBootCurrent L"BootCurrent" +#define VarDriverOption L"Driver%04x" +#define VarDriverOrder L"DriverOrder" +#define VarConsoleInpDev L"ConInDev" +#define VarConsoleOutDev L"ConOutDev" +#define VarErrorOutDev L"ErrOutDev" + +#define LanguageCodeEnglish "eng" + +extern EFI_DEVICE_PATH RootDevicePath[]; +extern EFI_DEVICE_PATH EndDevicePath[]; +extern EFI_DEVICE_PATH EndInstanceDevicePath[]; + +// +// Other public data in the EFI library +// + +extern EFI_MEMORY_TYPE PoolAllocationType; + +// +// STATIC - Name is internal to the module +// INTERNAL - Name is internal to the component (i.e., directory) +// BOOTSERVCE - Name of a boot service function +// + +#define STATIC static +#define INTERNAL +#define BOOTSERVICE + +// +// Prototypes +// + +VOID +InitializeLib ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE* SystemTable + ); + +VOID +InitializeUnicodeSupport ( + CHAR8* LangCode + ); + +VOID +EFIDebugVariable ( + VOID + ); + +VOID +Exit( + IN EFI_STATUS ExitStatus, + IN UINTN ExitDataSize, + IN CHAR16* ExitData OPTIONAL + ); + +INTN +GetShellArgcArgv( + EFI_HANDLE ImageHandle, + CHAR16 **Argv[] /* Statically allocated */ + ); + +VOID +SetCrc ( + IN OUT EFI_TABLE_HEADER* Hdr + ); + +VOID +SetCrcAltSize ( + IN UINTN Size, + IN OUT EFI_TABLE_HEADER* Hdr + ); + +BOOLEAN +CheckCrc ( + IN UINTN MaxSize, + IN OUT EFI_TABLE_HEADER* Hdr + ); + +BOOLEAN +CheckCrcAltSize ( + IN UINTN MaxSize, + IN UINTN Size, + IN OUT EFI_TABLE_HEADER* Hdr + ); + +UINT32 +CalculateCrc ( + UINT8* pt, + UINTN Size + ); + +VOID +ZeroMem ( + IN VOID* Buffer, + IN UINTN Size + ); + +VOID EFIAPI +SetMem ( + IN VOID* Buffer, + IN UINTN Size, + IN UINT8 Value + ); + +VOID EFIAPI +CopyMem_1 ( + IN VOID* Dest, + IN VOID* Src, + IN UINTN len + ); + +VOID EFIAPI +CopyMemC ( + IN VOID* Dest, + IN CONST VOID* Src, + IN UINTN len + ); + +INTN +CompareMem ( + IN CONST VOID* Dest, + IN CONST VOID* Src, + IN UINTN len + ); + +INTN +StrCmp ( + IN CONST CHAR16* s1, + IN CONST CHAR16* s2 + ); + +INTN +StrnCmp ( + IN CONST CHAR16* s1, + IN CONST CHAR16* s2, + IN UINTN len + ); + +INTN +StriCmp ( + IN CONST CHAR16* s1, + IN CONST CHAR16* s2 + ); + +VOID +StrLwr ( + IN CHAR16* Str + ); + +VOID +StrUpr ( + IN CHAR16* Str + ); + +VOID +StrCpy ( + IN CHAR16* Dest, + IN CONST CHAR16* Src + ); + +VOID +StrnCpy ( + IN CHAR16* Dest, + IN CONST CHAR16* Src, + IN UINTN Len + ); + +CHAR16 * +StpCpy ( + IN CHAR16* Dest, + IN CONST CHAR16* Src + ); + +CHAR16 * +StpnCpy ( + IN CHAR16* Dest, + IN CONST CHAR16* Src, + IN UINTN Len + ); + +VOID +StrCat ( + IN CHAR16* Dest, + IN CONST CHAR16* Src + ); + +VOID +StrnCat ( + IN CHAR16* Dest, + IN CONST CHAR16* Src, + IN UINTN Len + ); + +UINTN +StrLen ( + IN CONST CHAR16* s1 + ); + +UINTN +StrnLen ( + IN CONST CHAR16* s1, + IN UINTN Len + ); + +UINTN +StrSize ( + IN CONST CHAR16* s1 + ); + +CHAR16 * +StrDuplicate ( + IN CONST CHAR16* Src + ); + +UINTN +AsciiStrLen ( + IN CONST CHAR8* s1 + ); + +UINTN +AsciiStrCmp ( + IN CONST CHAR8* s1, + IN CONST CHAR8* s2 + ); + +UINTN +AsciiStrnCmp ( + IN CONST CHAR8* s1, + IN CONST CHAR8* s2, + IN UINTN len + ); + +// +// For compatibility with previous gnu-efi versions +// +#define strlena AsciiStrLen +#define strcmpa AsciiStrCmp +#define strncmpa AsciiStrnCmp + +UINTN +xtoi ( + CONST CHAR16* str + ); + +UINTN +Atoi ( + CONST CHAR16* str + ); + +BOOLEAN +MetaMatch ( + IN CHAR16* String, + IN CHAR16* Pattern + ); + +BOOLEAN +MetaiMatch ( + IN CHAR16* String, + IN CHAR16* Pattern + ); + +UINT64 +LShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +UINT64 +RShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +UINT64 +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINTN Multiplier + ); + +UINT64 +DivU64x32 ( + IN UINT64 Dividend, + IN UINTN Divisor, + OUT UINTN* Remainder OPTIONAL + ); + +VOID +InitializeLock ( + IN OUT FLOCK* Lock, + IN EFI_TPL Priority + ); + +VOID +AcquireLock ( + IN FLOCK* Lock + ); + +VOID +ReleaseLock ( + IN FLOCK* Lock + ); + + +INTN +CompareGuid( + IN EFI_GUID* Guid1, + IN EFI_GUID* Guid2 + ); + +VOID * +AllocatePool ( + IN UINTN Size + ); + +VOID * +AllocateZeroPool ( + IN UINTN Size + ); + +VOID * +EFIAPI +ReallocatePool_1 ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID* OldPool OPTIONAL +); + +VOID +FreePool ( + IN VOID* p + ); + + +VOID +Output ( + IN CHAR16* Str + ); + +VOID +Input ( + IN CHAR16* Prompt OPTIONAL, + OUT CHAR16* InStr, + IN UINTN StrLen + ); + +VOID +IInput ( + IN SIMPLE_TEXT_OUTPUT_INTERFACE* ConOut, + IN SIMPLE_INPUT_INTERFACE* ConIn, + IN CHAR16* Prompt OPTIONAL, + OUT CHAR16* InStr, + IN UINTN StrLen + ); + +UINTN +Print ( + IN CONST CHAR16* fmt, + ... + ); + +UINTN +VPrint ( + IN CONST CHAR16* fmt, + va_list args + ); + +UINTN +UnicodeSPrint ( + OUT CHAR16* Str, + IN UINTN StrSize, + IN CONST CHAR16* fmt, + ... + ); + +UINTN +UnicodeVSPrint ( + OUT CHAR16* Str, + IN UINTN StrSize, + IN CONST CHAR16* fmt, + va_list args + ); + +CHAR16 * +VPoolPrint ( + IN CONST CHAR16* fmt, + va_list args + ); + +CHAR16 * +PoolPrint ( + IN CONST CHAR16* fmt, + ... + ); + +typedef struct { + CHAR16* str; + UINTN len; + UINTN maxlen; +} POOL_PRINT; + +CHAR16 * +CatPrint ( + IN OUT POOL_PRINT* Str, + IN CONST CHAR16* fmt, + ... + ); + +UINTN +PrintAt ( + IN UINTN Column, + IN UINTN Row, + IN CONST CHAR16* fmt, + ... + ); + +UINTN +IPrint ( + IN SIMPLE_TEXT_OUTPUT_INTERFACE* Out, + IN CONST CHAR16* fmt, + ... + ); + +UINTN +IPrintAt ( + IN SIMPLE_TEXT_OUTPUT_INTERFACE* Out, + IN UINTN Column, + IN UINTN Row, + IN CONST CHAR16* fmt, + ... + ); + +UINTN +AsciiPrint ( + IN CONST CHAR8* fmt, + ... + ); + +UINTN +AsciiVSPrint( + OUT CHAR8* Str, + IN UINTN StrSize, + IN CONST CHAR8* fmt, + va_list args +); + +// +// For compatibility with previous gnu-efi versions +// +#define SPrint UnicodeSPrint +#define VSPrint UnicodeVSPrint +#define APrint AsciiPrint + +VOID +ValueToHex ( + IN CHAR16* Buffer, + IN UINT64 v + ); + +VOID +ValueToString ( + IN CHAR16* Buffer, + IN BOOLEAN Comma, + IN INT64 v + ); + +VOID +FloatToString ( + IN CHAR16* Buffer, + IN BOOLEAN Comma, + IN double v + ); + +VOID +TimeToString ( + OUT CHAR16* Buffer, + IN EFI_TIME* Time + ); + +VOID +GuidToString ( + OUT CHAR16* Buffer, + IN EFI_GUID* Guid + ); + +VOID +StatusToString ( + OUT CHAR16* Buffer, + EFI_STATUS Status + ); + +VOID +DumpHex ( + IN UINTN Indent, + IN UINTN Offset, + IN UINTN DataSize, + IN VOID* UserData + ); + +BOOLEAN +GrowBuffer( + IN OUT EFI_STATUS* Status, + IN OUT VOID **Buffer, + IN UINTN BufferSize + ); + +EFI_MEMORY_DESCRIPTOR * +LibMemoryMap ( + OUT UINTN* NoEntries, + OUT UINTN* MapKey, + OUT UINTN* DescriptorSize, + OUT UINT32* DescriptorVersion + ); + +VOID * +LibGetVariable ( + IN CHAR16* Name, + IN EFI_GUID* VendorGuid + ); + +VOID * +LibGetVariableAndSize ( + IN CHAR16* Name, + IN EFI_GUID* VendorGuid, + OUT UINTN* VarSize + ); + +EFI_STATUS +LibDeleteVariable ( + IN CHAR16* VarName, + IN EFI_GUID* VarGuid + ); + +EFI_STATUS +LibSetNVVariable ( + IN CHAR16* VarName, + IN EFI_GUID* VarGuid, + IN UINTN DataSize, + IN VOID* Data + ); + +EFI_STATUS +LibSetVariable ( + IN CHAR16* VarName, + IN EFI_GUID* VarGuid, + IN UINTN DataSize, + IN VOID* Data + ); +EFI_STATUS +LibInsertToTailOfBootOrder ( + IN UINT16 BootOption, + IN BOOLEAN OnlyInsertIfEmpty + ); + +EFI_STATUS +LibLocateProtocol ( + IN EFI_GUID* ProtocolGuid, + OUT VOID **Interface + ); + +EFI_STATUS +LibLocateHandle ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID* Protocol OPTIONAL, + IN VOID* SearchKey OPTIONAL, + IN OUT UINTN* NoHandles, + OUT EFI_HANDLE **Buffer + ); + +EFI_STATUS +LibLocateHandleByDiskSignature ( + IN UINT8 MBRType, + IN UINT8 SignatureType, + IN VOID* Signature, + IN OUT UINTN* NoHandles, + OUT EFI_HANDLE **Buffer + ); + +EFI_STATUS +LibInstallProtocolInterfaces ( + IN OUT EFI_HANDLE* Handle, + ... + ); + +VOID +LibUninstallProtocolInterfaces ( + IN EFI_HANDLE Handle, + ... + ); + +EFI_STATUS +LibReinstallProtocolInterfaces ( + IN OUT EFI_HANDLE* Handle, + ... + ); + +EFI_EVENT +LibCreateProtocolNotifyEvent ( + IN EFI_GUID* ProtocolGuid, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, + IN VOID* NotifyContext, + OUT VOID* Registration + ); + +EFI_STATUS +WaitForSingleEvent ( + IN EFI_EVENT Event, + IN UINT64 Timeout OPTIONAL + ); + +VOID +WaitForEventWithTimeout ( + IN EFI_EVENT Event, + IN UINTN Timeout, + IN UINTN Row, + IN UINTN Column, + IN CHAR16* String, + IN EFI_INPUT_KEY TimeoutKey, + OUT EFI_INPUT_KEY* Key + ); + +EFI_FILE_HANDLE +LibOpenRoot ( + IN EFI_HANDLE DeviceHandle + ); + +EFI_FILE_INFO * +LibFileInfo ( + IN EFI_FILE_HANDLE FHand + ); + +EFI_FILE_SYSTEM_INFO * +LibFileSystemInfo ( + IN EFI_FILE_HANDLE FHand + ); + +EFI_FILE_SYSTEM_VOLUME_LABEL_INFO * +LibFileSystemVolumeLabelInfo ( + IN EFI_FILE_HANDLE FHand + ); + +BOOLEAN +ValidMBR( + IN MASTER_BOOT_RECORD* Mbr, + IN EFI_BLOCK_IO* BlkIo + ); + +BOOLEAN +LibMatchDevicePaths ( + IN EFI_DEVICE_PATH* Multi, + IN EFI_DEVICE_PATH* Single + ); + +EFI_DEVICE_PATH * +LibDuplicateDevicePathInstance ( + IN EFI_DEVICE_PATH* DevPath + ); + +EFI_DEVICE_PATH * +DevicePathFromHandle ( + IN EFI_HANDLE Handle + ); + +EFI_DEVICE_PATH * +DevicePathInstance ( + IN OUT EFI_DEVICE_PATH **DevicePath, + OUT UINTN* Size + ); + +UINTN +DevicePathInstanceCount ( + IN EFI_DEVICE_PATH* DevicePath + ); + +EFI_DEVICE_PATH * +AppendDevicePath ( + IN EFI_DEVICE_PATH* Src1, + IN EFI_DEVICE_PATH* Src2 + ); + +EFI_DEVICE_PATH * +AppendDevicePathNode ( + IN EFI_DEVICE_PATH* Src1, + IN EFI_DEVICE_PATH* Src2 + ); + +EFI_DEVICE_PATH* +AppendDevicePathInstance ( + IN EFI_DEVICE_PATH* Src, + IN EFI_DEVICE_PATH* Instance + ); + +EFI_DEVICE_PATH * +FileDevicePath ( + IN EFI_HANDLE Device OPTIONAL, + IN CHAR16* FileName + ); + +UINTN +DevicePathSize ( + IN EFI_DEVICE_PATH* DevPath + ); + +EFI_DEVICE_PATH * +DuplicateDevicePath ( + IN EFI_DEVICE_PATH* DevPath + ); + +EFI_DEVICE_PATH * +UnpackDevicePath ( + IN EFI_DEVICE_PATH* DevPath + ); + +EFI_STATUS +LibDevicePathToInterface ( + IN EFI_GUID* Protocol, + IN EFI_DEVICE_PATH* FilePath, + OUT VOID **Interface + ); + +CHAR16 * +DevicePathToStr ( + EFI_DEVICE_PATH* DevPath + ); + +// +// BugBug: I need my own include files +// +typedef struct { + UINT8 Register; + UINT8 Function; + UINT8 Device; + UINT8 Bus; + UINT32 Reserved; +} EFI_ADDRESS; + +typedef union { + UINT64 Address; + EFI_ADDRESS EfiAddress; +} EFI_PCI_ADDRESS_UNION; + + +EFI_STATUS +PciFindDeviceClass ( + IN OUT EFI_PCI_ADDRESS_UNION* Address, + IN UINT8 BaseClass, + IN UINT8 SubClass + ); + +EFI_STATUS +PciFindDevice ( + IN OUT EFI_PCI_ADDRESS_UNION* DeviceAddress, + IN UINT16 VendorId, + IN UINT16 DeviceId, + IN OUT PCI_TYPE00* Pci + ); + +// +// SIMPLE_READ_FILE object used to access files +// + +typedef VOID* SIMPLE_READ_FILE; + +EFI_STATUS +OpenSimpleReadFile ( + IN BOOLEAN BootPolicy, + IN VOID* SourceBuffer OPTIONAL, + IN UINTN SourceSize, + IN OUT EFI_DEVICE_PATH **FilePath, + OUT EFI_HANDLE* DeviceHandle, + OUT SIMPLE_READ_FILE* SimpleReadHandle + ); + +EFI_STATUS +ReadSimpleReadFile ( + IN SIMPLE_READ_FILE SimpleReadHandle, + IN UINTN Offset, + IN OUT UINTN* ReadSize, + OUT VOID* Buffer + ); + + +VOID +CloseSimpleReadFile ( + IN SIMPLE_READ_FILE SimpleReadHandle + ); + +VOID +InitializeGuid ( + VOID + ); + +UINT8 +DecimaltoBCD( + IN UINT8 DecValue + ); + +UINT8 +BCDtoDecimal( + IN UINT8 BcdValue + ); + +EFI_STATUS +LibGetSystemConfigurationTable( + IN EFI_GUID* TableGuid, + IN OUT VOID **Table + ); + +BOOLEAN +LibIsValidTextGraphics ( + IN CHAR16 Graphic, + OUT CHAR8* PcAnsi, OPTIONAL + OUT CHAR8* Ascii OPTIONAL + ); + +BOOLEAN +IsValidAscii ( + IN CHAR16 Ascii + ); + +BOOLEAN +IsValidEfiCntlChar ( + IN CHAR16 c + ); + +CHAR16 * +LibGetUiString ( + IN EFI_HANDLE Handle, + IN UI_STRING_TYPE StringType, + IN ISO_639_2* LangCode, + IN BOOLEAN ReturnDevicePathStrOnMismatch + ); + +CHAR8* +LibGetSmbiosString ( + IN SMBIOS_STRUCTURE_POINTER* Smbios, + IN UINT16 StringNumber + ); + +EFI_STATUS +LibGetSmbiosSystemGuidAndSerialNumber ( + IN EFI_GUID* SystemGuid, + OUT CHAR8 **SystemSerialNumber + ); + + +EFI_STATUS +InitializeGlobalIoDevice ( + IN EFI_DEVICE_PATH* DevicePath, + IN EFI_GUID* Protocol, + IN CHAR8* ErrorStr, + OUT EFI_DEVICE_IO_INTERFACE **GlobalIoFncs + ); + +UINT32 +ReadPort ( + IN EFI_DEVICE_IO_INTERFACE* GlobalIoFncs, + IN EFI_IO_WIDTH Width, + IN UINTN Port + ); + +UINT32 +WritePort ( + IN EFI_DEVICE_IO_INTERFACE* GlobalIoFncs, + IN EFI_IO_WIDTH Width, + IN UINTN Port, + IN UINTN Data + ); + +UINT32 +ReadPciConfig ( + IN EFI_DEVICE_IO_INTERFACE* GlobalIoFncs, + IN EFI_IO_WIDTH Width, + IN UINTN Port + ); + +UINT32 +WritePciConfig ( + IN EFI_DEVICE_IO_INTERFACE* GlobalIoFncs, + IN EFI_IO_WIDTH Width, + IN UINTN Port, + IN UINTN Data + ); + +VOID +Pause ( + VOID +); + +extern EFI_DEVICE_IO_INTERFACE* GlobalIoFncs; + +#define outp(_Port, _DataByte) (UINT8)WritePort(GlobalIoFncs, IO_UINT8, (UINTN)_Port, (UINTN)_DataByte) +#define inp(_Port) (UINT8)ReadPort(GlobalIoFncs, IO_UINT8, (UINTN)_Port) +#define outpw(_Port, _DataByte) (UINT16)WritePort(GlobalIoFncs, IO_UINT16, (UINTN)_Port, (UINTN)_DataByte) +#define inpw(_Port) (UINT16)ReadPort(GlobalIoFncs, IO_UINT16, (UINTN)_Port) +#define outpd(_Port, _DataByte) (UINT32)WritePort(GlobalIoFncs, IO_UINT32, (UINTN)_Port, (UINTN)_DataByte) +#define inpd(_Port) (UINT32)ReadPort(GlobalIoFncs, IO_UINT32, (UINTN)_Port) + +#define writepci8(_Addr, _DataByte) (UINT8)WritePciConfig(GlobalIoFncs, IO_UINT8, (UINTN)_Addr, (UINTN)_DataByte) +#define readpci8(_Addr) (UINT8)ReadPciConfig(GlobalIoFncs, IO_UINT8, (UINTN)_Addr) +#define writepci16(_Addr, _DataByte) (UINT16)WritePciConfig(GlobalIoFncs, IO_UINT16, (UINTN)_Addr, (UINTN)_DataByte) +#define readpci16(_Addr) (UINT16)ReadPciConfig(GlobalIoFncs, IO_UINT16, (UINTN)_Addr) +#define writepci32(_Addr, _DataByte) (UINT32)WritePciConfig(GlobalIoFncs, IO_UINT32, (UINTN)_Addr, (UINTN)_DataByte) +#define readpci32(_Addr) (UINT32)ReadPciConfig(GlobalIoFncs, IO_UINT32, (UINTN)_Addr) + +#define Port80(_PostCode) GlobalIoFncs->Io.Write (GlobalIoFncs, IO_UINT16, (UINT64)0x80, 1, &(_PostCode)) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/code/boot/include/efilink.h b/code/boot/include/efilink.h new file mode 100644 index 0000000..f53c67b --- /dev/null +++ b/code/boot/include/efilink.h @@ -0,0 +1,182 @@ +#ifndef _EFI_LINK_H +#define _EFI_LINK_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + link.h (renamed efilink.h to avoid conflicts) + +Abstract: + + EFI link list macro's + + + +Revision History + +--*/ + +#ifndef EFI_NT_EMUL + +// +// List entry - doubly linked list +// + +typedef struct _LIST_ENTRY { + struct _LIST_ENTRY* Flink; + struct _LIST_ENTRY* Blink; +} LIST_ENTRY, EFI_LIST_ENTRY; + +#endif + + +// +// VOID +// InitializeListHead( +// LIST_ENTRY* ListHead +// ); +// + +#define InitializeListHead(ListHead) \ + (ListHead)->Flink = ListHead; \ + (ListHead)->Blink = ListHead; + +// +// BOOLEAN +// IsListEmpty( +// PLIST_ENTRY ListHead +// ); +// + +#define IsListEmpty(ListHead) \ + ((ListHead)->Flink == (ListHead)) + +// +// VOID +// RemoveEntryList( +// PLIST_ENTRY Entry +// ); +// + +#define _RemoveEntryList(Entry) { \ + LIST_ENTRY* _Blink, *_Flink; \ + _Flink = (Entry)->Flink; \ + _Blink = (Entry)->Blink; \ + _Blink->Flink = _Flink; \ + _Flink->Blink = _Blink; \ + } + +#if EFI_DEBUG + #define RemoveEntryList(Entry) \ + _RemoveEntryList(Entry); \ + (Entry)->Flink = (LIST_ENTRY *) BAD_POINTER; \ + (Entry)->Blink = (LIST_ENTRY *) BAD_POINTER; +#else + #define RemoveEntryList(Entry) \ + _RemoveEntryList(Entry); +#endif + +// +// VOID +// InsertTailList( +// PLIST_ENTRY ListHead, +// PLIST_ENTRY Entry +// ); +// + +#define InsertTailList(ListHead,Entry) {\ + LIST_ENTRY* _ListHead, *_Blink; \ + _ListHead = (ListHead); \ + _Blink = _ListHead->Blink; \ + (Entry)->Flink = _ListHead; \ + (Entry)->Blink = _Blink; \ + _Blink->Flink = (Entry); \ + _ListHead->Blink = (Entry); \ + } + +// +// VOID +// InsertHeadList( +// PLIST_ENTRY ListHead, +// PLIST_ENTRY Entry +// ); +// + +#define InsertHeadList(ListHead,Entry) {\ + LIST_ENTRY* _ListHead, *_Flink; \ + _ListHead = (ListHead); \ + _Flink = _ListHead->Flink; \ + (Entry)->Flink = _Flink; \ + (Entry)->Blink = _ListHead; \ + _Flink->Blink = (Entry); \ + _ListHead->Flink = (Entry); \ + } + +// VOID +// SwapListEntries( +// PLIST_ENTRY Entry1, +// PLIST_ENTRY Entry2 +// ); +// +// Put Entry2 before Entry1 +// +#define SwapListEntries(Entry1,Entry2) {\ + LIST_ENTRY* Entry1Flink, *Entry1Blink; \ + LIST_ENTRY* Entry2Flink, *Entry2Blink; \ + Entry2Flink = (Entry2)->Flink; \ + Entry2Blink = (Entry2)->Blink; \ + Entry1Flink = (Entry1)->Flink; \ + Entry1Blink = (Entry1)->Blink; \ + Entry2Blink->Flink = Entry2Flink; \ + Entry2Flink->Blink = Entry2Blink; \ + (Entry2)->Flink = Entry1; \ + (Entry2)->Blink = Entry1Blink; \ + Entry1Blink->Flink = (Entry2); \ + (Entry1)->Blink = (Entry2); \ + } + +// +// EFI_FIELD_OFFSET - returns the byte offset to a field within a structure +// + +#define EFI_FIELD_OFFSET(TYPE,Field) ((UINTN)(intptr_t)(&(((TYPE *) 0)->Field))) + +// +// CONTAINING_RECORD - returns a pointer to the structure +// from one of it's elements. +// + +#define _CR(Record, TYPE, Field) \ + ((TYPE *) ( (CHAR8 *)(Record) - (CHAR8 *) &(((TYPE *) 0)->Field))) + +// +// EDK2 uses BASE_CR for the above +// +#define BASE_CR _CR + +#if EFI_DEBUG + #define CR(Record, TYPE, Field, Sig) \ + _CR(Record, TYPE, Field)->Signature != Sig ? \ + (TYPE *) ASSERT_STRUCT(_CR(Record, TYPE, Field), Record) : \ + _CR(Record, TYPE, Field) +#else + #define CR(Record, TYPE, Field, Signature) \ + _CR(Record, TYPE, Field) +#endif + + +// +// A lock structure +// + +typedef struct _FLOCK { + EFI_TPL Tpl; + EFI_TPL OwnerTpl; + UINTN Lock; +} FLOCK; + +#endif + diff --git a/code/boot/include/efinet.h b/code/boot/include/efinet.h new file mode 100644 index 0000000..0795671 --- /dev/null +++ b/code/boot/include/efinet.h @@ -0,0 +1,348 @@ +#ifndef _EFINET_H +#define _EFINET_H + + +/*++ +Copyright (c) 1999 Intel Corporation + +Module Name: + efinet.h + +Abstract: + EFI Simple Network protocol + +Revision History +--*/ + + +/////////////////////////////////////////////////////////////////////////////// +// +// Simple Network Protocol +// + +#define EFI_SIMPLE_NETWORK_PROTOCOL_GUID \ + { 0xA19832B9, 0xAC25, 0x11D3, {0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D} } + +INTERFACE_DECL(_EFI_SIMPLE_NETWORK_PROTOCOL); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef struct { + // + // Total number of frames received. Includes frames with errors and + // dropped frames. + // + UINT64 RxTotalFrames; + + // + // Number of valid frames received and copied into receive buffers. + // + UINT64 RxGoodFrames; + + // + // Number of frames below the minimum length for the media. + // This would be <64 for ethernet. + // + UINT64 RxUndersizeFrames; + + // + // Number of frames longer than the maxminum length for the + // media. This would be >1500 for ethernet. + // + UINT64 RxOversizeFrames; + + // + // Valid frames that were dropped because receive buffers were full. + // + UINT64 RxDroppedFrames; + + // + // Number of valid unicast frames received and not dropped. + // + UINT64 RxUnicastFrames; + + // + // Number of valid broadcast frames received and not dropped. + // + UINT64 RxBroadcastFrames; + + // + // Number of valid mutlicast frames received and not dropped. + // + UINT64 RxMulticastFrames; + + // + // Number of frames w/ CRC or alignment errors. + // + UINT64 RxCrcErrorFrames; + + // + // Total number of bytes received. Includes frames with errors + // and dropped frames. + // + UINT64 RxTotalBytes; + + // + // Transmit statistics. + // + UINT64 TxTotalFrames; + UINT64 TxGoodFrames; + UINT64 TxUndersizeFrames; + UINT64 TxOversizeFrames; + UINT64 TxDroppedFrames; + UINT64 TxUnicastFrames; + UINT64 TxBroadcastFrames; + UINT64 TxMulticastFrames; + UINT64 TxCrcErrorFrames; + UINT64 TxTotalBytes; + + // + // Number of collisions detection on this subnet. + // + UINT64 Collisions; + + // + // Number of frames destined for unsupported protocol. + // + UINT64 UnsupportedProtocol; + +} EFI_NETWORK_STATISTICS; + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef enum { + EfiSimpleNetworkStopped, + EfiSimpleNetworkStarted, + EfiSimpleNetworkInitialized, + EfiSimpleNetworkMaxState +} EFI_SIMPLE_NETWORK_STATE; + +/////////////////////////////////////////////////////////////////////////////// +// + +#define EFI_SIMPLE_NETWORK_RECEIVE_UNICAST 0x01 +#define EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST 0x02 +#define EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST 0x04 +#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS 0x08 +#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST 0x10 + +/////////////////////////////////////////////////////////////////////////////// +// + +#define EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT 0x01 +#define EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT 0x02 +#define EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT 0x04 +#define EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT 0x08 + +/////////////////////////////////////////////////////////////////////////////// +// +#define MAX_MCAST_FILTER_CNT 16 +typedef struct { + UINT32 State; + UINT32 HwAddressSize; + UINT32 MediaHeaderSize; + UINT32 MaxPacketSize; + UINT32 NvRamSize; + UINT32 NvRamAccessSize; + UINT32 ReceiveFilterMask; + UINT32 ReceiveFilterSetting; + UINT32 MaxMCastFilterCount; + UINT32 MCastFilterCount; + EFI_MAC_ADDRESS MCastFilter[MAX_MCAST_FILTER_CNT]; + EFI_MAC_ADDRESS CurrentAddress; + EFI_MAC_ADDRESS BroadcastAddress; + EFI_MAC_ADDRESS PermanentAddress; + UINT8 IfType; + BOOLEAN MacAddressChangeable; + BOOLEAN MultipleTxSupported; + BOOLEAN MediaPresentSupported; + BOOLEAN MediaPresent; +} EFI_SIMPLE_NETWORK_MODE; + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI* EFI_SIMPLE_NETWORK_START) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL* This +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI* EFI_SIMPLE_NETWORK_STOP) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL* This +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI* EFI_SIMPLE_NETWORK_INITIALIZE) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL* This, + IN UINTN ExtraRxBufferSize OPTIONAL, + IN UINTN ExtraTxBufferSize OPTIONAL +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI* EFI_SIMPLE_NETWORK_RESET) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL* This, + IN BOOLEAN ExtendedVerification +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI* EFI_SIMPLE_NETWORK_SHUTDOWN) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL* This +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI* EFI_SIMPLE_NETWORK_RECEIVE_FILTERS) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL* This, + IN UINT32 Enable, + IN UINT32 Disable, + IN BOOLEAN ResetMCastFilter, + IN UINTN MCastFilterCnt OPTIONAL, + IN EFI_MAC_ADDRESS* MCastFilter OPTIONAL +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI* EFI_SIMPLE_NETWORK_STATION_ADDRESS) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL* This, + IN BOOLEAN Reset, + IN EFI_MAC_ADDRESS* New OPTIONAL +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI* EFI_SIMPLE_NETWORK_STATISTICS) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL* This, + IN BOOLEAN Reset, + IN OUT UINTN* StatisticsSize OPTIONAL, + OUT EFI_NETWORK_STATISTICS* StatisticsTable OPTIONAL +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI* EFI_SIMPLE_NETWORK_MCAST_IP_TO_MAC) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL* This, + IN BOOLEAN IPv6, + IN EFI_IP_ADDRESS* IP, + OUT EFI_MAC_ADDRESS* MAC +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI* EFI_SIMPLE_NETWORK_NVDATA) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL* This, + IN BOOLEAN ReadWrite, + IN UINTN Offset, + IN UINTN BufferSize, + IN OUT VOID* Buffer +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI* EFI_SIMPLE_NETWORK_GET_STATUS) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL* This, + OUT UINT32* InterruptStatus OPTIONAL, + OUT VOID **TxBuf OPTIONAL +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI* EFI_SIMPLE_NETWORK_TRANSMIT) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL* This, + IN UINTN HeaderSize, + IN UINTN BufferSize, + IN VOID* Buffer, + IN EFI_MAC_ADDRESS* SrcAddr OPTIONAL, + IN EFI_MAC_ADDRESS* DestAddr OPTIONAL, + IN UINT16* Protocol OPTIONAL +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI* EFI_SIMPLE_NETWORK_RECEIVE) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL* This, + OUT UINTN* HeaderSize OPTIONAL, + IN OUT UINTN* BufferSize, + OUT VOID* Buffer, + OUT EFI_MAC_ADDRESS* SrcAddr OPTIONAL, + OUT EFI_MAC_ADDRESS* DestAddr OPTIONAL, + OUT UINT16* Protocol OPTIONAL +); + +/////////////////////////////////////////////////////////////////////////////// +// + +#define EFI_SIMPLE_NETWORK_PROTOCOL_REVISION 0x00010000 +#define EFI_SIMPLE_NETWORK_INTERFACE_REVISION EFI_SIMPLE_NETWORK_PROTOCOL_REVISION + +typedef struct _EFI_SIMPLE_NETWORK_PROTOCOL { + UINT64 Revision; + EFI_SIMPLE_NETWORK_START Start; + EFI_SIMPLE_NETWORK_STOP Stop; + EFI_SIMPLE_NETWORK_INITIALIZE Initialize; + EFI_SIMPLE_NETWORK_RESET Reset; + EFI_SIMPLE_NETWORK_SHUTDOWN Shutdown; + EFI_SIMPLE_NETWORK_RECEIVE_FILTERS ReceiveFilters; + EFI_SIMPLE_NETWORK_STATION_ADDRESS StationAddress; + EFI_SIMPLE_NETWORK_STATISTICS Statistics; + EFI_SIMPLE_NETWORK_MCAST_IP_TO_MAC MCastIpToMac; + EFI_SIMPLE_NETWORK_NVDATA NvData; + EFI_SIMPLE_NETWORK_GET_STATUS GetStatus; + EFI_SIMPLE_NETWORK_TRANSMIT Transmit; + EFI_SIMPLE_NETWORK_RECEIVE Receive; + EFI_EVENT WaitForPacket; + EFI_SIMPLE_NETWORK_MODE* Mode; +} EFI_SIMPLE_NETWORK_PROTOCOL; + +// Note: Because it conflicted with the EDK2 struct name, the +// 'EFI_SIMPLE_NETWORK_PROTOCOL' GUID definition, from older +// versions of gnu-efi, is now obsoleted. +// Use 'EFI_SIMPLE_NETWORK_PROTOCOL_GUID' instead. + +typedef struct _EFI_SIMPLE_NETWORK_PROTOCOL _EFI_SIMPLE_NETWORK; +typedef EFI_SIMPLE_NETWORK_PROTOCOL EFI_SIMPLE_NETWORK; + +#endif /* _EFINET_H */ diff --git a/code/boot/include/efipart.h b/code/boot/include/efipart.h new file mode 100644 index 0000000..8c92814 --- /dev/null +++ b/code/boot/include/efipart.h @@ -0,0 +1,61 @@ +#ifndef _EFI_PART_H +#define _EFI_PART_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efipart.h + +Abstract: + Info about disk partitions and Master Boot Records + + + + +Revision History + +--*/ + +// +// +// + +#define EFI_PARTITION 0xef +#define MBR_SIZE 512 + +#pragma pack(1) + +typedef struct { + UINT8 BootIndicator; + UINT8 StartHead; + UINT8 StartSector; + UINT8 StartTrack; + UINT8 OSIndicator; + UINT8 EndHead; + UINT8 EndSector; + UINT8 EndTrack; + UINT8 StartingLBA[4]; + UINT8 SizeInLBA[4]; +} MBR_PARTITION_RECORD; + +#define EXTRACT_UINT32(D) (UINT32)(D[0] | (D[1] << 8) | (D[2] << 16) | (D[3] << 24)) + +#define MBR_SIGNATURE 0xaa55 +#define MIN_MBR_DEVICE_SIZE 0x80000 +#define MBR_ERRATA_PAD 0x40000 // 128 MB + +#define MAX_MBR_PARTITIONS 4 +typedef struct { + UINT8 BootStrapCode[440]; + UINT8 UniqueMbrSignature[4]; + UINT8 Unknown[2]; + MBR_PARTITION_RECORD Partition[MAX_MBR_PARTITIONS]; + UINT16 Signature; +} MASTER_BOOT_RECORD; +#pragma pack() + + +#endif diff --git a/code/boot/include/efipciio.h b/code/boot/include/efipciio.h new file mode 100644 index 0000000..707e82d --- /dev/null +++ b/code/boot/include/efipciio.h @@ -0,0 +1,399 @@ +#ifndef _EFI_PCI_IO_H +#define _EFI_PCI_IO_H + +#define EFI_PCI_IO_PROTOCOL_GUID \ + { 0x4cf5b200, 0x68b8, 0x4ca5, {0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x02, 0x9a} } + +#define EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID \ + { 0x2f707ebb, 0x4a1a, 0x11d4, {0x9a, 0x38, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } + +INTERFACE_DECL(_EFI_PCI_IO_PROTOCOL); +INTERFACE_DECL(_EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL); + +typedef enum { + EfiPciIoWidthUint8, + EfiPciIoWidthUint16, + EfiPciIoWidthUint32, + EfiPciIoWidthUint64, + EfiPciIoWidthFifoUint8, + EfiPciIoWidthFifoUint16, + EfiPciIoWidthFifoUint32, + EfiPciIoWidthFifoUint64, + EfiPciIoWidthFillUint8, + EfiPciIoWidthFillUint16, + EfiPciIoWidthFillUint32, + EfiPciIoWidthFillUint64, + EfiPciIoWidthMaximum +} EFI_PCI_IO_PROTOCOL_WIDTH, EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH; + +#define EFI_PCI_IO_PASS_THROUGH_BAR 0xff + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_IO_PROTOCOL_POLL_IO_MEM) ( + IN struct _EFI_PCI_IO_PROTOCOL* This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64* Result +); + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL* This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64* Result +); + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_IO_PROTOCOL_IO_MEM) ( + IN struct _EFI_PCI_IO_PROTOCOL* This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID* Buffer +); + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL* This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID* Buffer +); + +typedef struct { + EFI_PCI_IO_PROTOCOL_IO_MEM Read; + EFI_PCI_IO_PROTOCOL_IO_MEM Write; +} EFI_PCI_IO_PROTOCOL_ACCESS; + +typedef struct { + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM Read; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM Write; +} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS; + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_IO_PROTOCOL_CONFIG) ( + IN struct _EFI_PCI_IO_PROTOCOL* This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID* Buffer +); + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_CONFIGURATION) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL* This, + OUT VOID **Resources +); + +typedef struct { + EFI_PCI_IO_PROTOCOL_CONFIG Read; + EFI_PCI_IO_PROTOCOL_CONFIG Write; +} EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS; + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_IO_PROTOCOL_COPY_MEM) ( + IN struct _EFI_PCI_IO_PROTOCOL* This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 DestBarIndex, + IN UINT64 DestOffset, + IN UINT8 SrcBarIndex, + IN UINT64 SrcOffset, + IN UINTN Count +); + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_COPY_MEM) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL* This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 DestAddress, + IN UINT64 SrcAddress, + IN UINTN Count +); + +typedef enum { + EfiPciIoOperationBusMasterRead, + EfiPciIoOperationBusMasterWrite, + EfiPciIoOperationBusMasterCommonBuffer, + EfiPciIoOperationMaximum +} EFI_PCI_IO_PROTOCOL_OPERATION; + +typedef enum { + EfiPciOperationBusMasterRead, + EfiPciOperationBusMasterWrite, + EfiPciOperationBusMasterCommonBuffer, + EfiPciOperationBusMasterRead64, + EfiPciOperationBusMasterWrite64, + EfiPciOperationBusMasterCommonBuffer64, + EfiPciOperationMaximum +} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION; + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_IO_PROTOCOL_MAP) ( + IN struct _EFI_PCI_IO_PROTOCOL* This, + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, + IN VOID* HostAddress, + IN OUT UINTN* NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS* DeviceAddress, + OUT VOID **Mapping +); + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_MAP) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL* This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation, + IN VOID* HostAddress, + IN OUT UINTN* NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS* DeviceAddress, + OUT VOID **Mapping +); + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_IO_PROTOCOL_UNMAP) ( + IN struct _EFI_PCI_IO_PROTOCOL* This, + IN VOID* Mapping +); + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_UNMAP) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL* This, + IN VOID* Mapping +); + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_IO_PROTOCOL_ALLOCATE_BUFFER) ( + IN struct _EFI_PCI_IO_PROTOCOL* This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes +); + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ALLOCATE_BUFFER) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL* This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT VOID **HostAddress, + IN UINT64 Attributes +); + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_IO_PROTOCOL_FREE_BUFFER) ( + IN struct _EFI_PCI_IO_PROTOCOL* This, + IN UINTN Pages, + IN VOID* HostAddress + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FREE_BUFFER) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL* This, + IN UINTN Pages, + IN VOID* HostAddress +); + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_IO_PROTOCOL_FLUSH) ( + IN struct _EFI_PCI_IO_PROTOCOL* This +); + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FLUSH) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL* This +); + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_IO_PROTOCOL_GET_LOCATION) ( + IN struct _EFI_PCI_IO_PROTOCOL* This, + OUT UINTN* SegmentNumber, + OUT UINTN* BusNumber, + OUT UINTN* DeviceNumber, + OUT UINTN* FunctionNumber +); + +#define EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001 +#define EFI_PCI_ATTRIBUTE_ISA_IO 0x0002 +#define EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO 0x0004 +#define EFI_PCI_ATTRIBUTE_VGA_MEMORY 0x0008 +#define EFI_PCI_ATTRIBUTE_VGA_IO 0x0010 +#define EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO 0x0020 +#define EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO 0x0040 +#define EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080 +#define EFI_PCI_ATTRIBUTE_IO 0x0100 +#define EFI_PCI_ATTRIBUTE_MEMORY 0x0200 +#define EFI_PCI_ATTRIBUTE_BUS_MASTER 0x0400 +#define EFI_PCI_ATTRIBUTE_MEMORY_CACHED 0x0800 +#define EFI_PCI_ATTRIBUTE_MEMORY_DISABLE 0x1000 +#define EFI_PCI_ATTRIBUTE_EMBEDDED_DEVICE 0x2000 +#define EFI_PCI_ATTRIBUTE_EMBEDDED_ROM 0x4000 +#define EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000 +#define EFI_PCI_ATTRIBUTE_ISA_IO_16 0x10000 +#define EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000 +#define EFI_PCI_ATTRIBUTE_VGA_IO_16 0x40000 + +#define EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO +#define EFI_PCI_IO_ATTRIBUTE_ISA_IO EFI_PCI_ATTRIBUTE_ISA_IO +#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO +#define EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY EFI_PCI_ATTRIBUTE_VGA_MEMORY +#define EFI_PCI_IO_ATTRIBUTE_VGA_IO EFI_PCI_ATTRIBUTE_VGA_IO +#define EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO +#define EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO +#define EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE +#define EFI_PCI_IO_ATTRIBUTE_IO EFI_PCI_ATTRIBUTE_IO +#define EFI_PCI_IO_ATTRIBUTE_MEMORY EFI_PCI_ATTRIBUTE_MEMORY +#define EFI_PCI_IO_ATTRIBUTE_BUS_MASTER EFI_PCI_ATTRIBUTE_BUS_MASTER +#define EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED EFI_PCI_ATTRIBUTE_MEMORY_CACHED +#define EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE EFI_PCI_ATTRIBUTE_MEMORY_DISABLE +#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE EFI_PCI_ATTRIBUTE_EMBEDDED_DEVICE +#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM EFI_PCI_ATTRIBUTE_EMBEDDED_ROM +#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE +#define EFI_PCI_IO_ATTRIBUTE_ISA_IO_16 EFI_PCI_ATTRIBUTE_ISA_IO_16 +#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 +#define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 EFI_PCI_ATTRIBUTE_VGA_IO_16 + +#define EFI_PCI_ATTRIBUTE_VALID_FOR_ALLOCATE_BUFFER \ + (EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED | EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE) + +#define EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER \ + (~EFI_PCI_ATTRIBUTE_VALID_FOR_ALLOCATE_BUFFER) + +typedef struct { + UINT8 Register; + UINT8 Function; + UINT8 Device; + UINT8 Bus; + UINT32 ExtendedRegister; +} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS; + +typedef enum { + EfiPciIoAttributeOperationGet, + EfiPciIoAttributeOperationSet, + EfiPciIoAttributeOperationEnable, + EfiPciIoAttributeOperationDisable, + EfiPciIoAttributeOperationSupported, + EfiPciIoAttributeOperationMaximum +} EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION; + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_IO_PROTOCOL_ATTRIBUTES) ( + IN struct _EFI_PCI_IO_PROTOCOL* This, + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, + IN UINT64 Attributes, + OUT UINT64* Result OPTIONAL +); + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_IO_PROTOCOL_GET_BAR_ATTRIBUTES) ( + IN struct _EFI_PCI_IO_PROTOCOL* This, + IN UINT8 BarIndex, + OUT UINT64* Supports OPTIONAL, + OUT VOID **Resources OPTIONAL +); + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GET_ATTRIBUTES) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL* This, + OUT UINT64* Supports, + OUT UINT64* Attributes +); + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_IO_PROTOCOL_SET_BAR_ATTRIBUTES) ( + IN struct _EFI_PCI_IO_PROTOCOL* This, + IN UINT64 Attributes, + IN UINT8 BarIndex, + IN OUT UINT64* Offset, + IN OUT UINT64* Length +); + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_SET_ATTRIBUTES) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL* This, + IN UINT64 Attributes, + IN OUT UINT64* ResourceBase, + IN OUT UINT64* ResourceLength +); + +typedef struct _EFI_PCI_IO_PROTOCOL { + EFI_PCI_IO_PROTOCOL_POLL_IO_MEM PollMem; + EFI_PCI_IO_PROTOCOL_POLL_IO_MEM PollIo; + EFI_PCI_IO_PROTOCOL_ACCESS Mem; + EFI_PCI_IO_PROTOCOL_ACCESS Io; + EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS Pci; + EFI_PCI_IO_PROTOCOL_COPY_MEM CopyMem; + EFI_PCI_IO_PROTOCOL_MAP Map; + EFI_PCI_IO_PROTOCOL_UNMAP Unmap; + EFI_PCI_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer; + EFI_PCI_IO_PROTOCOL_FREE_BUFFER FreeBuffer; + EFI_PCI_IO_PROTOCOL_FLUSH Flush; + EFI_PCI_IO_PROTOCOL_GET_LOCATION GetLocation; + EFI_PCI_IO_PROTOCOL_ATTRIBUTES Attributes; + EFI_PCI_IO_PROTOCOL_GET_BAR_ATTRIBUTES GetBarAttributes; + EFI_PCI_IO_PROTOCOL_SET_BAR_ATTRIBUTES SetBarAttributes; + UINT64 RomSize; + VOID* RomImage; +} EFI_PCI_IO_PROTOCOL; + +// Note: Because it conflicted with the EDK2 struct name, the +// 'EFI_PCI_IO_PROTOCOL' GUID definition, from older versions +// of gnu-efi, is now obsoleted. +// Use 'EFI_PCI_IO_PROTOCOL_GUID' instead. + +typedef struct _EFI_PCI_IO_PROTOCOL _EFI_PCI_IO; +typedef EFI_PCI_IO_PROTOCOL EFI_PCI_IO; + +typedef struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL { + EFI_HANDLE ParentHandle; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM PollMem; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM PollIo; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Mem; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Io; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Pci; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_COPY_MEM CopyMem; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_MAP Map; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_UNMAP Unmap; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FREE_BUFFER FreeBuffer; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FLUSH Flush; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GET_ATTRIBUTES GetAttributes; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_SET_ATTRIBUTES SetAttributes; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_CONFIGURATION Configuration; + UINT32 SegmentNumber; +} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL; + +#endif /* _EFI_PCI_IO_H */ diff --git a/code/boot/include/efipoint.h b/code/boot/include/efipoint.h new file mode 100644 index 0000000..115a5ca --- /dev/null +++ b/code/boot/include/efipoint.h @@ -0,0 +1,115 @@ +/* Copyright (C) 2014 by John Cronin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef _EFI_POINT_H +#define _EFI_POINT_H + +#define EFI_SIMPLE_POINTER_PROTOCOL_GUID \ + { 0x31878c87, 0xb75, 0x11d5, { 0x9a, 0x4f, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } } + +INTERFACE_DECL(_EFI_SIMPLE_POINTER); + +typedef struct { + INT32 RelativeMovementX; + INT32 RelativeMovementY; + INT32 RelativeMovementZ; + BOOLEAN LeftButton; + BOOLEAN RightButton; +} EFI_SIMPLE_POINTER_STATE; + +typedef struct { + UINT64 ResolutionX; + UINT64 ResolutionY; + UINT64 ResolutionZ; + BOOLEAN LeftButton; + BOOLEAN RightButton; +} EFI_SIMPLE_POINTER_MODE; + +typedef +EFI_STATUS +(EFIAPI* EFI_SIMPLE_POINTER_RESET) ( + IN struct _EFI_SIMPLE_POINTER* This, + IN BOOLEAN ExtendedVerification +); + +typedef +EFI_STATUS +(EFIAPI* EFI_SIMPLE_POINTER_GET_STATE) ( + IN struct _EFI_SIMPLE_POINTER* This, + IN OUT EFI_SIMPLE_POINTER_STATE* State +); + +typedef struct _EFI_SIMPLE_POINTER { + EFI_SIMPLE_POINTER_RESET Reset; + EFI_SIMPLE_POINTER_GET_STATE GetState; + EFI_EVENT WaitForInput; + EFI_SIMPLE_POINTER_MODE* Mode; +} EFI_SIMPLE_POINTER_PROTOCOL; + +#define EFI_ABSOLUTE_POINTER_PROTOCOL_GUID \ + { 0x8D59D32B, 0xC655, 0x4AE9, { 0x9B, 0x15, 0xF2, 0x59, 0x04, 0x99, 0x2A, 0x43 } } + +INTERFACE_DECL(_EFI_ABSOLUTE_POINTER_PROTOCOL); + +typedef struct { + UINT64 AbsoluteMinX; + UINT64 AbsoluteMinY; + UINT64 AbsoluteMinZ; + UINT64 AbsoluteMaxX; + UINT64 AbsoluteMaxY; + UINT64 AbsoluteMaxZ; + UINT32 Attributes; +} EFI_ABSOLUTE_POINTER_MODE; + +typedef struct { + UINT64 CurrentX; + UINT64 CurrentY; + UINT64 CurrentZ; + UINT32 ActiveButtons; +} EFI_ABSOLUTE_POINTER_STATE; + +#define EFI_ABSP_SupportsAltActive 0x00000001 +#define EFI_ABSP_SupportsPressureAsZ 0x00000002 +#define EFI_ABSP_TouchActive 0x00000001 +#define EFI_ABS_AltActive 0x00000002 + +typedef +EFI_STATUS +(EFIAPI* EFI_ABSOLUTE_POINTER_RESET) ( + IN struct _EFI_ABSOLUTE_POINTER_PROTOCOL* This, + IN BOOLEAN ExtendedVerification +); + +typedef +EFI_STATUS +(EFIAPI* EFI_ABSOLUTE_POINTER_GET_STATE) ( + IN struct _EFI_ABSOLUTE_POINTER_PROTOCOL* This, + IN OUT EFI_ABSOLUTE_POINTER_STATE* State +); + +typedef struct _EFI_ABSOLUTE_POINTER_PROTOCOL { + EFI_ABSOLUTE_POINTER_RESET Reset; + EFI_ABSOLUTE_POINTER_GET_STATE GetState; + EFI_EVENT WaitForInput; + EFI_ABSOLUTE_POINTER_MODE* Mode; +} EFI_ABSOLUTE_POINTER_PROTOCOL; + +#endif diff --git a/code/boot/include/efiprot.h b/code/boot/include/efiprot.h new file mode 100644 index 0000000..24f5216 --- /dev/null +++ b/code/boot/include/efiprot.h @@ -0,0 +1,1466 @@ +#ifndef _EFI_PROT_H +#define _EFI_PROT_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efiprot.h + +Abstract: + + EFI Protocols + + + +Revision History + +--*/ + +// +// FPSWA library protocol +// +#define EFI_FPSWA_PROTOCOL_GUID \ + { 0xc41b6531, 0x97b9, 0x11d3, {0x9a, 0x29, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } +#define FPSWA_PROTOCOL EFI_FPSWA_PROTOCOL_GUID + +// +// Device Path protocol +// + +#define EFI_DEVICE_PATH_PROTOCOL_GUID \ + { 0x9576e91, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } +#define DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL_GUID + + +// +// Block IO protocol +// + +#define EFI_BLOCK_IO_PROTOCOL_GUID \ + { 0x964e5b21, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } +#define BLOCK_IO_PROTOCOL EFI_BLOCK_IO_PROTOCOL_GUID + +#define EFI_BLOCK_IO_PROTOCOL_REVISION 0x00010000 +#define EFI_BLOCK_IO_PROTOCOL_REVISION2 0x00020001 +#define EFI_BLOCK_IO_PROTOCOL_REVISION3 ((2<<16) | 31) +#define EFI_BLOCK_IO_INTERFACE_REVISION EFI_BLOCK_IO_PROTOCOL_REVISION +#define EFI_BLOCK_IO_INTERFACE_REVISION2 EFI_BLOCK_IO_PROTOCOL_REVISION2 +#define EFI_BLOCK_IO_INTERFACE_REVISION3 EFI_BLOCK_IO_PROTOCOL_REVISION3 + +INTERFACE_DECL(_EFI_BLOCK_IO_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI* EFI_BLOCK_RESET) ( + IN struct _EFI_BLOCK_IO_PROTOCOL* This, + IN BOOLEAN ExtendedVerification + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_BLOCK_READ) ( + IN struct _EFI_BLOCK_IO_PROTOCOL* This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID* Buffer + ); + + +typedef +EFI_STATUS +(EFIAPI* EFI_BLOCK_WRITE) ( + IN struct _EFI_BLOCK_IO_PROTOCOL* This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + IN VOID* Buffer + ); + + +typedef +EFI_STATUS +(EFIAPI* EFI_BLOCK_FLUSH) ( + IN struct _EFI_BLOCK_IO_PROTOCOL* This + ); + + + +typedef struct { + UINT32 MediaId; + BOOLEAN RemovableMedia; + BOOLEAN MediaPresent; + + BOOLEAN LogicalPartition; + BOOLEAN ReadOnly; + BOOLEAN WriteCaching; + + UINT32 BlockSize; + UINT32 IoAlign; + + EFI_LBA LastBlock; + + /* revision 2 */ + EFI_LBA LowestAlignedLba; + UINT32 LogicalBlocksPerPhysicalBlock; + /* revision 3 */ + UINT32 OptimalTransferLengthGranularity; +} EFI_BLOCK_IO_MEDIA; + +typedef struct _EFI_BLOCK_IO_PROTOCOL { + UINT64 Revision; + + EFI_BLOCK_IO_MEDIA* Media; + + EFI_BLOCK_RESET Reset; + EFI_BLOCK_READ ReadBlocks; + EFI_BLOCK_WRITE WriteBlocks; + EFI_BLOCK_FLUSH FlushBlocks; + +} EFI_BLOCK_IO_PROTOCOL; + +typedef struct _EFI_BLOCK_IO_PROTOCOL _EFI_BLOCK_IO; +typedef EFI_BLOCK_IO_PROTOCOL EFI_BLOCK_IO; + +#define EFI_BLOCK_IO2_PROTOCOL_GUID \ + { 0xa77b2472, 0xe282, 0x4e9f, {0xa2, 0x45, 0xc2, 0xc0, 0xe2, 0x7b, 0xbc, 0xc1} } + +INTERFACE_DECL(_EFI_BLOCK_IO2_PROTOCOL); + +typedef struct { + EFI_EVENT Event; + EFI_STATUS TransactionStatus; +} EFI_BLOCK_IO2_TOKEN; + +typedef +EFI_STATUS +(EFIAPI* EFI_BLOCK_RESET_EX) ( + IN struct _EFI_BLOCK_IO2_PROTOCOL* This, + IN BOOLEAN ExtendedVerification + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_BLOCK_READ_EX) ( + IN struct _EFI_BLOCK_IO2_PROTOCOL* This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN OUT EFI_BLOCK_IO2_TOKEN* Token, + IN UINTN BufferSize, + OUT VOID* Buffer + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_BLOCK_WRITE_EX) ( + IN struct _EFI_BLOCK_IO2_PROTOCOL* This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN OUT EFI_BLOCK_IO2_TOKEN* Token, + IN UINTN BufferSize, + IN VOID* Buffer + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_BLOCK_FLUSH_EX) ( + IN struct _EFI_BLOCK_IO2_PROTOCOL* This, + IN OUT EFI_BLOCK_IO2_TOKEN* Token + ); + +typedef struct _EFI_BLOCK_IO2_PROTOCOL { + EFI_BLOCK_IO_MEDIA* Media; + EFI_BLOCK_RESET_EX Reset; + EFI_BLOCK_READ_EX ReadBlocksEx; + EFI_BLOCK_WRITE_EX WriteBlocksEx; + EFI_BLOCK_FLUSH_EX FlushBlocksEx; +} EFI_BLOCK_IO2_PROTOCOL; + +// +// Disk Block IO protocol +// + +#define EFI_DISK_IO_PROTOCOL_GUID \ + { 0xce345171, 0xba0b, 0x11d2, {0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } +#define DISK_IO_PROTOCOL EFI_DISK_IO_PROTOCOL_GUID + +#define EFI_DISK_IO_PROTOCOL_REVISION 0x00010000 +#define EFI_DISK_IO_INTERFACE_REVISION EFI_DISK_IO_PROTOCOL_REVISION + +INTERFACE_DECL(_EFI_DISK_IO_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI* EFI_DISK_READ) ( + IN struct _EFI_DISK_IO_PROTOCOL* This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN UINTN BufferSize, + OUT VOID* Buffer + ); + + +typedef +EFI_STATUS +(EFIAPI* EFI_DISK_WRITE) ( + IN struct _EFI_DISK_IO_PROTOCOL* This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN UINTN BufferSize, + IN VOID* Buffer + ); + + +typedef struct _EFI_DISK_IO_PROTOCOL { + UINT64 Revision; + EFI_DISK_READ ReadDisk; + EFI_DISK_WRITE WriteDisk; +} EFI_DISK_IO_PROTOCOL; + +typedef struct _EFI_DISK_IO_PROTOCOL _EFI_DISK_IO; +typedef EFI_DISK_IO_PROTOCOL EFI_DISK_IO; + + +#define EFI_DISK_IO2_PROTOCOL_GUID \ + { 0x151c8eae, 0x7f2c, 0x472c, {0x9e, 0x54, 0x98, 0x28, 0x19, 0x4f, 0x6a, 0x88} } + +#define EFI_DISK_IO2_PROTOCOL_REVISION 0x00020000 + +INTERFACE_DECL(_EFI_DISK_IO2_PROTOCOL); + +typedef struct { + EFI_EVENT Event; + EFI_STATUS TransactionStatus; +} EFI_DISK_IO2_TOKEN; + +typedef +EFI_STATUS +(EFIAPI* EFI_DISK_CANCEL_EX) ( + IN struct _EFI_DISK_IO2_PROTOCOL* This + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_DISK_READ_EX) ( + IN struct _EFI_DISK_IO2_PROTOCOL* This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN OUT EFI_DISK_IO2_TOKEN* Token, + IN UINTN BufferSize, + OUT VOID* Buffer + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_DISK_WRITE_EX) ( + IN struct _EFI_DISK_IO2_PROTOCOL* This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN OUT EFI_DISK_IO2_TOKEN* Token, + IN UINTN BufferSize, + IN VOID* Buffer + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_DISK_FLUSH_EX) ( + IN struct _EFI_DISK_IO2_PROTOCOL* This, + IN OUT EFI_DISK_IO2_TOKEN* Token + ); + +typedef struct _EFI_DISK_IO2_PROTOCOL { + UINT64 Revision; + EFI_DISK_CANCEL_EX Cancel; + EFI_DISK_READ_EX ReadDiskEx; + EFI_DISK_WRITE_EX WriteDiskEx; + EFI_DISK_FLUSH_EX FlushDiskEx; +} EFI_DISK_IO2_PROTOCOL; + +// +// Simple file system protocol +// + +#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \ + { 0x964e5b22, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } +#define SIMPLE_FILE_SYSTEM_PROTOCOL EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID + +INTERFACE_DECL(_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL); +INTERFACE_DECL(_EFI_FILE_HANDLE); + +typedef +EFI_STATUS +(EFIAPI* EFI_VOLUME_OPEN) ( + IN struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* This, + OUT struct _EFI_FILE_HANDLE **Root + ); + +#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION 0x00010000 +#define EFI_FILE_IO_INTERFACE_REVISION EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION + +typedef struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL { + UINT64 Revision; + EFI_VOLUME_OPEN OpenVolume; +} EFI_SIMPLE_FILE_SYSTEM_PROTOCOL; + +typedef struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL _EFI_FILE_IO_INTERFACE; +typedef EFI_SIMPLE_FILE_SYSTEM_PROTOCOL EFI_FILE_IO_INTERFACE; + +// +// +// + +typedef +EFI_STATUS +(EFIAPI* EFI_FILE_OPEN) ( + IN struct _EFI_FILE_HANDLE* File, + OUT struct _EFI_FILE_HANDLE **NewHandle, + IN CHAR16* FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ); + +// Open modes +#define EFI_FILE_MODE_READ 0x0000000000000001 +#define EFI_FILE_MODE_WRITE 0x0000000000000002 +#define EFI_FILE_MODE_CREATE 0x8000000000000000 + +// File attributes +#define EFI_FILE_READ_ONLY 0x0000000000000001 +#define EFI_FILE_HIDDEN 0x0000000000000002 +#define EFI_FILE_SYSTEM 0x0000000000000004 +#define EFI_FILE_RESERVIED 0x0000000000000008 +#define EFI_FILE_DIRECTORY 0x0000000000000010 +#define EFI_FILE_ARCHIVE 0x0000000000000020 +#define EFI_FILE_VALID_ATTR 0x0000000000000037 + +typedef +EFI_STATUS +(EFIAPI* EFI_FILE_CLOSE) ( + IN struct _EFI_FILE_HANDLE* File + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_FILE_DELETE) ( + IN struct _EFI_FILE_HANDLE* File + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_FILE_READ) ( + IN struct _EFI_FILE_HANDLE* File, + IN OUT UINTN* BufferSize, + OUT VOID* Buffer + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_FILE_WRITE) ( + IN struct _EFI_FILE_HANDLE* File, + IN OUT UINTN* BufferSize, + IN VOID* Buffer + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_FILE_SET_POSITION) ( + IN struct _EFI_FILE_HANDLE* File, + IN UINT64 Position + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_FILE_GET_POSITION) ( + IN struct _EFI_FILE_HANDLE* File, + OUT UINT64* Position + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_FILE_GET_INFO) ( + IN struct _EFI_FILE_HANDLE* File, + IN EFI_GUID* InformationType, + IN OUT UINTN* BufferSize, + OUT VOID* Buffer + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_FILE_SET_INFO) ( + IN struct _EFI_FILE_HANDLE* File, + IN EFI_GUID* InformationType, + IN UINTN BufferSize, + IN VOID* Buffer + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_FILE_FLUSH) ( + IN struct _EFI_FILE_HANDLE* File + ); + +typedef struct { + EFI_EVENT Event; + EFI_STATUS Status; + UINTN BufferSize; + VOID* Buffer; +} EFI_FILE_IO_TOKEN; + +typedef +EFI_STATUS +(EFIAPI* EFI_FILE_OPEN_EX)( + IN struct _EFI_FILE_HANDLE* File, + OUT struct _EFI_FILE_HANDLE **NewHandle, + IN CHAR16* FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes, + IN OUT EFI_FILE_IO_TOKEN* Token + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_FILE_READ_EX) ( + IN struct _EFI_FILE_HANDLE* File, + IN OUT EFI_FILE_IO_TOKEN* Token + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_FILE_WRITE_EX) ( + IN struct _EFI_FILE_HANDLE* File, + IN OUT EFI_FILE_IO_TOKEN* Token + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_FILE_FLUSH_EX) ( + IN struct _EFI_FILE_HANDLE* File, + IN OUT EFI_FILE_IO_TOKEN* Token + ); + +#define EFI_FILE_PROTOCOL_REVISION 0x00010000 +#define EFI_FILE_PROTOCOL_REVISION2 0x00020000 +#define EFI_FILE_PROTOCOL_LATEST_REVISION EFI_FILE_PROTOCOL_REVISION2 +#define EFI_FILE_HANDLE_REVISION EFI_FILE_PROTOCOL_REVISION + +typedef struct _EFI_FILE_HANDLE { + UINT64 Revision; + EFI_FILE_OPEN Open; + EFI_FILE_CLOSE Close; + EFI_FILE_DELETE Delete; + EFI_FILE_READ Read; + EFI_FILE_WRITE Write; + EFI_FILE_GET_POSITION GetPosition; + EFI_FILE_SET_POSITION SetPosition; + EFI_FILE_GET_INFO GetInfo; + EFI_FILE_SET_INFO SetInfo; + EFI_FILE_FLUSH Flush; + EFI_FILE_OPEN_EX OpenEx; + EFI_FILE_READ_EX ReadEx; + EFI_FILE_WRITE_EX WriteEx; + EFI_FILE_FLUSH_EX FlushEx; +} EFI_FILE_PROTOCOL, *EFI_FILE_HANDLE; + +typedef EFI_FILE_PROTOCOL EFI_FILE; + + +// +// File information types +// + +#define EFI_FILE_INFO_ID \ + { 0x9576e92, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +typedef struct { + UINT64 Size; + UINT64 FileSize; + UINT64 PhysicalSize; + EFI_TIME CreateTime; + EFI_TIME LastAccessTime; + EFI_TIME ModificationTime; + UINT64 Attribute; + CHAR16 FileName[1]; +} EFI_FILE_INFO; + +// +// The FileName field of the EFI_FILE_INFO data structure is variable length. +// Whenever code needs to know the size of the EFI_FILE_INFO data structure, it needs to +// be the size of the data structure without the FileName field. The following macro +// computes this size correctly no matter how big the FileName array is declared. +// This is required to make the EFI_FILE_INFO data structure ANSI compilant. +// + +#define SIZE_OF_EFI_FILE_INFO EFI_FIELD_OFFSET(EFI_FILE_INFO,FileName) + +#define EFI_FILE_SYSTEM_INFO_ID \ + { 0x9576e93, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +typedef struct { + UINT64 Size; + BOOLEAN ReadOnly; + UINT64 VolumeSize; + UINT64 FreeSpace; + UINT32 BlockSize; + CHAR16 VolumeLabel[1]; +} EFI_FILE_SYSTEM_INFO; + +// +// The VolumeLabel field of the EFI_FILE_SYSTEM_INFO data structure is variable length. +// Whenever code needs to know the size of the EFI_FILE_SYSTEM_INFO data structure, it needs +// to be the size of the data structure without the VolumeLable field. The following macro +// computes this size correctly no matter how big the VolumeLable array is declared. +// This is required to make the EFI_FILE_SYSTEM_INFO data structure ANSI compilant. +// + +#define SIZE_OF_EFI_FILE_SYSTEM_INFO EFI_FIELD_OFFSET(EFI_FILE_SYSTEM_INFO,VolumeLabel) + +#define EFI_FILE_SYSTEM_VOLUME_LABEL_ID \ + { 0xDB47D7D3,0xFE81, 0x11d3, {0x9A, 0x35, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D} } + +typedef struct { + CHAR16 VolumeLabel[1]; +} EFI_FILE_SYSTEM_VOLUME_LABEL; + +#define SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO EFI_FIELD_OFFSET(EFI_FILE_SYSTEM_VOLUME_LABEL,VolumeLabel) + +// +// For compatibility with older versions of gnu-efi +// +#define EFI_FILE_SYSTEM_VOLUME_LABEL_INFO_ID EFI_FILE_SYSTEM_VOLUME_LABEL_ID +#define EFI_FILE_SYSTEM_VOLUME_LABEL_INFO EFI_FILE_SYSTEM_VOLUME_LABEL + +// +// Load file protocol +// + + +#define EFI_LOAD_FILE_PROTOCOL_GUID \ + { 0x56EC3091, 0x954C, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B} } +#define LOAD_FILE_PROTOCOL EFI_LOAD_FILE_PROTOCOL_GUID + +INTERFACE_DECL(_EFI_LOAD_FILE_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI* EFI_LOAD_FILE) ( + IN struct _EFI_LOAD_FILE_PROTOCOL* This, + IN EFI_DEVICE_PATH* FilePath, + IN BOOLEAN BootPolicy, + IN OUT UINTN* BufferSize, + IN VOID* Buffer OPTIONAL + ); + +typedef struct _EFI_LOAD_FILE_PROTOCOL { + EFI_LOAD_FILE LoadFile; +} EFI_LOAD_FILE_PROTOCOL; + +typedef struct _EFI_LOAD_FILE_PROTOCOL _EFI_LOAD_FILE_INTERFACE; +typedef EFI_LOAD_FILE_PROTOCOL EFI_LOAD_FILE_INTERFACE; + +// +// Device IO protocol +// + +#define EFI_DEVICE_IO_PROTOCOL_GUID \ + { 0xaf6ac311, 0x84c3, 0x11d2, {0x8e, 0x3c, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } +#define DEVICE_IO_PROTOCOL EFI_DEVICE_IO_PROTOCOL_GUID + +INTERFACE_DECL(_EFI_DEVICE_IO_PROTOCOL); + +typedef enum { + IO_UINT8, + IO_UINT16, + IO_UINT32, + IO_UINT64, +// +// Specification Change: Copy from MMIO to MMIO vs. MMIO to buffer, buffer to MMIO +// + MMIO_COPY_UINT8, + MMIO_COPY_UINT16, + MMIO_COPY_UINT32, + MMIO_COPY_UINT64 +} EFI_IO_WIDTH; + +#define EFI_PCI_ADDRESS(_bus,_dev,_func) \ + ( (UINT64) ( (((UINTN)_bus) << 24) + (((UINTN)_dev) << 16) + (((UINTN)_func) << 8) ) ) + + +typedef +EFI_STATUS +(EFIAPI* EFI_DEVICE_IO) ( + IN struct _EFI_DEVICE_IO_PROTOCOL* This, + IN EFI_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID* Buffer + ); + +typedef struct { + EFI_DEVICE_IO Read; + EFI_DEVICE_IO Write; +} EFI_IO_ACCESS; + +typedef +EFI_STATUS +(EFIAPI* EFI_PCI_DEVICE_PATH) ( + IN struct _EFI_DEVICE_IO_PROTOCOL* This, + IN UINT64 Address, + IN OUT EFI_DEVICE_PATH **PciDevicePath + ); + +typedef enum { + EfiBusMasterRead, + EfiBusMasterWrite, + EfiBusMasterCommonBuffer +} EFI_IO_OPERATION_TYPE; + +typedef +EFI_STATUS +(EFIAPI* EFI_IO_MAP) ( + IN struct _EFI_DEVICE_IO_PROTOCOL* This, + IN EFI_IO_OPERATION_TYPE Operation, + IN EFI_PHYSICAL_ADDRESS* HostAddress, + IN OUT UINTN* NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS* DeviceAddress, + OUT VOID **Mapping + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_IO_UNMAP) ( + IN struct _EFI_DEVICE_IO_PROTOCOL* This, + IN VOID* Mapping + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_IO_ALLOCATE_BUFFER) ( + IN struct _EFI_DEVICE_IO_PROTOCOL* This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT EFI_PHYSICAL_ADDRESS* HostAddress + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_IO_FLUSH) ( + IN struct _EFI_DEVICE_IO_PROTOCOL* This + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_IO_FREE_BUFFER) ( + IN struct _EFI_DEVICE_IO_PROTOCOL* This, + IN UINTN Pages, + IN EFI_PHYSICAL_ADDRESS HostAddress + ); + +typedef struct _EFI_DEVICE_IO_PROTOCOL { + EFI_IO_ACCESS Mem; + EFI_IO_ACCESS Io; + EFI_IO_ACCESS Pci; + EFI_IO_MAP Map; + EFI_PCI_DEVICE_PATH PciDevicePath; + EFI_IO_UNMAP Unmap; + EFI_IO_ALLOCATE_BUFFER AllocateBuffer; + EFI_IO_FLUSH Flush; + EFI_IO_FREE_BUFFER FreeBuffer; +} EFI_DEVICE_IO_PROTOCOL; + +typedef struct _EFI_DEVICE_IO_PROTOCOL _EFI_DEVICE_IO_INTERFACE; +typedef EFI_DEVICE_IO_PROTOCOL EFI_DEVICE_IO_INTERFACE; + +// +// Unicode Collation protocol +// + +#define EFI_UNICODE_COLLATION_PROTOCOL_GUID \ + { 0x1d85cd7f, 0xf43d, 0x11d2, {0x9a, 0xc, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } +#define UNICODE_COLLATION_PROTOCOL EFI_UNICODE_COLLATION_PROTOCOL_GUID + +#define EFI_UNICODE_BYTE_ORDER_MARK (CHAR16)(0xfeff) +#define UNICODE_BYTE_ORDER_MARK EFI_UNICODE_BYTE_ORDER_MARK + +INTERFACE_DECL(_EFI_UNICODE_COLLATION_PROTOCOL); + +typedef +INTN +(EFIAPI* EFI_UNICODE_STRICOLL) ( + IN struct _EFI_UNICODE_COLLATION_PROTOCOL* This, + IN CHAR16* s1, + IN CHAR16* s2 + ); + +typedef +BOOLEAN +(EFIAPI* EFI_UNICODE_METAIMATCH) ( + IN struct _EFI_UNICODE_COLLATION_PROTOCOL* This, + IN CHAR16* String, + IN CHAR16* Pattern + ); + +typedef +VOID +(EFIAPI* EFI_UNICODE_STRLWR) ( + IN struct _EFI_UNICODE_COLLATION_PROTOCOL* This, + IN OUT CHAR16* Str + ); + +typedef +VOID +(EFIAPI* EFI_UNICODE_STRUPR) ( + IN struct _EFI_UNICODE_COLLATION_PROTOCOL* This, + IN OUT CHAR16* Str + ); + +typedef +VOID +(EFIAPI* EFI_UNICODE_FATTOSTR) ( + IN struct _EFI_UNICODE_COLLATION_PROTOCOL* This, + IN UINTN FatSize, + IN CHAR8* Fat, + OUT CHAR16* String + ); + +typedef +BOOLEAN +(EFIAPI* EFI_UNICODE_STRTOFAT) ( + IN struct _EFI_UNICODE_COLLATION_PROTOCOL* This, + IN CHAR16* String, + IN UINTN FatSize, + OUT CHAR8* Fat + ); + +// +// Hash Protocol +// +#define EFI_HASH_PROTOCOL_GUID \ + { 0xC5184932, 0xDBA5, 0x46DB, { 0xA5, 0xBA, 0xCC, 0x0B, 0xDA, 0x9C, 0x14, 0x35 } } +#define HASH_PROTOCOL EFI_HASH_PROTOCOL_GUID + +#define EFI_HASH_ALGORITHM_SHA1_GUID \ + { 0x2AE9D80F, 0x3FB2, 0x4095, { 0xB7, 0xB1, 0xE9, 0x31, 0x57, 0xB9, 0x46, 0xB6 } } // Deprecated +#define EFI_HASH_ALGORITHM_SHA1 EFI_HASH_ALGORITHM_SHA1_GUID + +#define EFI_HASH_ALGORITHM_SHA224_GUID \ + { 0x8DF01A06, 0x9BD5, 0x4BF7, { 0xB0, 0x21, 0xDB, 0x4F, 0xD9, 0xCC, 0xF4, 0x5B } } // Deprecated +#define EFI_HASH_ALGORITHM_SHA224 EFI_HASH_ALGORITHM_SHA224_GUID + +#define EFI_HASH_ALGORITHM_SHA256_GUID \ + { 0x51AA59DE, 0xFDF2, 0x4EA3, { 0xBC, 0x63, 0x87, 0x5F, 0xB7, 0x84, 0x2E, 0xE9 } } // Deprecated +#define EFI_HASH_ALGORITHM_SHA256 EFI_HASH_ALGORITHM_SHA256_GUID + +#define EFI_HASH_ALGORITHM_SHA384_GUID \ + { 0xEFA96432, 0xDE33, 0x4DD2, { 0xAE, 0xE6, 0x32, 0x8C, 0x33, 0xDF, 0x77, 0x7A } } // Deprecated +#define EFI_HASH_ALGORITHM_SHA384 EFI_HASH_ALGORITHM_SHA384_GUID + +#define EFI_HASH_ALGORITHM_SHA512_GUID \ + { 0xCAA4381E, 0x750C, 0x4770, { 0xB8, 0x70, 0x7A, 0x23, 0xB4, 0xE4, 0x21, 0x30 } } // Deprecated +#define EFI_HASH_ALGORITHM_SHA512 EFI_HASH_ALGORITHM_SHA512_GUID + +#define EFI_HASH_ALGORITHM_MD5_GUID \ + { 0x0AF7C79C, 0x65B5, 0x4319, { 0xB0, 0xAE, 0x44, 0xEC, 0x48, 0x4E, 0x4A, 0xD7 } } // Deprecated +#define EFI_HASH_ALGORITHM_MD5 EFI_HASH_ALGORITHM_MD5_GUID + +#define EFI_HASH_ALGORITHM_SHA1_NOPAD_GUID \ + { 0x24C5DC2F, 0x53E2, 0x40CA, { 0x9E, 0xD6, 0xA5, 0xD9, 0xA4, 0x9F, 0x46, 0x3B } } +#define EFI_HASH_ALGORITHM_SHA1_NOPAD EFI_HASH_ALGORITHM_SHA1_NOPAD_GUID + +#define EFI_HASH_ALGORITHM_SHA256_NOPAD_GUID \ + { 0x8628752A, 0x6CB7, 0x4814, { 0x96, 0xFC, 0x24, 0xA8, 0x15, 0xAC, 0x22, 0x26 } } +#define EFI_HASH_ALGORITHM_SHA256_NOPAD EFI_HASH_ALGORITHM_SHA256_NOPAD_GUID + + +INTERFACE_DECL(_EFI_HASH_PROTOCOL); + +typedef UINT8 EFI_MD5_HASH[16]; +typedef UINT8 EFI_SHA1_HASH[20]; +typedef UINT8 EFI_SHA224_HASH[28]; +typedef UINT8 EFI_SHA256_HASH[32]; +typedef UINT8 EFI_SHA384_HASH[48]; +typedef UINT8 EFI_SHA512_HASH[64]; +typedef union _EFI_HASH_OUTPUT { + EFI_MD5_HASH* Md5Hash; + EFI_SHA1_HASH* Sha1Hash; + EFI_SHA224_HASH* Sha224Hash; + EFI_SHA256_HASH* Sha256Hash; + EFI_SHA384_HASH* Sha384Hash; + EFI_SHA512_HASH* Sha512Hash; +} EFI_HASH_OUTPUT; + +typedef +EFI_STATUS +(EFIAPI* EFI_HASH_GET_HASH_SIZE) ( + IN CONST struct _EFI_HASH_PROTOCOL* This, + IN CONST EFI_GUID* HashAlgorithm, + OUT UINTN* HashSize); + +typedef +EFI_STATUS +(EFIAPI* EFI_HASH_HASH) ( + IN CONST struct _EFI_HASH_PROTOCOL* This, + IN CONST EFI_GUID* HashAlgorithm, + IN BOOLEAN Extend, + IN CONST UINT8* Message, + IN UINT64 MessageSize, + IN OUT EFI_HASH_OUTPUT* Hash); + +typedef struct _EFI_HASH_PROTOCOL { + EFI_HASH_GET_HASH_SIZE GetHashSize; + EFI_HASH_HASH Hash; +} EFI_HASH_PROTOCOL; + +typedef struct _EFI_HASH_PROTOCOL _EFI_HASH; +typedef EFI_HASH_PROTOCOL EFI_HASH; + + +typedef struct _EFI_UNICODE_COLLATION_PROTOCOL { + + // general + EFI_UNICODE_STRICOLL StriColl; + EFI_UNICODE_METAIMATCH MetaiMatch; + EFI_UNICODE_STRLWR StrLwr; + EFI_UNICODE_STRUPR StrUpr; + + // for supporting fat volumes + EFI_UNICODE_FATTOSTR FatToStr; + EFI_UNICODE_STRTOFAT StrToFat; + + CHAR8* SupportedLanguages; +} EFI_UNICODE_COLLATION_PROTOCOL; + +typedef EFI_UNICODE_COLLATION_PROTOCOL EFI_UNICODE_COLLATION_INTERFACE; + +/* Graphics output protocol */ +#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \ + { 0x9042a9de, 0x23dc, 0x4a38, {0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a } } +typedef struct _EFI_GRAPHICS_OUTPUT_PROTOCOL EFI_GRAPHICS_OUTPUT_PROTOCOL; + +typedef struct { + UINT32 RedMask; + UINT32 GreenMask; + UINT32 BlueMask; + UINT32 ReservedMask; +} EFI_PIXEL_BITMASK; + +typedef enum { + PixelRedGreenBlueReserved8BitPerColor, + PixelBlueGreenRedReserved8BitPerColor, + PixelBitMask, + PixelBltOnly, + PixelFormatMax +} EFI_GRAPHICS_PIXEL_FORMAT; + +typedef struct { + UINT32 Version; + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; + EFI_PIXEL_BITMASK PixelInformation; + UINT32 PixelsPerScanLine; +} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION; + +/** + Return the current video mode information. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to return information on. + @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer. + @param Info A pointer to callee allocated buffer that returns information about ModeNumber. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode. + @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode () + @retval EFI_INVALID_PARAMETER One of the input args was NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI* EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE) ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL* This, + IN UINT32 ModeNumber, + OUT UINTN* SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ) +; + +/** + Return the current video mode information. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to be set. + + @retval EFI_SUCCESS Graphics mode was changed. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED ModeNumber is not supported by this device. + +**/ +typedef +EFI_STATUS +(EFIAPI* EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE) ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL* This, + IN UINT32 ModeNumber + ); + +typedef struct { + UINT8 Blue; + UINT8 Green; + UINT8 Red; + UINT8 Reserved; +} EFI_GRAPHICS_OUTPUT_BLT_PIXEL; + +typedef union { + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Pixel; + UINT32 Raw; +} EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION; + +typedef enum { + EfiBltVideoFill, + EfiBltVideoToBltBuffer, + EfiBltBufferToVideo, + EfiBltVideoToVideo, + EfiGraphicsOutputBltOperationMax +} EFI_GRAPHICS_OUTPUT_BLT_OPERATION; + +/** + The following table defines actions for BltOperations: + + EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY) + directly to every pixel of the video display rectangle + (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). + Only one pixel will be used from the BltBuffer. Delta is NOT used. + + EfiBltVideoToBltBuffer - Read data from the video display rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in + the BltBuffer rectangle (DestinationX, DestinationY ) + (DestinationX + Width, DestinationY + Height). If DestinationX or + DestinationY is not zero then Delta must be set to the length in bytes + of a row in the BltBuffer. + + EfiBltBufferToVideo - Write data from the BltBuffer rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the + video display rectangle (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is + not zero then Delta must be set to the length in bytes of a row in the + BltBuffer. + + EfiBltVideoToVideo - Copy from the video display rectangle (SourceX, SourceY) + (SourceX + Width, SourceY + Height) .to the video display rectangle + (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). + The BltBuffer and Delta are not used in this mode. + + @param This Protocol instance pointer. + @param BltBuffer Buffer containing data to blit into video buffer. This + buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + @param BltOperation Operation to perform on BlitBuffer and video memory + @param SourceX X coordinate of source for the BltBuffer. + @param SourceY Y coordinate of source for the BltBuffer. + @param DestinationX X coordinate of destination for the BltBuffer. + @param DestinationY Y coordinate of destination for the BltBuffer. + @param Width Width of rectangle in BltBuffer in pixels. + @param Height Hight of rectangle in BltBuffer in pixels. + @param Delta OPTIONAL + + @retval EFI_SUCCESS The Blt operation completed. + @retval EFI_INVALID_PARAMETER BltOperation is not valid. + @retval EFI_DEVICE_ERROR A hardware error occured writting to the video buffer. + +**/ +typedef +EFI_STATUS +(EFIAPI* EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT) ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL* This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL* BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ); + +typedef struct { + UINT32 MaxMode; + UINT32 Mode; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* Info; + UINTN SizeOfInfo; + EFI_PHYSICAL_ADDRESS FrameBufferBase; + UINTN FrameBufferSize; +} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE; + +struct _EFI_GRAPHICS_OUTPUT_PROTOCOL { + EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE QueryMode; + EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE SetMode; + EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT Blt; + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE* Mode; +}; + + + +/* + * EFI EDID Discovered Protocol + * UEFI Specification Version 2.5 Section 11.9 + */ +#define EFI_EDID_DISCOVERED_PROTOCOL_GUID \ + { 0x1C0C34F6, 0xD380, 0x41FA, { 0xA0, 0x49, 0x8a, 0xD0, 0x6C, 0x1A, 0x66, 0xAA} } + +typedef struct _EFI_EDID_DISCOVERED_PROTOCOL { + UINT32 SizeOfEdid; + UINT8* Edid; +} EFI_EDID_DISCOVERED_PROTOCOL; + + + +/* + * EFI EDID Active Protocol + * UEFI Specification Version 2.5 Section 11.9 + */ +#define EFI_EDID_ACTIVE_PROTOCOL_GUID \ + { 0xBD8C1056, 0x9F36, 0x44EC, { 0x92, 0xA8, 0xA6, 0x33, 0x7F, 0x81, 0x79, 0x86} } + +typedef struct _EFI_EDID_ACTIVE_PROTOCOL { + UINT32 SizeOfEdid; + UINT8* Edid; +} EFI_EDID_ACTIVE_PROTOCOL; + + + +/* + * EFI EDID Override Protocol + * UEFI Specification Version 2.5 Section 11.9 + */ +#define EFI_EDID_OVERRIDE_PROTOCOL_GUID \ + { 0x48ECB431, 0xFB72, 0x45C0, { 0xA9, 0x22, 0xF4, 0x58, 0xFE, 0x04, 0x0B, 0xD5} } + +INTERFACE_DECL(_EFI_EDID_OVERRIDE_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI* EFI_EDID_OVERRIDE_PROTOCOL_GET_EDID) ( + IN struct _EFI_EDID_OVERRIDE_PROTOCOL* This, + IN EFI_HANDLE* ChildHandle, + OUT UINT32* Attributes, + IN OUT UINTN* EdidSize, + IN OUT UINT8 **Edid); + +typedef struct _EFI_EDID_OVERRIDE_PROTOCOL { + EFI_EDID_OVERRIDE_PROTOCOL_GET_EDID GetEdid; +} EFI_EDID_OVERRIDE_PROTOCOL; + + + +INTERFACE_DECL(_EFI_SERVICE_BINDING); + +typedef +EFI_STATUS +(EFIAPI* EFI_SERVICE_BINDING_CREATE_CHILD) ( + IN struct _EFI_SERVICE_BINDING* This, + IN EFI_HANDLE* ChildHandle + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SERVICE_BINDING_DESTROY_CHILD) ( + IN struct _EFI_SERVICE_BINDING* This, + IN EFI_HANDLE ChildHandle + ); + +typedef struct _EFI_SERVICE_BINDING { + EFI_SERVICE_BINDING_CREATE_CHILD CreateChild; + EFI_SERVICE_BINDING_DESTROY_CHILD DestroyChild; +} EFI_SERVICE_BINDING; + + + +/* + * EFI Driver Binding Protocol + * UEFI Specification Version 2.5 Section 10.1 + */ +#define EFI_DRIVER_BINDING_PROTOCOL_GUID \ + { 0x18A031AB, 0xB443, 0x4D1A, { 0xA5, 0xC0, 0x0C, 0x09, 0x26, 0x1E, 0x9F, 0x71} } +#define DRIVER_BINDING_PROTOCOL EFI_DRIVER_BINDING_PROTOCOL_GUID + +INTERFACE_DECL(_EFI_DRIVER_BINDING_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI* EFI_DRIVER_BINDING_PROTOCOL_SUPPORTED) ( + IN struct _EFI_DRIVER_BINDING_PROTOCOL* This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH* RemainingDevicePath OPTIONAL); + +typedef +EFI_STATUS +(EFIAPI* EFI_DRIVER_BINDING_PROTOCOL_START) ( + IN struct _EFI_DRIVER_BINDING_PROTOCOL* This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH* RemainingDevicePath OPTIONAL); + +typedef +EFI_STATUS +(EFIAPI* EFI_DRIVER_BINDING_PROTOCOL_STOP) ( + IN struct _EFI_DRIVER_BINDING_PROTOCOL* This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE* ChildHandleBuffer OPTIONAL); + +typedef struct _EFI_DRIVER_BINDING_PROTOCOL { + EFI_DRIVER_BINDING_PROTOCOL_SUPPORTED Supported; + EFI_DRIVER_BINDING_PROTOCOL_START Start; + EFI_DRIVER_BINDING_PROTOCOL_STOP Stop; + UINT32 Version; + EFI_HANDLE ImageHandle; + EFI_HANDLE DriverBindingHandle; +} EFI_DRIVER_BINDING_PROTOCOL; + +typedef struct _EFI_DRIVER_BINDING_PROTOCOL _EFI_DRIVER_BINDING; +typedef EFI_DRIVER_BINDING_PROTOCOL EFI_DRIVER_BINDING; + + +/* + * Backwards compatibility with older GNU-EFI versions. Deprecated. + */ +#define EFI_DRIVER_SUPPORTED EFI_DRIVER_BINDING_PROTOCOL_SUPPORTED +#define EFI_DRIVER_START EFI_DRIVER_BINDING_PROTOCOL_START +#define EFI_DRIVER_STOP EFI_DRIVER_BINDING_PROTOCOL_STOP + + + +/* + * EFI Component Name Protocol + * Deprecated - use EFI Component Name 2 Protocol instead + */ +#define EFI_COMPONENT_NAME_PROTOCOL_GUID \ + {0x107A772C, 0xD5E1, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D} } +#define COMPONENT_NAME_PROTOCOL EFI_COMPONENT_NAME_PROTOCOL_GUID + +INTERFACE_DECL(_EFI_COMPONENT_NAME_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI* EFI_COMPONENT_NAME_GET_DRIVER_NAME) ( + IN struct _EFI_COMPONENT_NAME_PROTOCOL* This, + IN CHAR8* Language, + OUT CHAR16 **DriverName); + +typedef +EFI_STATUS +(EFIAPI* EFI_COMPONENT_NAME_GET_CONTROLLER_NAME) ( + IN struct _EFI_COMPONENT_NAME_PROTOCOL* This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8* Language, + OUT CHAR16 **ControllerName); + +typedef struct _EFI_COMPONENT_NAME_PROTOCOL { + EFI_COMPONENT_NAME_GET_DRIVER_NAME GetDriverName; + EFI_COMPONENT_NAME_GET_CONTROLLER_NAME GetControllerName; + CHAR8* SupportedLanguages; +} EFI_COMPONENT_NAME_PROTOCOL; + +typedef struct _EFI_COMPONENT_NAME_PROTOCOL _EFI_COMPONENT_NAME; +typedef EFI_COMPONENT_NAME_PROTOCOL EFI_COMPONENT_NAME; + + +/* + * EFI Component Name 2 Protocol + * UEFI Specification Version 2.5 Section 10.5 + */ +#define EFI_COMPONENT_NAME2_PROTOCOL_GUID \ + {0x6A7A5CFF, 0xE8D9, 0x4F70, { 0xBA, 0xDA, 0x75, 0xAB, 0x30, 0x25, 0xCE, 0x14} } +#define COMPONENT_NAME2_PROTOCOL EFI_COMPONENT_NAME2_PROTOCOL_GUID + +INTERFACE_DECL(_EFI_COMPONENT_NAME2_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI* EFI_COMPONENT_NAME2_GET_DRIVER_NAME) ( + IN struct _EFI_COMPONENT_NAME2_PROTOCOL* This, + IN CHAR8* Language, + OUT CHAR16 **DriverName); + +typedef +EFI_STATUS +(EFIAPI* EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) ( + IN struct _EFI_COMPONENT_NAME2_PROTOCOL* This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8* Language, + OUT CHAR16 **ControllerName); + +typedef struct _EFI_COMPONENT_NAME2_PROTOCOL { + EFI_COMPONENT_NAME2_GET_DRIVER_NAME GetDriverName; + EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME GetControllerName; + CHAR8* SupportedLanguages; +} EFI_COMPONENT_NAME2_PROTOCOL; + +typedef struct _EFI_COMPONENT_NAME2_PROTOCOL _EFI_COMPONENT_NAME2; +typedef EFI_COMPONENT_NAME2_PROTOCOL EFI_COMPONENT_NAME2; + + + +/* + * EFI Loaded Image Protocol + * UEFI Specification Version 2.5 Section 8.1 + */ +#define EFI_LOADED_IMAGE_PROTOCOL_GUID \ + { 0x5B1B31A1, 0x9562, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B} } +#define LOADED_IMAGE_PROTOCOL EFI_LOADED_IMAGE_PROTOCOL_GUID + +#define EFI_LOADED_IMAGE_PROTOCOL_REVISION 0x1000 +#define EFI_IMAGE_INFORMATION_REVISION EFI_LOADED_IMAGE_PROTOCOL_REVISION + +typedef +EFI_STATUS +(EFIAPI* EFI_IMAGE_UNLOAD) ( + IN EFI_HANDLE ImageHandle + ); + +typedef struct { + UINT32 Revision; + EFI_HANDLE ParentHandle; + struct _EFI_SYSTEM_TABLE* SystemTable; + + // Source location of image + EFI_HANDLE DeviceHandle; + EFI_DEVICE_PATH* FilePath; + VOID* Reserved; + + // Images load options + UINT32 LoadOptionsSize; + VOID* LoadOptions; + + // Location of where image was loaded + VOID* ImageBase; + UINT64 ImageSize; + EFI_MEMORY_TYPE ImageCodeType; + EFI_MEMORY_TYPE ImageDataType; + + // If the driver image supports a dynamic unload request + EFI_IMAGE_UNLOAD Unload; +} EFI_LOADED_IMAGE_PROTOCOL; + +typedef EFI_LOADED_IMAGE_PROTOCOL EFI_LOADED_IMAGE; + +#define EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID \ + {0xbc62157e, 0x3e33, 0x4fec, {0x99, 0x20, 0x2d, 0x3b, 0x36, 0xd7, 0x50, 0xdf} } + +/* + * Random Number Generator Protocol + * UEFI Specification Version 2.5 Section 35.5 + */ +#define EFI_RNG_PROTOCOL_GUID \ + { 0x3152bca5, 0xeade, 0x433d, {0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44} } + +typedef EFI_GUID EFI_RNG_ALGORITHM; + +#define EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID \ + {0xa7af67cb, 0x603b, 0x4d42, {0xba, 0x21, 0x70, 0xbf, 0xb6, 0x29, 0x3f, 0x96} } + +#define EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID \ + {0xc5149b43, 0xae85, 0x4f53, {0x99, 0x82, 0xb9, 0x43, 0x35, 0xd3, 0xa9, 0xe7} } + +#define EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID \ + {0x44f0de6e, 0x4d8c, 0x4045, {0xa8, 0xc7, 0x4d, 0xd1, 0x68, 0x85, 0x6b, 0x9e} } + +#define EFI_RNG_ALGORITHM_X9_31_3DES_GUID \ + {0x63c4785a, 0xca34, 0x4012, {0xa3, 0xc8, 0x0b, 0x6a, 0x32, 0x4f, 0x55, 0x46} } + +#define EFI_RNG_ALGORITHM_X9_31_AES_GUID \ + {0xacd03321, 0x777e, 0x4d3d, {0xb1, 0xc8, 0x20, 0xcf, 0xd8, 0x88, 0x20, 0xc9} } + +#define EFI_RNG_ALGORITHM_RAW \ + {0xe43176d7, 0xb6e8, 0x4827, {0xb7, 0x84, 0x7f, 0xfd, 0xc4, 0xb6, 0x85, 0x61} } + +INTERFACE_DECL(_EFI_RNG_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI* EFI_RNG_GET_INFO) ( + IN struct _EFI_RNG_PROTOCOL* This, + IN OUT UINTN* RNGAlgorithmListSize, + OUT EFI_RNG_ALGORITHM* RNGAlgorithmList +); + +typedef +EFI_STATUS +(EFIAPI* EFI_RNG_GET_RNG) ( + IN struct _EFI_RNG_PROTOCOL* This, + IN EFI_RNG_ALGORITHM* RNGAlgorithm, OPTIONAL + IN UINTN RNGValueLength, + OUT UINT8* RNGValue +); + +typedef struct _EFI_RNG_PROTOCOL { + EFI_RNG_GET_INFO GetInfo; + EFI_RNG_GET_RNG GetRNG; +} EFI_RNG_PROTOCOL; + + +// +// EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL +// + +#define EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL_GUID \ + { 0x6b30c738, 0xa391, 0x11d4, {0x9a, 0x3b, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } + +INTERFACE_DECL(_EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI* EFI_PLATFORM_DRIVER_OVERRIDE_GET_DRIVER) ( +IN struct _EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL* This, +IN EFI_HANDLE ControllerHandle, +IN OUT EFI_HANDLE* DriverImageHandle); + +typedef +EFI_STATUS +(EFIAPI* EFI_PLATFORM_DRIVER_OVERRIDE_GET_DRIVER_PATH) ( +IN struct _EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL* This, +IN EFI_HANDLE ControllerHandle, +IN OUT EFI_DEVICE_PATH **DriverImagePath); + +typedef +EFI_STATUS +(EFIAPI* EFI_PLATFORM_DRIVER_OVERRIDE_DRIVER_LOADED) ( +IN struct _EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL* This, +IN EFI_HANDLE ControllerHandle, +IN EFI_DEVICE_PATH* DriverImagePath, +IN EFI_HANDLE DriverImageHandle); + +typedef struct _EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL { + EFI_PLATFORM_DRIVER_OVERRIDE_GET_DRIVER GetDriver; + EFI_PLATFORM_DRIVER_OVERRIDE_GET_DRIVER_PATH GetDriverPath; + EFI_PLATFORM_DRIVER_OVERRIDE_DRIVER_LOADED DriverLoaded; +} EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL; + +// +// EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL +// + +#define EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_GUID \ + { 0x3bc1b285, 0x8a15, 0x4a82, {0xaa, 0xbf, 0x4d, 0x7d, 0x13, 0xfb, 0x32, 0x65} } + +INTERFACE_DECL(_EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI* EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_GET_DRIVER) ( +IN struct _EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL* This, +IN OUT EFI_HANDLE* DriverImageHandle); + +typedef struct _EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL { + EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_GET_DRIVER GetDriver; +} EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL; + +// +// EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL +// + +#define EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL_GUID \ + { 0xb1ee129e, 0xda36, 0x4181, {0x91, 0xf8, 0x04, 0xa4, 0x92, 0x37, 0x66, 0xa7} } + +INTERFACE_DECL(_EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL); + +typedef +UINT32 +(EFIAPI* EFI_DRIVER_FAMILY_OVERRIDE_GET_VERSION) ( +IN struct _EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL* This); + +typedef struct _EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL { + EFI_DRIVER_FAMILY_OVERRIDE_GET_VERSION GetVersion; +} EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL; + +// +// EFI_EBC_PROTOCOL +// + +#define EFI_EBC_INTERPRETER_PROTOCOL_GUID \ + {0x13ac6dd1, 0x73d0, 0x11d4, {0xb0, 0x6b, 0x00, 0xaa, 0x00, 0xbd, 0x6d, 0xe7} } + +#define EFI_EBC_PROTOCOL_GUID EFI_EBC_INTERPRETER_PROTOCOL_GUID + +INTERFACE_DECL(_EFI_EBC_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI* EFI_EBC_CREATE_THUNK)( + IN struct _EFI_EBC_PROTOCOL* This, + IN EFI_HANDLE ImageHandle, + IN VOID* EbcEntryPoint, + OUT VOID **Thunk); + +typedef +EFI_STATUS +(EFIAPI* EFI_EBC_UNLOAD_IMAGE)( + IN struct _EFI_EBC_PROTOCOL* This, + IN EFI_HANDLE ImageHandle); + +typedef +EFI_STATUS +(EFIAPI* EBC_ICACHE_FLUSH)( + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length); + +typedef +EFI_STATUS +(EFIAPI* EFI_EBC_REGISTER_ICACHE_FLUSH)( + IN struct _EFI_EBC_PROTOCOL* This, + IN EBC_ICACHE_FLUSH Flush); + +typedef +EFI_STATUS +(EFIAPI* EFI_EBC_GET_VERSION)( + IN struct _EFI_EBC_PROTOCOL* This, + IN OUT UINT64* Version); + +typedef struct _EFI_EBC_PROTOCOL { + EFI_EBC_CREATE_THUNK CreateThunk; + EFI_EBC_UNLOAD_IMAGE UnloadImage; + EFI_EBC_REGISTER_ICACHE_FLUSH RegisterICacheFlush; + EFI_EBC_GET_VERSION GetVersion; +} EFI_EBC_PROTOCOL; + +INTERFACE_DECL(_EFI_MEMORY_ATTRIBUTE_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI* EFI_GET_MEMORY_ATTRIBUTES)( + IN struct _EFI_MEMORY_ATTRIBUTE_PROTOCOL* This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + OUT UINT64* Attributes + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SET_MEMORY_ATTRIBUTES)( + IN struct _EFI_MEMORY_ATTRIBUTE_PROTOCOL* This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_CLEAR_MEMORY_ATTRIBUTES)( + IN struct _EFI_MEMORY_ATTRIBUTE_PROTOCOL* This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ); + +typedef struct _EFI_MEMORY_ATTRIBUTE_PROTOCOL { + EFI_GET_MEMORY_ATTRIBUTES GetMemoryAttributes; + EFI_SET_MEMORY_ATTRIBUTES SetMemoryAttributes; + EFI_CLEAR_MEMORY_ATTRIBUTES ClearMemoryAttributes; +} EFI_MEMORY_ATTRIBUTE_PROTOCOL; + +#endif diff --git a/code/boot/include/efipxebc.h b/code/boot/include/efipxebc.h new file mode 100644 index 0000000..d22a857 --- /dev/null +++ b/code/boot/include/efipxebc.h @@ -0,0 +1,482 @@ +#ifndef _EFIPXEBC_H +#define _EFIPXEBC_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efipxebc.h + +Abstract: + + EFI PXE Base Code Protocol + + + +Revision History + +--*/ + +// +// PXE Base Code protocol +// + +#define EFI_PXE_BASE_CODE_PROTOCOL_GUID \ + { 0x03c4e603, 0xac28, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } + +INTERFACE_DECL(_EFI_PXE_BASE_CODE_PROTOCOL); + +#define DEFAULT_TTL 4 +#define DEFAULT_ToS 0 +// +// Address definitions +// + +typedef union { + UINT32 Addr[4]; + EFI_IPv4_ADDRESS v4; + EFI_IPv6_ADDRESS v6; +} EFI_IP_ADDRESS; + +typedef UINT16 EFI_PXE_BASE_CODE_UDP_PORT; + +// +// Packet definitions +// + +typedef struct { + UINT8 BootpOpcode; + UINT8 BootpHwType; + UINT8 BootpHwAddrLen; + UINT8 BootpGateHops; + UINT32 BootpIdent; + UINT16 BootpSeconds; + UINT16 BootpFlags; + UINT8 BootpCiAddr[4]; + UINT8 BootpYiAddr[4]; + UINT8 BootpSiAddr[4]; + UINT8 BootpGiAddr[4]; + UINT8 BootpHwAddr[16]; + UINT8 BootpSrvName[64]; + UINT8 BootpBootFile[128]; + UINT32 DhcpMagik; + UINT8 DhcpOptions[56]; +} EFI_PXE_BASE_CODE_DHCPV4_PACKET; + +typedef struct { + UINT32 MessageType:8; + UINT32 TransactionId:24; + UINT8 DhcpOptions[1024]; +} EFI_PXE_BASE_CODE_DHCPV6_PACKET; + +typedef union { + UINT8 Raw[1472]; + EFI_PXE_BASE_CODE_DHCPV4_PACKET Dhcpv4; + EFI_PXE_BASE_CODE_DHCPV6_PACKET Dhcpv6; +} EFI_PXE_BASE_CODE_PACKET; + +typedef struct { + UINT8 Type; + UINT8 Code; + UINT16 Checksum; + union { + UINT32 reserved; + UINT32 Mtu; + UINT32 Pointer; + struct { + UINT16 Identifier; + UINT16 Sequence; + } Echo; + } u; + UINT8 Data[494]; +} EFI_PXE_BASE_CODE_ICMP_ERROR; + +typedef struct { + UINT8 ErrorCode; + CHAR8 ErrorString[127]; +} EFI_PXE_BASE_CODE_TFTP_ERROR; + +// +// IP Receive Filter definitions +// +#define EFI_PXE_BASE_CODE_MAX_IPCNT 8 +typedef struct { + UINT8 Filters; + UINT8 IpCnt; + UINT16 reserved; + EFI_IP_ADDRESS IpList[EFI_PXE_BASE_CODE_MAX_IPCNT]; +} EFI_PXE_BASE_CODE_IP_FILTER; + +#define EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP 0x0001 +#define EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST 0x0002 +#define EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS 0x0004 +#define EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST 0x0008 + +// +// ARP Cache definitions +// + +typedef struct { + EFI_IP_ADDRESS IpAddr; + EFI_MAC_ADDRESS MacAddr; +} EFI_PXE_BASE_CODE_ARP_ENTRY; + +typedef struct { + EFI_IP_ADDRESS IpAddr; + EFI_IP_ADDRESS SubnetMask; + EFI_IP_ADDRESS GwAddr; +} EFI_PXE_BASE_CODE_ROUTE_ENTRY; + +// +// UDP definitions +// + +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP 0x0001 +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT 0x0002 +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP 0x0004 +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT 0x0008 +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER 0x0010 +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT 0x0020 + +// +// Discover() definitions +// + +#define EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP 0 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_MS_WINNT_RIS 1 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_INTEL_LCM 2 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_DOSUNDI 3 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_NEC_ESMPRO 4 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_IBM_WSoD 5 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_IBM_LCCM 6 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_CA_UNICENTER_TNG 7 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_HP_OPENVIEW 8 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_ALTIRIS_9 9 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_ALTIRIS_10 10 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_ALTIRIS_11 11 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_NOT_USED_12 12 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_REDHAT_INSTALL 13 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_REDHAT_BOOT 14 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_REMBO 15 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_BEOBOOT 16 +// +// 17 through 32767 are reserved +// 32768 through 65279 are for vendor use +// 65280 through 65534 are reserved +// +#define EFI_PXE_BASE_CODE_BOOT_TYPE_PXETEST 65535 + +#define EFI_PXE_BASE_CODE_BOOT_LAYER_MASK 0x7FFF +#define EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL 0x0000 + + +typedef struct { + UINT16 Type; + BOOLEAN AcceptAnyResponse; + UINT8 Reserved; + EFI_IP_ADDRESS IpAddr; +} EFI_PXE_BASE_CODE_SRVLIST; + +typedef struct { + BOOLEAN UseMCast; + BOOLEAN UseBCast; + BOOLEAN UseUCast; + BOOLEAN MustUseList; + EFI_IP_ADDRESS ServerMCastIp; + UINT16 IpCnt; + EFI_PXE_BASE_CODE_SRVLIST SrvList[1]; +} EFI_PXE_BASE_CODE_DISCOVER_INFO; + +// +// Mtftp() definitions +// + +typedef enum { + EFI_PXE_BASE_CODE_TFTP_FIRST, + EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE, + EFI_PXE_BASE_CODE_TFTP_READ_FILE, + EFI_PXE_BASE_CODE_TFTP_WRITE_FILE, + EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY, + EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE, + EFI_PXE_BASE_CODE_MTFTP_READ_FILE, + EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY, + EFI_PXE_BASE_CODE_MTFTP_LAST +} EFI_PXE_BASE_CODE_TFTP_OPCODE; + +typedef struct { + EFI_IP_ADDRESS MCastIp; + EFI_PXE_BASE_CODE_UDP_PORT CPort; + EFI_PXE_BASE_CODE_UDP_PORT SPort; + UINT16 ListenTimeout; + UINT16 TransmitTimeout; +} EFI_PXE_BASE_CODE_MTFTP_INFO; + +// +// PXE Base Code Mode structure +// + +#define EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES 8 +#define EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES 8 + +typedef struct { + BOOLEAN Started; + BOOLEAN Ipv6Available; + BOOLEAN Ipv6Supported; + BOOLEAN UsingIpv6; + BOOLEAN BisSupported; + BOOLEAN BisDetected; + BOOLEAN AutoArp; + BOOLEAN SendGUID; + BOOLEAN DhcpDiscoverValid; + BOOLEAN DhcpAckReceived; + BOOLEAN ProxyOfferReceived; + BOOLEAN PxeDiscoverValid; + BOOLEAN PxeReplyReceived; + BOOLEAN PxeBisReplyReceived; + BOOLEAN IcmpErrorReceived; + BOOLEAN TftpErrorReceived; + BOOLEAN MakeCallbacks; + UINT8 TTL; + UINT8 ToS; + EFI_IP_ADDRESS StationIp; + EFI_IP_ADDRESS SubnetMask; + EFI_PXE_BASE_CODE_PACKET DhcpDiscover; + EFI_PXE_BASE_CODE_PACKET DhcpAck; + EFI_PXE_BASE_CODE_PACKET ProxyOffer; + EFI_PXE_BASE_CODE_PACKET PxeDiscover; + EFI_PXE_BASE_CODE_PACKET PxeReply; + EFI_PXE_BASE_CODE_PACKET PxeBisReply; + EFI_PXE_BASE_CODE_IP_FILTER IpFilter; + UINT32 ArpCacheEntries; + EFI_PXE_BASE_CODE_ARP_ENTRY ArpCache[EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES]; + UINT32 RouteTableEntries; + EFI_PXE_BASE_CODE_ROUTE_ENTRY RouteTable[EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES]; + EFI_PXE_BASE_CODE_ICMP_ERROR IcmpError; + EFI_PXE_BASE_CODE_TFTP_ERROR TftpError; +} EFI_PXE_BASE_CODE_MODE; + +// +// PXE Base Code Interface Function definitions +// + +typedef +EFI_STATUS +(EFIAPI* EFI_PXE_BASE_CODE_START) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL* This, + IN BOOLEAN UseIpv6 + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_PXE_BASE_CODE_STOP) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL* This + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_PXE_BASE_CODE_DHCP) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL* This, + IN BOOLEAN SortOffers + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_PXE_BASE_CODE_DISCOVER) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL* This, + IN UINT16 Type, + IN UINT16* Layer, + IN BOOLEAN UseBis, + IN OUT EFI_PXE_BASE_CODE_DISCOVER_INFO* Info OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_PXE_BASE_CODE_MTFTP) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL* This, + IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation, + IN OUT VOID* BufferPtr OPTIONAL, + IN BOOLEAN Overwrite, + IN OUT UINT64* BufferSize, + IN UINTN* BlockSize OPTIONAL, + IN EFI_IP_ADDRESS* ServerIp, + IN UINT8* Filename, + IN EFI_PXE_BASE_CODE_MTFTP_INFO* Info OPTIONAL, + IN BOOLEAN DontUseBuffer + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_PXE_BASE_CODE_UDP_WRITE) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL* This, + IN UINT16 OpFlags, + IN EFI_IP_ADDRESS* DestIp, + IN EFI_PXE_BASE_CODE_UDP_PORT* DestPort, + IN EFI_IP_ADDRESS* GatewayIp, OPTIONAL + IN EFI_IP_ADDRESS* SrcIp, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT* SrcPort, OPTIONAL + IN UINTN* HeaderSize, OPTIONAL + IN VOID* HeaderPtr, OPTIONAL + IN UINTN* BufferSize, + IN VOID* BufferPtr + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_PXE_BASE_CODE_UDP_READ) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL* This, + IN UINT16 OpFlags, + IN OUT EFI_IP_ADDRESS* DestIp, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT* DestPort, OPTIONAL + IN OUT EFI_IP_ADDRESS* SrcIp, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT* SrcPort, OPTIONAL + IN UINTN* HeaderSize, OPTIONAL + IN VOID* HeaderPtr, OPTIONAL + IN OUT UINTN* BufferSize, + IN VOID* BufferPtr + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_PXE_BASE_CODE_SET_IP_FILTER) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL* This, + IN EFI_PXE_BASE_CODE_IP_FILTER* NewFilter + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_PXE_BASE_CODE_ARP) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL* This, + IN EFI_IP_ADDRESS* IpAddr, + IN EFI_MAC_ADDRESS* MacAddr OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_PXE_BASE_CODE_SET_PARAMETERS) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL* This, + IN BOOLEAN* NewAutoArp, OPTIONAL + IN BOOLEAN* NewSendGUID, OPTIONAL + IN UINT8* NewTTL, OPTIONAL + IN UINT8* NewToS, OPTIONAL + IN BOOLEAN* NewMakeCallback OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_PXE_BASE_CODE_SET_STATION_IP) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL* This, + IN EFI_IP_ADDRESS* NewStationIp, OPTIONAL + IN EFI_IP_ADDRESS* NewSubnetMask OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_PXE_BASE_CODE_SET_PACKETS) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL* This, + BOOLEAN* NewDhcpDiscoverValid, OPTIONAL + BOOLEAN* NewDhcpAckReceived, OPTIONAL + BOOLEAN* NewProxyOfferReceived, OPTIONAL + BOOLEAN* NewPxeDiscoverValid, OPTIONAL + BOOLEAN* NewPxeReplyReceived, OPTIONAL + BOOLEAN* NewPxeBisReplyReceived,OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET* NewDhcpDiscover, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET* NewDhcpAck, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET* NewProxyOffer, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET* NewPxeDiscover, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET* NewPxeReply, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET* NewPxeBisReply OPTIONAL + ); + +// +// PXE Base Code Protocol structure +// + +#define EFI_PXE_BASE_CODE_PROTOCOL_REVISION 0x00010000 +#define EFI_PXE_BASE_CODE_INTERFACE_REVISION EFI_PXE_BASE_CODE_PROTOCOL_REVISION + +typedef struct _EFI_PXE_BASE_CODE_PROTOCOL { + UINT64 Revision; + EFI_PXE_BASE_CODE_START Start; + EFI_PXE_BASE_CODE_STOP Stop; + EFI_PXE_BASE_CODE_DHCP Dhcp; + EFI_PXE_BASE_CODE_DISCOVER Discover; + EFI_PXE_BASE_CODE_MTFTP Mtftp; + EFI_PXE_BASE_CODE_UDP_WRITE UdpWrite; + EFI_PXE_BASE_CODE_UDP_READ UdpRead; + EFI_PXE_BASE_CODE_SET_IP_FILTER SetIpFilter; + EFI_PXE_BASE_CODE_ARP Arp; + EFI_PXE_BASE_CODE_SET_PARAMETERS SetParameters; + EFI_PXE_BASE_CODE_SET_STATION_IP SetStationIp; + EFI_PXE_BASE_CODE_SET_PACKETS SetPackets; + EFI_PXE_BASE_CODE_MODE* Mode; +} EFI_PXE_BASE_CODE_PROTOCOL; + +// Note: Because it conflicted with the EDK2 struct name, the +// 'EFI_PXE_BASE_CODE_PROTOCOL' GUID definition, from older +// versions of gnu-efi, is now obsoleted. +// Use 'EFI_PXE_BASE_CODE_PROTOCOL_GUID' instead. + +typedef struct _EFI_PXE_BASE_CODE_PROTOCOL _EFI_PXE_BASE_CODE; +typedef struct _EFI_PXE_BASE_CODE_PROTOCOL EFI_PXE_BASE_CODE; + +// +// Call Back Definitions +// + +#define EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_GUID \ + { 0x245dca21, 0xfb7b, 0x11d3, {0x8f, 0x01, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +// +// Revision Number +// + +#define EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_REVISION 0x00010000 +#define EFI_PXE_BASE_CODE_CALLBACK_INTERFACE_REVISION EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_REVISION + +INTERFACE_DECL(_EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL); + +typedef enum { + EFI_PXE_BASE_CODE_FUNCTION_FIRST, + EFI_PXE_BASE_CODE_FUNCTION_DHCP, + EFI_PXE_BASE_CODE_FUNCTION_DISCOVER, + EFI_PXE_BASE_CODE_FUNCTION_MTFTP, + EFI_PXE_BASE_CODE_FUNCTION_UDP_WRITE, + EFI_PXE_BASE_CODE_FUNCTION_UDP_READ, + EFI_PXE_BASE_CODE_FUNCTION_ARP, + EFI_PXE_BASE_CODE_FUNCTION_IGMP, + EFI_PXE_BASE_CODE_PXE_FUNCTION_LAST +} EFI_PXE_BASE_CODE_FUNCTION; + +typedef enum { + EFI_PXE_BASE_CODE_CALLBACK_STATUS_FIRST, + EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE, + EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT, + EFI_PXE_BASE_CODE_CALLBACK_STATUS_LAST +} EFI_PXE_BASE_CODE_CALLBACK_STATUS; + +typedef +EFI_PXE_BASE_CODE_CALLBACK_STATUS +(EFIAPI* EFI_PXE_CALLBACK) ( + IN struct _EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL* This, + IN EFI_PXE_BASE_CODE_FUNCTION Function, + IN BOOLEAN Received, + IN UINT32 PacketLen, + IN EFI_PXE_BASE_CODE_PACKET* Packet OPTIONAL + ); + +typedef struct _EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL { + UINT64 Revision; + EFI_PXE_CALLBACK Callback; +} EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL; + +// Note: Because it conflicted with the EDK2 struct name, the +// 'EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL' GUID definition, from +// older versions of gnu-efi, is now obsoleted. +// Use 'EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_GUID' instead. + +typedef struct _EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL _EFI_PXE_BASE_CODE_CALLBACK; +typedef EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL EFI_PXE_BASE_CODE_CALLBACK; + +#endif /* _EFIPXEBC_H */ diff --git a/code/boot/include/efirtlib.h b/code/boot/include/efirtlib.h new file mode 100644 index 0000000..c14df2c --- /dev/null +++ b/code/boot/include/efirtlib.h @@ -0,0 +1,204 @@ +#ifndef _EFI_RT_LIB_INCLUDE_ +#define _EFI_RT_LIB_INCLUDE_ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efilib.h + +Abstract: + + EFI Runtime library functions + + + +Revision History + +--*/ + +#include "efidebug.h" +#include "efipart.h" +#if defined(_M_X64) || defined(__x86_64__) || defined(__amd64__) +#include "x86_64/efilibplat.h" +#elif defined(_M_IX86) || defined(__i386__) +#include "ia32/efilibplat.h" +#elif defined(_M_IA64) || defined(__ia64__) +#include "ia64/efilibplat.h" +#elif defined (_M_ARM64) || defined(__aarch64__) +#include "aarch64/efilibplat.h" +#elif defined (_M_ARM) || defined(__arm__) +#include "arm/efilibplat.h" +#elif defined (_M_MIPS64) || defined(__mips64__) || defined(__mips64) +#include "mips64el/efilibplat.h" +#elif defined (__riscv) && __riscv_xlen == 64 +#include "riscv64/efilibplat.h" +#endif + + +VOID +RUNTIMEFUNCTION +RtZeroMem ( + IN VOID* Buffer, + IN UINTN Size + ); + +VOID +EFIAPI +RUNTIMEFUNCTION +RtSetMem ( + IN VOID* Buffer, + IN UINTN Size, + IN UINT8 Value + ); + +VOID +EFIAPI +RUNTIMEFUNCTION +RtCopyMem ( + IN VOID* Dest, + IN VOID* Src, + IN UINTN len + ); + +VOID +EFIAPI +RUNTIMEFUNCTION +RtCopyMemC ( + IN VOID* Dest, + IN CONST VOID* Src, + IN UINTN len + ); + +INTN +RUNTIMEFUNCTION +RtCompareMem ( + IN CONST VOID* Dest, + IN CONST VOID* Src, + IN UINTN len + ); + +INTN +RUNTIMEFUNCTION +RtStrCmp ( + IN CONST CHAR16* s1, + IN CONST CHAR16* s2 + ); + + +VOID +RUNTIMEFUNCTION +RtStrCpy ( + IN CHAR16* Dest, + IN CONST CHAR16* Src + ); + +VOID +RUNTIMEFUNCTION +RtStrnCpy ( + IN CHAR16* Dest, + IN CONST CHAR16* Src, + IN UINTN Len + ); + +CHAR16 * +RUNTIMEFUNCTION +RtStpCpy ( + IN CHAR16* Dest, + IN CONST CHAR16* Src + ); + +CHAR16 * +RUNTIMEFUNCTION +RtStpnCpy ( + IN CHAR16* Dest, + IN CONST CHAR16* Src, + IN UINTN Len + ); + +VOID +RUNTIMEFUNCTION +RtStrCat ( + IN CHAR16* Dest, + IN CONST CHAR16* Src + ); + +VOID +RUNTIMEFUNCTION +RtStrnCat ( + IN CHAR16* Dest, + IN CONST CHAR16* Src, + IN UINTN Len + ); + +UINTN +RUNTIMEFUNCTION +RtStrLen ( + IN CONST CHAR16* s1 + ); + +UINTN +RUNTIMEFUNCTION +RtStrnLen ( + IN CONST CHAR16* s1, + IN UINTN Len + ); + +UINTN +RUNTIMEFUNCTION +RtStrSize ( + IN CONST CHAR16* s1 + ); + +INTN +RUNTIMEFUNCTION +RtCompareGuid ( + IN EFI_GUID* Guid1, + IN EFI_GUID* Guid2 + ); + +UINT8 +RUNTIMEFUNCTION +RtDecimaltoBCD( + IN UINT8 BcdValue + ); + +UINT8 +RUNTIMEFUNCTION +RtBCDtoDecimal( + IN UINT8 BcdValue + ); + +// +// Virtual mapping transition support. (Only used during +// the virtual address change transisition) +// + +VOID +RUNTIMEFUNCTION +RtLibEnableVirtualMappings ( + VOID + ); + +VOID +RUNTIMEFUNCTION +RtConvertList ( + IN UINTN DebugDisposition, + IN OUT LIST_ENTRY* ListHead + ); + +VOID +RUNTIMEFUNCTION +RtAcquireLock ( + IN FLOCK* Lock + ); + +VOID +RUNTIMEFUNCTION +RtReleaseLock ( + IN FLOCK* Lock + ); + + +#endif diff --git a/code/boot/include/efiser.h b/code/boot/include/efiser.h new file mode 100644 index 0000000..51b4d64 --- /dev/null +++ b/code/boot/include/efiser.h @@ -0,0 +1,136 @@ +#ifndef _EFI_SER_H +#define _EFI_SER_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efiser.h + +Abstract: + + EFI serial protocol + +Revision History + +--*/ + +// +// Serial protocol +// + +#define EFI_SERIAL_IO_PROTOCOL_GUID \ + { 0xBB25CF6F, 0xF1D4, 0x11D2, {0x9A, 0x0C, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0xFD} } +#define SERIAL_IO_PROTOCOL EFI_SERIAL_IO_PROTOCOL_GUID + +INTERFACE_DECL(_EFI_SERIAL_IO_PROTOCOL); + +typedef enum { + DefaultParity, + NoParity, + EvenParity, + OddParity, + MarkParity, + SpaceParity +} EFI_PARITY_TYPE; + +typedef enum { + DefaultStopBits, + OneStopBit, // 1 stop bit + OneFiveStopBits, // 1.5 stop bits + TwoStopBits // 2 stop bits +} EFI_STOP_BITS_TYPE; + +#define EFI_SERIAL_CLEAR_TO_SEND 0x0010 // RO +#define EFI_SERIAL_DATA_SET_READY 0x0020 // RO +#define EFI_SERIAL_RING_INDICATE 0x0040 // RO +#define EFI_SERIAL_CARRIER_DETECT 0x0080 // RO +#define EFI_SERIAL_REQUEST_TO_SEND 0x0002 // WO +#define EFI_SERIAL_DATA_TERMINAL_READY 0x0001 // WO +#define EFI_SERIAL_INPUT_BUFFER_EMPTY 0x0100 // RO +#define EFI_SERIAL_OUTPUT_BUFFER_EMPTY 0x0200 // RO +#define EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE 0x1000 // RW +#define EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE 0x2000 // RW +#define EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE 0x4000 // RW + +typedef +EFI_STATUS +(EFIAPI* EFI_SERIAL_RESET) ( + IN struct _EFI_SERIAL_IO_PROTOCOL* This + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SERIAL_SET_ATTRIBUTES) ( + IN struct _EFI_SERIAL_IO_PROTOCOL* This, + IN UINT64 BaudRate, + IN UINT32 ReceiveFifoDepth, + IN UINT32 Timeout, + IN EFI_PARITY_TYPE Parity, + IN UINT8 DataBits, + IN EFI_STOP_BITS_TYPE StopBits + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SERIAL_SET_CONTROL_BITS) ( + IN struct _EFI_SERIAL_IO_PROTOCOL* This, + IN UINT32 Control + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SERIAL_GET_CONTROL_BITS) ( + IN struct _EFI_SERIAL_IO_PROTOCOL* This, + OUT UINT32* Control + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SERIAL_WRITE) ( + IN struct _EFI_SERIAL_IO_PROTOCOL* This, + IN OUT UINTN* BufferSize, + IN VOID* Buffer + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SERIAL_READ) ( + IN struct _EFI_SERIAL_IO_PROTOCOL* This, + IN OUT UINTN* BufferSize, + OUT VOID* Buffer + ); + +typedef struct { + UINT32 ControlMask; + + // current Attributes + UINT32 Timeout; + UINT64 BaudRate; + UINT32 ReceiveFifoDepth; + UINT32 DataBits; + UINT32 Parity; + UINT32 StopBits; +} SERIAL_IO_MODE; + +#define SERIAL_IO_INTERFACE_REVISION 0x00010000 + +typedef struct _EFI_SERIAL_IO_PROTOCOL { + UINT32 Revision; + EFI_SERIAL_RESET Reset; + EFI_SERIAL_SET_ATTRIBUTES SetAttributes; + EFI_SERIAL_SET_CONTROL_BITS SetControl; + EFI_SERIAL_GET_CONTROL_BITS GetControl; + EFI_SERIAL_WRITE Write; + EFI_SERIAL_READ Read; + + SERIAL_IO_MODE* Mode; +} EFI_SERIAL_IO_PROTOCOL; + +typedef struct _EFI_SERIAL_IO_PROTOCOL _SERIAL_IO_INTERFACE; +typedef EFI_SERIAL_IO_PROTOCOL SERIAL_IO_INTERFACE; + +#endif + diff --git a/code/boot/include/efisetjmp.h b/code/boot/include/efisetjmp.h new file mode 100644 index 0000000..428cac9 --- /dev/null +++ b/code/boot/include/efisetjmp.h @@ -0,0 +1,10 @@ +#ifndef GNU_EFI_SETJMP_H +#define GNU_EFI_SETJMP_H + +#include "eficompiler.h" +#include "efisetjmp_arch.h" + +extern UINTN setjmp(jmp_buf env) __attribute__((returns_twice)); +extern VOID longjmp(jmp_buf env, UINTN value) EFI_NORETURN; + +#endif /* GNU_EFI_SETJMP_H */ diff --git a/code/boot/include/efishell.h b/code/boot/include/efishell.h new file mode 100644 index 0000000..226eb50 --- /dev/null +++ b/code/boot/include/efishell.h @@ -0,0 +1,449 @@ +/** + EFI Shell protocol as defined in the UEFI Shell Specification 2.2. + + (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + + This file is based on MdePkg/Include/Protocol/Shell.h from EDK2 + Ported to gnu-efi by Jiaqing Zhao +**/ + +#ifndef _EFI_SHELL_H +#define _EFI_SHELL_H + +#include "efilink.h" + +#define EFI_SHELL_PROTOCOL_GUID \ + { 0x6302d008, 0x7f9b, 0x4f30, { 0x87, 0xac, 0x60, 0xc9, 0xfe, 0xf5, 0xda, 0x4e } } + +INTERFACE_DECL(_EFI_SHELL_PROTOCOL); + +typedef enum { + SHELL_SUCCESS = 0, + SHELL_LOAD_ERROR = 1, + SHELL_INVALID_PARAMETER = 2, + SHELL_UNSUPPORTED = 3, + SHELL_BAD_BUFFER_SIZE = 4, + SHELL_BUFFER_TOO_SMALL = 5, + SHELL_NOT_READY = 6, + SHELL_DEVICE_ERROR = 7, + SHELL_WRITE_PROTECTED = 8, + SHELL_OUT_OF_RESOURCES = 9, + SHELL_VOLUME_CORRUPTED = 10, + SHELL_VOLUME_FULL = 11, + SHELL_NO_MEDIA = 12, + SHELL_MEDIA_CHANGED = 13, + SHELL_NOT_FOUND = 14, + SHELL_ACCESS_DENIED = 15, + SHELL_TIMEOUT = 18, + SHELL_NOT_STARTED = 19, + SHELL_ALREADY_STARTED = 20, + SHELL_ABORTED = 21, + SHELL_INCOMPATIBLE_VERSION = 25, + SHELL_SECURITY_VIOLATION = 26, + SHELL_NOT_EQUAL = 27 +} SHELL_STATUS; + +typedef VOID* SHELL_FILE_HANDLE; + +typedef struct { + EFI_LIST_ENTRY Link; + EFI_STATUS Status; + CONST CHAR16* FullName; + CONST CHAR16* FileName; + SHELL_FILE_HANDLE Handle; + EFI_FILE_INFO* Info; +} EFI_SHELL_FILE_INFO; + +typedef +BOOLEAN +(EFIAPI* EFI_SHELL_BATCH_IS_ACTIVE) ( + VOID + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_CLOSE_FILE) ( + IN SHELL_FILE_HANDLE FileHandle + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_CREATE_FILE) ( + IN CONST CHAR16* FileName, + IN UINT64 FileAttribs, + OUT SHELL_FILE_HANDLE* FileHandle + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_DELETE_FILE) ( + IN SHELL_FILE_HANDLE FileHandle + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_DELETE_FILE_BY_NAME) ( + IN CONST CHAR16* FileName + ); + +typedef +VOID +(EFIAPI* EFI_SHELL_DISABLE_PAGE_BREAK) ( + VOID + ); + +typedef +VOID +(EFIAPI* EFI_SHELL_ENABLE_PAGE_BREAK) ( + VOID + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_EXECUTE) ( + IN EFI_HANDLE* ParentImageHandle, + IN CHAR16* CommandLine OPTIONAL, + IN CHAR16 **Environment OPTIONAL, + OUT EFI_STATUS* StatusCode OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_FIND_FILES) ( + IN CONST CHAR16* FilePattern, + OUT EFI_SHELL_FILE_INFO **FileList + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_FIND_FILES_IN_DIR) ( + IN SHELL_FILE_HANDLE FileDirHandle, + OUT EFI_SHELL_FILE_INFO **FileList + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_FLUSH_FILE) ( + IN SHELL_FILE_HANDLE FileHandle + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_FREE_FILE_LIST) ( + IN EFI_SHELL_FILE_INFO **FileList + ); + +typedef +CONST CHAR16 * +(EFIAPI* EFI_SHELL_GET_ALIAS) ( + IN CONST CHAR16* Alias, + OUT BOOLEAN* Volatile OPTIONAL + ); + +typedef +CONST CHAR16 * +(EFIAPI* EFI_SHELL_GET_CUR_DIR) ( + IN CONST CHAR16* FileSystemMapping OPTIONAL + ); + +typedef UINT32 EFI_SHELL_DEVICE_NAME_FLAGS; +#define EFI_DEVICE_NAME_USE_COMPONENT_NAME 0x00000001 +#define EFI_DEVICE_NAME_USE_DEVICE_PATH 0x00000002 + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_GET_DEVICE_NAME) ( + IN EFI_HANDLE DeviceHandle, + IN EFI_SHELL_DEVICE_NAME_FLAGS Flags, + IN CHAR8* Language, + OUT CHAR16 **BestDeviceName + ); + +typedef +CONST EFI_DEVICE_PATH_PROTOCOL * +(EFIAPI* EFI_SHELL_GET_DEVICE_PATH_FROM_MAP) ( + IN CONST CHAR16* Mapping + ); + +typedef +EFI_DEVICE_PATH_PROTOCOL * +(EFIAPI* EFI_SHELL_GET_DEVICE_PATH_FROM_FILE_PATH) ( + IN CONST CHAR16* Path + ); + +typedef +CONST CHAR16 * +(EFIAPI* EFI_SHELL_GET_ENV) ( + IN CONST CHAR16* Name + ); + +typedef +CONST CHAR16 * +(EFIAPI* EFI_SHELL_GET_ENV_EX) ( + IN CONST CHAR16* Name, + OUT UINT32* Attributes OPTIONAL + ); + +typedef +EFI_FILE_INFO * +(EFIAPI* EFI_SHELL_GET_FILE_INFO) ( + IN SHELL_FILE_HANDLE FileHandle + ); + +typedef +CHAR16 * +(EFIAPI* EFI_SHELL_GET_FILE_PATH_FROM_DEVICE_PATH) ( + IN CONST EFI_DEVICE_PATH_PROTOCOL* Path + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_GET_FILE_POSITION) ( + IN SHELL_FILE_HANDLE FileHandle, + OUT UINT64* Position + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_GET_FILE_SIZE) ( + IN SHELL_FILE_HANDLE FileHandle, + OUT UINT64* Size + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_GET_GUID_FROM_NAME) ( + IN CONST CHAR16* GuidName, + OUT EFI_GUID* Guid + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_GET_GUID_NAME)( + IN CONST EFI_GUID* Guid, + OUT CONST CHAR16 **GuidName + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_GET_HELP_TEXT) ( + IN CONST CHAR16* Command, + IN CONST CHAR16* Sections, + OUT CHAR16 **HelpText + ); + +typedef +CONST CHAR16 * +(EFIAPI* EFI_SHELL_GET_MAP_FROM_DEVICE_PATH) ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ); + +typedef +BOOLEAN +(EFIAPI* EFI_SHELL_GET_PAGE_BREAK) ( + VOID + ); + +typedef +BOOLEAN +(EFIAPI* EFI_SHELL_IS_ROOT_SHELL) ( + VOID + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_OPEN_FILE_BY_NAME) ( + IN CONST CHAR16* FileName, + OUT SHELL_FILE_HANDLE* FileHandle, + IN UINT64 OpenMode + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_OPEN_FILE_LIST) ( + IN CHAR16* Path, + IN UINT64 OpenMode, + IN OUT EFI_SHELL_FILE_INFO **FileList + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_OPEN_ROOT) ( + IN EFI_DEVICE_PATH_PROTOCOL* DevicePath, + OUT SHELL_FILE_HANDLE* FileHandle + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_OPEN_ROOT_BY_HANDLE) ( + IN EFI_HANDLE DeviceHandle, + OUT SHELL_FILE_HANDLE* FileHandle + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_READ_FILE) ( + IN SHELL_FILE_HANDLE FileHandle, + IN OUT UINTN* ReadSize, + IN OUT VOID* Buffer + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_REGISTER_GUID_NAME) ( + IN CONST EFI_GUID* Guid, + IN CONST CHAR16* GuidName + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_REMOVE_DUP_IN_FILE_LIST) ( + IN EFI_SHELL_FILE_INFO **FileList + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_SET_ALIAS) ( + IN CONST CHAR16* Command, + IN CONST CHAR16* Alias, + IN BOOLEAN Replace, + IN BOOLEAN Volatile + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_SET_CUR_DIR) ( + IN CONST CHAR16* FileSystem OPTIONAL, + IN CONST CHAR16* Dir + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_SET_ENV) ( + IN CONST CHAR16* Name, + IN CONST CHAR16* Value, + IN BOOLEAN Volatile + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_SET_FILE_INFO) ( + IN SHELL_FILE_HANDLE FileHandle, + IN CONST EFI_FILE_INFO* FileInfo + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_SET_FILE_POSITION) ( + IN SHELL_FILE_HANDLE FileHandle, + IN UINT64 Position + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_SET_MAP) ( + IN CONST EFI_DEVICE_PATH_PROTOCOL* DevicePath, + IN CONST CHAR16* Mapping + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_SHELL_WRITE_FILE) ( + IN SHELL_FILE_HANDLE FileHandle, + IN OUT UINTN* BufferSize, + IN VOID* Buffer + ); + +typedef struct _EFI_SHELL_PROTOCOL { + EFI_SHELL_EXECUTE Execute; + EFI_SHELL_GET_ENV GetEnv; + EFI_SHELL_SET_ENV SetEnv; + EFI_SHELL_GET_ALIAS GetAlias; + EFI_SHELL_SET_ALIAS SetAlias; + EFI_SHELL_GET_HELP_TEXT GetHelpText; + EFI_SHELL_GET_DEVICE_PATH_FROM_MAP GetDevicePathFromMap; + EFI_SHELL_GET_MAP_FROM_DEVICE_PATH GetMapFromDevicePath; + EFI_SHELL_GET_DEVICE_PATH_FROM_FILE_PATH GetDevicePathFromFilePath; + EFI_SHELL_GET_FILE_PATH_FROM_DEVICE_PATH GetFilePathFromDevicePath; + EFI_SHELL_SET_MAP SetMap; + EFI_SHELL_GET_CUR_DIR GetCurDir; + EFI_SHELL_SET_CUR_DIR SetCurDir; + EFI_SHELL_OPEN_FILE_LIST OpenFileList; + EFI_SHELL_FREE_FILE_LIST FreeFileList; + EFI_SHELL_REMOVE_DUP_IN_FILE_LIST RemoveDupInFileList; + EFI_SHELL_BATCH_IS_ACTIVE BatchIsActive; + EFI_SHELL_IS_ROOT_SHELL IsRootShell; + EFI_SHELL_ENABLE_PAGE_BREAK EnablePageBreak; + EFI_SHELL_DISABLE_PAGE_BREAK DisablePageBreak; + EFI_SHELL_GET_PAGE_BREAK GetPageBreak; + EFI_SHELL_GET_DEVICE_NAME GetDeviceName; + EFI_SHELL_GET_FILE_INFO GetFileInfo; + EFI_SHELL_SET_FILE_INFO SetFileInfo; + EFI_SHELL_OPEN_FILE_BY_NAME OpenFileByName; + EFI_SHELL_CLOSE_FILE CloseFile; + EFI_SHELL_CREATE_FILE CreateFile; + EFI_SHELL_READ_FILE ReadFile; + EFI_SHELL_WRITE_FILE WriteFile; + EFI_SHELL_DELETE_FILE DeleteFile; + EFI_SHELL_DELETE_FILE_BY_NAME DeleteFileByName; + EFI_SHELL_GET_FILE_POSITION GetFilePosition; + EFI_SHELL_SET_FILE_POSITION SetFilePosition; + EFI_SHELL_FLUSH_FILE FlushFile; + EFI_SHELL_FIND_FILES FindFiles; + EFI_SHELL_FIND_FILES_IN_DIR FindFilesInDir; + EFI_SHELL_GET_FILE_SIZE GetFileSize; + EFI_SHELL_OPEN_ROOT OpenRoot; + EFI_SHELL_OPEN_ROOT_BY_HANDLE OpenRootByHandle; + EFI_EVENT ExecutionBreak; + UINT32 MajorVersion; + UINT32 MinorVersion; + // Added for Shell 2.1 + EFI_SHELL_REGISTER_GUID_NAME RegisterGuidName; + EFI_SHELL_GET_GUID_NAME GetGuidName; + EFI_SHELL_GET_GUID_FROM_NAME GetGuidFromName; + EFI_SHELL_GET_ENV_EX GetEnvEx; +} EFI_SHELL_PROTOCOL; + +#define EFI_SHELL_PARAMETERS_PROTOCOL_GUID \ + { 0x752f3136, 0x4e16, 0x4fdc, { 0xa2, 0x2a, 0xe5, 0xf4, 0x68, 0x12, 0xf4, 0xca } } + +INTERFACE_DECL(_EFI_SHELL_PARAMETERS_PROTOCOL); + +typedef struct _EFI_SHELL_PARAMETERS_PROTOCOL { + CHAR16 **Argv; + UINTN Argc; + SHELL_FILE_HANDLE StdIn; + SHELL_FILE_HANDLE StdOut; + SHELL_FILE_HANDLE StdErr; +} EFI_SHELL_PARAMETERS_PROTOCOL; + +#define EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL_GUID \ + { 0x3c7200e9, 0x005f, 0x4ea4, { 0x87, 0xde, 0xa3, 0xdf, 0xac, 0x8a, 0x27, 0xc3 } } + +INTERFACE_DECL(_EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL); + +typedef +SHELL_STATUS +(EFIAPI* SHELL_COMMAND_HANDLER)( + IN struct _EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL* This, + IN EFI_SYSTEM_TABLE* SystemTable, + IN EFI_SHELL_PARAMETERS_PROTOCOL* ShellParameters, + IN EFI_SHELL_PROTOCOL* Shell + ); + +typedef +CHAR16* +(EFIAPI* SHELL_COMMAND_GETHELP)( + IN struct _EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL* This, + IN CONST CHAR8* Language + ); + +typedef struct _EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL { + CONST CHAR16* CommandName; + SHELL_COMMAND_HANDLER Handler; + SHELL_COMMAND_GETHELP GetHelp; +} EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL; + +#endif diff --git a/code/boot/include/efishellintf.h b/code/boot/include/efishellintf.h new file mode 100644 index 0000000..c0af227 --- /dev/null +++ b/code/boot/include/efishellintf.h @@ -0,0 +1,94 @@ +/** @file + SHELL_INTERFACE_PROTOCOL from EDK shell (no spec). + + Shell Interface - additional information (over image_info) provided + to an application started by the shell. + + ConIo provides a file-style interface to the console. + + The shell interface's and data (including ConIo) are only valid during + the applications Entry Point. Once the application returns from it's + entry point the data is freed by the invoking shell. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/* + * This is based on ShellPkg/Include/Protocol/EfiShellInterface.h from EDK II. + */ + +#ifndef _SHELLINTERFACE_H_ +#define _SHELLINTERFACE_H_ + + +#define SHELL_INTERFACE_PROTOCOL_GUID \ + { \ + 0x47c7b223, 0xc42a, 0x11d2, {0x8e, 0x57, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} \ + } + +/// +/// Bit definitions for EFI_SHELL_ARG_INFO +/// +typedef enum { + ARG_NO_ATTRIB = 0x0, + ARG_IS_QUOTED = 1<<0, + ARG_PARTIALLY_QUOTED = 1<<1, + ARG_FIRST_HALF_QUOTED = 1<<2, + ARG_FIRST_CHAR_IS_ESC = 1<<3 +} EFI_SHELL_ARG_INFO_TYPES; + +/// +/// Attributes for an argument. +/// +typedef struct _EFI_SHELL_ARG_INFO { + UINT32 Attributes; +} EFI_SHELL_ARG_INFO; + +/// +/// This protocol provides access to additional information about a shell application. +/// +typedef struct { + /// + /// Handle back to original image handle & image information. + /// + EFI_HANDLE ImageHandle; + EFI_LOADED_IMAGE* Info; + + /// + /// Parsed arg list converted more C-like format. + /// + CHAR16 **Argv; + UINTN Argc; + + /// + /// Storage for file redirection args after parsing. + /// + CHAR16 **RedirArgv; + UINTN RedirArgc; + + /// + /// A file style handle for console io. + /// + EFI_FILE* StdIn; + EFI_FILE* StdOut; + EFI_FILE* StdErr; + + /// + /// List of attributes for each argument. + /// + EFI_SHELL_ARG_INFO* ArgInfo; + + /// + /// Whether we are echoing. + /// + BOOLEAN EchoOn; +} EFI_SHELL_INTERFACE; + +#endif diff --git a/code/boot/include/efistdarg.h b/code/boot/include/efistdarg.h new file mode 100644 index 0000000..afe4201 --- /dev/null +++ b/code/boot/include/efistdarg.h @@ -0,0 +1,33 @@ +#ifndef _EFISTDARG_H_ +#define _EFISTDARG_H_ + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + devpath.h + +Abstract: + + Defines for parsing the EFI Device Path structures + + + +Revision History + +--*/ + +#if !defined(GNU_EFI_USE_EXTERNAL_STDARG) && !defined(_MSC_VER) +typedef __builtin_va_list va_list; + +# define va_start(v,l) __builtin_va_start(v,l) +# define va_end(v) __builtin_va_end(v) +# define va_arg(v,l) __builtin_va_arg(v,l) +# define va_copy(d,s) __builtin_va_copy(d,s) +#else +# include +#endif + +#endif diff --git a/code/boot/include/efitcp.h b/code/boot/include/efitcp.h new file mode 100644 index 0000000..c9abfca --- /dev/null +++ b/code/boot/include/efitcp.h @@ -0,0 +1,391 @@ +#ifndef _EFI_TCP_H +#define _EFI_TCP_H + +/*++ +Copyright (c) 2013 Intel Corporation + +--*/ + +#define EFI_TCP4_SERVICE_BINDING_PROTOCOL \ + { 0x00720665, 0x67eb, 0x4a99, {0xba, 0xf7, 0xd3, 0xc3, 0x3a, 0x1c,0x7c, 0xc9}} + +#define EFI_TCP4_PROTOCOL \ + { 0x65530bc7, 0xa359, 0x410f, {0xb0, 0x10, 0x5a, 0xad, 0xc7, 0xec, 0x2b, 0x62}} + +#define EFI_TCP6_SERVICE_BINDING_PROTOCOL \ + { 0xec20eb79, 0x6c1a, 0x4664, {0x9a, 0xd, 0xd2, 0xe4, 0xcc, 0x16, 0xd6, 0x64}} + +#define EFI_TCP6_PROTOCOL \ + { 0x46e44855, 0xbd60, 0x4ab7, {0xab, 0xd, 0xa6, 0x79, 0xb9, 0x44, 0x7d, 0x77}} + +INTERFACE_DECL(_EFI_TCP4); +INTERFACE_DECL(_EFI_TCP6); + +typedef struct { + BOOLEAN UseDefaultAddress; + EFI_IPv4_ADDRESS StationAddress; + EFI_IPv4_ADDRESS SubnetMask; + UINT16 StationPort; + EFI_IPv4_ADDRESS RemoteAddress; + UINT16 RemotePort; + BOOLEAN ActiveFlag; +} EFI_TCP4_ACCESS_POINT; + +typedef struct { + UINT32 ReceiveBufferSize; + UINT32 SendBufferSize; + UINT32 MaxSynBackLog; + UINT32 ConnectionTimeout; + UINT32 DataRetries; + UINT32 FinTimeout; + UINT32 TimeWaitTimeout; + UINT32 KeepAliveProbes; + UINT32 KeepAliveTime; + UINT32 KeepAliveInterval; + BOOLEAN EnableNagle; + BOOLEAN EnableTimeStamp; + BOOLEAN EnableWindowScaling; + BOOLEAN EnableSelectiveAck; + BOOLEAN EnablePAthMtuDiscovery; +} EFI_TCP4_OPTION; + +typedef struct { + // Receiving Filters + // I/O parameters + UINT8 TypeOfService; + UINT8 TimeToLive; + + // Access Point + EFI_TCP4_ACCESS_POINT AccessPoint; + + // TCP Control Options + EFI_TCP4_OPTION* ControlOption; +} EFI_TCP4_CONFIG_DATA; + +typedef enum { + Tcp4StateClosed = 0, + Tcp4StateListen = 1, + Tcp4StateSynSent = 2, + Tcp4StateSynReceived = 3, + Tcp4StateEstablished = 4, + Tcp4StateFinWait1 = 5, + Tcp4StateFinWait2 = 6, + Tcp4StateClosing = 7, + Tcp4StateTimeWait = 8, + Tcp4StateCloseWait = 9, + Tcp4StateLastAck = 10 +} EFI_TCP4_CONNECTION_STATE; + +typedef +EFI_STATUS +(EFIAPI* EFI_TCP4_GET_MODE_DATA) ( + IN struct _EFI_TCP4* This, + OUT EFI_TCP4_CONNECTION_STATE* Tcp4State OPTIONAL, + OUT EFI_TCP4_CONFIG_DATA* Tcp4ConfigData OPTIONAL, + OUT EFI_IP4_MODE_DATA* Ip4ModeData OPTIONAL, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA* MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE* SnpModeData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_TCP4_CONFIGURE) ( + IN struct _EFI_TCP4* This, + IN EFI_TCP4_CONFIG_DATA* TcpConfigData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_TCP4_ROUTES) ( + IN struct _EFI_TCP4* This, + IN BOOLEAN DeleteRoute, + IN EFI_IPv4_ADDRESS* SubnetAddress, + IN EFI_IPv4_ADDRESS* SubnetMask, + IN EFI_IPv4_ADDRESS* GatewayAddress +); + +typedef struct { + EFI_EVENT Event; + EFI_STATUS Status; +} EFI_TCP4_COMPLETION_TOKEN; + +typedef struct { + EFI_TCP4_COMPLETION_TOKEN CompletionToken; +} EFI_TCP4_CONNECTION_TOKEN; + +typedef +EFI_STATUS +(EFIAPI* EFI_TCP4_CONNECT) ( + IN struct _EFI_TCP4* This, + IN EFI_TCP4_CONNECTION_TOKEN* ConnectionToken + ); + +typedef struct { + EFI_TCP4_COMPLETION_TOKEN CompletionToken; + EFI_HANDLE NewChildHandle; +} EFI_TCP4_LISTEN_TOKEN; + +typedef +EFI_STATUS +(EFIAPI* EFI_TCP4_ACCEPT) ( + IN struct _EFI_TCP4* This, + IN EFI_TCP4_LISTEN_TOKEN* ListenToken + ); + +#define EFI_CONNECTION_FIN EFIERR(104) +#define EFI_CONNECTION_RESET EFIERR(105) +#define EFI_CONNECTION_REFUSED EFIERR(106) + +typedef struct { + UINT32 FragmentLength; + VOID* FragmentBuffer; +} EFI_TCP4_FRAGMENT_DATA; + +typedef struct { + BOOLEAN UrgentFlag; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_TCP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_TCP4_RECEIVE_DATA; + +typedef struct { + BOOLEAN Push; + BOOLEAN Urgent; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_TCP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_TCP4_TRANSMIT_DATA; + +typedef struct { + EFI_TCP4_COMPLETION_TOKEN CompletionToken; + union { + EFI_TCP4_RECEIVE_DATA* RxData; + EFI_TCP4_TRANSMIT_DATA* TxData; + } Packet; +} EFI_TCP4_IO_TOKEN; + +typedef +EFI_STATUS +(EFIAPI* EFI_TCP4_TRANSMIT) ( + IN struct _EFI_TCP4* This, + IN EFI_TCP4_IO_TOKEN* Token + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_TCP4_RECEIVE) ( + IN struct _EFI_TCP4* This, + IN EFI_TCP4_IO_TOKEN* Token + ); + +typedef struct { + EFI_TCP4_COMPLETION_TOKEN CompletionToken; + BOOLEAN AbortOnClose; +} EFI_TCP4_CLOSE_TOKEN; + +typedef +EFI_STATUS +(EFIAPI* EFI_TCP4_CLOSE)( + IN struct _EFI_TCP4* This, + IN EFI_TCP4_CLOSE_TOKEN* CloseToken + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_TCP4_CANCEL)( + IN struct _EFI_TCP4* This, + IN EFI_TCP4_COMPLETION_TOKEN* Token OPTIONAL +); + +typedef +EFI_STATUS +(EFIAPI* EFI_TCP4_POLL) ( + IN struct _EFI_TCP4* This + ); + +typedef struct _EFI_TCP4 { + EFI_TCP4_GET_MODE_DATA GetModeData; + EFI_TCP4_CONFIGURE Configure; + EFI_TCP4_ROUTES Routes; + EFI_TCP4_CONNECT Connect; + EFI_TCP4_ACCEPT Accept; + EFI_TCP4_TRANSMIT Transmit; + EFI_TCP4_RECEIVE Receive; + EFI_TCP4_CLOSE Close; + EFI_TCP4_CANCEL Cancel; + EFI_TCP4_POLL Poll; +} EFI_TCP4; + +typedef enum { + Tcp6StateClosed = 0, + Tcp6StateListen = 1, + Tcp6StateSynSent = 2, + Tcp6StateSynReceived = 3, + Tcp6StateEstablished = 4, + Tcp6StateFinWait1 = 5, + Tcp6StateFinWait2 = 6, + Tcp6StateClosing = 7, + Tcp6StateTimeWait = 8, + Tcp6StateCloseWait = 9, + Tcp6StateLastAck = 10 +} EFI_TCP6_CONNECTION_STATE; + +typedef struct { + EFI_IPv6_ADDRESS StationAddress; + UINT16 StationPort; + EFI_IPv6_ADDRESS RemoteAddress; + UINT16 RemotePort; + BOOLEAN ActiveFlag; +} EFI_TCP6_ACCESS_POINT; + +typedef struct { + UINT32 ReceiveBufferSize; + UINT32 SendBufferSize; + UINT32 MaxSynBackLog; + UINT32 ConnectionTimeout; + UINT32 DataRetries; + UINT32 FinTimeout; + UINT32 TimeWaitTimeout; + UINT32 KeepAliveProbes; + UINT32 KeepAliveTime; + UINT32 KeepAliveInterval; + BOOLEAN EnableNagle; + BOOLEAN EnableTimeStamp; + BOOLEAN EnableWindbowScaling; + BOOLEAN EnableSelectiveAck; + BOOLEAN EnablePathMtuDiscovery; +} EFI_TCP6_OPTION; + +typedef struct { + UINT8 TrafficClass; + UINT8 HopLimit; + EFI_TCP6_ACCESS_POINT AccessPoint; + EFI_TCP6_OPTION* ControlOption; +} EFI_TCP6_CONFIG_DATA; + +typedef +EFI_STATUS +(EFIAPI* EFI_TCP6_GET_MODE_DATA) ( + IN struct _EFI_TCP6* This, + OUT EFI_TCP6_CONNECTION_STATE* Tcp6State OPTIONAL, + OUT EFI_TCP6_CONFIG_DATA* Tcp6ConfigData OPTIONAL, + OUT EFI_IP6_MODE_DATA* Ip6ModeData OPTIONAL, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA* MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE* SnpModeData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_TCP6_CONFIGURE) ( + IN struct _EFI_TCP6* This, + IN EFI_TCP6_CONFIG_DATA* Tcp6ConfigData OPTIONAL + ); + +typedef struct { + EFI_EVENT Event; + EFI_STATUS Status; +} EFI_TCP6_COMPLETION_TOKEN; + +typedef struct { + EFI_TCP6_COMPLETION_TOKEN CompletionToken; +} EFI_TCP6_CONNECTION_TOKEN; + +typedef +EFI_STATUS +(EFIAPI* EFI_TCP6_CONNECT) ( + IN struct _EFI_TCP6* This, + IN EFI_TCP6_CONNECTION_TOKEN* ConnectionToken + ); + +typedef struct { + EFI_TCP6_COMPLETION_TOKEN CompletionToken; + EFI_HANDLE NewChildHandle; +} EFI_TCP6_LISTEN_TOKEN; + +typedef +EFI_STATUS +(EFIAPI* EFI_TCP6_ACCEPT) ( + IN struct _EFI_TCP6* This, + IN EFI_TCP6_LISTEN_TOKEN* ListenToken + ); + +typedef struct { + UINT32 FragmentLength; + VOID* FragmentBuffer; +} EFI_TCP6_FRAGMENT_DATA; + +typedef struct { + BOOLEAN UrgentFlag; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_TCP6_FRAGMENT_DATA FragmentTable[1]; +} EFI_TCP6_RECEIVE_DATA; + +typedef struct { + BOOLEAN Push; + BOOLEAN Urgent; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_TCP6_FRAGMENT_DATA FragmentTable[1]; +} EFI_TCP6_TRANSMIT_DATA; + +typedef struct { + EFI_TCP6_COMPLETION_TOKEN CompletionToken; + union { + EFI_TCP6_RECEIVE_DATA* RxData; + EFI_TCP6_TRANSMIT_DATA* TxData; + } Packet; +} EFI_TCP6_IO_TOKEN; + +typedef +EFI_STATUS +(EFIAPI* EFI_TCP6_TRANSMIT) ( + IN struct _EFI_TCP6* This, + IN EFI_TCP6_IO_TOKEN* Token + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_TCP6_RECEIVE) ( + IN struct _EFI_TCP6* This, + IN EFI_TCP6_IO_TOKEN* Token + ); + +typedef struct { + EFI_TCP6_COMPLETION_TOKEN CompletionToken; + BOOLEAN AbortOnClose; +} EFI_TCP6_CLOSE_TOKEN; + +typedef +EFI_STATUS +(EFIAPI* EFI_TCP6_CLOSE)( + IN struct _EFI_TCP6* This, + IN EFI_TCP6_CLOSE_TOKEN* CloseToken + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_TCP6_CANCEL)( + IN struct _EFI_TCP6* This, + IN EFI_TCP6_COMPLETION_TOKEN* Token OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_TCP6_POLL) ( + IN struct _EFI_TCP6* This + ); + +typedef struct _EFI_TCP6 { + EFI_TCP6_GET_MODE_DATA GetModeData; + EFI_TCP6_CONFIGURE Configure; + EFI_TCP6_CONNECT Connect; + EFI_TCP6_ACCEPT Accept; + EFI_TCP6_TRANSMIT Transmit; + EFI_TCP6_RECEIVE Receive; + EFI_TCP6_CLOSE Close; + EFI_TCP6_CANCEL Cancel; + EFI_TCP6_POLL Poll; +} EFI_TCP6; + +#endif /* _EFI_TCP_H */ diff --git a/code/boot/include/efiudp.h b/code/boot/include/efiudp.h new file mode 100644 index 0000000..cec7721 --- /dev/null +++ b/code/boot/include/efiudp.h @@ -0,0 +1,272 @@ +#ifndef _EFI_UDP_H +#define _EFI_UDP_H + + +/*++ +Copyright (c) 2013 Intel Corporation + +--*/ + +#define EFI_UDP4_SERVICE_BINDING_PROTOCOL \ + { 0x83f01464, 0x99bd, 0x45e5, {0xb3, 0x83, 0xaf, 0x63, 0x05, 0xd8, 0xe9, 0xe6} } + +#define EFI_UDP4_PROTOCOL \ + { 0x3ad9df29, 0x4501, 0x478d, {0xb1, 0xf8, 0x7f, 0x7f, 0xe7, 0x0e, 0x50, 0xf3} } + +#define EFI_UDP6_SERVICE_BINDING_PROTOCOL \ + { 0x66ed4721, 0x3c98, 0x4d3e, {0x81, 0xe3, 0xd0, 0x3d, 0xd3, 0x9a, 0x72, 0x54} } + +#define EFI_UDP6_PROTOCOL \ + { 0x4f948815, 0xb4b9, 0x43cb, {0x8a, 0x33, 0x90, 0xe0, 0x60, 0xb3,0x49, 0x55} } + +INTERFACE_DECL(_EFI_UDP4); +INTERFACE_DECL(_EFI_UDP6); + +typedef struct { + BOOLEAN AcceptBroadcast; + BOOLEAN AcceptPromiscuous; + BOOLEAN AcceptAnyPort; + BOOLEAN AllowDuplicatePort; + UINT8 TypeOfService; + UINT8 TimeToLive; + BOOLEAN DoNotFragment; + UINT32 ReceiveTimeout; + UINT32 TransmitTimeout; + BOOLEAN UseDefaultAddress; + EFI_IPv4_ADDRESS StationAddress; + EFI_IPv4_ADDRESS SubnetMask; + UINT16 StationPort; + EFI_IPv4_ADDRESS RemoteAddress; + UINT16 RemotePort; +} EFI_UDP4_CONFIG_DATA; + +typedef +EFI_STATUS +(EFIAPI* EFI_UDP4_GET_MODE_DATA) ( + IN struct _EFI_UDP4* This, + OUT EFI_UDP4_CONFIG_DATA* Udp4ConfigData OPTIONAL, + OUT EFI_IP4_MODE_DATA* Ip4ModeData OPTIONAL, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA* MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE* SnpModeData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_UDP4_CONFIGURE) ( + IN struct _EFI_UDP4* This, + IN EFI_UDP4_CONFIG_DATA* UdpConfigData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_UDP4_GROUPS) ( + IN struct _EFI_UDP4* This, + IN BOOLEAN JoinFlag, + IN EFI_IPv4_ADDRESS* MulticastAddress OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_UDP4_ROUTES) ( + IN struct _EFI_UDP4* This, + IN BOOLEAN DeleteRoute, + IN EFI_IPv4_ADDRESS* SubnetAddress, + IN EFI_IPv4_ADDRESS* SubnetMask, + IN EFI_IPv4_ADDRESS* GatewayAddress + ); + +#define EFI_NETWORK_UNREACHABLE EFIERR(100) +#define EFI_HOST_UNREACHABLE EFIERR(101) +#define EFI_PROTOCOL_UNREACHABLE EFIERR(102) +#define EFI_PORT_UNREACHABLE EFIERR(103) + +typedef struct { + EFI_IPv4_ADDRESS SourceAddress; + UINT16 SourcePort; + EFI_IPv4_ADDRESS DestinationAddress; + UINT16 DestinationPort; +} EFI_UDP4_SESSION_DATA; + +typedef struct { + UINT32 FragmentLength; + VOID* FragmentBuffer; +} EFI_UDP4_FRAGMENT_DATA; + +typedef struct { + EFI_TIME TimeStamp; + EFI_EVENT RecycleSignal; + EFI_UDP4_SESSION_DATA UdpSession; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_UDP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_UDP4_RECEIVE_DATA; + +typedef struct { + EFI_UDP4_SESSION_DATA* UdpSessionData; + EFI_IPv4_ADDRESS* GatewayAddress; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_UDP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_UDP4_TRANSMIT_DATA; + +typedef struct { + EFI_EVENT Event; + EFI_STATUS Status; + union { + EFI_UDP4_RECEIVE_DATA* RxData; + EFI_UDP4_TRANSMIT_DATA* TxData; + } Packet; +} EFI_UDP4_COMPLETION_TOKEN; + +typedef +EFI_STATUS +(EFIAPI* EFI_UDP4_TRANSMIT) ( + IN struct _EFI_UDP4* This, + IN EFI_UDP4_COMPLETION_TOKEN* Token + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_UDP4_RECEIVE) ( + IN struct _EFI_UDP4* This, + IN EFI_UDP4_COMPLETION_TOKEN* Token + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_UDP4_CANCEL)( + IN struct _EFI_UDP4* This, + IN EFI_UDP4_COMPLETION_TOKEN* Token OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_UDP4_POLL) ( + IN struct _EFI_UDP4* This + ); + +typedef struct _EFI_UDP4 { + EFI_UDP4_GET_MODE_DATA GetModeData; + EFI_UDP4_CONFIGURE Configure; + EFI_UDP4_GROUPS Groups; + EFI_UDP4_ROUTES Routes; + EFI_UDP4_TRANSMIT Transmit; + EFI_UDP4_RECEIVE Receive; + EFI_UDP4_CANCEL Cancel; + EFI_UDP4_POLL Poll; +} EFI_UDP4; + +typedef struct { + BOOLEAN AcceptPromiscuous; + BOOLEAN AcceptAnyPort; + BOOLEAN AllowDuplicatePort; + UINT8 TrafficClass; + UINT8 HopLimit; + UINT32 ReceiveTimeout; + UINT32 TransmitTimeout; + EFI_IPv6_ADDRESS StationAddress; + UINT16 StationPort; + EFI_IPv6_ADDRESS RemoteAddress; + UINT16 RemotePort; +} EFI_UDP6_CONFIG_DATA; + +typedef +EFI_STATUS +(EFIAPI* EFI_UDP6_GET_MODE_DATA) ( + IN struct _EFI_UDP6* This, + OUT EFI_UDP6_CONFIG_DATA* Udp6ConfigData OPTIONAL, + OUT EFI_IP6_MODE_DATA* Ip6ModeData OPTIONAL, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA* MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE* SnpModeData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_UDP6_CONFIGURE) ( + IN struct _EFI_UDP6* This, + IN EFI_UDP6_CONFIG_DATA* UdpConfigData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_UDP6_GROUPS) ( + IN struct _EFI_UDP6* This, + IN BOOLEAN JoinFlag, + IN EFI_IPv6_ADDRESS* MulticastAddress OPTIONAL + ); + +typedef struct { + EFI_IPv6_ADDRESS SourceAddress; + UINT16 SourcePort; + EFI_IPv6_ADDRESS DestinationAddress; + UINT16 DestinationPort; +} EFI_UDP6_SESSION_DATA; + +typedef struct { + UINT32 FragmentLength; + VOID* FragmentBuffer; +} EFI_UDP6_FRAGMENT_DATA; + +typedef struct { + EFI_TIME TimeStamp; + EFI_EVENT RecycleSignal; + EFI_UDP6_SESSION_DATA UdpSession; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_UDP6_FRAGMENT_DATA FragmentTable[1]; +} EFI_UDP6_RECEIVE_DATA; + +typedef struct { + EFI_UDP6_SESSION_DATA* UdpSessionData; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_UDP6_FRAGMENT_DATA FragmentTable[1]; +} EFI_UDP6_TRANSMIT_DATA; + +typedef struct { + EFI_EVENT Event; + EFI_STATUS Status; + union { + EFI_UDP6_RECEIVE_DATA* RxData; + EFI_UDP6_TRANSMIT_DATA* TxData; + } Packet; +} EFI_UDP6_COMPLETION_TOKEN; + +typedef +EFI_STATUS +(EFIAPI* EFI_UDP6_TRANSMIT) ( + IN struct _EFI_UDP6* This, + IN EFI_UDP6_COMPLETION_TOKEN* Token + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_UDP6_RECEIVE) ( + IN struct _EFI_UDP6* This, + IN EFI_UDP6_COMPLETION_TOKEN* Token + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_UDP6_CANCEL)( + IN struct _EFI_UDP6* This, + IN EFI_UDP6_COMPLETION_TOKEN* Token OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_UDP6_POLL) ( + IN struct _EFI_UDP6* This + ); + +typedef struct _EFI_UDP6 { + EFI_UDP6_GET_MODE_DATA GetModeData; + EFI_UDP6_CONFIGURE Configure; + EFI_UDP6_GROUPS Groups; + EFI_UDP6_TRANSMIT Transmit; + EFI_UDP6_RECEIVE Receive; + EFI_UDP6_CANCEL Cancel; + EFI_UDP6_POLL Poll; +} EFI_UDP6; + +#endif /* _EFI_UDP_H */ diff --git a/code/boot/include/efiui.h b/code/boot/include/efiui.h new file mode 100644 index 0000000..9789fb7 --- /dev/null +++ b/code/boot/include/efiui.h @@ -0,0 +1,58 @@ +#ifndef _EFI_UI_H +#define _EFI_UI_H + +/*++ + +Copyright (c) 200 Intel Corporation + +Module Name: + + EfiUi.h + +Abstract: + Protocol used to build User Interface (UI) stuff. + + This protocol is just data. It is a multi dimentional array. + For each string there is an array of UI_STRING_ENTRY. Each string + is for a different language translation of the same string. The list + is terminated by a NULL UiString. There can be any number of + UI_STRING_ENTRY arrays. A NULL array terminates the list. A NULL array + entry contains all zeros. + + Thus the shortest possible EFI_UI_PROTOCOL has three UI_STRING_ENTRY. + The String, it's NULL terminator, and the NULL terminator for the entire + thing. + + +Revision History + +--*/ + +#define EFI_UI_INTERFACE_PROTOCOL_GUID \ + { 0x32dd7981, 0x2d27, 0x11d4, {0xbc, 0x8b, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81} } +#define EFI_UI_PROTOCOL EFI_UI_INTERFACE_PROTOCOL_GUID + + +typedef enum { + UiDeviceString, + UiVendorString, + UiMaxString +} UI_STRING_TYPE; + +typedef struct { + ISO_639_2* LangCode; + CHAR16* UiString; +} UI_STRING_ENTRY; + +#define EFI_UI_INTERFACE_PROTOCOL_VERSION 0x00010000 +#define EFI_UI_VERSION EFI_UI_INTERFACE_PROTOCOL_VERSION + +typedef struct _EFI_UI_INTERFACE_PROTOCOL { + UINT32 Version; + UI_STRING_ENTRY* Entry; +} EFI_UI_INTERFACE_PROTOCOL; + +typedef struct _EFI_UI_INTERFACE_PROTOCOL _UI_INTERFACE; +typedef EFI_UI_INTERFACE_PROTOCOL UI_INTERFACE; + +#endif diff --git a/code/boot/include/ia32/efibind.h b/code/boot/include/ia32/efibind.h new file mode 100644 index 0000000..d31a56d --- /dev/null +++ b/code/boot/include/ia32/efibind.h @@ -0,0 +1,294 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efefind.h + +Abstract: + + EFI to compile bindings + + + + +Revision History + +--*/ + +#ifndef __GNUC__ +#pragma pack() +#endif + +// +// Basic int types of various widths +// + +#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L ) && !defined(__cplusplus) + + // No ANSI C 1999/2000 stdint.h integer width declarations + + #if defined(_MSC_EXTENSIONS) + + // Use Microsoft C compiler integer width declarations + + typedef unsigned __int64 uint64_t; + typedef __int64 int64_t; + typedef unsigned __int32 uint32_t; + typedef __int32 int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef char int8_t; + #elif defined(__GNUC__) + typedef int __attribute__((__mode__(__DI__))) int64_t; + typedef unsigned int __attribute__((__mode__(__DI__))) uint64_t; + typedef unsigned int uint32_t; + typedef int int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef signed char int8_t; + #elif defined(UNIX_LP64) + + /* Use LP64 programming model from C_FLAGS for integer width declarations */ + + typedef unsigned long uint64_t; + typedef long int64_t; + typedef unsigned int uint32_t; + typedef int int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef char int8_t; + #else + + /* Assume P64 programming model from C_FLAGS for integer width declarations */ + + typedef unsigned long long uint64_t __attribute__((aligned (8))); + typedef long long int64_t __attribute__((aligned (8))); + typedef unsigned int uint32_t; + typedef int int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef char int8_t; + #endif + typedef uint32_t uintptr_t; + typedef int32_t intptr_t; +#elif defined(__GNUC__) + #include +#endif + +// +// Basic EFI types of various widths +// + +#include + +typedef wchar_t CHAR16; +#define WCHAR CHAR16 + + +typedef uint64_t UINT64; +typedef int64_t INT64; + +#ifndef _BASETSD_H_ + typedef uint32_t UINT32; + typedef int32_t INT32; +#endif + +typedef uint16_t UINT16; +typedef int16_t INT16; + +typedef uint8_t UINT8; +typedef char CHAR8; +typedef int8_t INT8; + +#undef VOID +typedef void VOID; + + +typedef int32_t INTN; +typedef uint32_t UINTN; + +#ifdef EFI_NT_EMULATOR + #define POST_CODE(_Data) +#else + #ifdef EFI_DEBUG +#define POST_CODE(_Data) __asm mov eax,(_Data) __asm out 0x80,al + #else + #define POST_CODE(_Data) + #endif +#endif + +#define EFIERR(a) (0x80000000 | a) +#define EFI_ERROR_MASK 0x80000000 +#define EFIERR_OEM(a) (0xc0000000 | a) + + +#define BAD_POINTER 0xFBFBFBFB +#define MAX_ADDRESS 0xFFFFFFFF + +#ifdef EFI_NT_EMULATOR + #define BREAKPOINT() __asm { int 3 } +#else + #define BREAKPOINT() while (TRUE); // Make it hang on Bios[Dbg]32 +#endif + +// +// Pointers must be aligned to these address to function +// + +#define MIN_ALIGNMENT_SIZE 4 + +#define ALIGN_VARIABLE(Value ,Adjustment) \ + (UINTN)Adjustment = 0; \ + if((UINTN)Value % MIN_ALIGNMENT_SIZE) \ + (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \ + Value = (UINTN)Value + (UINTN)Adjustment + + +// +// Define macros to build data structure signatures from characters. +// + +#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8)) +#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16)) +#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32)) +// +// To export & import functions in the EFI emulator environment +// + +#ifdef EFI_NT_EMULATOR + #define EXPORTAPI __declspec( dllexport ) +#else + #define EXPORTAPI +#endif + + +// +// EFIAPI - prototype calling convention for EFI function pointers +// BOOTSERVICE - prototype for implementation of a boot service interface +// RUNTIMESERVICE - prototype for implementation of a runtime service interface +// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service +// RUNTIME_CODE - pragma macro for declaring runtime code +// + +#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options + #ifdef _MSC_EXTENSIONS + #define EFIAPI __cdecl // Force C calling convention for Microsoft C compiler + #else + #define EFIAPI // Substitute expresion to force C calling convention + #endif +#endif + +#define BOOTSERVICE +//#define RUNTIMESERVICE(proto,a) alloc_text("rtcode",a); proto a +//#define RUNTIMEFUNCTION(proto,a) alloc_text("rtcode",a); proto a +#define RUNTIMESERVICE +#define RUNTIMEFUNCTION + + +#define RUNTIME_CODE(a) alloc_text("rtcode", a) +#define BEGIN_RUNTIME_DATA() data_seg("rtdata") +#define END_RUNTIME_DATA() data_seg("") + +#define VOLATILE volatile + +#define MEMORY_FENCE() + +#ifdef EFI_NT_EMULATOR + +// +// To help ensure proper coding of integrated drivers, they are +// compiled as DLLs. In NT they require a dll init entry pointer. +// The macro puts a stub entry point into the DLL so it will load. +// + +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + UINTN \ + __stdcall \ + _DllMainCRTStartup ( \ + UINTN Inst, \ + UINTN reason_for_call, \ + VOID* rserved \ + ) \ + { \ + return 1; \ + } \ + \ + int \ + EXPORTAPI \ + __cdecl \ + InitializeDriver ( \ + void* ImageHandle, \ + void* SystemTable \ + ) \ + { \ + return InitFunction(ImageHandle, SystemTable); \ + } + + + #define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, NULL) + +#else // EFI_NT_EMULATOR + +// +// When build similiar to FW, then link everything together as +// one big module. For the MSVC toolchain, we simply tell the +// linker what our driver init function is using /ENTRY. +// +#if defined(_MSC_EXTENSIONS) + #define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + __pragma(comment(linker, "/ENTRY:" # InitFunction)) +#else + #define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + UINTN \ + InitializeDriver ( \ + VOID* ImageHandle, \ + VOID* SystemTable \ + ) \ + { \ + return InitFunction(ImageHandle, \ + SystemTable); \ + } \ + \ + EFI_STATUS efi_main( \ + EFI_HANDLE image, \ + EFI_SYSTEM_TABLE* systab \ + ) __attribute__((weak, \ + alias ("InitializeDriver"))); +#endif + + #define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, entry) + +#endif // EFI_FW_NT + +// +// Some compilers don't support the forward reference construct: +// typedef struct XXXXX +// +// The following macro provide a workaround for such cases. +// +#ifdef NO_INTERFACE_DECL +#define INTERFACE_DECL(x) +#else +#if defined(__GNUC__) || defined(_MSC_EXTENSIONS) +#define INTERFACE_DECL(x) struct x +#else +#define INTERFACE_DECL(x) typedef struct x +#endif +#endif + +/* No efi call wrapper for IA32 architecture */ +#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__) +#define EFI_FUNCTION + +#ifdef _MSC_EXTENSIONS +#pragma warning ( disable : 4731 ) // Suppress warnings about modification of EBP +#endif + diff --git a/code/boot/include/ia32/efilibplat.h b/code/boot/include/ia32/efilibplat.h new file mode 100644 index 0000000..0173875 --- /dev/null +++ b/code/boot/include/ia32/efilibplat.h @@ -0,0 +1,26 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efilibplat.h + +Abstract: + + EFI to compile bindings + + + + +Revision History + +--*/ + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE* SystemTable + ); + + diff --git a/code/boot/include/ia32/efisetjmp_arch.h b/code/boot/include/ia32/efisetjmp_arch.h new file mode 100644 index 0000000..3b775e6 --- /dev/null +++ b/code/boot/include/ia32/efisetjmp_arch.h @@ -0,0 +1,15 @@ +#ifndef GNU_EFI_IA32_SETJMP_H +#define GNU_EFI_IA32_SETJMP_H + +#define JMPBUF_ALIGN 4 + +typedef struct { + UINT32 Ebx; + UINT32 Esi; + UINT32 Edi; + UINT32 Ebp; + UINT32 Esp; + UINT32 Eip; +} EFI_ALIGN(JMPBUF_ALIGN) jmp_buf[1]; + +#endif /* GNU_EFI_IA32_SETJMP_H */ diff --git a/code/boot/include/ia32/pe.h b/code/boot/include/ia32/pe.h new file mode 100644 index 0000000..05f7851 --- /dev/null +++ b/code/boot/include/ia32/pe.h @@ -0,0 +1,595 @@ +/* + PE32+ header file + */ +#ifndef _PE_H +#define _PE_H + +#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ +#define IMAGE_OS2_SIGNATURE 0x454E // NE +#define IMAGE_OS2_SIGNATURE_LE 0x454C // LE +#define IMAGE_NT_SIGNATURE 0x00004550 // PE00 +#define IMAGE_EDOS_SIGNATURE 0x44454550 // PEED + + +typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header + UINT16 e_magic; // Magic number + UINT16 e_cblp; // Bytes on last page of file + UINT16 e_cp; // Pages in file + UINT16 e_crlc; // Relocations + UINT16 e_cparhdr; // Size of header in paragraphs + UINT16 e_minalloc; // Minimum extra paragraphs needed + UINT16 e_maxalloc; // Maximum extra paragraphs needed + UINT16 e_ss; // Initial (relative) SS value + UINT16 e_sp; // Initial SP value + UINT16 e_csum; // Checksum + UINT16 e_ip; // Initial IP value + UINT16 e_cs; // Initial (relative) CS value + UINT16 e_lfarlc; // File address of relocation table + UINT16 e_ovno; // Overlay number + UINT16 e_res[4]; // Reserved words + UINT16 e_oemid; // OEM identifier (for e_oeminfo) + UINT16 e_oeminfo; // OEM information; e_oemid specific + UINT16 e_res2[10]; // Reserved words + UINT32 e_lfanew; // File address of new exe header + } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; + +typedef struct _IMAGE_OS2_HEADER { // OS/2 .EXE header + UINT16 ne_magic; // Magic number + UINT8 ne_ver; // Version number + UINT8 ne_rev; // Revision number + UINT16 ne_enttab; // Offset of Entry Table + UINT16 ne_cbenttab; // Number of bytes in Entry Table + UINT32 ne_crc; // Checksum of whole file + UINT16 ne_flags; // Flag UINT16 + UINT16 ne_autodata; // Automatic data segment number + UINT16 ne_heap; // Initial heap allocation + UINT16 ne_stack; // Initial stack allocation + UINT32 ne_csip; // Initial CS:IP setting + UINT32 ne_sssp; // Initial SS:SP setting + UINT16 ne_cseg; // Count of file segments + UINT16 ne_cmod; // Entries in Module Reference Table + UINT16 ne_cbnrestab; // Size of non-resident name table + UINT16 ne_segtab; // Offset of Segment Table + UINT16 ne_rsrctab; // Offset of Resource Table + UINT16 ne_restab; // Offset of resident name table + UINT16 ne_modtab; // Offset of Module Reference Table + UINT16 ne_imptab; // Offset of Imported Names Table + UINT32 ne_nrestab; // Offset of Non-resident Names Table + UINT16 ne_cmovent; // Count of movable entries + UINT16 ne_align; // Segment alignment shift count + UINT16 ne_cres; // Count of resource segments + UINT8 ne_exetyp; // Target Operating system + UINT8 ne_flagsothers; // Other .EXE flags + UINT16 ne_pretthunks; // offset to return thunks + UINT16 ne_psegrefbytes; // offset to segment ref. bytes + UINT16 ne_swaparea; // Minimum code swap area size + UINT16 ne_expver; // Expected Windows version number + } IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER; + +// +// File header format. +// + +typedef struct _IMAGE_FILE_HEADER { + UINT16 Machine; + UINT16 NumberOfSections; + UINT32 TimeDateStamp; + UINT32 PointerToSymbolTable; + UINT32 NumberOfSymbols; + UINT16 SizeOfOptionalHeader; + UINT16 Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; + +#define IMAGE_SIZEOF_FILE_HEADER 20 + +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references). +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file. +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed. +#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file +#define IMAGE_FILE_SYSTEM 0x1000 // System File. +#define IMAGE_FILE_DLL 0x2000 // File is a DLL. +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed. + +#define IMAGE_FILE_MACHINE_UNKNOWN 0 +#define IMAGE_FILE_MACHINE_I386 0x14c // Intel 386. +#define IMAGE_FILE_MACHINE_R3000 0x162 // MIPS little-endian, 0540 big-endian +#define IMAGE_FILE_MACHINE_R4000 0x166 // MIPS little-endian +#define IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP +#define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED 0x1c2 // Arm/Thumb +#define IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM PowerPC Little-Endian +#define IMAGE_FILE_MACHINE_IA64 0x200 // IA-64 +#define IMAGE_FILE_MACHINE_TAHOE 0x7cc // Intel EM machine +#define IMAGE_FILE_MACHINE_EBC 0xebc // EFI Byte Code +#define IMAGE_FILE_MACHINE_X64 0x8664 // x86_64 +// +// Directory format. +// + +typedef struct _IMAGE_DATA_DIRECTORY { + UINT32 VirtualAddress; + UINT32 Size; +} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 + +// +// Optional header format. +// + +typedef struct _IMAGE_OPTIONAL_HEADER { + // + // Standard fields. + // + + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + UINT32 BaseOfData; + + // + // NT additional fields. + // + + UINT32 ImageBase; + UINT32 SectionAlignment; + UINT32 FileAlignment; + UINT16 MajorOperatingSystemVersion; + UINT16 MinorOperatingSystemVersion; + UINT16 MajorImageVersion; + UINT16 MinorImageVersion; + UINT16 MajorSubsystemVersion; + UINT16 MinorSubsystemVersion; + UINT32 Reserved1; + UINT32 SizeOfImage; + UINT32 SizeOfHeaders; + UINT32 CheckSum; + UINT16 Subsystem; + UINT16 DllCharacteristics; + UINT32 SizeOfStackReserve; + UINT32 SizeOfStackCommit; + UINT32 SizeOfHeapReserve; + UINT32 SizeOfHeapCommit; + UINT32 LoaderFlags; + UINT32 NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER; + +typedef struct _IMAGE_ROM_OPTIONAL_HEADER { + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + UINT32 BaseOfData; + UINT32 BaseOfBss; + UINT32 GprMask; + UINT32 CprMask[4]; + UINT32 GpValue; +} IMAGE_ROM_OPTIONAL_HEADER, *PIMAGE_ROM_OPTIONAL_HEADER; + +#define IMAGE_SIZEOF_ROM_OPTIONAL_HEADER 56 +#define IMAGE_SIZEOF_STD_OPTIONAL_HEADER 28 +#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER 224 + +#define IMAGE_NT_OPTIONAL_HDR_MAGIC 0x10b +#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107 + +typedef struct _IMAGE_NT_HEADERS { + UINT32 Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER OptionalHeader; +} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS; + +typedef struct _IMAGE_ROM_HEADERS { + IMAGE_FILE_HEADER FileHeader; + IMAGE_ROM_OPTIONAL_HEADER OptionalHeader; +} IMAGE_ROM_HEADERS, *PIMAGE_ROM_HEADERS; + +#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) \ + ((UINT32)ntheader + \ + FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + \ + ((PIMAGE_NT_HEADERS)(ntheader))->FileHeader.SizeOfOptionalHeader \ + )) + + +// Subsystem Values + +#define IMAGE_SUBSYSTEM_UNKNOWN 0 // Unknown subsystem. +#define IMAGE_SUBSYSTEM_NATIVE 1 // Image doesn't require a subsystem. +#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem. +#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem. +#define IMAGE_SUBSYSTEM_OS2_CUI 5 // image runs in the OS/2 character subsystem. +#define IMAGE_SUBSYSTEM_POSIX_CUI 7 // image run in the Posix character subsystem. + + +// Directory Entries + +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory +#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory +#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table +#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory +#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // Description String +#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // Machine Value (MIPS GP) +#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory +#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory + +// +// Section header format. +// + +#define IMAGE_SIZEOF_SHORT_NAME 8 + +typedef struct _IMAGE_SECTION_HEADER { + UINT8 Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + UINT32 PhysicalAddress; + UINT32 VirtualSize; + } Misc; + UINT32 VirtualAddress; + UINT32 SizeOfRawData; + UINT32 PointerToRawData; + UINT32 PointerToRelocations; + UINT32 PointerToLinenumbers; + UINT16 NumberOfRelocations; + UINT16 NumberOfLinenumbers; + UINT32 Characteristics; +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; + +#define IMAGE_SIZEOF_SECTION_HEADER 40 + +#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved. + +#define IMAGE_SCN_CNT_CODE 0x00000020 // Section contains code. +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // Section contains initialized data. +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 // Section contains uninitialized data. + +#define IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved. +#define IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information. +#define IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image. +#define IMAGE_SCN_LNK_COMDAT 0x00001000 // Section contents comdat. + +#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 // +#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 // +#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 // +#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 // +#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 // Default alignment if no others are specified. +#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 // +#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 // + +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // Section can be discarded. +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 // Section is not cachable. +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 // Section is not pageable. +#define IMAGE_SCN_MEM_SHARED 0x10000000 // Section is shareable. +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable. +#define IMAGE_SCN_MEM_READ 0x40000000 // Section is readable. +#define IMAGE_SCN_MEM_WRITE 0x80000000 // Section is writeable. + +// +// Symbol format. +// + + +#define IMAGE_SIZEOF_SYMBOL 18 + +// +// Section values. +// +// Symbols have a section number of the section in which they are +// defined. Otherwise, section numbers have the following meanings: +// + +#define IMAGE_SYM_UNDEFINED (UINT16)0 // Symbol is undefined or is common. +#define IMAGE_SYM_ABSOLUTE (UINT16)-1 // Symbol is an absolute value. +#define IMAGE_SYM_DEBUG (UINT16)-2 // Symbol is a special debug item. + +// +// Type (fundamental) values. +// + +#define IMAGE_SYM_TYPE_NULL 0 // no type. +#define IMAGE_SYM_TYPE_VOID 1 // +#define IMAGE_SYM_TYPE_CHAR 2 // type character. +#define IMAGE_SYM_TYPE_SHORT 3 // type short integer. +#define IMAGE_SYM_TYPE_INT 4 // +#define IMAGE_SYM_TYPE_LONG 5 // +#define IMAGE_SYM_TYPE_FLOAT 6 // +#define IMAGE_SYM_TYPE_DOUBLE 7 // +#define IMAGE_SYM_TYPE_STRUCT 8 // +#define IMAGE_SYM_TYPE_UNION 9 // +#define IMAGE_SYM_TYPE_ENUM 10 // enumeration. +#define IMAGE_SYM_TYPE_MOE 11 // member of enumeration. +#define IMAGE_SYM_TYPE_BYTE 12 // +#define IMAGE_SYM_TYPE_WORD 13 // +#define IMAGE_SYM_TYPE_UINT 14 // +#define IMAGE_SYM_TYPE_DWORD 15 // + +// +// Type (derived) values. +// + +#define IMAGE_SYM_DTYPE_NULL 0 // no derived type. +#define IMAGE_SYM_DTYPE_POINTER 1 // pointer. +#define IMAGE_SYM_DTYPE_FUNCTION 2 // function. +#define IMAGE_SYM_DTYPE_ARRAY 3 // array. + +// +// Storage classes. +// + +#define IMAGE_SYM_CLASS_END_OF_FUNCTION (BYTE )-1 +#define IMAGE_SYM_CLASS_NULL 0 +#define IMAGE_SYM_CLASS_AUTOMATIC 1 +#define IMAGE_SYM_CLASS_EXTERNAL 2 +#define IMAGE_SYM_CLASS_STATIC 3 +#define IMAGE_SYM_CLASS_REGISTER 4 +#define IMAGE_SYM_CLASS_EXTERNAL_DEF 5 +#define IMAGE_SYM_CLASS_LABEL 6 +#define IMAGE_SYM_CLASS_UNDEFINED_LABEL 7 +#define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8 +#define IMAGE_SYM_CLASS_ARGUMENT 9 +#define IMAGE_SYM_CLASS_STRUCT_TAG 10 +#define IMAGE_SYM_CLASS_MEMBER_OF_UNION 11 +#define IMAGE_SYM_CLASS_UNION_TAG 12 +#define IMAGE_SYM_CLASS_TYPE_DEFINITION 13 +#define IMAGE_SYM_CLASS_UNDEFINED_STATIC 14 +#define IMAGE_SYM_CLASS_ENUM_TAG 15 +#define IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16 +#define IMAGE_SYM_CLASS_REGISTER_PARAM 17 +#define IMAGE_SYM_CLASS_BIT_FIELD 18 +#define IMAGE_SYM_CLASS_BLOCK 100 +#define IMAGE_SYM_CLASS_FUNCTION 101 +#define IMAGE_SYM_CLASS_END_OF_STRUCT 102 +#define IMAGE_SYM_CLASS_FILE 103 +// new +#define IMAGE_SYM_CLASS_SECTION 104 +#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 105 + +// type packing constants + +#define N_BTMASK 017 +#define N_TMASK 060 +#define N_TMASK1 0300 +#define N_TMASK2 0360 +#define N_BTSHFT 4 +#define N_TSHIFT 2 + +// MACROS + +// +// Communal selection types. +// + +#define IMAGE_COMDAT_SELECT_NODUPLICATES 1 +#define IMAGE_COMDAT_SELECT_ANY 2 +#define IMAGE_COMDAT_SELECT_SAME_SIZE 3 +#define IMAGE_COMDAT_SELECT_EXACT_MATCH 4 +#define IMAGE_COMDAT_SELECT_ASSOCIATIVE 5 + +#define IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1 +#define IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2 +#define IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3 + + +// +// Relocation format. +// + +typedef struct _IMAGE_RELOCATION { + UINT32 VirtualAddress; + UINT32 SymbolTableIndex; + UINT16 Type; +} IMAGE_RELOCATION; + +#define IMAGE_SIZEOF_RELOCATION 10 + +// +// I386 relocation types. +// + +#define IMAGE_REL_I386_ABSOLUTE 0 // Reference is absolute, no relocation is necessary +#define IMAGE_REL_I386_DIR16 01 // Direct 16-bit reference to the symbols virtual address +#define IMAGE_REL_I386_REL16 02 // PC-relative 16-bit reference to the symbols virtual address +#define IMAGE_REL_I386_DIR32 06 // Direct 32-bit reference to the symbols virtual address +#define IMAGE_REL_I386_DIR32NB 07 // Direct 32-bit reference to the symbols virtual address, base not included +#define IMAGE_REL_I386_SEG12 011 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address +#define IMAGE_REL_I386_SECTION 012 +#define IMAGE_REL_I386_SECREL 013 +#define IMAGE_REL_I386_REL32 024 // PC-relative 32-bit reference to the symbols virtual address + +// +// MIPS relocation types. +// + +#define IMAGE_REL_MIPS_ABSOLUTE 0 // Reference is absolute, no relocation is necessary +#define IMAGE_REL_MIPS_REFHALF 01 +#define IMAGE_REL_MIPS_REFWORD 02 +#define IMAGE_REL_MIPS_JMPADDR 03 +#define IMAGE_REL_MIPS_REFHI 04 +#define IMAGE_REL_MIPS_REFLO 05 +#define IMAGE_REL_MIPS_GPREL 06 +#define IMAGE_REL_MIPS_LITERAL 07 +#define IMAGE_REL_MIPS_SECTION 012 +#define IMAGE_REL_MIPS_SECREL 013 +#define IMAGE_REL_MIPS_REFWORDNB 042 +#define IMAGE_REL_MIPS_PAIR 045 + +// +// Alpha Relocation types. +// + +#define IMAGE_REL_ALPHA_ABSOLUTE 0x0 +#define IMAGE_REL_ALPHA_REFLONG 0x1 +#define IMAGE_REL_ALPHA_REFQUAD 0x2 +#define IMAGE_REL_ALPHA_GPREL32 0x3 +#define IMAGE_REL_ALPHA_LITERAL 0x4 +#define IMAGE_REL_ALPHA_LITUSE 0x5 +#define IMAGE_REL_ALPHA_GPDISP 0x6 +#define IMAGE_REL_ALPHA_BRADDR 0x7 +#define IMAGE_REL_ALPHA_HINT 0x8 +#define IMAGE_REL_ALPHA_INLINE_REFLONG 0x9 +#define IMAGE_REL_ALPHA_REFHI 0xA +#define IMAGE_REL_ALPHA_REFLO 0xB +#define IMAGE_REL_ALPHA_PAIR 0xC +#define IMAGE_REL_ALPHA_MATCH 0xD +#define IMAGE_REL_ALPHA_SECTION 0xE +#define IMAGE_REL_ALPHA_SECREL 0xF +#define IMAGE_REL_ALPHA_REFLONGNB 0x10 + +// +// IBM PowerPC relocation types. +// + +#define IMAGE_REL_PPC_ABSOLUTE 0x0000 // NOP +#define IMAGE_REL_PPC_ADDR64 0x0001 // 64-bit address +#define IMAGE_REL_PPC_ADDR32 0x0002 // 32-bit address +#define IMAGE_REL_PPC_ADDR24 0x0003 // 26-bit address, shifted left 2 (branch absolute) +#define IMAGE_REL_PPC_ADDR16 0x0004 // 16-bit address +#define IMAGE_REL_PPC_ADDR14 0x0005 // 16-bit address, shifted left 2 (load doubleword) +#define IMAGE_REL_PPC_REL24 0x0006 // 26-bit PC-relative offset, shifted left 2 (branch relative) +#define IMAGE_REL_PPC_REL14 0x0007 // 16-bit PC-relative offset, shifted left 2 (br cond relative) +#define IMAGE_REL_PPC_TOCREL16 0x0008 // 16-bit offset from TOC base +#define IMAGE_REL_PPC_TOCREL14 0x0009 // 16-bit offset from TOC base, shifted left 2 (load doubleword) + +#define IMAGE_REL_PPC_ADDR32NB 0x000A // 32-bit addr w/o image base +#define IMAGE_REL_PPC_SECREL 0x000B // va of containing section (as in an image sectionhdr) +#define IMAGE_REL_PPC_SECTION 0x000C // sectionheader number +#define IMAGE_REL_PPC_IFGLUE 0x000D // substitute TOC restore instruction iff symbol is glue code +#define IMAGE_REL_PPC_IMGLUE 0x000E // symbol is glue code; virtual address is TOC restore instruction + +#define IMAGE_REL_PPC_TYPEMASK 0x00FF // mask to isolate above values in IMAGE_RELOCATION.Type + +// Flag bits in IMAGE_RELOCATION.TYPE + +#define IMAGE_REL_PPC_NEG 0x0100 // subtract reloc value rather than adding it +#define IMAGE_REL_PPC_BRTAKEN 0x0200 // fix branch prediction bit to predict branch taken +#define IMAGE_REL_PPC_BRNTAKEN 0x0400 // fix branch prediction bit to predict branch not taken +#define IMAGE_REL_PPC_TOCDEFN 0x0800 // toc slot defined in file (or, data in toc) + +// +// Based relocation format. +// + +typedef struct _IMAGE_BASE_RELOCATION { + UINT32 VirtualAddress; + UINT32 SizeOfBlock; +// UINT16 TypeOffset[1]; +} IMAGE_BASE_RELOCATION, *PIMAGE_BASE_RELOCATION; + +#define IMAGE_SIZEOF_BASE_RELOCATION 8 + +// +// Based relocation types. +// + +#define IMAGE_REL_BASED_ABSOLUTE 0 +#define IMAGE_REL_BASED_HIGH 1 +#define IMAGE_REL_BASED_LOW 2 +#define IMAGE_REL_BASED_HIGHLOW 3 +#define IMAGE_REL_BASED_HIGHADJ 4 +#define IMAGE_REL_BASED_MIPS_JMPADDR 5 +#define IMAGE_REL_BASED_IA64_IMM64 9 +#define IMAGE_REL_BASED_DIR64 10 + +// +// Line number format. +// + +typedef struct _IMAGE_LINENUMBER { + union { + UINT32 SymbolTableIndex; // Symbol table index of function name if Linenumber is 0. + UINT32 VirtualAddress; // Virtual address of line number. + } Type; + UINT16 Linenumber; // Line number. +} IMAGE_LINENUMBER; + +#define IMAGE_SIZEOF_LINENUMBER 6 + +// +// Archive format. +// + +#define IMAGE_ARCHIVE_START_SIZE 8 +#define IMAGE_ARCHIVE_START "!\n" +#define IMAGE_ARCHIVE_END "`\n" +#define IMAGE_ARCHIVE_PAD "\n" +#define IMAGE_ARCHIVE_LINKER_MEMBER "/ " +#define IMAGE_ARCHIVE_LONGNAMES_MEMBER "// " + +typedef struct _IMAGE_ARCHIVE_MEMBER_HEADER { + UINT8 Name[16]; // File member name - `/' terminated. + UINT8 Date[12]; // File member date - decimal. + UINT8 UserID[6]; // File member user id - decimal. + UINT8 GroupID[6]; // File member group id - decimal. + UINT8 Mode[8]; // File member mode - octal. + UINT8 Size[10]; // File member size - decimal. + UINT8 EndHeader[2]; // String to end header. +} IMAGE_ARCHIVE_MEMBER_HEADER, *PIMAGE_ARCHIVE_MEMBER_HEADER; + +#define IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60 + +// +// DLL support. +// + +// +// Export Format +// + +typedef struct _IMAGE_EXPORT_DIRECTORY { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT16 MajorVersion; + UINT16 MinorVersion; + UINT32 Name; + UINT32 Base; + UINT32 NumberOfFunctions; + UINT32 NumberOfNames; + UINT32* AddressOfFunctions; + UINT32* AddressOfNames; + UINT32* AddressOfNameOrdinals; +} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; + +// +// Import Format +// + +typedef struct _IMAGE_IMPORT_BY_NAME { + UINT16 Hint; + UINT8 Name[1]; +} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; + +typedef struct _IMAGE_THUNK_DATA { + union { + UINT32 Function; + UINT32 Ordinal; + PIMAGE_IMPORT_BY_NAME AddressOfData; + } u1; +} IMAGE_THUNK_DATA, *PIMAGE_THUNK_DATA; + +#define IMAGE_ORDINAL_FLAG 0x80000000 +#define IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG) != 0) +#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff) + +typedef struct _IMAGE_IMPORT_DESCRIPTOR { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT32 ForwarderChain; + UINT32 Name; + PIMAGE_THUNK_DATA FirstThunk; +} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR; + +#endif diff --git a/code/boot/include/ia64/efibind.h b/code/boot/include/ia64/efibind.h new file mode 100644 index 0000000..e070bb2 --- /dev/null +++ b/code/boot/include/ia64/efibind.h @@ -0,0 +1,236 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efefind.h + +Abstract: + + EFI to compile bindings + + + + +Revision History + +--*/ + +#pragma pack() + + +// +// Basic int types of various widths +// + +#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L ) && !defined(__cplusplus) + + // No ANSI C 1999/2000 stdint.h integer width declarations + + #ifdef _MSC_EXTENSIONS + // Use Microsoft C compiler integer width declarations + + typedef unsigned __int64 uint64_t; + typedef __int64 int64_t; + typedef unsigned __int32 uint32_t; + typedef __int32 int32_t; + typedef unsigned __int16 uint16_t; + typedef __int16 int16_t; + typedef unsigned __int8 uint8_t; + typedef __int8 int8_t; + #elif defined(UNIX_LP64) + // Use LP64 programming model from C_FLAGS for integer width declarations + + typedef unsigned long uint64_t; + typedef long int64_t; + typedef unsigned int uint32_t; + typedef int int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef char int8_t; + #else + // Assume P64 programming model from C_FLAGS for integer width declarations + + typedef unsigned long long uint64_t; + typedef long long int64_t; + typedef unsigned int uint32_t; + typedef int int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef char int8_t; + #endif + typedef uint64_t uintptr_t; + typedef int64_t intptr_t; +#elif defined(__GNUC__) + #include +#endif + +// +// Basic EFI types of various widths +// + +#include + +typedef wchar_t CHAR16; +#define WCHAR CHAR16 + +typedef uint64_t UINT64; +typedef int64_t INT64; + +typedef uint32_t UINT32; +typedef int32_t INT32; + +typedef uint16_t UINT16; +typedef int16_t INT16; + +typedef uint8_t UINT8; +typedef char CHAR8; +typedef int8_t INT8; + +#undef VOID +typedef void VOID; + + +typedef int64_t INTN; +typedef uint64_t UINTN; + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// BugBug: Code to debug +// +#define BIT63 0x8000000000000000 + +#define PLATFORM_IOBASE_ADDRESS (0xffffc000000 | BIT63) +#define PORT_TO_MEMD(_Port) (PLATFORM_IOBASE_ADDRESS | ( ( ( (_Port) & 0xfffc) << 10 ) | ( (_Port) & 0x0fff) ) ) + +// +// Macro's with casts make this much easier to use and read. +// +#define PORT_TO_MEM8D(_Port) (*(UINT8 *)(PORT_TO_MEMD(_Port))) +#define POST_CODE(_Data) (PORT_TO_MEM8D(0x80) = (_Data)) +// +// BugBug: End Debug Code!!! +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +#define EFIERR(a) (0x8000000000000000 | a) +#define EFI_ERROR_MASK 0x8000000000000000 +#define EFIERR_OEM(a) (0xc000000000000000 | a) + +#define BAD_POINTER 0xFBFBFBFBFBFBFBFB +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF + +#define BREAKPOINT() while (TRUE) + +// +// Pointers must be aligned to these address to function +// you will get an alignment fault if this value is less than 8 +// +#define MIN_ALIGNMENT_SIZE 8 + +#define ALIGN_VARIABLE(Value , Adjustment) \ + (UINTN) Adjustment = 0; \ + if((UINTN)Value % MIN_ALIGNMENT_SIZE) \ + (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \ + Value = (UINTN)Value + (UINTN)Adjustment + +// +// Define macros to create data structure signatures. +// + +#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8)) +#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16)) +#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32)) +// +// To export & import functions in the EFI emulator environment +// + + #define EXPORTAPI + +// +// EFIAPI - prototype calling convention for EFI function pointers +// BOOTSERVICE - prototype for implementation of a boot service interface +// RUNTIMESERVICE - prototype for implementation of a runtime service interface +// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service +// RUNTIME_CODE - pragma macro for declaring runtime code +// + +#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options + #ifdef _MSC_EXTENSIONS + #define EFIAPI __cdecl // Force C calling convention for Microsoft C compiler + #else + #define EFIAPI // Substitute expresion to force C calling convention + #endif +#endif + +#define BOOTSERVICE +#define RUNTIMESERVICE +#define RUNTIMEFUNCTION + +#define RUNTIME_CODE(a) alloc_text("rtcode", a) +#define BEGIN_RUNTIME_DATA() data_seg("rtdata") +#define END_RUNTIME_DATA() data_seg("") + +#define VOLATILE volatile + +// +// BugBug: Need to find out if this is portable accross compliers. +// +#ifdef __GNUC__ +#define MEMORY_FENCE() __asm__ __volatile__ ("mf.a" ::: "memory") +#else +void __mf (void); +#pragma intrinsic (__mf) +#define MEMORY_FENCE() __mf() +#endif + +// +// When build similiar to FW, then link everything together as +// one big module. For the MSVC toolchain, we simply tell the +// linker what our driver init function is using /ENTRY. +// +#if defined(_MSC_EXTENSIONS) + #define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + __pragma(comment(linker, "/ENTRY:" # InitFunction)) +#else + #define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + UINTN \ + InitializeDriver ( \ + VOID* ImageHandle, \ + VOID* SystemTable \ + ) \ + { \ + return InitFunction(ImageHandle, \ + SystemTable); \ + } \ + \ + EFI_STATUS efi_main( \ + EFI_HANDLE image, \ + EFI_SYSTEM_TABLE* systab \ + ) __attribute__((weak, \ + alias ("InitializeDriver"))); +#endif + +#define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, entry) + +// +// Some compilers don't support the forward reference construct: +// typedef struct XXXXX +// +// The following macro provide a workaround for such cases. +// +#ifdef NO_INTERFACE_DECL +#define INTERFACE_DECL(x) +#else +#if defined(__GNUC__) || defined(_MSC_EXTENSIONS) +#define INTERFACE_DECL(x) struct x +#else +#define INTERFACE_DECL(x) typedef struct x +#endif +#endif + +/* No efi call wrapper for IA32 architecture */ +#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__) +#define EFI_FUNCTION diff --git a/code/boot/include/ia64/efilibplat.h b/code/boot/include/ia64/efilibplat.h new file mode 100644 index 0000000..e1a0c84 --- /dev/null +++ b/code/boot/include/ia64/efilibplat.h @@ -0,0 +1,80 @@ +#ifndef _EFI_LIB_PLAT_H +#define _EFI_LIB_PLAT_H +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efilibplat.h + +Abstract: + + EFI to compile bindings + + + +Revision History + +--*/ + +#include "salproc.h" + + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE* SystemTable + ); + +VOID +LibInitSalAndPalProc( + OUT PLABEL* SalPlabel, + OUT UINT64* PalEntry + ); + +EFI_STATUS +LibGetSalIoPortMapping ( + OUT UINT64* IoPortMapping + ); + +EFI_STATUS +LibGetSalIpiBlock ( + OUT UINT64* IpiBlock + ); + +EFI_STATUS +LibGetSalWakeupVector ( + OUT UINT64* WakeVector + ); + +VOID * +LibSearchSalSystemTable ( + IN UINT8 EntryType + ); + + +VOID +LibSalProc ( + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8, + OUT rArg* Results OPTIONAL + ); + +VOID +LibPalProc ( + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + OUT rArg* Results OPTIONAL + ); + +#endif + diff --git a/code/boot/include/ia64/efisetjmp_arch.h b/code/boot/include/ia64/efisetjmp_arch.h new file mode 100644 index 0000000..da264fa --- /dev/null +++ b/code/boot/include/ia64/efisetjmp_arch.h @@ -0,0 +1,47 @@ +#ifndef GNU_EFI_IA64_SETJMP_H +#define GNU_EFI_IA64_SETJMP_H + +#define JMPBUF_ALIGN 0x10 + +typedef struct { + UINT64 F2[2]; + UINT64 F3[2]; + UINT64 F4[2]; + UINT64 F5[2]; + UINT64 F16[2]; + UINT64 F17[2]; + UINT64 F18[2]; + UINT64 F19[2]; + UINT64 F20[2]; + UINT64 F21[2]; + UINT64 F22[2]; + UINT64 F23[2]; + UINT64 F24[2]; + UINT64 F25[2]; + UINT64 F26[2]; + UINT64 F27[2]; + UINT64 F28[2]; + UINT64 F29[2]; + UINT64 F30[2]; + UINT64 F31[2]; + UINT64 R4; + UINT64 R5; + UINT64 R6; + UINT64 R7; + UINT64 SP; + UINT64 BR0; + UINT64 BR1; + UINT64 BR2; + UINT64 BR3; + UINT64 BR4; + UINT64 BR5; + UINT64 InitialUNAT; + UINT64 AfterSpillUNAT; + UINT64 PFS; + UINT64 BSP; + UINT64 Predicates; + UINT64 LoopCount; + UINT64 FPSR; +} EFI_ALIGN(JMPBUF_ALIGN) jmp_buf[1]; + +#endif /* GNU_EFI_IA64_SETJMP_H */ diff --git a/code/boot/include/ia64/pe.h b/code/boot/include/ia64/pe.h new file mode 100644 index 0000000..4646b80 --- /dev/null +++ b/code/boot/include/ia64/pe.h @@ -0,0 +1,601 @@ +/* + PE32+ header file + */ +#ifndef _PE_H +#define _PE_H + +#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ +#define IMAGE_OS2_SIGNATURE 0x454E // NE +#define IMAGE_OS2_SIGNATURE_LE 0x454C // LE +#define IMAGE_NT_SIGNATURE 0x00004550 // PE00 +#define IMAGE_EDOS_SIGNATURE 0x44454550 // PEED + +/***************************************************************************** + * The following stuff comes from winnt.h from the ia64sdk, plus the Plabel for + * loading EM executables. + *****************************************************************************/ +// +// Intel IA64 specific +// + +#define IMAGE_REL_BASED_IA64_IMM64 9 +#define IMAGE_REL_BASED_IA64_DIR64 10 + +struct Plabel { + UINT64 EntryPoint; + UINT64 NewGP; +}; + +typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header + UINT16 e_magic; // Magic number + UINT16 e_cblp; // Bytes on last page of file + UINT16 e_cp; // Pages in file + UINT16 e_crlc; // Relocations + UINT16 e_cparhdr; // Size of header in paragraphs + UINT16 e_minalloc; // Minimum extra paragraphs needed + UINT16 e_maxalloc; // Maximum extra paragraphs needed + UINT16 e_ss; // Initial (relative) SS value + UINT16 e_sp; // Initial SP value + UINT16 e_csum; // Checksum + UINT16 e_ip; // Initial IP value + UINT16 e_cs; // Initial (relative) CS value + UINT16 e_lfarlc; // File address of relocation table + UINT16 e_ovno; // Overlay number + UINT16 e_res[4]; // Reserved words + UINT16 e_oemid; // OEM identifier (for e_oeminfo) + UINT16 e_oeminfo; // OEM information; e_oemid specific + UINT16 e_res2[10]; // Reserved words + UINT32 e_lfanew; // File address of new exe header + } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; + +typedef struct _IMAGE_OS2_HEADER { // OS/2 .EXE header + UINT16 ne_magic; // Magic number + UINT8 ne_ver; // Version number + UINT8 ne_rev; // Revision number + UINT16 ne_enttab; // Offset of Entry Table + UINT16 ne_cbenttab; // Number of bytes in Entry Table + UINT32 ne_crc; // Checksum of whole file + UINT16 ne_flags; // Flag UINT16 + UINT16 ne_autodata; // Automatic data segment number + UINT16 ne_heap; // Initial heap allocation + UINT16 ne_stack; // Initial stack allocation + UINT32 ne_csip; // Initial CS:IP setting + UINT32 ne_sssp; // Initial SS:SP setting + UINT16 ne_cseg; // Count of file segments + UINT16 ne_cmod; // Entries in Module Reference Table + UINT16 ne_cbnrestab; // Size of non-resident name table + UINT16 ne_segtab; // Offset of Segment Table + UINT16 ne_rsrctab; // Offset of Resource Table + UINT16 ne_restab; // Offset of resident name table + UINT16 ne_modtab; // Offset of Module Reference Table + UINT16 ne_imptab; // Offset of Imported Names Table + UINT32 ne_nrestab; // Offset of Non-resident Names Table + UINT16 ne_cmovent; // Count of movable entries + UINT16 ne_align; // Segment alignment shift count + UINT16 ne_cres; // Count of resource segments + UINT8 ne_exetyp; // Target Operating system + UINT8 ne_flagsothers; // Other .EXE flags + UINT16 ne_pretthunks; // offset to return thunks + UINT16 ne_psegrefbytes; // offset to segment ref. bytes + UINT16 ne_swaparea; // Minimum code swap area size + UINT16 ne_expver; // Expected Windows version number + } IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER; + +// +// File header format. +// + +typedef struct _IMAGE_FILE_HEADER { + UINT16 Machine; + UINT16 NumberOfSections; + UINT32 TimeDateStamp; + UINT32 PointerToSymbolTable; + UINT32 NumberOfSymbols; + UINT16 SizeOfOptionalHeader; + UINT16 Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; + +#define IMAGE_SIZEOF_FILE_HEADER 20 + +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references). +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file. +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed. +#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file +#define IMAGE_FILE_SYSTEM 0x1000 // System File. +#define IMAGE_FILE_DLL 0x2000 // File is a DLL. +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed. + +#define IMAGE_FILE_MACHINE_UNKNOWN 0 +#define IMAGE_FILE_MACHINE_I386 0x14c // Intel 386. +#define IMAGE_FILE_MACHINE_R3000 0x162 // MIPS little-endian, 0540 big-endian +#define IMAGE_FILE_MACHINE_R4000 0x166 // MIPS little-endian +#define IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP +#define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED 0x1c2 // Arm/Thumb +#define IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM PowerPC Little-Endian +#define IMAGE_FILE_MACHINE_IA64 0x200 // IA-64 +#define IMAGE_FILE_MACHINE_TAHOE 0x7cc // Intel EM machine +#define IMAGE_FILE_MACHINE_EBC 0xebc // EFI Byte Code +#define IMAGE_FILE_MACHINE_X64 0x8664 // x86_64 +// +// Directory format. +// + +typedef struct _IMAGE_DATA_DIRECTORY { + UINT32 VirtualAddress; + UINT32 Size; +} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 + + +typedef struct _IMAGE_ROM_OPTIONAL_HEADER { + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + UINT32 BaseOfData; + UINT32 BaseOfBss; + UINT32 GprMask; + UINT32 CprMask[4]; + UINT32 GpValue; +} IMAGE_ROM_OPTIONAL_HEADER, *PIMAGE_ROM_OPTIONAL_HEADER; + +typedef struct _IMAGE_OPTIONAL_HEADER { + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + // UINT32 BaseOfData; + UINT64 ImageBase; + UINT32 SectionAlignment; + UINT32 FileAlignment; + UINT16 MajorOperatingSystemVersion; + UINT16 MinorOperatingSystemVersion; + UINT16 MajorImageVersion; + UINT16 MinorImageVersion; + UINT16 MajorSubsystemVersion; + UINT16 MinorSubsystemVersion; + UINT32 Win32VersionValue; + UINT32 SizeOfImage; + UINT32 SizeOfHeaders; + UINT32 CheckSum; + UINT16 Subsystem; + UINT16 DllCharacteristics; + UINT64 SizeOfStackReserve; + UINT64 SizeOfStackCommit; + UINT64 SizeOfHeapReserve; + UINT64 SizeOfHeapCommit; + UINT32 LoaderFlags; + UINT32 NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER; + + +#define IMAGE_SIZEOF_ROM_OPTIONAL_HEADER 56 +#define IMAGE_SIZEOF_STD_OPTIONAL_HEADER 28 +#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER 224 +#define IMAGE_SIZEOF_NT_OPTIONAL64_HEADER 244 + +#define IMAGE_NT_OPTIONAL_HDR_MAGIC 0x10b +#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b +#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107 + +typedef struct _IMAGE_NT_HEADERS { + UINT32 Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER OptionalHeader; +} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS; + +typedef struct _IMAGE_ROM_HEADERS { + IMAGE_FILE_HEADER FileHeader; + IMAGE_ROM_OPTIONAL_HEADER OptionalHeader; +} IMAGE_ROM_HEADERS, *PIMAGE_ROM_HEADERS; + +#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) \ + ((UINT32)ntheader + \ + FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + \ + ((PIMAGE_NT_HEADERS)(ntheader))->FileHeader.SizeOfOptionalHeader \ + )) + + +// Subsystem Values + +#define IMAGE_SUBSYSTEM_UNKNOWN 0 // Unknown subsystem. +#define IMAGE_SUBSYSTEM_NATIVE 1 // Image doesn't require a subsystem. +#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem. +#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem. +#define IMAGE_SUBSYSTEM_OS2_CUI 5 // image runs in the OS/2 character subsystem. +#define IMAGE_SUBSYSTEM_POSIX_CUI 7 // image run in the Posix character subsystem. + + +// Directory Entries + +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory +#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory +#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table +#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory +#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // Description String +#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // Machine Value (MIPS GP) +#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory +#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory + +// +// Section header format. +// + +#define IMAGE_SIZEOF_SHORT_NAME 8 + +typedef struct _IMAGE_SECTION_HEADER { + UINT8 Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + UINT32 PhysicalAddress; + UINT32 VirtualSize; + } Misc; + UINT32 VirtualAddress; + UINT32 SizeOfRawData; + UINT32 PointerToRawData; + UINT32 PointerToRelocations; + UINT32 PointerToLinenumbers; + UINT16 NumberOfRelocations; + UINT16 NumberOfLinenumbers; + UINT32 Characteristics; +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; + +#define IMAGE_SIZEOF_SECTION_HEADER 40 + +#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved. + +#define IMAGE_SCN_CNT_CODE 0x00000020 // Section contains code. +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // Section contains initialized data. +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 // Section contains uninitialized data. + +#define IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved. +#define IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information. +#define IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image. +#define IMAGE_SCN_LNK_COMDAT 0x00001000 // Section contents comdat. + +#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 // +#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 // +#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 // +#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 // +#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 // Default alignment if no others are specified. +#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 // +#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 // + +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // Section can be discarded. +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 // Section is not cachable. +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 // Section is not pageable. +#define IMAGE_SCN_MEM_SHARED 0x10000000 // Section is shareable. +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable. +#define IMAGE_SCN_MEM_READ 0x40000000 // Section is readable. +#define IMAGE_SCN_MEM_WRITE 0x80000000 // Section is writeable. + +// +// Symbol format. +// + + +#define IMAGE_SIZEOF_SYMBOL 18 + +// +// Section values. +// +// Symbols have a section number of the section in which they are +// defined. Otherwise, section numbers have the following meanings: +// + +#define IMAGE_SYM_UNDEFINED (UINT16)0 // Symbol is undefined or is common. +#define IMAGE_SYM_ABSOLUTE (UINT16)-1 // Symbol is an absolute value. +#define IMAGE_SYM_DEBUG (UINT16)-2 // Symbol is a special debug item. + +// +// Type (fundamental) values. +// + +#define IMAGE_SYM_TYPE_NULL 0 // no type. +#define IMAGE_SYM_TYPE_VOID 1 // +#define IMAGE_SYM_TYPE_CHAR 2 // type character. +#define IMAGE_SYM_TYPE_SHORT 3 // type short integer. +#define IMAGE_SYM_TYPE_INT 4 // +#define IMAGE_SYM_TYPE_LONG 5 // +#define IMAGE_SYM_TYPE_FLOAT 6 // +#define IMAGE_SYM_TYPE_DOUBLE 7 // +#define IMAGE_SYM_TYPE_STRUCT 8 // +#define IMAGE_SYM_TYPE_UNION 9 // +#define IMAGE_SYM_TYPE_ENUM 10 // enumeration. +#define IMAGE_SYM_TYPE_MOE 11 // member of enumeration. +#define IMAGE_SYM_TYPE_BYTE 12 // +#define IMAGE_SYM_TYPE_WORD 13 // +#define IMAGE_SYM_TYPE_UINT 14 // +#define IMAGE_SYM_TYPE_DWORD 15 // + +// +// Type (derived) values. +// + +#define IMAGE_SYM_DTYPE_NULL 0 // no derived type. +#define IMAGE_SYM_DTYPE_POINTER 1 // pointer. +#define IMAGE_SYM_DTYPE_FUNCTION 2 // function. +#define IMAGE_SYM_DTYPE_ARRAY 3 // array. + +// +// Storage classes. +// + +#define IMAGE_SYM_CLASS_END_OF_FUNCTION (BYTE )-1 +#define IMAGE_SYM_CLASS_NULL 0 +#define IMAGE_SYM_CLASS_AUTOMATIC 1 +#define IMAGE_SYM_CLASS_EXTERNAL 2 +#define IMAGE_SYM_CLASS_STATIC 3 +#define IMAGE_SYM_CLASS_REGISTER 4 +#define IMAGE_SYM_CLASS_EXTERNAL_DEF 5 +#define IMAGE_SYM_CLASS_LABEL 6 +#define IMAGE_SYM_CLASS_UNDEFINED_LABEL 7 +#define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8 +#define IMAGE_SYM_CLASS_ARGUMENT 9 +#define IMAGE_SYM_CLASS_STRUCT_TAG 10 +#define IMAGE_SYM_CLASS_MEMBER_OF_UNION 11 +#define IMAGE_SYM_CLASS_UNION_TAG 12 +#define IMAGE_SYM_CLASS_TYPE_DEFINITION 13 +#define IMAGE_SYM_CLASS_UNDEFINED_STATIC 14 +#define IMAGE_SYM_CLASS_ENUM_TAG 15 +#define IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16 +#define IMAGE_SYM_CLASS_REGISTER_PARAM 17 +#define IMAGE_SYM_CLASS_BIT_FIELD 18 +#define IMAGE_SYM_CLASS_BLOCK 100 +#define IMAGE_SYM_CLASS_FUNCTION 101 +#define IMAGE_SYM_CLASS_END_OF_STRUCT 102 +#define IMAGE_SYM_CLASS_FILE 103 +// new +#define IMAGE_SYM_CLASS_SECTION 104 +#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 105 + +// type packing constants + +#define N_BTMASK 017 +#define N_TMASK 060 +#define N_TMASK1 0300 +#define N_TMASK2 0360 +#define N_BTSHFT 4 +#define N_TSHIFT 2 + +// MACROS + +// +// Communal selection types. +// + +#define IMAGE_COMDAT_SELECT_NODUPLICATES 1 +#define IMAGE_COMDAT_SELECT_ANY 2 +#define IMAGE_COMDAT_SELECT_SAME_SIZE 3 +#define IMAGE_COMDAT_SELECT_EXACT_MATCH 4 +#define IMAGE_COMDAT_SELECT_ASSOCIATIVE 5 + +#define IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1 +#define IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2 +#define IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3 + + +// +// Relocation format. +// + +typedef struct _IMAGE_RELOCATION { + UINT32 VirtualAddress; + UINT32 SymbolTableIndex; + UINT16 Type; +} IMAGE_RELOCATION; + +#define IMAGE_SIZEOF_RELOCATION 10 + +// +// I386 relocation types. +// + +#define IMAGE_REL_I386_ABSOLUTE 0 // Reference is absolute, no relocation is necessary +#define IMAGE_REL_I386_DIR16 01 // Direct 16-bit reference to the symbols virtual address +#define IMAGE_REL_I386_REL16 02 // PC-relative 16-bit reference to the symbols virtual address +#define IMAGE_REL_I386_DIR32 06 // Direct 32-bit reference to the symbols virtual address +#define IMAGE_REL_I386_DIR32NB 07 // Direct 32-bit reference to the symbols virtual address, base not included +#define IMAGE_REL_I386_SEG12 011 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address +#define IMAGE_REL_I386_SECTION 012 +#define IMAGE_REL_I386_SECREL 013 +#define IMAGE_REL_I386_REL32 024 // PC-relative 32-bit reference to the symbols virtual address + +// +// MIPS relocation types. +// + +#define IMAGE_REL_MIPS_ABSOLUTE 0 // Reference is absolute, no relocation is necessary +#define IMAGE_REL_MIPS_REFHALF 01 +#define IMAGE_REL_MIPS_REFWORD 02 +#define IMAGE_REL_MIPS_JMPADDR 03 +#define IMAGE_REL_MIPS_REFHI 04 +#define IMAGE_REL_MIPS_REFLO 05 +#define IMAGE_REL_MIPS_GPREL 06 +#define IMAGE_REL_MIPS_LITERAL 07 +#define IMAGE_REL_MIPS_SECTION 012 +#define IMAGE_REL_MIPS_SECREL 013 +#define IMAGE_REL_MIPS_REFWORDNB 042 +#define IMAGE_REL_MIPS_PAIR 045 + +// +// Alpha Relocation types. +// + +#define IMAGE_REL_ALPHA_ABSOLUTE 0x0 +#define IMAGE_REL_ALPHA_REFLONG 0x1 +#define IMAGE_REL_ALPHA_REFQUAD 0x2 +#define IMAGE_REL_ALPHA_GPREL32 0x3 +#define IMAGE_REL_ALPHA_LITERAL 0x4 +#define IMAGE_REL_ALPHA_LITUSE 0x5 +#define IMAGE_REL_ALPHA_GPDISP 0x6 +#define IMAGE_REL_ALPHA_BRADDR 0x7 +#define IMAGE_REL_ALPHA_HINT 0x8 +#define IMAGE_REL_ALPHA_INLINE_REFLONG 0x9 +#define IMAGE_REL_ALPHA_REFHI 0xA +#define IMAGE_REL_ALPHA_REFLO 0xB +#define IMAGE_REL_ALPHA_PAIR 0xC +#define IMAGE_REL_ALPHA_MATCH 0xD +#define IMAGE_REL_ALPHA_SECTION 0xE +#define IMAGE_REL_ALPHA_SECREL 0xF +#define IMAGE_REL_ALPHA_REFLONGNB 0x10 + +// +// IBM PowerPC relocation types. +// + +#define IMAGE_REL_PPC_ABSOLUTE 0x0000 // NOP +#define IMAGE_REL_PPC_ADDR64 0x0001 // 64-bit address +#define IMAGE_REL_PPC_ADDR32 0x0002 // 32-bit address +#define IMAGE_REL_PPC_ADDR24 0x0003 // 26-bit address, shifted left 2 (branch absolute) +#define IMAGE_REL_PPC_ADDR16 0x0004 // 16-bit address +#define IMAGE_REL_PPC_ADDR14 0x0005 // 16-bit address, shifted left 2 (load doubleword) +#define IMAGE_REL_PPC_REL24 0x0006 // 26-bit PC-relative offset, shifted left 2 (branch relative) +#define IMAGE_REL_PPC_REL14 0x0007 // 16-bit PC-relative offset, shifted left 2 (br cond relative) +#define IMAGE_REL_PPC_TOCREL16 0x0008 // 16-bit offset from TOC base +#define IMAGE_REL_PPC_TOCREL14 0x0009 // 16-bit offset from TOC base, shifted left 2 (load doubleword) + +#define IMAGE_REL_PPC_ADDR32NB 0x000A // 32-bit addr w/o image base +#define IMAGE_REL_PPC_SECREL 0x000B // va of containing section (as in an image sectionhdr) +#define IMAGE_REL_PPC_SECTION 0x000C // sectionheader number +#define IMAGE_REL_PPC_IFGLUE 0x000D // substitute TOC restore instruction iff symbol is glue code +#define IMAGE_REL_PPC_IMGLUE 0x000E // symbol is glue code; virtual address is TOC restore instruction + +#define IMAGE_REL_PPC_TYPEMASK 0x00FF // mask to isolate above values in IMAGE_RELOCATION.Type + +// Flag bits in IMAGE_RELOCATION.TYPE + +#define IMAGE_REL_PPC_NEG 0x0100 // subtract reloc value rather than adding it +#define IMAGE_REL_PPC_BRTAKEN 0x0200 // fix branch prediction bit to predict branch taken +#define IMAGE_REL_PPC_BRNTAKEN 0x0400 // fix branch prediction bit to predict branch not taken +#define IMAGE_REL_PPC_TOCDEFN 0x0800 // toc slot defined in file (or, data in toc) + +// +// Based relocation format. +// + +typedef struct _IMAGE_BASE_RELOCATION { + UINT32 VirtualAddress; + UINT32 SizeOfBlock; +// UINT16 TypeOffset[1]; +} IMAGE_BASE_RELOCATION, *PIMAGE_BASE_RELOCATION; + +#define IMAGE_SIZEOF_BASE_RELOCATION 8 + +// +// Based relocation types. +// + +#define IMAGE_REL_BASED_ABSOLUTE 0 +#define IMAGE_REL_BASED_HIGH 1 +#define IMAGE_REL_BASED_LOW 2 +#define IMAGE_REL_BASED_HIGHLOW 3 +#define IMAGE_REL_BASED_HIGHADJ 4 +#define IMAGE_REL_BASED_MIPS_JMPADDR 5 +#define IMAGE_REL_BASED_IA64_IMM64 9 +#define IMAGE_REL_BASED_DIR64 10 + +// +// Line number format. +// + +typedef struct _IMAGE_LINENUMBER { + union { + UINT32 SymbolTableIndex; // Symbol table index of function name if Linenumber is 0. + UINT32 VirtualAddress; // Virtual address of line number. + } Type; + UINT16 Linenumber; // Line number. +} IMAGE_LINENUMBER; + +#define IMAGE_SIZEOF_LINENUMBER 6 + +// +// Archive format. +// + +#define IMAGE_ARCHIVE_START_SIZE 8 +#define IMAGE_ARCHIVE_START "!\n" +#define IMAGE_ARCHIVE_END "`\n" +#define IMAGE_ARCHIVE_PAD "\n" +#define IMAGE_ARCHIVE_LINKER_MEMBER "/ " +#define IMAGE_ARCHIVE_LONGNAMES_MEMBER "// " + +typedef struct _IMAGE_ARCHIVE_MEMBER_HEADER { + UINT8 Name[16]; // File member name - `/' terminated. + UINT8 Date[12]; // File member date - decimal. + UINT8 UserID[6]; // File member user id - decimal. + UINT8 GroupID[6]; // File member group id - decimal. + UINT8 Mode[8]; // File member mode - octal. + UINT8 Size[10]; // File member size - decimal. + UINT8 EndHeader[2]; // String to end header. +} IMAGE_ARCHIVE_MEMBER_HEADER, *PIMAGE_ARCHIVE_MEMBER_HEADER; + +#define IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60 + +// +// DLL support. +// + +// +// Export Format +// + +typedef struct _IMAGE_EXPORT_DIRECTORY { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT16 MajorVersion; + UINT16 MinorVersion; + UINT32 Name; + UINT32 Base; + UINT32 NumberOfFunctions; + UINT32 NumberOfNames; + UINT32 AddressOfFunctions; + UINT32 AddressOfNames; + UINT32 AddressOfNameOrdinals; +} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; + +// +// Import Format +// + +typedef struct _IMAGE_IMPORT_BY_NAME { + UINT16 Hint; + UINT8 Name[1]; +} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; + +typedef struct _IMAGE_THUNK_DATA { + union { + UINT32 Function; + UINT32 Ordinal; + PIMAGE_IMPORT_BY_NAME AddressOfData; + } u1; +} IMAGE_THUNK_DATA, *PIMAGE_THUNK_DATA; + +#define IMAGE_ORDINAL_FLAG 0x80000000 +#define IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG) != 0) +#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff) + +typedef struct _IMAGE_IMPORT_DESCRIPTOR { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT32 ForwarderChain; + UINT32 Name; + PIMAGE_THUNK_DATA FirstThunk; +} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR; + +#endif diff --git a/code/boot/include/ia64/salproc.h b/code/boot/include/ia64/salproc.h new file mode 100644 index 0000000..0ce71f9 --- /dev/null +++ b/code/boot/include/ia64/salproc.h @@ -0,0 +1,264 @@ +#ifndef _SAL_PROC_H +#define _SAL_PROC_H +// +// +//Copyright (c) 1999 Intel Corporation +// +//Module Name: +// +// SalProc.h +// +//Abstract: +// +// Main SAL interface routins for IA-64 calls. +// +// +//Revision History +// +// + +// return value that mimicks r8,r9,r10 & r11 registers +typedef struct { + UINT64 p0; + UINT64 p1; + UINT64 p2; + UINT64 p3; +} rArg; + +#define SAL_PCI_CONFIG_READ 0x01000010 +#define SAL_PCI_CONFIG_WRITE 0x01000011 + +typedef VOID (*PFN)(); +typedef rArg (*PFN_SAL_PROC)(UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64); +typedef rArg (*PFN_SAL_CALLBACK)(UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64); + +typedef struct _PLABEL { + UINT64 ProcEntryPoint; + UINT64 GP; +} PLABEL; + +typedef struct tagIA32_BIOS_REGISTER_STATE { + + // general registers + UINT32 eax; + UINT32 ecx; + UINT32 edx; + UINT32 ebx; + + // stack registers + UINT32 esp; + UINT32 ebp; + UINT32 esi; + UINT32 edi; + + // eflags + UINT32 eflags; + + // instruction pointer + UINT32 eip; + + UINT16 cs; + UINT16 ds; + UINT16 es; + UINT16 fs; + UINT16 gs; + UINT16 ss; + + // Reserved + UINT32 Reserved1; + UINT64 Reserved2; +} IA32_BIOS_REGISTER_STATE; + +VOID EFIInitMsg(VOID); + +EFI_STATUS +PlRegisterAndStartTimer( + IN UINTN Period + ); + +EFI_STATUS +PlDeRegisterAndCancelTimer(VOID); + +VOID +SalProc ( + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8, + OUT rArg* Results OPTIONAL + ); + +VOID +SalCallBack ( + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8, + OUT rArg* Results OPTIONAL + ); + +VOID +RUNTIMEFUNCTION +RtSalCallBack ( + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8, + OUT rArg* Results OPTIONAL + ); + + +extern PLABEL RtGlobalSalProcEntry; +extern PLABEL RtGlobalSALCallBack; + +#pragma pack(1) +// +// SAL System Table +// +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT16 Revision; + UINT16 EntryCount; + UINT8 CheckSum; + UINT8 Reserved[7]; + UINT16 SALA_Ver; + UINT16 SALB_Ver; + UINT8 OemId[32]; + UINT8 ProductID[32]; + UINT8 Reserved2[8]; +} SAL_SYSTEM_TABLE_HDR; + +#define SAL_ST_ENTRY_POINT 0 +#define SAL_ST_MEMORY_DESCRIPTOR 1 +#define SAL_ST_PLATFORM_FEATURES 2 +#define SAL_ST_TR_USAGE 3 +#define SAL_ST_PTC 4 +#define SAL_ST_AP_WAKEUP 5 + +typedef struct { + UINT8 Type; // Type == 0 + UINT8 Reserved[7]; + UINT64 PalProcEntry; + UINT64 SalProcEntry; + UINT64 GlobalDataPointer; + UINT64 Reserved2[2]; +} SAL_ST_ENTRY_POINT_DESCRIPTOR; + +typedef struct { + UINT8 Type; // Type == 1 + UINT8 NeedVirtualRegistration; + UINT8 MemoryAttributes; + UINT8 PageAccessRights; + UINT8 SupportedAttributes; + UINT8 Reserved; + UINT16 MemoryType; + UINT64 PhysicalMemoryAddress; + UINT32 Length; + UINT32 Reserved1; + UINT64 OemReserved; +} SAL_ST_MEMORY_DESCRIPTOR_ENTRY; + +// +// MemoryType info +// +#define SAL_SAPIC_IPI_BLOCK 0x0002 +#define SAL_IO_PORT_MAPPING 0x0003 + +typedef struct { + UINT8 Type; // Type == 2 + UINT8 PlatformFeatures; + UINT8 Reserved[14]; +} SAL_ST_MEMORY_DECRIPTOR; + +typedef struct { + UINT8 Type; // Type == 3 + UINT8 TRType; + UINT8 TRNumber; + UINT8 Reserved[5]; + UINT64 VirtualAddress; + UINT64 EncodedPageSize; + UINT64 Reserved1; +} SAL_ST_TR_DECRIPTOR; + +typedef struct { + UINT64 NumberOfProcessors; + UINT64 LocalIDRegister; +} SAL_COHERENCE_DOMAIN_INFO; + +typedef struct { + UINT8 Type; // Type == 4 + UINT8 Reserved[3]; + UINT32 NumberOfDomains; + SAL_COHERENCE_DOMAIN_INFO* DomainInformation; +} SAL_ST_CACHE_COHERENCE_DECRIPTOR; + +typedef struct { + UINT8 Type; // Type == 5 + UINT8 WakeUpType; + UINT8 Reserved[6]; + UINT64 ExternalInterruptVector; +} SAL_ST_AP_WAKEUP_DECRIPTOR; + +typedef struct { + SAL_SYSTEM_TABLE_HDR Header; + SAL_ST_ENTRY_POINT_DESCRIPTOR Entry0; +} SAL_SYSTEM_TABLE_ASCENDING_ORDER; + +#define FIT_ENTRY_PTR (0x100000000 - 32) // 4GB - 24 +#define FIT_PALA_ENTRY (0x100000000 - 48) // 4GB - 32 +#define FIT_PALB_TYPE 01 + +typedef struct { + UINT64 Address; + UINT8 Size[3]; + UINT8 Reserved; + UINT16 Revision; + UINT8 Type:7; + UINT8 CheckSumValid:1; + UINT8 CheckSum; +} FIT_ENTRY; + +#pragma pack() + +typedef + rArg +(*CALL_SAL_PROC)( + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8 + ); + +typedef + rArg +(*CALL_PAL_PROC)( + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4 + ); + +extern CALL_SAL_PROC GlobalSalProc; +extern CALL_PAL_PROC GlobalPalProc; +extern PLABEL SalProcPlabel; +extern PLABEL PalProcPlabel; + +#endif + diff --git a/code/boot/include/inc.mak b/code/boot/include/inc.mak new file mode 100644 index 0000000..64fc7bb --- /dev/null +++ b/code/boot/include/inc.mak @@ -0,0 +1,23 @@ + + +INC_DEPS = $(INC_DEPS) \ + efi.h \ + efiapi.h \ + efibind.h \ + eficon.h \ + efidebug.h \ + efidef.h \ + efidevp.h \ + efierr.h \ + efifs.h \ + efilib.h \ + efipart.h \ + efipciio.h \ + efiprot.h \ + efipxe.h \ + efivar.h \ + pe.h \ + efiip.h \ + efiudp.h \ + efitcp.h \ + stdarg.h diff --git a/code/boot/include/legacy.h b/code/boot/include/legacy.h new file mode 100644 index 0000000..cbfd6c4 --- /dev/null +++ b/code/boot/include/legacy.h @@ -0,0 +1,60 @@ +#ifndef _EFI_LEGACY_H +#define _EFI_LEGACY_H + +/* +ABIs: +Default ABI will be highest number +Older versions can be selected via compiler defines +*/ + +/* ReallocatePool */ +#ifndef GNU_EFI_USE_REALLOCATEPOOL_ABI +#define GNU_EFI_USE_REALLOCATEPOOL_ABI 1 +#endif + +#if GNU_EFI_USE_REALLOCATEPOOL_ABI == 0 +#define ReallocatePool ReallocatePool_0 +#else +#define ReallocatePool ReallocatePool_1 +#endif + +/* prevent circular headers */ +VOID * +EFIAPI +ReallocatePool_1 ( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID* OldPool OPTIONAL +); + +inline +VOID * +EFIAPI +ReallocatePool_0 ( + IN VOID* OldPool, + IN UINTN OldSize, + IN UINTN NewSize +) +{ + return ReallocatePool_1(OldSize, NewSize, OldPool); +} + +/* end ReallocatePool */ + +/* CopyMem */ +/* CopyMemC isn't deprecated - serves different purpose to CopyMem */ + +#ifndef GNU_EFI_USE_COPYMEM_ABI +#define GNU_EFI_USE_COPYMEM_ABI 1 +#endif + +#if GNU_EFI_USE_COPYMEM_ABI == 0 +#define CopyMem CopyMemC +#else +#define CopyMem CopyMem_1 +#endif + +/* end CopyMem */ + +#endif + diff --git a/code/boot/include/lib.h b/code/boot/include/lib.h new file mode 100644 index 0000000..8c7cf20 --- /dev/null +++ b/code/boot/include/lib.h @@ -0,0 +1,92 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + lib.h + +Abstract: + + EFI library header files + + + +Revision History + +--*/ + +#ifdef __GNUC__ +#pragma GCC visibility push(hidden) +#endif + +#include "efi.h" +#include "efilib.h" +#include "efirtlib.h" + +// +// Include non architectural protocols +// +#include "protocol/efivar.h" +#include "protocol/legacyboot.h" +#include "protocol/intload.h" +#include "protocol/vgaclass.h" +#include "protocol/eficonsplit.h" +#include "protocol/adapterdebug.h" +#include "protocol/intload.h" + +#include "efigpt.h" +#include "libsmbios.h" + +// +// Prototypes +// + +VOID +InitializeGuid ( + VOID + ); + +INTN EFIAPI +LibStubStriCmp ( + IN EFI_UNICODE_COLLATION_INTERFACE* This, + IN CHAR16* S1, + IN CHAR16* S2 + ); + +BOOLEAN EFIAPI +LibStubMetaiMatch ( + IN EFI_UNICODE_COLLATION_INTERFACE* This, + IN CHAR16* String, + IN CHAR16* Pattern + ); + +VOID EFIAPI +LibStubStrLwrUpr ( + IN EFI_UNICODE_COLLATION_INTERFACE* This, + IN CHAR16* Str + ); + +BOOLEAN +LibMatchDevicePaths ( + IN EFI_DEVICE_PATH* Multi, + IN EFI_DEVICE_PATH* Single + ); + +EFI_DEVICE_PATH * +LibDuplicateDevicePathInstance ( + IN EFI_DEVICE_PATH* DevPath + ); + + +// +// Globals +// +extern BOOLEAN LibInitialized; +extern BOOLEAN LibFwInstance; +extern EFI_HANDLE LibImageHandle; +extern SIMPLE_TEXT_OUTPUT_INTERFACE* LibRuntimeDebugOut; +extern EFI_UNICODE_COLLATION_INTERFACE* UnicodeInterface; +extern EFI_UNICODE_COLLATION_INTERFACE LibStubUnicodeInterface; +extern EFI_RAISE_TPL LibRuntimeRaiseTPL; +extern EFI_RESTORE_TPL LibRuntimeRestoreTPL; diff --git a/code/boot/include/libsmbios.h b/code/boot/include/libsmbios.h new file mode 100644 index 0000000..a99148c --- /dev/null +++ b/code/boot/include/libsmbios.h @@ -0,0 +1,149 @@ +#ifndef _LIB_SMBIOS_H +#define _LIB_SMBIOS_H +/*++ + +Copyright (c) 2000 Intel Corporation + +Module Name: + + LibSmbios.h + +Abstract: + + Lib include for SMBIOS services. Used to get system serial number and GUID + +Revision History + +--*/ + +// +// Define SMBIOS tables. +// +#pragma pack(1) +typedef struct { + UINT8 AnchorString[4]; + UINT8 EntryPointStructureChecksum; + UINT8 EntryPointLength; + UINT8 MajorVersion; + UINT8 MinorVersion; + UINT16 MaxStructureSize; + UINT8 EntryPointRevision; + UINT8 FormattedArea[5]; + UINT8 IntermediateAnchorString[5]; + UINT8 IntermediateChecksum; + UINT16 TableLength; + UINT32 TableAddress; + UINT16 NumberOfSmbiosStructures; + UINT8 SmbiosBcdRevision; +} SMBIOS_TABLE_ENTRY_POINT; + +#define SMBIOS_STRUCTURE_TABLE SMBIOS_TABLE_ENTRY_POINT + +typedef struct { + UINT8 AnchorString[5]; + UINT8 EntryPointStructureChecksum; + UINT8 EntryPointLength; + UINT8 MajorVersion; + UINT8 MinorVersion; + UINT8 DocRev; + UINT8 EntryPointRevision; + UINT8 Reserved; + UINT32 TableMaximumSize; + UINT64 TableAddress; +} SMBIOS_TABLE_3_0_ENTRY_POINT; + +#define SMBIOS3_STRUCTURE_TABLE SMBIOS_TABLE_3_0_ENTRY_POINT + +// +// Please note that SMBIOS structures can be odd byte aligned since the +// unformated section of each record is a set of arbitrary size strings. +// + +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Handle[2]; +} SMBIOS_STRUCTURE; + +#define SMBIOS_HEADER SMBIOS_STRUCTURE + +typedef UINT8 SMBIOS_STRING; + +typedef struct { + SMBIOS_HEADER Hdr; + SMBIOS_STRING Vendor; + SMBIOS_STRING BiosVersion; + UINT8 BiosSegment[2]; + SMBIOS_STRING BiosReleaseDate; + UINT8 BiosSize; + UINT8 BiosCharacteristics[8]; +} SMBIOS_TYPE0; + +typedef struct { + SMBIOS_HEADER Hdr; + SMBIOS_STRING Manufacturer; + SMBIOS_STRING ProductName; + SMBIOS_STRING Version; + SMBIOS_STRING SerialNumber; + + // + // always byte copy this data to prevent alignment faults! + // + EFI_GUID Uuid; + + UINT8 WakeUpType; +} SMBIOS_TYPE1; + +typedef struct { + SMBIOS_HEADER Hdr; + SMBIOS_STRING Manufacturer; + SMBIOS_STRING ProductName; + SMBIOS_STRING Version; + SMBIOS_STRING SerialNumber; +} SMBIOS_TYPE2; + +typedef struct { + SMBIOS_HEADER Hdr; + SMBIOS_STRING Manufacturer; + UINT8 Type; + SMBIOS_STRING Version; + SMBIOS_STRING SerialNumber; + SMBIOS_STRING AssetTag; + UINT8 BootupState; + UINT8 PowerSupplyState; + UINT8 ThermalState; + UINT8 SecurityStatus; + UINT8 OemDefined[4]; +} SMBIOS_TYPE3; + +typedef struct { + SMBIOS_HEADER Hdr; + UINT8 Socket; + UINT8 ProcessorType; + UINT8 ProcessorFamily; + SMBIOS_STRING ProcessorManufacture; + UINT8 ProcessorId[8]; + SMBIOS_STRING ProcessorVersion; + UINT8 Voltage; + UINT8 ExternalClock[2]; + UINT8 MaxSpeed[2]; + UINT8 CurrentSpeed[2]; + UINT8 Status; + UINT8 ProcessorUpgrade; + UINT8 L1CacheHandle[2]; + UINT8 L2CacheHandle[2]; + UINT8 L3CacheHandle[2]; +} SMBIOS_TYPE4; + +typedef union { + SMBIOS_HEADER* Hdr; + SMBIOS_TYPE0* Type0; + SMBIOS_TYPE1* Type1; + SMBIOS_TYPE2* Type2; + SMBIOS_TYPE3* Type3; + SMBIOS_TYPE4* Type4; + UINT8* Raw; +} SMBIOS_STRUCTURE_POINTER; +#pragma pack() + +#endif diff --git a/code/boot/include/loongarch64/efibind.h b/code/boot/include/loongarch64/efibind.h new file mode 100644 index 0000000..9735f7d --- /dev/null +++ b/code/boot/include/loongarch64/efibind.h @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2014 - 2015 Linaro Ltd. + * Author: Ard Biesheuvel + * Copyright (C) 2017 Lemote Co. + * Author: Heiher + * Copyright (C) 2021 Loongson Technology Corporation Limited. + * Author: zhoumingtao + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License as published by the Free Software Foundation; + * either version 2 of the License, or (at your option) any later version. + */ + +#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L ) && !defined(__cplusplus) + +// ANSI C 1999/2000 stdint.h integer width declarations + +typedef unsigned long uint64_t; +typedef long int64_t; +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef signed char int8_t; +typedef uint64_t uintptr_t; +typedef int64_t intptr_t; + +#else +#include +#endif + +// +// Basic EFI types of various widths +// + +#include + +typedef wchar_t CHAR16; +#define WCHAR CHAR16 + +typedef uint64_t UINT64; +typedef int64_t INT64; + +typedef uint32_t UINT32; +typedef int32_t INT32; + +typedef uint16_t UINT16; +typedef int16_t INT16; + +typedef uint8_t UINT8; +typedef char CHAR8; +typedef int8_t INT8; + +#undef VOID +typedef void VOID; + +typedef int64_t INTN; +typedef uint64_t UINTN; + +#define EFIERR(a) (0x8000000000000000 | a) +#define EFI_ERROR_MASK 0x8000000000000000 +#define EFIERR_OEM(a) (0xc000000000000000 | a) + +#define BAD_POINTER 0xFBFBFBFBFBFBFBFB +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF + +#define BREAKPOINT() while (TRUE); // Make it hang on Bios[Dbg]32 + +// +// Pointers must be aligned to these address to function +// + +#define MIN_ALIGNMENT_SIZE 8 + +#define ALIGN_VARIABLE(Value ,Adjustment) \ + (UINTN)Adjustment = 0; \ + if((UINTN)Value % MIN_ALIGNMENT_SIZE) \ + (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \ + Value = (UINTN)Value + (UINTN)Adjustment + + +// +// Define macros to build data structure signatures from characters. +// + +#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8)) +#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16)) +#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32)) + +// +// EFIAPI - prototype calling convention for EFI function pointers +// BOOTSERVICE - prototype for implementation of a boot service interface +// RUNTIMESERVICE - prototype for implementation of a runtime service interface +// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service +// RUNTIME_CODE - pragma macro for declaring runtime code +// + +#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options +#define EFIAPI // Substitute expresion to force C calling convention +#endif + +#define BOOTSERVICE +#define RUNTIMESERVICE +#define RUNTIMEFUNCTION + + +#define RUNTIME_CODE(a) alloc_text("rtcode", a) +#define BEGIN_RUNTIME_DATA() data_seg("rtdata") +#define END_RUNTIME_DATA() data_seg("") + +#define VOLATILE volatile + +#define MEMORY_FENCE __sync_synchronize + +// +// When build similiar to FW, then link everything together as +// one big module. +// + +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + UINTN \ + InitializeDriver ( \ + VOID* ImageHandle, \ + VOID* SystemTable \ + ) \ + { \ + return InitFunction(ImageHandle, \ + SystemTable); \ + } \ + \ + EFI_STATUS efi_main( \ + EFI_HANDLE image, \ + EFI_SYSTEM_TABLE* systab \ + ) __attribute__((weak, \ + alias ("InitializeDriver"))); + +#define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, entry) + + +// +// Some compilers don't support the forward reference construct: +// typedef struct XXXXX +// +// The following macro provide a workaround for such cases. + +#define INTERFACE_DECL(x) struct x + +#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__) +#define EFI_FUNCTION diff --git a/code/boot/include/loongarch64/efilibplat.h b/code/boot/include/loongarch64/efilibplat.h new file mode 100644 index 0000000..0f92321 --- /dev/null +++ b/code/boot/include/loongarch64/efilibplat.h @@ -0,0 +1,24 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efilibplat.h + +Abstract: + + EFI to compile bindings + + + + +Revision History + +--*/ + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE* SystemTable + ); diff --git a/code/boot/include/loongarch64/efisetjmp_arch.h b/code/boot/include/loongarch64/efisetjmp_arch.h new file mode 100644 index 0000000..91cc554 --- /dev/null +++ b/code/boot/include/loongarch64/efisetjmp_arch.h @@ -0,0 +1,23 @@ +#ifndef GNU_EFI_LOONGARCH64_SETJMP_H +#define GNU_EFI_LOONGARCH64_SETJMP_H + +#define JMPBUF_ALIGN 8 + +typedef struct { + /* GP regs */ + UINT64 RA; + UINT64 SP; + UINT64 FP; + + UINT64 S0; + UINT64 S1; + UINT64 S2; + UINT64 S3; + UINT64 S4; + UINT64 S5; + UINT64 S6; + UINT64 S7; + UINT64 S8; +} EFI_ALIGN(JMPBUF_ALIGN) jmp_buf[1]; + +#endif /* GNU_EFI_LOONGARCH64_SETJMP_H */ diff --git a/code/boot/include/make.inf b/code/boot/include/make.inf new file mode 100644 index 0000000..e9ccc9e --- /dev/null +++ b/code/boot/include/make.inf @@ -0,0 +1,33 @@ +# +# +# + +[sources] + efi.h + efiapi.h + eficon.h + efidebug.h + efidef.h + efidevp.h + efierr.h + efifs.h + efilib.h + efipart.h + efipciio.h + efiprot.h + efipxebc.h + efistdarg.h + efinet.h + efiip.h + efiudp.h + efitcp.h + +[ia32sources] + efibind.h + pe.h + efilibplat.h + +[ia64sources] + efibind.h + pe.h + efilibplat.h diff --git a/code/boot/include/makefile.hdr b/code/boot/include/makefile.hdr new file mode 100644 index 0000000..808d5c5 --- /dev/null +++ b/code/boot/include/makefile.hdr @@ -0,0 +1,48 @@ + +# +# This is a machine generated file - DO NOT EDIT +# Generated by genmake.exe +# Generated from make.inf +# Copyright (c) 1998 Intel Corporation +# + +INC_DEPS = $(INC_DEPS) \ + $(SDK_INSTALL_DIR)\include\efi\efi.h \ + $(SDK_INSTALL_DIR)\include\efi\efiapi.h \ + $(SDK_INSTALL_DIR)\include\efi\eficon.h \ + $(SDK_INSTALL_DIR)\include\efi\efidebug.h \ + $(SDK_INSTALL_DIR)\include\efi\efidef.h \ + $(SDK_INSTALL_DIR)\include\efi\efidevp.h \ + $(SDK_INSTALL_DIR)\include\efi\efierr.h \ + $(SDK_INSTALL_DIR)\include\efi\efifs.h \ + $(SDK_INSTALL_DIR)\include\efi\efilib.h \ + $(SDK_INSTALL_DIR)\include\efi\efipart.h \ + $(SDK_INSTALL_DIR)\include\efi\efipciio.h \ + $(SDK_INSTALL_DIR)\include\efi\efiprot.h \ + $(SDK_INSTALL_DIR)\include\efi\efipxebc.h \ + $(SDK_INSTALL_DIR)\include\efi\efistdarg.h \ + $(SDK_INSTALL_DIR)\include\efi\efinet.h \ + $(SDK_INSTALL_DIR)\include\efi\efiip.h \ + $(SDK_INSTALL_DIR)\include\efi\efiudp.h \ + $(SDK_INSTALL_DIR)\include\efi\efitcp.h \ + + +!IF "$(PROCESSOR)" == "Ia32" +INC_DEPS = $(INC_DEPS) \ + $(SDK_INSTALL_DIR)\include\efi\Ia32\efibind.h \ + $(SDK_INSTALL_DIR)\include\efi\Ia32\pe.h \ + $(SDK_INSTALL_DIR)\include\efi\Ia32\efilibplat.h \ + + +!ENDIF + + +!IF "$(PROCESSOR)" == "Ia64" +INC_DEPS = $(INC_DEPS) \ + $(SDK_INSTALL_DIR)\include\efi\Ia64\efibind.h \ + $(SDK_INSTALL_DIR)\include\efi\Ia64\pe.h \ + $(SDK_INSTALL_DIR)\include\efi\Ia64\efilibplat.h \ + + +!ENDIF + diff --git a/code/boot/include/mips64el/efibind.h b/code/boot/include/mips64el/efibind.h new file mode 100644 index 0000000..d230e75 --- /dev/null +++ b/code/boot/include/mips64el/efibind.h @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2014 - 2015 Linaro Ltd. + * Author: Ard Biesheuvel + * Copyright (C) 2017 Lemote Co. + * Author: Heiher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License as published by the Free Software Foundation; + * either version 2 of the License, or (at your option) any later version. + */ + +#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L ) && !defined(__cplusplus) + +// ANSI C 1999/2000 stdint.h integer width declarations + +typedef unsigned long uint64_t; +typedef long int64_t; +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef signed char int8_t; // unqualified 'char' is unsigned on ARM +typedef uint64_t uintptr_t; +typedef int64_t intptr_t; + +#else +#include +#endif + +// +// Basic EFI types of various widths +// + +#include + +typedef wchar_t CHAR16; +#define WCHAR CHAR16 + +typedef uint64_t UINT64; +typedef int64_t INT64; + +typedef uint32_t UINT32; +typedef int32_t INT32; + +typedef uint16_t UINT16; +typedef int16_t INT16; + +typedef uint8_t UINT8; +typedef char CHAR8; +typedef int8_t INT8; + +#undef VOID +typedef void VOID; + +typedef int64_t INTN; +typedef uint64_t UINTN; + +#define EFIERR(a) (0x8000000000000000 | a) +#define EFI_ERROR_MASK 0x8000000000000000 +#define EFIERR_OEM(a) (0xc000000000000000 | a) + +#define BAD_POINTER 0xFBFBFBFBFBFBFBFB +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF + +#define BREAKPOINT() while (TRUE); // Make it hang on Bios[Dbg]32 + +// +// Pointers must be aligned to these address to function +// + +#define MIN_ALIGNMENT_SIZE 8 + +#define ALIGN_VARIABLE(Value ,Adjustment) \ + (UINTN)Adjustment = 0; \ + if((UINTN)Value % MIN_ALIGNMENT_SIZE) \ + (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \ + Value = (UINTN)Value + (UINTN)Adjustment + + +// +// Define macros to build data structure signatures from characters. +// + +#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8)) +#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16)) +#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32)) + +// +// EFIAPI - prototype calling convention for EFI function pointers +// BOOTSERVICE - prototype for implementation of a boot service interface +// RUNTIMESERVICE - prototype for implementation of a runtime service interface +// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service +// RUNTIME_CODE - pragma macro for declaring runtime code +// + +#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options +#define EFIAPI // Substitute expresion to force C calling convention +#endif + +#define BOOTSERVICE +#define RUNTIMESERVICE +#define RUNTIMEFUNCTION + + +#define RUNTIME_CODE(a) alloc_text("rtcode", a) +#define BEGIN_RUNTIME_DATA() data_seg("rtdata") +#define END_RUNTIME_DATA() data_seg("") + +#define VOLATILE volatile + +#define MEMORY_FENCE __sync_synchronize + +// +// When build similiar to FW, then link everything together as +// one big module. +// + +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + UINTN \ + InitializeDriver ( \ + VOID* ImageHandle, \ + VOID* SystemTable \ + ) \ + { \ + return InitFunction(ImageHandle, \ + SystemTable); \ + } \ + \ + EFI_STATUS efi_main( \ + EFI_HANDLE image, \ + EFI_SYSTEM_TABLE* systab \ + ) __attribute__((weak, \ + alias ("InitializeDriver"))); + +#define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, entry) + + +// +// Some compilers don't support the forward reference construct: +// typedef struct XXXXX +// +// The following macro provide a workaround for such cases. + +#define INTERFACE_DECL(x) struct x + +#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__) +#define EFI_FUNCTION + +static inline UINT64 swap_uint64 (UINT64 v) +{ + __asm__ volatile ( + "dsbh %[v], %[v] \n\t" + "dshd %[v], %[v] \n\t" + :[v]"+r"(v) + ); + + return v; +} diff --git a/code/boot/include/mips64el/efilibplat.h b/code/boot/include/mips64el/efilibplat.h new file mode 100644 index 0000000..ba280b0 --- /dev/null +++ b/code/boot/include/mips64el/efilibplat.h @@ -0,0 +1,25 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efilibplat.h + +Abstract: + + EFI to compile bindings + + + + +Revision History + +--*/ + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE* SystemTable + ); + diff --git a/code/boot/include/mips64el/efisetjmp_arch.h b/code/boot/include/mips64el/efisetjmp_arch.h new file mode 100644 index 0000000..6f65513 --- /dev/null +++ b/code/boot/include/mips64el/efisetjmp_arch.h @@ -0,0 +1,34 @@ +#ifndef GNU_EFI_MIPS64EL_SETJMP_H +#define GNU_EFI_MIPS64EL_SETJMP_H + +#define JMPBUF_ALIGN 8 + +typedef struct { + /* GP regs */ + UINT64 RA; + UINT64 SP; + UINT64 FP; + UINT64 GP; + UINT64 S0; + UINT64 S1; + UINT64 S2; + UINT64 S3; + UINT64 S4; + UINT64 S5; + UINT64 S6; + UINT64 S7; + +#ifdef __mips_hard_float + /* FP regs */ + UINT64 F24; + UINT64 F25; + UINT64 F26; + UINT64 F27; + UINT64 F28; + UINT64 F29; + UINT64 F30; + UINT64 F31; +#endif +} EFI_ALIGN(JMPBUF_ALIGN) jmp_buf[1]; + +#endif /* GNU_EFI_MIPS64EL_SETJMP_H */ diff --git a/code/boot/include/pci22.h b/code/boot/include/pci22.h new file mode 100644 index 0000000..1937314 --- /dev/null +++ b/code/boot/include/pci22.h @@ -0,0 +1,193 @@ +#ifndef _PCI22_H +#define _PCI22_H + +/*++ + +Copyright (c) 1999 Intel Corporation + +Module Name: + + pci22.h + +Abstract: + Support for PCI 2.2 standard. + + + + +Revision History + +--*/ + +#ifdef SOFT_SDV +#define PCI_MAX_BUS 1 +#else +#define PCI_MAX_BUS 255 +#endif + +#define PCI_MAX_DEVICE 31 +#define PCI_MAX_FUNC 7 + +// +// Command +// +#define PCI_VGA_PALETTE_SNOOP_DISABLED 0x20 + +#pragma pack(1) +typedef struct { + UINT16 VendorId; + UINT16 DeviceId; + UINT16 Command; + UINT16 Status; + UINT8 RevisionID; + UINT8 ClassCode[3]; + UINT8 CacheLineSize; + UINT8 LaytencyTimer; + UINT8 HeaderType; + UINT8 BIST; +} PCI_DEVICE_INDEPENDENT_REGION; + +typedef struct { + UINT32 Bar[6]; + UINT32 CISPtr; + UINT16 SubsystemVendorID; + UINT16 SubsystemID; + UINT32 ExpansionRomBar; + UINT32 Reserved[2]; + UINT8 InterruptLine; + UINT8 InterruptPin; + UINT8 MinGnt; + UINT8 MaxLat; +} PCI_DEVICE_HEADER_TYPE_REGION; + +typedef struct { + PCI_DEVICE_INDEPENDENT_REGION Hdr; + PCI_DEVICE_HEADER_TYPE_REGION Device; +} PCI_TYPE00; + +typedef struct { + UINT32 Bar[2]; + UINT8 PrimaryBus; + UINT8 SecondaryBus; + UINT8 SubordinateBus; + UINT8 SecondaryLatencyTimer; + UINT8 IoBase; + UINT8 IoLimit; + UINT16 SecondaryStatus; + UINT16 MemoryBase; + UINT16 MemoryLimit; + UINT16 PrefetchableMemoryBase; + UINT16 PrefetchableMemoryLimit; + UINT32 PrefetchableBaseUpper32; + UINT32 PrefetchableLimitUpper32; + UINT16 IoBaseUpper16; + UINT16 IoLimitUpper16; + UINT32 Reserved; + UINT32 ExpansionRomBAR; + UINT8 InterruptLine; + UINT8 InterruptPin; + UINT16 BridgeControl; +} PCI_BRIDGE_CONTROL_REGISTER; + +#define PCI_CLASS_DISPLAY_CTRL 0x03 +#define PCI_CLASS_VGA 0x00 + +#define PCI_CLASS_BRIDGE 0x06 +#define PCI_CLASS_ISA 0x01 +#define PCI_CLASS_ISA_POSITIVE_DECODE 0x80 + +#define PCI_CLASS_NETWORK 0x02 +#define PCI_CLASS_ETHERNET 0x00 + +#define HEADER_TYPE_DEVICE 0x00 +#define HEADER_TYPE_PCI_TO_PCI_BRIDGE 0x01 +#define HEADER_TYPE_MULTI_FUNCTION 0x80 +#define HEADER_LAYOUT_CODE 0x7f + +#define IS_PCI_BRIDGE(_p) ((((_p)->Hdr.HeaderType) & HEADER_LAYOUT_CODE) == HEADER_TYPE_PCI_TO_PCI_BRIDGE) +#define IS_PCI_MULTI_FUNC(_p) (((_p)->Hdr.HeaderType) & HEADER_TYPE_MULTI_FUNCTION) + +typedef struct { + PCI_DEVICE_INDEPENDENT_REGION Hdr; + PCI_BRIDGE_CONTROL_REGISTER Bridge; +} PCI_TYPE01; + +typedef struct { + UINT8 Register; + UINT8 Function; + UINT8 Device; + UINT8 Bus; + UINT8 Reserved[4]; +} DEFIO_PCI_ADDR; + +typedef struct { + UINT32 Reg : 8; + UINT32 Func : 3; + UINT32 Dev : 5; + UINT32 Bus : 8; + UINT32 Reserved: 7; + UINT32 Enable : 1; +} PCI_CONFIG_ACCESS_CF8; + +#pragma pack() + +#define EFI_ROOT_BRIDGE_LIST 'eprb' +typedef struct { + UINTN Signature; + + UINT16 BridgeNumber; + UINT16 PrimaryBus; + UINT16 SubordinateBus; + + EFI_DEVICE_PATH* DevicePath; + + LIST_ENTRY Link; +} PCI_ROOT_BRIDGE_ENTRY; + + +#define PCI_EXPANSION_ROM_HEADER_SIGNATURE 0xaa55 +#define EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE 0x0EF1 +#define PCI_DATA_STRUCTURE_SIGNATURE EFI_SIGNATURE_32('P','C','I','R') + +#pragma pack(1) +typedef struct { + UINT16 Signature; // 0xaa55 + UINT8 Reserved[0x16]; + UINT16 PcirOffset; +} PCI_EXPANSION_ROM_HEADER; + + +typedef struct { + UINT16 Signature; // 0xaa55 + UINT16 InitializationSize; + UINT16 EfiSignature; // 0x0EF1 + UINT16 EfiSubsystem; + UINT16 EfiMachineType; + UINT8 Reserved[0x0A]; + UINT16 EfiImageHeaderOffset; + UINT16 PcirOffset; +} EFI_PCI_EXPANSION_ROM_HEADER; + +typedef struct { + UINT32 Signature; // "PCIR" + UINT16 VendorId; + UINT16 DeviceId; + UINT16 Reserved0; + UINT16 Length; + UINT8 Revision; + UINT8 ClassCode[3]; + UINT16 ImageLength; + UINT16 CodeRevision; + UINT8 CodeType; + UINT8 Indicator; + UINT16 Reserved1; +} PCI_DATA_STRUCTURE; +#pragma pack() + +#endif + + + + + + diff --git a/code/boot/include/protocol/adapterdebug.h b/code/boot/include/protocol/adapterdebug.h new file mode 100644 index 0000000..06d461a --- /dev/null +++ b/code/boot/include/protocol/adapterdebug.h @@ -0,0 +1,32 @@ +#ifndef _ADAPTER_DEBUG_H +#define _ADAPTER_DEBUG_H + +/*++ + +Copyright (c) 1999 Intel Corporation + +Module Name: + + AdapterDebug.h + +Abstract: + + Protocol to debug the EDD 3.0 enablement of BIOS option ROMs + + + +Revision History + +--*/ + +// {82F86881-282B-11d4-BC7D-0080C73C8881} +#define ADAPTER_DEBUG_PROTOCOL \ +{ 0x82f86881, 0x282b, 0x11d4, {0xbc, 0x7d, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81} } + +// +// This protocol points to the BIOS_LEGACY_DRIVE data structure +// see edd.h for more details +// + +#endif + diff --git a/code/boot/include/protocol/eficonsplit.h b/code/boot/include/protocol/eficonsplit.h new file mode 100644 index 0000000..366cda0 --- /dev/null +++ b/code/boot/include/protocol/eficonsplit.h @@ -0,0 +1,32 @@ +#ifndef _EFI_CONFORK_H +#define _EFI_CONFORK_H +/*++ + +Copyright (c) 1999 Intel Corporation + +Module Name: + +Abstract: + + + +Revision History + +--*/ + + + +// +// ConOut Forker Protocol +// + +#define TEXT_OUT_SPLITER_PROTOCOL \ + { 0x56d830a0, 0x7e7a, 0x11d3, {0xbb, 0xa0, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +#define ERROR_OUT_SPLITER_PROTOCOL \ + { 0xf0ba9039, 0x68f1, 0x425e, {0xaa, 0x7f, 0xd9, 0xaa, 0xf9, 0x1b, 0x82, 0xa1}} + +#define TEXT_IN_SPLITER_PROTOCOL \ + { 0xf9a3c550, 0x7fb5, 0x11d3, {0xbb, 0xa0, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +#endif diff --git a/code/boot/include/protocol/efidbg.h b/code/boot/include/protocol/efidbg.h new file mode 100644 index 0000000..824f6a8 --- /dev/null +++ b/code/boot/include/protocol/efidbg.h @@ -0,0 +1,210 @@ +/* + * Copyright (c) 1999, 2000 + * Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * + * This product includes software developed by Intel Corporation and + * its contributors. + * + * 4. Neither the name of Intel Corporation or its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef _EFIDBG_H_ +#define _EFIDBG_H_ + +#include "eficontext.h" +#include "efiser.h" + +typedef struct _DEBUGPORT_16550_CONFIG_DATA { + UINT32 PortAddress; + UINT64 BaudRate; + UINT32 ReceiveFifoDepth; + UINT32 Timeout; + UINT8 Parity; + UINT8 DataBits; + UINT8 StopBits; + UINT32 ControlMask; + BOOLEAN RtsCtsEnable; // RTS, CTS control +} DEBUGPORT_16550_CONFIG_DATA; + +typedef struct _DEBUGPORT_16550_DEVICE_PATH { + EFI_DEVICE_PATH Header; + DEBUGPORT_16550_CONFIG_DATA ConfigData; +} DEBUGPORT_16550_DEVICE_PATH; + +typedef union { + EFI_DEVICE_PATH DevPath; + DEBUGPORT_16550_DEVICE_PATH Uart; + // add new types of debugport device paths to this union... +} DEBUGPORT_DEV_PATH; + + +// +// Debug Support protocol {2755590C-6F3C-42FA-9EA4-A3BA543CDA25} +// + +#define DEBUG_SUPPORT_PROTOCOL \ +{ 0x2755590C, 0x6F3C, 0x42fa, 0x9E, 0xA4, 0xA3, 0xBA, 0x54, 0x3C, 0xDA, 0x25 } + + +typedef UINTN EXCEPTION_TYPE; + +typedef +VOID +(*EXCEPTION_HANDLER) ( + IN EXCEPTION_TYPE ExceptionType, + IN SYSTEM_CONTEXT* SystemContext + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_REGISTER_TIMER_TICK_CALLBACK) ( + IN struct _EFI_DEBUG_SUPPORT_INTERFACE* This, + IN EXCEPTION_HANDLER TimerTickCallback + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_REGISTER_EXCEPTION_HANDLER) ( + IN struct _EFI_DEBUG_SUPPORT_INTERFACE* This, + IN EXCEPTION_HANDLER ExceptionHandler, + IN EXCEPTION_TYPE ExceptionType + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_IP_CALL_TRACE) ( + IN struct _EFI_DEBUG_SUPPORT_INTERFACE* This + ); + + +#define EFI_DEBUG_SUPPORT_INTERFACE_REVISION 0x00010000 + +typedef struct _EFI_DEBUG_SUPPORT_INTERFACE { + UINT32 Revision; + EFI_REGISTER_TIMER_TICK_CALLBACK RegisterTimerTickCallback; + EFI_REGISTER_EXCEPTION_HANDLER RegisterExceptionHandler; + EFI_IP_CALL_TRACE IpCallTrace; +} EFI_DEBUG_SUPPORT_INTERFACE; + + +// +// Debugport io protocol {EBA4E8D2-3858-41EC-A281-2647BA9660D0} +// + +#define DEBUGPORT_IO_PROTOCOL \ +{ 0XEBA4E8D2, 0X3858, 0X41EC, 0XA2, 0X81, 0X26, 0X47, 0XBA, 0X96, 0X60, 0XD0 } + + +typedef +EFI_STATUS +(EFIAPI* EFI_DEBUGPORT_IO_RESET) ( + IN struct _EFI_DEBUGPORT_IO_INTERFACE* This + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_DEBUGPORT_IO_READ) ( + IN struct _EFI_DEBUGPORT_IO_INTERFACE* This, + IN OUT UINTN* BufferSize, + OUT VOID* Buffer + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_DEBUGPORT_IO_WRITE) ( + IN struct _EFI_DEBUGPORT_IO_INTERFACE* This, + IN OUT UINTN* BufferSize, + IN VOID* Buffer + ); + +#define EFI_DEBUGPORT_IO_INTERFACE_REVISION 0x00010000 + +typedef struct _EFI_DEBUGPORT_IO_INTERFACE { + UINT32 Revision; + EFI_DEBUGPORT_IO_READ Read; + EFI_DEBUGPORT_IO_WRITE Write; + EFI_DEBUGPORT_IO_RESET Reset; +} EFI_DEBUGPORT_IO_INTERFACE; + + +// +// Debugport UART16550 control protocol {628EA978-4C26-4605-BC02-A42A496917DD} +// + +#define DEBUGPORT_UART16550_CONTROL_PROTOCOL \ +{ 0X628EA978, 0X4C26, 0X4605, 0XBC, 0X2, 0XA4, 0X2A, 0X49, 0X69, 0X17, 0XDD } + +// Note: The definitions for EFI_PARITY_TYPE, EFI_STOP_BITS_TYPE, and +// SERIAL_IO_MODE are included from efiser.h + +typedef +EFI_STATUS +(EFIAPI* EFI_UART16550_SET_ATTRIBUTES) ( + IN struct _EFI_DEBUGPORT_UART16550_CONTROL_INTERFACE* This, + IN UINT64 BaudRate, + IN UINT32 ReceiveFifoDepth, + IN UINT32 Timeout, + IN EFI_PARITY_TYPE Parity, + IN UINT8 DataBits, + IN EFI_STOP_BITS_TYPE StopBits + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_UART16550_SET_CONTROL_BITS) ( + IN struct _EFI_DEBUGPORT_UART16550_CONTROL_INTERFACE* This, + IN UINT32 Control + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_UART16550_GET_CONTROL_BITS) ( + IN struct _EFI_DEBUGPORT_UART16550_CONTROL_INTERFACE* This, + OUT UINT32* Control + ); + +#define EFI_DEBUGPORT_UART16550_CONTROL_INTERFACE_REVISION 0x00010000 + +typedef struct _EFI_DEBUGPORT_UART16550_CONTROL_INTERFACE { + UINT32 Revision; + EFI_UART16550_SET_ATTRIBUTES SetAttributes; + EFI_UART16550_SET_CONTROL_BITS SetControl; + EFI_UART16550_GET_CONTROL_BITS GetControl; + DEBUGPORT_16550_CONFIG_DATA* Mode; +} EFI_DEBUGPORT_UART16550_CONTROL_INTERFACE; + + +#define DEVICE_PATH_DEBUGPORT DEBUGPORT_IO_PROTOCOL + +#endif /* _EFIDBG_H_ */ diff --git a/code/boot/include/protocol/efivar.h b/code/boot/include/protocol/efivar.h new file mode 100644 index 0000000..837d0c5 --- /dev/null +++ b/code/boot/include/protocol/efivar.h @@ -0,0 +1,133 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + +Abstract: + + + +Revision History + +--*/ + + + +// +// The variable store protocol interface is specific to the reference +// implementation. The initialization code adds variable store devices +// to the system, and the FW connects to the devices to provide the +// variable store interfaces through these devices. +// + +// +// Variable Store Device protocol +// + +#define VARIABLE_STORE_PROTOCOL \ + { 0xf088cd91, 0xa046, 0x11d2, {0x8e, 0x42, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +INTERFACE_DECL(_EFI_VARIABLE_STORE); + +typedef +EFI_STATUS +(EFIAPI* EFI_STORE_CLEAR) ( + IN struct _EFI_VARIABLE_STORE* This, + IN UINTN BankNo, + IN OUT VOID* Scratch + ); + + +typedef +EFI_STATUS +(EFIAPI* EFI_STORE_READ) ( + IN struct _EFI_VARIABLE_STORE* This, + IN UINTN BankNo, + IN UINTN Offset, + IN UINTN BufferSize, + OUT VOID* Buffer + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_STORE_UPDATE) ( + IN struct _EFI_VARIABLE_STORE* This, + IN UINTN BankNo, + IN UINTN Offset, + IN UINTN BufferSize, + IN VOID* Buffer + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_STORE_SIZE) ( + IN struct _EFI_VARIABLE_STORE* This, + IN UINTN NoBanks + ); + +typedef +EFI_STATUS +(EFIAPI* EFI_TRANSACTION_UPDATE) ( + IN struct _EFI_VARIABLE_STORE* This, + IN UINTN BankNo, + IN VOID* NewContents + ); + +typedef struct _EFI_VARIABLE_STORE { + + // + // Number of banks and bank size + // + + UINT32 Attributes; + UINT32 BankSize; + UINT32 NoBanks; + + // + // Functions to access the storage banks + // + + EFI_STORE_CLEAR ClearStore; + EFI_STORE_READ ReadStore; + EFI_STORE_UPDATE UpdateStore; + EFI_STORE_SIZE SizeStore OPTIONAL; + EFI_TRANSACTION_UPDATE TransactionUpdate OPTIONAL; + +} EFI_VARIABLE_STORE; + + +// +// +// ClearStore() - A function to clear the requested storage bank. A cleared +// bank contains all "on" bits. +// +// ReadStore() - Read data from the requested store. +// +// UpdateStore() - Updates data on the requested store. The FW will only +// ever issue updates to clear bits in the store. Updates must be +// performed in LSb to MSb order of the update buffer. +// +// SizeStore() - An optional function for non-runtime stores that can be +// dynamically sized. The FW will only ever increase or decrease the store +// by 1 banksize at a time, and it is always adding or removing a bank from +// the end of the store. +// +// By default the FW will update variables and storage banks in an +// "atomic" manner by keeping 1 old copy of the data during an update, +// and recovering appropiately if the power is lost during the middle +// of an operation. To do this the FW needs to have multiple banks +// of storage dedicated to its use. If that's not possible, the driver +// can implement an atomic bank update function and the FW will allow +// 1 bank in this case. (It will allow any number of banks, +// but it won't require an "extra" bank to provide its bank transaction +// function). +// +// TransactionUpdate() - An optional function that can clear & update an +// entire bank in an "atomic" fashion. If the operation fails in the +// middle the driver is responsible for having either the previous copy +// of the bank's data or the new copy. A copy that's partially written +// is not valid as internal data settings may get lost. Supply this +// function only when needed. +// + diff --git a/code/boot/include/protocol/ia64/eficontext.h b/code/boot/include/protocol/ia64/eficontext.h new file mode 100644 index 0000000..1a39a6d --- /dev/null +++ b/code/boot/include/protocol/ia64/eficontext.h @@ -0,0 +1,208 @@ +/* + * Copyright (c) 1999, 2000 + * Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * + * This product includes software developed by Intel Corporation and + * its contributors. + * + * 4. Neither the name of Intel Corporation or its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef _EFICONTEXT_H_ +#define _EFICONTEXT_H_ + + +// +// IA-64 processor exception types +// +#define EXCPT_ALT_DTLB 4 +#define EXCPT_DNESTED_TLB 5 +#define EXCPT_BREAKPOINT 11 +#define EXCPT_EXTERNAL_INTERRUPT 12 +#define EXCPT_GEN_EXCEPT 24 +#define EXCPT_NAT_CONSUMPTION 26 +#define EXCPT_DEBUG_EXCEPT 29 +#define EXCPT_UNALIGNED_ACCESS 30 +#define EXCPT_FP_FAULT 32 +#define EXCPT_FP_TRAP 33 +#define EXCPT_TAKEN_BRANCH 35 +#define EXCPT_SINGLE_STEP 36 + +// +// IA-64 processor context definition - must be 512 byte aligned!!! +// +typedef +struct { + UINT64 reserved; // necessary to preserve alignment for the correct bits in UNAT and to insure F2 is 16 byte aligned... + + UINT64 r1; + UINT64 r2; + UINT64 r3; + UINT64 r4; + UINT64 r5; + UINT64 r6; + UINT64 r7; + UINT64 r8; + UINT64 r9; + UINT64 r10; + UINT64 r11; + UINT64 r12; + UINT64 r13; + UINT64 r14; + UINT64 r15; + UINT64 r16; + UINT64 r17; + UINT64 r18; + UINT64 r19; + UINT64 r20; + UINT64 r21; + UINT64 r22; + UINT64 r23; + UINT64 r24; + UINT64 r25; + UINT64 r26; + UINT64 r27; + UINT64 r28; + UINT64 r29; + UINT64 r30; + UINT64 r31; + + UINT64 f2[2]; + UINT64 f3[2]; + UINT64 f4[2]; + UINT64 f5[2]; + UINT64 f6[2]; + UINT64 f7[2]; + UINT64 f8[2]; + UINT64 f9[2]; + UINT64 f10[2]; + UINT64 f11[2]; + UINT64 f12[2]; + UINT64 f13[2]; + UINT64 f14[2]; + UINT64 f15[2]; + UINT64 f16[2]; + UINT64 f17[2]; + UINT64 f18[2]; + UINT64 f19[2]; + UINT64 f20[2]; + UINT64 f21[2]; + UINT64 f22[2]; + UINT64 f23[2]; + UINT64 f24[2]; + UINT64 f25[2]; + UINT64 f26[2]; + UINT64 f27[2]; + UINT64 f28[2]; + UINT64 f29[2]; + UINT64 f30[2]; + UINT64 f31[2]; + + UINT64 pr; + + UINT64 b0; + UINT64 b1; + UINT64 b2; + UINT64 b3; + UINT64 b4; + UINT64 b5; + UINT64 b6; + UINT64 b7; + + // application registers + UINT64 ar_rsc; + UINT64 ar_bsp; + UINT64 ar_bspstore; + UINT64 ar_rnat; + + UINT64 ar_fcr; + + UINT64 ar_eflag; + UINT64 ar_csd; + UINT64 ar_ssd; + UINT64 ar_cflg; + UINT64 ar_fsr; + UINT64 ar_fir; + UINT64 ar_fdr; + + UINT64 ar_ccv; + + UINT64 ar_unat; + + UINT64 ar_fpsr; + + UINT64 ar_pfs; + UINT64 ar_lc; + UINT64 ar_ec; + + // control registers + UINT64 cr_dcr; + UINT64 cr_itm; + UINT64 cr_iva; + UINT64 cr_pta; + UINT64 cr_ipsr; + UINT64 cr_isr; + UINT64 cr_iip; + UINT64 cr_ifa; + UINT64 cr_itir; + UINT64 cr_iipa; + UINT64 cr_ifs; + UINT64 cr_iim; + UINT64 cr_iha; + + // debug registers + UINT64 dbr0; + UINT64 dbr1; + UINT64 dbr2; + UINT64 dbr3; + UINT64 dbr4; + UINT64 dbr5; + UINT64 dbr6; + UINT64 dbr7; + + UINT64 ibr0; + UINT64 ibr1; + UINT64 ibr2; + UINT64 ibr3; + UINT64 ibr4; + UINT64 ibr5; + UINT64 ibr6; + UINT64 ibr7; + + // virtual registers + UINT64 int_nat; // nat bits for R1-R31 + +} SYSTEM_CONTEXT; + +#endif /* _EFI_CONTEXT_H_ */ diff --git a/code/boot/include/protocol/intload.h b/code/boot/include/protocol/intload.h new file mode 100644 index 0000000..911add9 --- /dev/null +++ b/code/boot/include/protocol/intload.h @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 1999 Intel Corporation + +Module Name: + + intload + +Abstract: + + EFI support for loading internally linked in apps + + + +Revision History + +--*/ + +#ifndef _INTERNAL_LOAD_INCLUDE_ +#define _INTERNAL_LOAD_INCLUDE_ + +// {D65A6B8C-71E5-4df0-A909-F0D2992B5AA9} +#define INTERNAL_SHELL_GUID \ + { 0xd65a6b8c, 0x71e5, 0x4df0, {0xa9, 0x09, 0xf0, 0xd2, 0x99, 0x2b, 0x5a, 0xa9} } + + +#endif diff --git a/code/boot/include/protocol/legacyboot.h b/code/boot/include/protocol/legacyboot.h new file mode 100644 index 0000000..4a69410 --- /dev/null +++ b/code/boot/include/protocol/legacyboot.h @@ -0,0 +1,119 @@ +/*++ + +Copyright (c) 1999 Intel Corporation + +Module Name: + + legacyboot + +Abstract: + + EFI support for legacy boot + + + +Revision History + +--*/ + +#ifndef _LEGACY_BOOT_INCLUDE_ +#define _LEGACY_BOOT_INCLUDE_ + +#define LEGACY_BOOT_PROTOCOL \ + { 0x376e5eb2, 0x30e4, 0x11d3, { 0xba, 0xe5, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } } + +#pragma pack(1) + +// +// BBS 1.01 (See Appendix A) IPL and BCV Table Entry Data structure. +// Seg:Off pointers have been converted to EFI pointers in this data structure +// This is the structure that also maps to the EFI device path for the boot selection +// +typedef struct { + UINT16 DeviceType; + UINT16 StatusFlag; + UINT32 Reserved; + VOID* BootHandler; // Not an EFI entry point + CHAR8* DescString; +} BBS_TABLE_ENTRY; +#pragma pack() + +typedef +EFI_STATUS +(EFIAPI* LEGACY_BOOT_CALL) ( + IN EFI_DEVICE_PATH* DevicePath + ); + + +// +// BBS support functions +// PnP Call numbers and BiosSelector hidden in implementation +// + +typedef enum { + IplRelative, + BcvRelative +} BBS_TYPE; + +INTERFACE_DECL(_LEGACY_BOOT_INTERFACE); + +// +// == PnP Function 0x60 then BbsVersion == 0x0101 if this call fails then BbsVersion == 0x0000 +// + +// +// == PnP Function 0x61 +// +typedef +EFI_STATUS +(EFIAPI* GET_DEVICE_COUNT) ( + IN struct _LEGACY_BOOT_INTERFACE* This, + IN BBS_TYPE* TableType, + OUT UINTN* DeviceCount, + OUT UINTN* MaxCount + ); + +// +// == PnP Function 0x62 +// +typedef +EFI_STATUS +(EFIAPI* GET_PRIORITY_AND_TABLE) ( + IN struct _LEGACY_BOOT_INTERFACE* This, + IN BBS_TYPE* TableType, + IN OUT UINTN* PrioritySize, // MaxCount * sizeof(UINT8) + OUT UINTN* Priority, + IN OUT UINTN* TableSize, // MaxCount * sizeof(BBS_TABLE_ENTRY) + OUT BBS_TABLE_ENTRY* TableEntrySize + ); + +// +// == PnP Function 0x63 +// +typedef +EFI_STATUS +(EFIAPI* SET_PRIORITY) ( + IN struct _LEGACY_BOOT_INTERFACE* This, + IN BBS_TYPE* TableType, + IN OUT UINTN* PrioritySize, + OUT UINTN* Priority + ); + +typedef struct _LEGACY_BOOT_INTERFACE { + LEGACY_BOOT_CALL BootIt; + + // + // New functions to allow BBS booting to be configured from EFI + // + UINTN BbsVersion; // Currently 0x0101 + GET_DEVICE_COUNT GetDeviceCount; + GET_PRIORITY_AND_TABLE GetPriorityAndTable; + SET_PRIORITY SetPriority; +} LEGACY_BOOT_INTERFACE; + +EFI_STATUS +PlInitializeLegacyBoot ( + VOID + ); + +#endif diff --git a/code/boot/include/protocol/make.inf b/code/boot/include/protocol/make.inf new file mode 100644 index 0000000..f3bb907 --- /dev/null +++ b/code/boot/include/protocol/make.inf @@ -0,0 +1,13 @@ +# +# +# + +[sources] + efivar.h + legacyboot.h + VgaClass.h + intload.h + +[ia32sources] + +[ia64sources] diff --git a/code/boot/include/protocol/makefile.hdr b/code/boot/include/protocol/makefile.hdr new file mode 100644 index 0000000..118d6ba --- /dev/null +++ b/code/boot/include/protocol/makefile.hdr @@ -0,0 +1,29 @@ + +# +# This is a machine generated file - DO NOT EDIT +# Generated by genmake.exe +# Generated from make.inf +# Copyright (c) 1998 Intel Corporation +# + +INC_DEPS = $(INC_DEPS) \ + $(SDK_INSTALL_DIR)\include\efi\protocol\efivar.h \ + $(SDK_INSTALL_DIR)\include\efi\protocol\legacyboot.h \ + $(SDK_INSTALL_DIR)\include\efi\protocol\vgaclass.h \ + $(SDK_INSTALL_DIR)\include\efi\protocol\efidbg.h \ + + +!IF "$(PROCESSOR)" == "Ia32" +INC_DEPS = $(INC_DEPS) \ + + +!ENDIF + + +!IF "$(PROCESSOR)" == "Ia64" +INC_DEPS = $(INC_DEPS) \ + $(SDK_INSTALL_DIR)\include\efi\protocol\$(PROCESSOR)\eficontext.h \ + + +!ENDIF + diff --git a/code/boot/include/protocol/piflash64.h b/code/boot/include/protocol/piflash64.h new file mode 100644 index 0000000..6b0b41e --- /dev/null +++ b/code/boot/include/protocol/piflash64.h @@ -0,0 +1,121 @@ +#ifndef _PIFLASH64_H +#define _PIFLASH64_H + +/*++ + +Copyright (c) 1999 Intel Corporation + +Module Name: + + PIflash64.h + +Abstract: + + Iflash64.efi protocol to abstract iflash from + the system. + +Revision History + +--*/ + +// +// Guid that identifies the IFLASH protocol +// +#define IFLASH64_PROTOCOL_PROTOCOL \ + { 0x65cba110, 0x74ab, 0x11d3, 0xbb, 0x89, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 }; + +// +// Unlock FLASH from StartAddress to EndAddress and return a LockKey +// +typedef +EFI_STATUS +(EFIAPI* UNLOCK_FLASH_API)( + IN struct _IFLASH64_PROTOCOL_INTERFACE* This + ); + +// +// Lock the flash represented by the LockKey +// +typedef +EFI_STATUS +(EFIAPI* LOCK_FLASH_API)( + IN struct _IFLASH64_PROTOCOL_INTERFACE* This + ); + +// +// Status callback for a utility like IFLASH64 +// +// Token would map to a list like Ted proposed. The utility has no idea what +// happens on the other side. +// ErrorStatus - Level of Error or success. Independent of Token. If you +// don't know the token you will at least know pass or fail. +// String - Optional extra information about the error. Could be used for +// debug or future expansion +// +// Attributes - Options screen attributes for String. Could allow the string to be different colors. +// +typedef +EFI_STATUS +(EFIAPI* UTILITY_PROGRESS_API)( + IN struct _IFLASH64_PROTOCOL_INTERFACE* This, + IN UINTN Token, + IN EFI_STATUS ErrorStatus, + IN CHAR16* String, OPTIONAL + IN UINTN* Attributes OPTIONAL + ); + +// +// Token Values +// +// IFlash64 Token Codes +#define IFLASH_TOKEN_IFLASHSTART 0xB0 // IFlash64 has started +#define IFLASH_TOKEN_READINGFILE 0xB1 // Reading File +#define IFLASH_TOKEN_INITVPP 0xB2 // Initializing Vpp +#define IFLASH_TOKEN_DISABLEVPP 0x10 // Disable Vpp +#define IFLASH_TOKEN_FLASHUNLOCK 0xB3 // Unlocking FLASH Devices +#define IFLASH_TOKEN_FLASHERASE 0xB4 // Erasing FLASH Devices +#define IFLASH_TOKEN_FLASHPROGRAM 0xB5 // Programming FLASH +#define IFLASH_TOKEN_FLASHVERIFY 0xB6 // Verifying FLASH +#define IFLASH_TOKEN_UPDATESUCCES 0xB7 // FLASH Updage Success! + +#define IFLASH_TOKEN_PROGRESS_READINGFILE 0x11 // % Reading File +#define IFLASH_TOKEN_PROGRESS_FLASHUNLOCK 0x13 // % Unlocking FLASH Devices +#define IFLASH_TOKEN_PROGRESS_FLASHERASE 0x14 // % Erasing FLASH Devices +#define IFLASH_TOKEN_PROGRESS_FLASHPROGRAM 0x15 // % Programming FLASH +#define IFLASH_TOKEN_PROGRESS_FLASHVERIFY 0x16 // % Verifying FLASH + +#define IFLASH_TOKEN_READINGFILE_ER 0xB8 // File Read Error +#define IFLASH_TOKEN_INITVPP_ER 0xB9 // Initialization of IFB Error +#define IFLASH_TOKEN_FLASHUNLOCK_ER 0xBA // FLASH Unlock Error +#define IFLASH_TOKEN_FLASHERASE_ER 0xBB // FLASH Erase Error +#define IFLASH_TOKEN_FLASHVERIFY_ER 0xBC // FLASH Verify Error +#define IFLASH_TOKEN_FLASHPROG_ER 0xBD // FLASH Program Error + +#define IFLASH_TABLE_END 0x00 + +// +// If this number changes one of the existing API's has changes +// +#define IFLASH_PI_MAJOR_VERSION 0x01 + +// +// This number changes when new APIs or data variables get added to the end +// of the data structure +// +#define IFLASH_PI_MINOR_VERSION 0x01 + +typedef struct _IFLASH64_PROTOCOL_INTERFACE { + UINT32 MajorVersion; + UINT32 MinorVersion; + UNLOCK_FLASH_API UnlockFlash; + LOCK_FLASH_API LockFlash; + UTILITY_PROGRESS_API Progress; + + // + // Future expansion goes here + // + +} IFLASH64_PROTOCOL_INTERFACE; + + +#endif diff --git a/code/boot/include/protocol/readme.txt b/code/boot/include/protocol/readme.txt new file mode 100644 index 0000000..66e155c --- /dev/null +++ b/code/boot/include/protocol/readme.txt @@ -0,0 +1,3 @@ +The protocol directory contains non Architectural +Protocols that span the FW, Platform, or application +space. \ No newline at end of file diff --git a/code/boot/include/protocol/vgaclass.h b/code/boot/include/protocol/vgaclass.h new file mode 100644 index 0000000..3b27690 --- /dev/null +++ b/code/boot/include/protocol/vgaclass.h @@ -0,0 +1,95 @@ +#ifndef _VGA_CLASS_H +#define _VGA_CLASS_H + +/*++ + +Copyright (c) 1999 Intel Corporation + +Module Name: + + VgaClass.h + +Abstract: + + Vga Mini port binding to Vga Class protocol + + + +Revision History + +--*/ + +// +// VGA Device Structure +// + +// {0E3D6310-6FE4-11d3-BB81-0080C73C8881} +#define VGA_CLASS_DRIVER_PROTOCOL \ + { 0xe3d6310, 0x6fe4, 0x11d3, {0xbb, 0x81, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81} } + +typedef +EFI_STATUS +(* INIT_VGA_CARD) ( + IN UINTN VgaMode, + IN VOID* Context + ); + +typedef struct { + UINTN MaxColumns; + UINTN MaxRows; +} MAX_CONSOLE_GEOMETRY; + +#define VGA_CON_OUT_DEV_SIGNATURE EFI_SIGNATURE_32('c','v','g','a') +typedef struct { + UINTN Signature; + + EFI_HANDLE Handle; + SIMPLE_TEXT_OUTPUT_INTERFACE ConOut; + SIMPLE_TEXT_OUTPUT_MODE ConOutMode; + EFI_DEVICE_PATH* DevicePath; + + UINT8* Buffer; + EFI_DEVICE_IO_INTERFACE* DeviceIo; + + // + // Video Card Context + // + INIT_VGA_CARD InitVgaCard; + VOID* VgaCardContext; + MAX_CONSOLE_GEOMETRY* Geometry; + // + // Video buffer normally 0xb8000 + // + UINT64 VideoBuffer; + + // + // Clear Screen & Default Attribute + // + UINT32 Attribute; + + // + // -1 means search for active VGA device + // + EFI_PCI_ADDRESS_UNION Pci; +} VGA_CON_OUT_DEV; + +#define VGA_CON_OUT_DEV_FROM_THIS(a) CR(a, VGA_CON_OUT_DEV, ConOut, VGA_CON_OUT_DEV_SIGNATURE) + +// +// Vga Class Driver Protocol. +// GUID defined in EFI Lib +// + +typedef +EFI_STATUS +(EFIAPI* INSTALL_VGA_DRIVER) ( + IN VGA_CON_OUT_DEV* ConOutDev + ); + +typedef struct { + UINT32 Version; + INSTALL_VGA_DRIVER InstallGenericVgaDriver; +} INSTALL_VGA_DRIVER_INTERFACE; + +#endif + diff --git a/code/boot/include/riscv64/efibind.h b/code/boot/include/riscv64/efibind.h new file mode 100644 index 0000000..253adaf --- /dev/null +++ b/code/boot/include/riscv64/efibind.h @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */ +/* + * Copyright (C) 2014 - 2015 Linaro Ltd. + * Author: Ard Biesheuvel + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License as published by the Free Software Foundation; + * either version 2 of the License, or (at your option) any later version. + */ + +#include + +// +// Basic EFI types of various widths +// + +#include + +typedef uint64_t UINT64; +typedef int64_t INT64; +typedef uint32_t UINT32; +typedef int32_t INT32; +typedef uint16_t UINT16; +typedef int16_t INT16; +typedef uint8_t UINT8; +typedef int8_t INT8; +typedef char CHAR8; +typedef wchar_t CHAR16; +#define WCHAR CHAR16 +#undef VOID +typedef void VOID; +typedef int64_t INTN; +typedef uint64_t UINTN; + +#define EFI_ERROR_MASK 0x8000000000000000 +#define EFIERR(a) (EFI_ERROR_MASK | a) +#define EFIERR_OEM(a) (0xc000000000000000 | a) + +#define BAD_POINTER 0xFBFBFBFBFBFBFBFB +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF + +#define BREAKPOINT() while(1); + +// +// Pointers must be aligned to these address to function +// +#define MIN_ALIGNMENT_SIZE 8 + +#define ALIGN_VARIABLE(Value, Adjustment) \ + (UINTN)Adjustment = 0; \ + if((UINTN)Value % MIN_ALIGNMENT_SIZE) \ + (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \ + Value = (UINTN)Value + (UINTN)Adjustment + +// +// Define macros to build data structure signatures from characters. +// +#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8)) +#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16)) +#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32)) + +// +// EFIAPI - prototype calling convention for EFI function pointers +// BOOTSERVICE - prototype for implementation of a boot service interface +// RUNTIMESERVICE - prototype for implementation of a runtime service interface +// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service +// RUNTIME_CODE - pragma macro for declaring runtime code +// +#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options +#define EFIAPI // Substitute expresion to force C calling convention +#endif +#define BOOTSERVICE +#define RUNTIMESERVICE +#define RUNTIMEFUNCTION +#define RUNTIME_CODE(a) alloc_text("rtcode", a) +#define BEGIN_RUNTIME_DATA() data_seg("rtdata") +#define END_RUNTIME_DATA() data_seg("") + +#define VOLATILE volatile +#define MEMORY_FENCE __sync_synchronize + +// +// When build similiar to FW, then link everything together as +// one big module. For the MSVC toolchain, we simply tell the +// linker what our driver init function is using /ENTRY. +// +#if defined(_MSC_EXTENSIONS) +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + __pragma(comment(linker, "/ENTRY:" # InitFunction)) +#else +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + UINTN \ + InitializeDriver ( \ + VOID* ImageHandle, \ + VOID* SystemTable \ + ) \ + { \ + return InitFunction(ImageHandle, \ + SystemTable); \ + } \ + \ + EFI_STATUS efi_main( \ + EFI_HANDLE image, \ + EFI_SYSTEM_TABLE* systab \ + ) __attribute__((weak, \ + alias ("InitializeDriver"))); +#endif + +#define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, entry) + +// +// Some compilers don't support the forward reference construct: +// typedef struct XXXXX +// +// The following macro provide a workaround for such cases. +#define INTERFACE_DECL(x) struct x + +#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__) +#define EFI_FUNCTION diff --git a/code/boot/include/riscv64/efilibplat.h b/code/boot/include/riscv64/efilibplat.h new file mode 100644 index 0000000..ece45e0 --- /dev/null +++ b/code/boot/include/riscv64/efilibplat.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */ + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE* SystemTable + ); diff --git a/code/boot/include/riscv64/efisetjmp_arch.h b/code/boot/include/riscv64/efisetjmp_arch.h new file mode 100644 index 0000000..f526143 --- /dev/null +++ b/code/boot/include/riscv64/efisetjmp_arch.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause */ + +#ifndef GNU_EFI_RISCV64_SETJMP_H +#define GNU_EFI_RISCV64_SETJMP_H + +#define JMPBUF_ALIGN 8 + +typedef struct { + /* GP regs */ + UINT64 s0; + UINT64 s1; + UINT64 s2; + UINT64 s3; + UINT64 s4; + UINT64 s5; + UINT64 s6; + UINT64 s7; + UINT64 s8; + UINT64 s9; + UINT64 s10; + UINT64 s11; + UINT64 sp; + UINT64 ra; + + /* FP regs */ + UINT64 fs0; + UINT64 fs1; + UINT64 fs2; + UINT64 fs3; + UINT64 fs4; + UINT64 fs5; + UINT64 fs6; + UINT64 fs7; + UINT64 fs8; + UINT64 fs9; + UINT64 fs10; + UINT64 fs11; +} EFI_ALIGN(JMPBUF_ALIGN) jmp_buf[1]; + +#endif /* GNU_EFI_RISCV64_SETJMP_H */ diff --git a/code/boot/include/romload.h b/code/boot/include/romload.h new file mode 100644 index 0000000..de747a7 --- /dev/null +++ b/code/boot/include/romload.h @@ -0,0 +1,41 @@ +#ifndef _EFI_ROMLOAD_H +#define _EFI_ROMLOAD_H + +#define ROM_SIGNATURE 0xaa55 +#define PCIDS_SIGNATURE "PCIR" +#pragma pack(push) +#pragma pack(1) +typedef struct +{ + UINT8 Pcids_Sig[4]; + UINT16 VendId; + UINT16 DevId; + UINT16 Vpd_Off; + UINT16 Size; + UINT8 Rev; + UINT8 Class_Code[3]; + UINT16 Image_Len; + UINT16 Rev_Lvl; + UINT8 Code_Type; + UINT8 Indi; + UINT16 Rsvd; +}PciDataStructure; +typedef struct +{ + UINT16 Size; + UINT32 Header_Sig; + UINT16 SubSystem; + UINT16 MachineType; + UINT8 Resvd[10]; + UINT16 EfiOffset; +}ArchData; +typedef struct +{ + UINT16 Rom_Sig; + ArchData Arch_Data; + UINT16 Pcids_Off; + UINT8 resvd[38]; +}RomHeader; +#pragma pack(pop) + +#endif diff --git a/code/boot/include/x86_64/efibind.h b/code/boot/include/x86_64/efibind.h new file mode 100644 index 0000000..ce82af5 --- /dev/null +++ b/code/boot/include/x86_64/efibind.h @@ -0,0 +1,396 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efefind.h + +Abstract: + + EFI to compile bindings + + + + +Revision History + +--*/ +#ifndef X86_64_EFI_BIND +#define X86_64_EFI_BIND +#ifndef __GNUC__ +#pragma pack() +#endif + +#if defined(_MSC_VER) + #define HAVE_USE_MS_ABI 1 +#elif defined(GNU_EFI_USE_MS_ABI) + #if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)))||(defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 2))) + #define HAVE_USE_MS_ABI 1 + #else + #error Compiler is too old for GNU_EFI_USE_MS_ABI + #endif +#endif + +// +// Basic int types of various widths +// + +#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L ) && !defined(__cplusplus) + + // No ANSI C 1999/2000 stdint.h integer width declarations + + #if defined(_MSC_EXTENSIONS) + + // Use Microsoft C compiler integer width declarations + + typedef unsigned __int64 uint64_t; + typedef __int64 int64_t; + typedef unsigned __int32 uint32_t; + typedef __int32 int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef char int8_t; + #elif defined(__GNUC__) + typedef int __attribute__((__mode__(__DI__))) int64_t; + typedef unsigned int __attribute__((__mode__(__DI__))) uint64_t; + typedef unsigned int uint32_t; + typedef int int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef signed char int8_t; + #elif defined(UNIX_LP64) + + /* Use LP64 programming model from C_FLAGS for integer width declarations */ + + typedef unsigned long uint64_t; + typedef long int64_t; + typedef unsigned int uint32_t; + typedef int int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef char int8_t; + #else + + /* Assume P64 programming model from C_FLAGS for integer width declarations */ + + typedef unsigned long long uint64_t __attribute__((aligned (8))); + typedef long long int64_t __attribute__((aligned (8))); + typedef unsigned int uint32_t; + typedef int int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef char int8_t; + #endif + typedef uint64_t uintptr_t; + typedef int64_t intptr_t; +#else + #include +#endif + +// +// Basic EFI types of various widths +// + +#include + +typedef wchar_t CHAR16; +#define WCHAR CHAR16 + +typedef uint64_t UINT64; +typedef int64_t INT64; + +#ifndef _BASETSD_H_ + typedef uint32_t UINT32; + typedef int32_t INT32; +#endif + +typedef uint16_t UINT16; +typedef int16_t INT16; + +typedef uint8_t UINT8; +typedef char CHAR8; +typedef int8_t INT8; + +#undef VOID +typedef void VOID; + + +typedef int64_t INTN; +typedef uint64_t UINTN; + +#ifdef EFI_NT_EMULATOR + #define POST_CODE(_Data) +#else + #ifdef EFI_DEBUG +#define POST_CODE(_Data) __asm mov eax,(_Data) __asm out 0x80,al + #else + #define POST_CODE(_Data) + #endif +#endif + +#define EFIERR(a) (0x8000000000000000 | a) +#define EFI_ERROR_MASK 0x8000000000000000 +#define EFIERR_OEM(a) (0xc000000000000000 | a) + + +#define BAD_POINTER 0xFBFBFBFBFBFBFBFB +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF + +#ifdef EFI_NT_EMULATOR + #define BREAKPOINT() __asm { int 3 } +#else + #define BREAKPOINT() while (TRUE); // Make it hang on Bios[Dbg]32 +#endif + +// +// Pointers must be aligned to these address to function +// + +#define MIN_ALIGNMENT_SIZE 4 + +#define ALIGN_VARIABLE(Value ,Adjustment) \ + (UINTN)Adjustment = 0; \ + if((UINTN)Value % MIN_ALIGNMENT_SIZE) \ + (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \ + Value = (UINTN)Value + (UINTN)Adjustment + + +// +// Define macros to build data structure signatures from characters. +// + +#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8)) +#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16)) +#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32)) +// +// To export & import functions in the EFI emulator environment +// + +#ifdef EFI_NT_EMULATOR + #define EXPORTAPI __declspec( dllexport ) +#else + #define EXPORTAPI +#endif + + +// +// EFIAPI - prototype calling convention for EFI function pointers +// BOOTSERVICE - prototype for implementation of a boot service interface +// RUNTIMESERVICE - prototype for implementation of a runtime service interface +// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service +// RUNTIME_CODE - pragma macro for declaring runtime code +// + +#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options + #ifdef _MSC_EXTENSIONS + #define EFIAPI __cdecl // Force C calling convention for Microsoft C compiler + #elif defined(HAVE_USE_MS_ABI) + // Force amd64/ms calling conventions. + #define EFIAPI __attribute__((ms_abi)) + #else + #define EFIAPI // Substitute expresion to force C calling convention + #endif +#endif + +#define BOOTSERVICE +//#define RUNTIMESERVICE(proto,a) alloc_text("rtcode",a); proto a +//#define RUNTIMEFUNCTION(proto,a) alloc_text("rtcode",a); proto a +#define RUNTIMESERVICE +#define RUNTIMEFUNCTION + + +#define RUNTIME_CODE(a) alloc_text("rtcode", a) +#define BEGIN_RUNTIME_DATA() data_seg("rtdata") +#define END_RUNTIME_DATA() data_seg("") + +#define VOLATILE volatile + +#define MEMORY_FENCE() + +#ifdef EFI_NT_EMULATOR + +// +// To help ensure proper coding of integrated drivers, they are +// compiled as DLLs. In NT they require a dll init entry pointer. +// The macro puts a stub entry point into the DLL so it will load. +// + +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + UINTN \ + __stdcall \ + _DllMainCRTStartup ( \ + UINTN Inst, \ + UINTN reason_for_call, \ + VOID* rserved \ + ) \ + { \ + return 1; \ + } \ + \ + int \ + EXPORTAPI \ + __cdecl \ + InitializeDriver ( \ + void* ImageHandle, \ + void* SystemTable \ + ) \ + { \ + return InitFunction(ImageHandle, SystemTable); \ + } + + + #define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, NULL) + +#else // EFI_NT_EMULATOR + +// +// When build similiar to FW, then link everything together as +// one big module. For the MSVC toolchain, we simply tell the +// linker what our driver init function is using /ENTRY. +// +#if defined(_MSC_EXTENSIONS) + #define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + __pragma(comment(linker, "/ENTRY:" # InitFunction)) +#else + #define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + UINTN \ + InitializeDriver ( \ + VOID* ImageHandle, \ + VOID* SystemTable \ + ) \ + { \ + return InitFunction(ImageHandle, \ + SystemTable); \ + } \ + \ + EFI_STATUS efi_main( \ + EFI_HANDLE image, \ + EFI_SYSTEM_TABLE* systab \ + ) __attribute__((weak, \ + alias ("InitializeDriver"))); +#endif + + #define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, entry) + +#endif // EFI_NT_EMULATOR + +// +// Some compilers don't support the forward reference construct: +// typedef struct XXXXX +// +// The following macro provide a workaround for such cases. +// +#ifdef NO_INTERFACE_DECL +#define INTERFACE_DECL(x) +#else +#if defined(__GNUC__) || defined(_MSC_EXTENSIONS) +#define INTERFACE_DECL(x) struct x +#else +#define INTERFACE_DECL(x) typedef struct x +#endif +#endif + +/* for x86_64, EFI_FUNCTION_WRAPPER must be defined */ +#if defined(HAVE_USE_MS_ABI) +#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__) +#else +/* + Credits for macro-magic: + https://groups.google.com/forum/?fromgroups#!topic/comp.std.c/d-6Mj5Lko_s + http://efesx.com/2010/08/31/overloading-macros/ +*/ +#define __VA_NARG__(...) \ + __VA_NARG_(_0, ## __VA_ARGS__, __RSEQ_N()) +#define __VA_NARG_(...) \ + __VA_ARG_N(__VA_ARGS__) +#define __VA_ARG_N( \ + _0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,N,...) N +#define __RSEQ_N() \ + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 + +#define __VA_ARG_NSUFFIX__(prefix,...) \ + __VA_ARG_NSUFFIX_N(prefix, __VA_NARG__(__VA_ARGS__)) +#define __VA_ARG_NSUFFIX_N(prefix,nargs) \ + __VA_ARG_NSUFFIX_N_(prefix, nargs) +#define __VA_ARG_NSUFFIX_N_(prefix,nargs) \ + prefix ## nargs + +/* Prototypes of EFI cdecl -> stdcall trampolines */ +UINT64 efi_call0(void* func); +UINT64 efi_call1(void* func, UINT64 arg1); +UINT64 efi_call2(void* func, UINT64 arg1, UINT64 arg2); +UINT64 efi_call3(void* func, UINT64 arg1, UINT64 arg2, UINT64 arg3); +UINT64 efi_call4(void* func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4); +UINT64 efi_call5(void* func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5); +UINT64 efi_call6(void* func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5, UINT64 arg6); +UINT64 efi_call7(void* func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7); +UINT64 efi_call8(void* func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7, + UINT64 arg8); +UINT64 efi_call9(void* func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7, + UINT64 arg8, UINT64 arg9); +UINT64 efi_call10(void* func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7, + UINT64 arg8, UINT64 arg9, UINT64 arg10); + +/* Front-ends to efi_callX to avoid compiler warnings */ +#define _cast64_efi_call0(f) \ + efi_call0(f) +#define _cast64_efi_call1(f,a1) \ + efi_call1(f, (UINT64)(a1)) +#define _cast64_efi_call2(f,a1,a2) \ + efi_call2(f, (UINT64)(a1), (UINT64)(a2)) +#define _cast64_efi_call3(f,a1,a2,a3) \ + efi_call3(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3)) +#define _cast64_efi_call4(f,a1,a2,a3,a4) \ + efi_call4(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4)) +#define _cast64_efi_call5(f,a1,a2,a3,a4,a5) \ + efi_call5(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5)) +#define _cast64_efi_call6(f,a1,a2,a3,a4,a5,a6) \ + efi_call6(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5), (UINT64)(a6)) +#define _cast64_efi_call7(f,a1,a2,a3,a4,a5,a6,a7) \ + efi_call7(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5), (UINT64)(a6), (UINT64)(a7)) +#define _cast64_efi_call8(f,a1,a2,a3,a4,a5,a6,a7,a8) \ + efi_call8(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8)) +#define _cast64_efi_call9(f,a1,a2,a3,a4,a5,a6,a7,a8,a9) \ + efi_call9(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8), \ + (UINT64)(a9)) +#define _cast64_efi_call10(f,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) \ + efi_call10(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8), \ + (UINT64)(a9), (UINT64)(a10)) + +/* main wrapper (va_num ignored) */ +#define uefi_call_wrapper(func,va_num,...) \ + __VA_ARG_NSUFFIX__(_cast64_efi_call, __VA_ARGS__) (func , ##__VA_ARGS__) + +#endif + +#if defined(HAVE_USE_MS_ABI) && !defined(_MSC_EXTENSIONS) + #define EFI_FUNCTION __attribute__((ms_abi)) +#else + #define EFI_FUNCTION +#endif + +#ifdef _MSC_EXTENSIONS +#pragma warning ( disable : 4731 ) // Suppress warnings about modification of EBP +#endif + +#endif diff --git a/code/boot/include/x86_64/efilibplat.h b/code/boot/include/x86_64/efilibplat.h new file mode 100644 index 0000000..0173875 --- /dev/null +++ b/code/boot/include/x86_64/efilibplat.h @@ -0,0 +1,26 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efilibplat.h + +Abstract: + + EFI to compile bindings + + + + +Revision History + +--*/ + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE* SystemTable + ); + + diff --git a/code/boot/include/x86_64/efisetjmp_arch.h b/code/boot/include/x86_64/efisetjmp_arch.h new file mode 100644 index 0000000..9657514 --- /dev/null +++ b/code/boot/include/x86_64/efisetjmp_arch.h @@ -0,0 +1,22 @@ +#ifndef GNU_EFI_X86_64_SETJMP_H +#define GNU_EFI_X86_64_SETJMP_H + +#define JMPBUF_ALIGN 8 + +typedef struct { + UINT64 Rbx; + UINT64 Rsp; + UINT64 Rbp; + + UINT64 Rdi; + UINT64 Rsi; + UINT64 R12; + UINT64 R13; + UINT64 R14; + UINT64 R15; + UINT64 Rip; + UINT64 MxCsr; + UINT8 XmmBuffer[160]; // XMM6 - XMM15 +} EFI_ALIGN(JMPBUF_ALIGN) jmp_buf[1]; + +#endif /* GNU_EFI_X86_64_SETJMP_H */ diff --git a/code/boot/include/x86_64/pe.h b/code/boot/include/x86_64/pe.h new file mode 100644 index 0000000..05f7851 --- /dev/null +++ b/code/boot/include/x86_64/pe.h @@ -0,0 +1,595 @@ +/* + PE32+ header file + */ +#ifndef _PE_H +#define _PE_H + +#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ +#define IMAGE_OS2_SIGNATURE 0x454E // NE +#define IMAGE_OS2_SIGNATURE_LE 0x454C // LE +#define IMAGE_NT_SIGNATURE 0x00004550 // PE00 +#define IMAGE_EDOS_SIGNATURE 0x44454550 // PEED + + +typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header + UINT16 e_magic; // Magic number + UINT16 e_cblp; // Bytes on last page of file + UINT16 e_cp; // Pages in file + UINT16 e_crlc; // Relocations + UINT16 e_cparhdr; // Size of header in paragraphs + UINT16 e_minalloc; // Minimum extra paragraphs needed + UINT16 e_maxalloc; // Maximum extra paragraphs needed + UINT16 e_ss; // Initial (relative) SS value + UINT16 e_sp; // Initial SP value + UINT16 e_csum; // Checksum + UINT16 e_ip; // Initial IP value + UINT16 e_cs; // Initial (relative) CS value + UINT16 e_lfarlc; // File address of relocation table + UINT16 e_ovno; // Overlay number + UINT16 e_res[4]; // Reserved words + UINT16 e_oemid; // OEM identifier (for e_oeminfo) + UINT16 e_oeminfo; // OEM information; e_oemid specific + UINT16 e_res2[10]; // Reserved words + UINT32 e_lfanew; // File address of new exe header + } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; + +typedef struct _IMAGE_OS2_HEADER { // OS/2 .EXE header + UINT16 ne_magic; // Magic number + UINT8 ne_ver; // Version number + UINT8 ne_rev; // Revision number + UINT16 ne_enttab; // Offset of Entry Table + UINT16 ne_cbenttab; // Number of bytes in Entry Table + UINT32 ne_crc; // Checksum of whole file + UINT16 ne_flags; // Flag UINT16 + UINT16 ne_autodata; // Automatic data segment number + UINT16 ne_heap; // Initial heap allocation + UINT16 ne_stack; // Initial stack allocation + UINT32 ne_csip; // Initial CS:IP setting + UINT32 ne_sssp; // Initial SS:SP setting + UINT16 ne_cseg; // Count of file segments + UINT16 ne_cmod; // Entries in Module Reference Table + UINT16 ne_cbnrestab; // Size of non-resident name table + UINT16 ne_segtab; // Offset of Segment Table + UINT16 ne_rsrctab; // Offset of Resource Table + UINT16 ne_restab; // Offset of resident name table + UINT16 ne_modtab; // Offset of Module Reference Table + UINT16 ne_imptab; // Offset of Imported Names Table + UINT32 ne_nrestab; // Offset of Non-resident Names Table + UINT16 ne_cmovent; // Count of movable entries + UINT16 ne_align; // Segment alignment shift count + UINT16 ne_cres; // Count of resource segments + UINT8 ne_exetyp; // Target Operating system + UINT8 ne_flagsothers; // Other .EXE flags + UINT16 ne_pretthunks; // offset to return thunks + UINT16 ne_psegrefbytes; // offset to segment ref. bytes + UINT16 ne_swaparea; // Minimum code swap area size + UINT16 ne_expver; // Expected Windows version number + } IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER; + +// +// File header format. +// + +typedef struct _IMAGE_FILE_HEADER { + UINT16 Machine; + UINT16 NumberOfSections; + UINT32 TimeDateStamp; + UINT32 PointerToSymbolTable; + UINT32 NumberOfSymbols; + UINT16 SizeOfOptionalHeader; + UINT16 Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; + +#define IMAGE_SIZEOF_FILE_HEADER 20 + +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references). +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file. +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed. +#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file +#define IMAGE_FILE_SYSTEM 0x1000 // System File. +#define IMAGE_FILE_DLL 0x2000 // File is a DLL. +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed. + +#define IMAGE_FILE_MACHINE_UNKNOWN 0 +#define IMAGE_FILE_MACHINE_I386 0x14c // Intel 386. +#define IMAGE_FILE_MACHINE_R3000 0x162 // MIPS little-endian, 0540 big-endian +#define IMAGE_FILE_MACHINE_R4000 0x166 // MIPS little-endian +#define IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP +#define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED 0x1c2 // Arm/Thumb +#define IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM PowerPC Little-Endian +#define IMAGE_FILE_MACHINE_IA64 0x200 // IA-64 +#define IMAGE_FILE_MACHINE_TAHOE 0x7cc // Intel EM machine +#define IMAGE_FILE_MACHINE_EBC 0xebc // EFI Byte Code +#define IMAGE_FILE_MACHINE_X64 0x8664 // x86_64 +// +// Directory format. +// + +typedef struct _IMAGE_DATA_DIRECTORY { + UINT32 VirtualAddress; + UINT32 Size; +} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 + +// +// Optional header format. +// + +typedef struct _IMAGE_OPTIONAL_HEADER { + // + // Standard fields. + // + + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + UINT32 BaseOfData; + + // + // NT additional fields. + // + + UINT32 ImageBase; + UINT32 SectionAlignment; + UINT32 FileAlignment; + UINT16 MajorOperatingSystemVersion; + UINT16 MinorOperatingSystemVersion; + UINT16 MajorImageVersion; + UINT16 MinorImageVersion; + UINT16 MajorSubsystemVersion; + UINT16 MinorSubsystemVersion; + UINT32 Reserved1; + UINT32 SizeOfImage; + UINT32 SizeOfHeaders; + UINT32 CheckSum; + UINT16 Subsystem; + UINT16 DllCharacteristics; + UINT32 SizeOfStackReserve; + UINT32 SizeOfStackCommit; + UINT32 SizeOfHeapReserve; + UINT32 SizeOfHeapCommit; + UINT32 LoaderFlags; + UINT32 NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER; + +typedef struct _IMAGE_ROM_OPTIONAL_HEADER { + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + UINT32 BaseOfData; + UINT32 BaseOfBss; + UINT32 GprMask; + UINT32 CprMask[4]; + UINT32 GpValue; +} IMAGE_ROM_OPTIONAL_HEADER, *PIMAGE_ROM_OPTIONAL_HEADER; + +#define IMAGE_SIZEOF_ROM_OPTIONAL_HEADER 56 +#define IMAGE_SIZEOF_STD_OPTIONAL_HEADER 28 +#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER 224 + +#define IMAGE_NT_OPTIONAL_HDR_MAGIC 0x10b +#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107 + +typedef struct _IMAGE_NT_HEADERS { + UINT32 Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER OptionalHeader; +} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS; + +typedef struct _IMAGE_ROM_HEADERS { + IMAGE_FILE_HEADER FileHeader; + IMAGE_ROM_OPTIONAL_HEADER OptionalHeader; +} IMAGE_ROM_HEADERS, *PIMAGE_ROM_HEADERS; + +#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) \ + ((UINT32)ntheader + \ + FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + \ + ((PIMAGE_NT_HEADERS)(ntheader))->FileHeader.SizeOfOptionalHeader \ + )) + + +// Subsystem Values + +#define IMAGE_SUBSYSTEM_UNKNOWN 0 // Unknown subsystem. +#define IMAGE_SUBSYSTEM_NATIVE 1 // Image doesn't require a subsystem. +#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem. +#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem. +#define IMAGE_SUBSYSTEM_OS2_CUI 5 // image runs in the OS/2 character subsystem. +#define IMAGE_SUBSYSTEM_POSIX_CUI 7 // image run in the Posix character subsystem. + + +// Directory Entries + +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory +#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory +#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table +#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory +#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // Description String +#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // Machine Value (MIPS GP) +#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory +#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory + +// +// Section header format. +// + +#define IMAGE_SIZEOF_SHORT_NAME 8 + +typedef struct _IMAGE_SECTION_HEADER { + UINT8 Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + UINT32 PhysicalAddress; + UINT32 VirtualSize; + } Misc; + UINT32 VirtualAddress; + UINT32 SizeOfRawData; + UINT32 PointerToRawData; + UINT32 PointerToRelocations; + UINT32 PointerToLinenumbers; + UINT16 NumberOfRelocations; + UINT16 NumberOfLinenumbers; + UINT32 Characteristics; +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; + +#define IMAGE_SIZEOF_SECTION_HEADER 40 + +#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved. + +#define IMAGE_SCN_CNT_CODE 0x00000020 // Section contains code. +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // Section contains initialized data. +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 // Section contains uninitialized data. + +#define IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved. +#define IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information. +#define IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image. +#define IMAGE_SCN_LNK_COMDAT 0x00001000 // Section contents comdat. + +#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 // +#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 // +#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 // +#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 // +#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 // Default alignment if no others are specified. +#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 // +#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 // + +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // Section can be discarded. +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 // Section is not cachable. +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 // Section is not pageable. +#define IMAGE_SCN_MEM_SHARED 0x10000000 // Section is shareable. +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable. +#define IMAGE_SCN_MEM_READ 0x40000000 // Section is readable. +#define IMAGE_SCN_MEM_WRITE 0x80000000 // Section is writeable. + +// +// Symbol format. +// + + +#define IMAGE_SIZEOF_SYMBOL 18 + +// +// Section values. +// +// Symbols have a section number of the section in which they are +// defined. Otherwise, section numbers have the following meanings: +// + +#define IMAGE_SYM_UNDEFINED (UINT16)0 // Symbol is undefined or is common. +#define IMAGE_SYM_ABSOLUTE (UINT16)-1 // Symbol is an absolute value. +#define IMAGE_SYM_DEBUG (UINT16)-2 // Symbol is a special debug item. + +// +// Type (fundamental) values. +// + +#define IMAGE_SYM_TYPE_NULL 0 // no type. +#define IMAGE_SYM_TYPE_VOID 1 // +#define IMAGE_SYM_TYPE_CHAR 2 // type character. +#define IMAGE_SYM_TYPE_SHORT 3 // type short integer. +#define IMAGE_SYM_TYPE_INT 4 // +#define IMAGE_SYM_TYPE_LONG 5 // +#define IMAGE_SYM_TYPE_FLOAT 6 // +#define IMAGE_SYM_TYPE_DOUBLE 7 // +#define IMAGE_SYM_TYPE_STRUCT 8 // +#define IMAGE_SYM_TYPE_UNION 9 // +#define IMAGE_SYM_TYPE_ENUM 10 // enumeration. +#define IMAGE_SYM_TYPE_MOE 11 // member of enumeration. +#define IMAGE_SYM_TYPE_BYTE 12 // +#define IMAGE_SYM_TYPE_WORD 13 // +#define IMAGE_SYM_TYPE_UINT 14 // +#define IMAGE_SYM_TYPE_DWORD 15 // + +// +// Type (derived) values. +// + +#define IMAGE_SYM_DTYPE_NULL 0 // no derived type. +#define IMAGE_SYM_DTYPE_POINTER 1 // pointer. +#define IMAGE_SYM_DTYPE_FUNCTION 2 // function. +#define IMAGE_SYM_DTYPE_ARRAY 3 // array. + +// +// Storage classes. +// + +#define IMAGE_SYM_CLASS_END_OF_FUNCTION (BYTE )-1 +#define IMAGE_SYM_CLASS_NULL 0 +#define IMAGE_SYM_CLASS_AUTOMATIC 1 +#define IMAGE_SYM_CLASS_EXTERNAL 2 +#define IMAGE_SYM_CLASS_STATIC 3 +#define IMAGE_SYM_CLASS_REGISTER 4 +#define IMAGE_SYM_CLASS_EXTERNAL_DEF 5 +#define IMAGE_SYM_CLASS_LABEL 6 +#define IMAGE_SYM_CLASS_UNDEFINED_LABEL 7 +#define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8 +#define IMAGE_SYM_CLASS_ARGUMENT 9 +#define IMAGE_SYM_CLASS_STRUCT_TAG 10 +#define IMAGE_SYM_CLASS_MEMBER_OF_UNION 11 +#define IMAGE_SYM_CLASS_UNION_TAG 12 +#define IMAGE_SYM_CLASS_TYPE_DEFINITION 13 +#define IMAGE_SYM_CLASS_UNDEFINED_STATIC 14 +#define IMAGE_SYM_CLASS_ENUM_TAG 15 +#define IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16 +#define IMAGE_SYM_CLASS_REGISTER_PARAM 17 +#define IMAGE_SYM_CLASS_BIT_FIELD 18 +#define IMAGE_SYM_CLASS_BLOCK 100 +#define IMAGE_SYM_CLASS_FUNCTION 101 +#define IMAGE_SYM_CLASS_END_OF_STRUCT 102 +#define IMAGE_SYM_CLASS_FILE 103 +// new +#define IMAGE_SYM_CLASS_SECTION 104 +#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 105 + +// type packing constants + +#define N_BTMASK 017 +#define N_TMASK 060 +#define N_TMASK1 0300 +#define N_TMASK2 0360 +#define N_BTSHFT 4 +#define N_TSHIFT 2 + +// MACROS + +// +// Communal selection types. +// + +#define IMAGE_COMDAT_SELECT_NODUPLICATES 1 +#define IMAGE_COMDAT_SELECT_ANY 2 +#define IMAGE_COMDAT_SELECT_SAME_SIZE 3 +#define IMAGE_COMDAT_SELECT_EXACT_MATCH 4 +#define IMAGE_COMDAT_SELECT_ASSOCIATIVE 5 + +#define IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1 +#define IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2 +#define IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3 + + +// +// Relocation format. +// + +typedef struct _IMAGE_RELOCATION { + UINT32 VirtualAddress; + UINT32 SymbolTableIndex; + UINT16 Type; +} IMAGE_RELOCATION; + +#define IMAGE_SIZEOF_RELOCATION 10 + +// +// I386 relocation types. +// + +#define IMAGE_REL_I386_ABSOLUTE 0 // Reference is absolute, no relocation is necessary +#define IMAGE_REL_I386_DIR16 01 // Direct 16-bit reference to the symbols virtual address +#define IMAGE_REL_I386_REL16 02 // PC-relative 16-bit reference to the symbols virtual address +#define IMAGE_REL_I386_DIR32 06 // Direct 32-bit reference to the symbols virtual address +#define IMAGE_REL_I386_DIR32NB 07 // Direct 32-bit reference to the symbols virtual address, base not included +#define IMAGE_REL_I386_SEG12 011 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address +#define IMAGE_REL_I386_SECTION 012 +#define IMAGE_REL_I386_SECREL 013 +#define IMAGE_REL_I386_REL32 024 // PC-relative 32-bit reference to the symbols virtual address + +// +// MIPS relocation types. +// + +#define IMAGE_REL_MIPS_ABSOLUTE 0 // Reference is absolute, no relocation is necessary +#define IMAGE_REL_MIPS_REFHALF 01 +#define IMAGE_REL_MIPS_REFWORD 02 +#define IMAGE_REL_MIPS_JMPADDR 03 +#define IMAGE_REL_MIPS_REFHI 04 +#define IMAGE_REL_MIPS_REFLO 05 +#define IMAGE_REL_MIPS_GPREL 06 +#define IMAGE_REL_MIPS_LITERAL 07 +#define IMAGE_REL_MIPS_SECTION 012 +#define IMAGE_REL_MIPS_SECREL 013 +#define IMAGE_REL_MIPS_REFWORDNB 042 +#define IMAGE_REL_MIPS_PAIR 045 + +// +// Alpha Relocation types. +// + +#define IMAGE_REL_ALPHA_ABSOLUTE 0x0 +#define IMAGE_REL_ALPHA_REFLONG 0x1 +#define IMAGE_REL_ALPHA_REFQUAD 0x2 +#define IMAGE_REL_ALPHA_GPREL32 0x3 +#define IMAGE_REL_ALPHA_LITERAL 0x4 +#define IMAGE_REL_ALPHA_LITUSE 0x5 +#define IMAGE_REL_ALPHA_GPDISP 0x6 +#define IMAGE_REL_ALPHA_BRADDR 0x7 +#define IMAGE_REL_ALPHA_HINT 0x8 +#define IMAGE_REL_ALPHA_INLINE_REFLONG 0x9 +#define IMAGE_REL_ALPHA_REFHI 0xA +#define IMAGE_REL_ALPHA_REFLO 0xB +#define IMAGE_REL_ALPHA_PAIR 0xC +#define IMAGE_REL_ALPHA_MATCH 0xD +#define IMAGE_REL_ALPHA_SECTION 0xE +#define IMAGE_REL_ALPHA_SECREL 0xF +#define IMAGE_REL_ALPHA_REFLONGNB 0x10 + +// +// IBM PowerPC relocation types. +// + +#define IMAGE_REL_PPC_ABSOLUTE 0x0000 // NOP +#define IMAGE_REL_PPC_ADDR64 0x0001 // 64-bit address +#define IMAGE_REL_PPC_ADDR32 0x0002 // 32-bit address +#define IMAGE_REL_PPC_ADDR24 0x0003 // 26-bit address, shifted left 2 (branch absolute) +#define IMAGE_REL_PPC_ADDR16 0x0004 // 16-bit address +#define IMAGE_REL_PPC_ADDR14 0x0005 // 16-bit address, shifted left 2 (load doubleword) +#define IMAGE_REL_PPC_REL24 0x0006 // 26-bit PC-relative offset, shifted left 2 (branch relative) +#define IMAGE_REL_PPC_REL14 0x0007 // 16-bit PC-relative offset, shifted left 2 (br cond relative) +#define IMAGE_REL_PPC_TOCREL16 0x0008 // 16-bit offset from TOC base +#define IMAGE_REL_PPC_TOCREL14 0x0009 // 16-bit offset from TOC base, shifted left 2 (load doubleword) + +#define IMAGE_REL_PPC_ADDR32NB 0x000A // 32-bit addr w/o image base +#define IMAGE_REL_PPC_SECREL 0x000B // va of containing section (as in an image sectionhdr) +#define IMAGE_REL_PPC_SECTION 0x000C // sectionheader number +#define IMAGE_REL_PPC_IFGLUE 0x000D // substitute TOC restore instruction iff symbol is glue code +#define IMAGE_REL_PPC_IMGLUE 0x000E // symbol is glue code; virtual address is TOC restore instruction + +#define IMAGE_REL_PPC_TYPEMASK 0x00FF // mask to isolate above values in IMAGE_RELOCATION.Type + +// Flag bits in IMAGE_RELOCATION.TYPE + +#define IMAGE_REL_PPC_NEG 0x0100 // subtract reloc value rather than adding it +#define IMAGE_REL_PPC_BRTAKEN 0x0200 // fix branch prediction bit to predict branch taken +#define IMAGE_REL_PPC_BRNTAKEN 0x0400 // fix branch prediction bit to predict branch not taken +#define IMAGE_REL_PPC_TOCDEFN 0x0800 // toc slot defined in file (or, data in toc) + +// +// Based relocation format. +// + +typedef struct _IMAGE_BASE_RELOCATION { + UINT32 VirtualAddress; + UINT32 SizeOfBlock; +// UINT16 TypeOffset[1]; +} IMAGE_BASE_RELOCATION, *PIMAGE_BASE_RELOCATION; + +#define IMAGE_SIZEOF_BASE_RELOCATION 8 + +// +// Based relocation types. +// + +#define IMAGE_REL_BASED_ABSOLUTE 0 +#define IMAGE_REL_BASED_HIGH 1 +#define IMAGE_REL_BASED_LOW 2 +#define IMAGE_REL_BASED_HIGHLOW 3 +#define IMAGE_REL_BASED_HIGHADJ 4 +#define IMAGE_REL_BASED_MIPS_JMPADDR 5 +#define IMAGE_REL_BASED_IA64_IMM64 9 +#define IMAGE_REL_BASED_DIR64 10 + +// +// Line number format. +// + +typedef struct _IMAGE_LINENUMBER { + union { + UINT32 SymbolTableIndex; // Symbol table index of function name if Linenumber is 0. + UINT32 VirtualAddress; // Virtual address of line number. + } Type; + UINT16 Linenumber; // Line number. +} IMAGE_LINENUMBER; + +#define IMAGE_SIZEOF_LINENUMBER 6 + +// +// Archive format. +// + +#define IMAGE_ARCHIVE_START_SIZE 8 +#define IMAGE_ARCHIVE_START "!\n" +#define IMAGE_ARCHIVE_END "`\n" +#define IMAGE_ARCHIVE_PAD "\n" +#define IMAGE_ARCHIVE_LINKER_MEMBER "/ " +#define IMAGE_ARCHIVE_LONGNAMES_MEMBER "// " + +typedef struct _IMAGE_ARCHIVE_MEMBER_HEADER { + UINT8 Name[16]; // File member name - `/' terminated. + UINT8 Date[12]; // File member date - decimal. + UINT8 UserID[6]; // File member user id - decimal. + UINT8 GroupID[6]; // File member group id - decimal. + UINT8 Mode[8]; // File member mode - octal. + UINT8 Size[10]; // File member size - decimal. + UINT8 EndHeader[2]; // String to end header. +} IMAGE_ARCHIVE_MEMBER_HEADER, *PIMAGE_ARCHIVE_MEMBER_HEADER; + +#define IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60 + +// +// DLL support. +// + +// +// Export Format +// + +typedef struct _IMAGE_EXPORT_DIRECTORY { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT16 MajorVersion; + UINT16 MinorVersion; + UINT32 Name; + UINT32 Base; + UINT32 NumberOfFunctions; + UINT32 NumberOfNames; + UINT32* AddressOfFunctions; + UINT32* AddressOfNames; + UINT32* AddressOfNameOrdinals; +} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; + +// +// Import Format +// + +typedef struct _IMAGE_IMPORT_BY_NAME { + UINT16 Hint; + UINT8 Name[1]; +} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; + +typedef struct _IMAGE_THUNK_DATA { + union { + UINT32 Function; + UINT32 Ordinal; + PIMAGE_IMPORT_BY_NAME AddressOfData; + } u1; +} IMAGE_THUNK_DATA, *PIMAGE_THUNK_DATA; + +#define IMAGE_ORDINAL_FLAG 0x80000000 +#define IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG) != 0) +#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff) + +typedef struct _IMAGE_IMPORT_DESCRIPTOR { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT32 ForwarderChain; + UINT32 Name; + PIMAGE_THUNK_DATA FirstThunk; +} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR; + +#endif diff --git a/code/boot/main.c b/code/boot/main.c new file mode 100644 index 0000000..15db6e2 --- /dev/null +++ b/code/boot/main.c @@ -0,0 +1,808 @@ +// boot/main.c - UEFI bootloader +// +// Responsibilities (see design §5.2): +// 1. Parse boot.ini +// 2. Read drivers/drivers.ini +// 3. Load PE images (kernel.exe, hal.dll, syscall.dll, win32.dll, *.sys) +// 4. Validate PE checksums +// 5. Map images into the upper half of a new PML4 +// 6. Map all RAM as direct physical window at 0xFFFF880000000000 +// 7. Convert EFI memory map -> MEMORY_MAP +// 8. ExitBootServices +// 9. Set up minimal GDT/IDT, enable NXE, set CR3 +// 10. Fill BOOT_INFO and jump to KernelMain +// + +#include +#include +#include +int _fltused = 0; + +#include "../kernel/boot_info.h" +#include "../kernel/memory_map.h" +#include "ini_parser.h" + +#define KERNEL_VIRT_BASE 0xFFFF800000000000ULL +#define PHYS_MAP_BASE 0xFFFF880000000000ULL +#define PAGE_SIZE 4096ULL + +static int AsciiStrToUnicodeStrS(const char* Source, uint16_t* Dest, size_t DestMax) { + if (!Source || !Dest || !DestMax) return -1; + + for (size_t i = 0; i < DestMax; i++) { + if ((Dest[i] = (unsigned char)Source[i]) == '\0') return 0; + } + + Dest[DestMax - 1] = '\0'; + return -1; // Buffer too small +} + +int AsciiStrCpyS(char* Dest, size_t DestMax, const char* Source) { + if (!Dest || !Source || !DestMax) return -1; + + for (size_t i = 0; i < DestMax; i++) { + if ((Dest[i] = Source[i]) == '\0') return 0; + } + + Dest[DestMax - 1] = '\0'; // Ensure termination on truncation + return -1; +} + +int UnicodeStrToAsciiStrS(const uint16_t* Source, char* Dest, size_t DestMax) { + if (!Source || !Dest || !DestMax) return -1; + + for (size_t i = 0; i < DestMax; i++) { + // Narrowing: only taking the lower 8 bits + Dest[i] = (char)(Source[i] & 0xFF); + + if (Source[i] == 0) return 0; + } + + Dest[DestMax - 1] = '\0'; + return -1; +} + +// --------------------------------------------------------------------------- +// PE32+ checksum validation +// --------------------------------------------------------------------------- +static UINT32 ComputePeChecksum(const UINT8* buf, UINTN size) { + UINT64 checksum = 0; + const UINT16* words = (const UINT16 *)buf; + UINTN wordCount = size / 2; + + // Locate and zero the CheckSum field in the optional header. + UINT32 peOff = *(UINT32 *)(buf + 0x3C); + UINTN cksumOff = peOff + 4 + 20 + 64; // COFF hdr + optional hdr offset to CheckSum + UINT16 savedLo = words[cksumOff / 2]; + UINT16 savedHi = words[cksumOff / 2 + 1]; + ((UINT16 *)buf)[cksumOff / 2] = 0; + ((UINT16 *)buf)[cksumOff / 2 + 1] = 0; + + for (UINTN i = 0; i < wordCount; i++) { + checksum += words[i]; + if (checksum > 0xFFFF) checksum = (checksum & 0xFFFF) + (checksum >> 16); + } + if (size & 1) { checksum += buf[size - 1]; } + checksum = (checksum & 0xFFFF) + (checksum >> 16); + checksum += (UINT64)size; + + // Restore. + ((UINT16 *)buf)[cksumOff / 2] = savedLo; + ((UINT16 *)buf)[cksumOff / 2 + 1] = savedHi; + return (UINT32)checksum; +} + +// --------------------------------------------------------------------------- +// Page table helpers +// --------------------------------------------------------------------------- +static UINT64* AllocPage(EFI_PHYSICAL_ADDRESS* physOut) { + VOID* mem = NULL; + gBS->AllocatePages(AllocateAnyPages, EfiLoaderData, 1, (EFI_PHYSICAL_ADDRESS *)&mem); + gBS->SetMem(mem, PAGE_SIZE, 0); + if (physOut) *physOut = (EFI_PHYSICAL_ADDRESS)mem; // identity-mapped in UEFI + return (UINT64 *)mem; +} + +#define PML4_IDX(va) (((va) >> 39) & 0x1FF) +#define PDPT_IDX(va) (((va) >> 30) & 0x1FF) +#define PDT_IDX(va) (((va) >> 21) & 0x1FF) +#define PT_IDX(va) (((va) >> 12) & 0x1FF) + +static UINT64* gPml4; + +static void MapPage(UINT64 virt, UINT64 phys, UINT64 flags) { + UINT64* pml4e = &gPml4[PML4_IDX(virt)]; + if (!(*pml4e & 1)) { EFI_PHYSICAL_ADDRESS p; AllocPage(&p); *pml4e = p | 3; } + UINT64* pdpt = (UINT64 *)(*pml4e & ~0xFFFULL); + UINT64* pdpte = &pdpt[PDPT_IDX(virt)]; + if (!(*pdpte & 1)) { EFI_PHYSICAL_ADDRESS p; AllocPage(&p); *pdpte = p | 3; } + UINT64* pdt = (UINT64 *)(*pdpte & ~0xFFFULL); + UINT64* pdte = &pdt[PDT_IDX(virt)]; + if (!(*pdte & 1)) { EFI_PHYSICAL_ADDRESS p; AllocPage(&p); *pdte = p | 3; } + UINT64* pt = (UINT64 *)(*pdte & ~0xFFFULL); + pt[PT_IDX(virt)] = phys | flags; +} + +// --------------------------------------------------------------------------- +// File loading +// --------------------------------------------------------------------------- +static EFI_FILE_PROTOCOL* gRoot; + +static UINT8* LoadFile(CHAR16* path, UINTN* sizeOut) { + EFI_STATUS Status; + EFI_FILE_PROTOCOL* fh; + + // Open the file + Status = gRoot->Open(gRoot, &fh, path, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(Status)) return NULL; + + // Get the correct buffer size for EFI_FILE_INFO + EFI_FILE_INFO* info; + UINTN infoSz = 0; + + // This first call will fail but will return the required size in infoSz + fh->GetInfo(fh, &gEfiFileInfoGuid, &infoSz, NULL); + + // Allocate the buffer for the info struct + info = AllocatePool(infoSz); + if (info == NULL) { + fh->Close(fh); + return NULL; + } + + // Now actually get the info + Status = fh->GetInfo(fh, &gEfiFileInfoGuid, &infoSz, info); + if (EFI_ERROR(Status)) { + FreePool(info); + fh->Close(fh); + return NULL; + } + + // Allocate buffer for file content + UINTN sz = (UINTN)info->FileSize; + FreePool(info); // Don't need this anymore + + UINT8* buf = AllocatePool(sz); + if (buf == NULL) { + fh->Close(fh); + return NULL; + } + + // Read the file into the buffer + Status = fh->Read(fh, &sz, buf); + fh->Close(fh); + + if (EFI_ERROR(Status)) { + FreePool(buf); + return NULL; + } + + if (sizeOut) *sizeOut = sz; + return buf; +} + +// --------------------------------------------------------------------------- +// INI parsing state +// --------------------------------------------------------------------------- +typedef struct { + BOOT_INFO* bi; + CHAR16 drivers[32][64]; + int driverCount; + int debug; + char commandLine[64]; +} PARSE_STATE; + +static void BootIniCb(const char* section, const char* key, + const char* val, void* ud) { + PARSE_STATE* s = (PARSE_STATE *)ud; + // [kernel] debug = 1 + if (!AsciiStrCmp(section, "kernel") && !AsciiStrCmp(key, "debug")) + s->debug = (int)(val[0] - '0'); + // [init] commandline = hello.exe + else if (!AsciiStrCmp(section, "init") && !AsciiStrCmp(key, "commandline")) + AsciiStrCpyS(s->commandLine, 64, val); +} + +static void DriversIniCb(const char* section, const char* key, + const char* val, void* ud) { + (void)val; + PARSE_STATE* s = (PARSE_STATE *)ud; + if (!AsciiStrCmp(section, "boot") && s->driverCount < 32) { + AsciiStrToUnicodeStrS(key, s->drivers[s->driverCount], 64); + s->driverCount++; + } +} + +// --------------------------------------------------------------------------- +// EFI Memory Map -> MEMORY_MAP conversion +// --------------------------------------------------------------------------- +static void ConvertMemoryMap(MEMORY_MAP* out) { + UINTN mapSize = 0, descSz = 0, mapKey; UINT32 descVer; + gBS->GetMemoryMap(&mapSize, NULL, &mapKey, &descSz, &descVer); + mapSize += 8 * descSz; + EFI_MEMORY_DESCRIPTOR* efiMap = AllocatePool(mapSize); + gBS->GetMemoryMap(&mapSize, efiMap, &mapKey, &descSz, &descVer); + + out->Magic = MEMORY_MAP_MAGIC; + out->RegionCount = 0; + + EFI_MEMORY_DESCRIPTOR* desc = efiMap; + for (UINTN i = 0; i < mapSize / descSz && out->RegionCount < MEMORY_MAX_REGIONS; i++) { + MEMORY_TYPE type; + switch (desc->Type) { + case EfiConventionalMemory: type = MemoryUsable; break; + case EfiMemoryMappedIO: + case EfiMemoryMappedIOPortSpace: type = MemoryMappedIO; break; + case EfiLoaderCode: + case EfiLoaderData: type = MemoryBootloader; break; + case EfiRuntimeServicesCode: + case EfiRuntimeServicesData: + default: type = MemoryReserved; break; + } + MEMORY_REGION* r = &out->Regions[out->RegionCount++]; + r->Base = desc->PhysicalStart; + r->Length = desc->NumberOfPages * PAGE_SIZE; + r->Type = type; + r->_pad = 0; + desc = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)desc + descSz); + } + FreePool(efiMap); +} + +#pragma pack(push, 1) +typedef struct { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT16 MajorVersion; + UINT16 MinorVersion; + UINT32 Name; + UINT32 Base; + UINT32 NumberOfFunctions; + UINT32 NumberOfNames; + UINT32 AddressOfFunctions; // RVA to array of RVAs + UINT32 AddressOfNames; // RVA to array of RVAs + UINT32 AddressOfNameOrdinals; // RVA to array of UINT16 +} IMAGE_EXPORT_DIRECTORY; + +typedef struct { + union { + UINT32 Characteristics; + UINT32 OriginalFirstThunk; // RVA to Import Lookup Table + } DUMMYUNIONNAME; + UINT32 TimeDateStamp; + UINT32 ForwarderChain; + UINT32 Name; // RVA to DLL Name + UINT32 FirstThunk; // RVA to IAT (Import Address Table) +} IMAGE_IMPORT_DESCRIPTOR; + +typedef struct { + union { + UINT64 ForwarderString; + UINT64 Function; + UINT64 Ordinal; + UINT64 AddressOfData; // RVA to IMAGE_IMPORT_BY_NAME + } u1; +} IMAGE_THUNK_DATA64; + +typedef struct { + UINT16 Hint; + CHAR8 Name[1]; +} IMAGE_IMPORT_BY_NAME; +#pragma pack(pop) + +#define IMAGE_ORDINAL_FLAG64 0x8000000000000000ULL + +// --- Essential PE Structures (if not in your headers) --- +#pragma pack(push, 1) +typedef struct { + UINT32 VirtualAddress; + UINT32 Size; +} IMAGE_DATA_DIRECTORY; + +typedef struct { + UINT32 VirtualAddress; + UINT32 SizeOfBlock; +} IMAGE_BASE_RELOCATION; + +typedef struct { + UINT8 Name[8]; + UINT32 VirtualSize; + UINT32 VirtualAddress; + UINT32 SizeOfRawData; + UINT32 PointerToRawData; + UINT32 PointerToRelocations; + UINT32 PointerToLinenumbers; + UINT16 NumberOfRelocations; + UINT16 NumberOfLinenumbers; + UINT32 Characteristics; +} IMAGE_SECTION_HEADER; +#pragma pack(pop) + +// --- The PE Loader --- +EFI_STATUS LoadPeImage(UINT8* rawFile, UINT64 virtDest, EFI_PHYSICAL_ADDRESS* outPhys) { + UINT32 peOff = *(UINT32*)(rawFile + 0x3C); + UINT8* ntHeaders = rawFile + peOff; + + // Validate Signature + if (*(UINT32*)ntHeaders != 0x00004550) { Print(L"no\n"); return EFI_INVALID_PARAMETER; } // "PE\0\0" + + UINT16 sizeOfOptHeader = *(UINT16*)(ntHeaders + 20); + UINT16 numSections = *(UINT16*)(ntHeaders + 6); + + // Offsets for PE32+ (64-bit) + UINT64 imageBase = *(UINT64*)(ntHeaders + 24 + 24); + UINT32 sizeOfImage = *(UINT32*)(ntHeaders + 24 + 56); + UINT32 sizeOfHeaders = *(UINT32*)(ntHeaders + 24 + 60); + + IMAGE_DATA_DIRECTORY* dataDirs = (IMAGE_DATA_DIRECTORY*)(ntHeaders + 24 + 112); + IMAGE_DATA_DIRECTORY* relocDir = &dataDirs[5]; + //IMAGE_DATA_DIRECTORY* importDir = &dataDirs[1]; + + // Allocate Physical Memory for the mapped image + UINTN pages = (sizeOfImage + PAGE_SIZE - 1) / PAGE_SIZE; + EFI_PHYSICAL_ADDRESS physBase; + gBS->AllocatePages(AllocateAnyPages, EfiLoaderData, pages, &physBase); + gBS->SetMem((VOID*)physBase, pages * PAGE_SIZE, 0); + + // Copy Headers + gBS->CopyMem((VOID*)physBase, rawFile, sizeOfHeaders); + + // Map Sections to their RVAs + IMAGE_SECTION_HEADER* sections = (IMAGE_SECTION_HEADER*)(ntHeaders + 24 + sizeOfOptHeader); + for (int i = 0; i < numSections; i++) { + if (sections[i].SizeOfRawData > 0) { + UINT8* dest = (UINT8*)physBase + sections[i].VirtualAddress; + UINT8* src = rawFile + sections[i].PointerToRawData; + gBS->CopyMem(dest, src, sections[i].SizeOfRawData); + } + } + + // Apply Base Relocations (.reloc) + // We calculate the delta between where it wants to be (ImageBase) + // and where it will actually be (virtDest). + UINT64 delta = virtDest - imageBase; + + if (delta != 0 && relocDir->Size > 0) { + IMAGE_BASE_RELOCATION* reloc = (IMAGE_BASE_RELOCATION*)((UINT8*)physBase + relocDir->VirtualAddress); + UINTN endOfRelocs = (UINTN)reloc + relocDir->Size; + + while ((UINTN)reloc < endOfRelocs && reloc->SizeOfBlock > 0) { + UINTN count = (reloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(UINT16); + UINT16* entries = (UINT16*)(reloc + 1); + + for (UINTN i = 0; i < count; i++) { + UINT16 type = entries[i] >> 12; + UINT16 offset = entries[i] & 0x0FFF; + + if (type == 10) { // IMAGE_REL_BASED_DIR64 + UINT64* patchAddr = (UINT64*)((UINT8*)physBase + reloc->VirtualAddress + offset); + *patchAddr += delta; + } + } + reloc = (IMAGE_BASE_RELOCATION*)((UINT8*)reloc + reloc->SizeOfBlock); + } + } + + *outPhys = physBase; + return EFI_SUCCESS; +} + +static UINT32 GetExportRva(UINT8* providerPhys, const char* funcName) { + UINT32 peOff = *(UINT32*)(providerPhys + 0x3C); + UINT8* ntHeaders = providerPhys + peOff; + + // Export Dir is index 0 in the DataDirectory array + UINT32 exportDirRva = *(UINT32*)(ntHeaders + 24 + 112); + if (!exportDirRva) return 0; // No exports! + + IMAGE_EXPORT_DIRECTORY* exports = (IMAGE_EXPORT_DIRECTORY*)(providerPhys + exportDirRva); + + UINT32* addrOfFunctions = (UINT32*)(providerPhys + exports->AddressOfFunctions); + UINT32* addrOfNames = (UINT32*)(providerPhys + exports->AddressOfNames); + UINT16* addrOfOrdinals = (UINT16*)(providerPhys + exports->AddressOfNameOrdinals); + + // Binary search is faster, but linear is fine for a bootloader + for (UINT32 i = 0; i < exports->NumberOfNames; i++) { + char* name = (char*)(providerPhys + addrOfNames[i]); + if (AsciiStrCmp(name, funcName) == 0) { + UINT16 ordinal = addrOfOrdinals[i]; + return addrOfFunctions[ordinal]; + } + } + return 0; // Function not found +} + +EFI_STATUS ResolveImports(UINT8* consumerPhys, UINT8* providerPhys, UINT64 providerVirt) { + UINT32 peOff = *(UINT32*)(consumerPhys + 0x3C); + UINT8* ntHeaders = consumerPhys + peOff; + + // Import Dir is index 1 in the DataDirectory array + UINT32 importDirRva = *(UINT32*)(ntHeaders + 24 + 112 + 8); + if (!importDirRva) return EFI_SUCCESS; // No imports to resolve + + IMAGE_IMPORT_DESCRIPTOR* importDesc = (IMAGE_IMPORT_DESCRIPTOR*)(consumerPhys + importDirRva); + + // Iterate through all imported DLLs + while (importDesc->Name != 0) { + char* dllName = (char*)(consumerPhys + importDesc->Name); + + // In a full OS, you'd loop through all loaded modules here. + // For now, we assume we are resolving hal.dll. + // Convert to lowercase or do a case-insensitive check if needed! + if (AsciiStrCmp(dllName, "hal.dll") == 0) { + + IMAGE_THUNK_DATA64* origFirstThunk = (IMAGE_THUNK_DATA64*)(consumerPhys + importDesc->DUMMYUNIONNAME.OriginalFirstThunk); + IMAGE_THUNK_DATA64* firstThunk = (IMAGE_THUNK_DATA64*)(consumerPhys + importDesc->FirstThunk); + + if (!importDesc->DUMMYUNIONNAME.OriginalFirstThunk) { + origFirstThunk = firstThunk; // Some compilers omit OriginalFirstThunk + } + + int i = 0; + while (origFirstThunk[i].u1.Function != 0) { + if (origFirstThunk[i].u1.Ordinal & IMAGE_ORDINAL_FLAG64) { + // Import by Ordinal (Usually you don't do this in modern kernels, but good to handle) + Print(L"Error: Ordinal imports not supported in basic loader.\n"); + return EFI_UNSUPPORTED; + } else { + // Import by Name + IMAGE_IMPORT_BY_NAME* importByName = (IMAGE_IMPORT_BY_NAME*)(consumerPhys + origFirstThunk[i].u1.AddressOfData); + char* funcName = (char*)importByName->Name; + + UINT32 funcRva = GetExportRva(providerPhys, funcName); + if (funcRva == 0) { + Print(L"FATAL: Unresolved import: %a\n", funcName); + return EFI_NOT_FOUND; + } + + // PATCH THE IAT! + // We write the final Virtual Address (Provider Base + Target RVA) + // into the physical memory of the consumer's IAT. + firstThunk[i].u1.Function = providerVirt + funcRva; + } + i++; + } + } + importDesc++; + } + + return EFI_SUCCESS; +} + +// --------------------------------------------------------------------------- +// UefiMain +// --------------------------------------------------------------------------- +EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { + InitializeLib(ImageHandle, SystemTable); + + // Open root filesystem on the device we actually booted from + EFI_LOADED_IMAGE_PROTOCOL* LoadedImage; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* fs; + + // Get the LoadedImage protocol for this application + EFI_STATUS Status = gBS->HandleProtocol( + ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **)&LoadedImage + ); + + if (EFI_ERROR(Status)) { + Print(L"Failed to get LoadedImage protocol\n"); + return Status; + } + + // Get the SimpleFileSystem protocol for the device we were loaded from + Status = gBS->HandleProtocol( + LoadedImage->DeviceHandle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID **)&fs + ); + + if (EFI_ERROR(Status)) { + Print(L"Failed to get SimpleFileSystem protocol on boot device\n"); + return Status; + } + + // Open the volume + Status = fs->OpenVolume(fs, &gRoot); + if (EFI_ERROR(Status)) { + Print(L"Failed to open root volume\n"); + return Status; + } + + Print(L"1\n"); + + // --- Parse boot.ini --- + UINTN sz; + UINT8* bootIniRaw = LoadFile(L"boot.ini", &sz); + PARSE_STATE ps = {0}; + if (bootIniRaw) { + char* txt = (char *)bootIniRaw; + txt[sz] = '\0'; + IniParse(txt, BootIniCb, &ps); + FreePool(bootIniRaw); + } + + Print(L"2\n"); + + // --- Parse drivers/drivers.ini --- + UINT8* drvIniRaw = LoadFile(L"drivers\\drivers.ini", &sz); + if (drvIniRaw) { + char* txt = (char *)drvIniRaw; + txt[sz] = '\0'; + IniParse(txt, DriversIniCb, &ps); + FreePool(drvIniRaw); + } + + Print(L"3\n"); + + BOOT_INFO* bi = AllocateZeroPool(sizeof(BOOT_INFO)); + bi->Magic = BOOT_INFO_MAGIC; + AsciiStrCpyS(bi->CommandLine, 64, ps.commandLine); + + // Build PML4. + gPml4 = AllocPage(NULL); + + // Current mapping cursor for upper half. + UINT64 virtCursor = KERNEL_VIRT_BASE; + + Print(L"4\n"); + + // --- Load and validate PE images --- + typedef struct { + CHAR16* path; + char name[32]; + UINT8* physBase; // Temporary storage for import resolution + UINT64 virtBase; + } MODULE_LOAD_INFO; + + MODULE_LOAD_INFO core[] = { + { L"kernel.exe", "kernel.exe", NULL, KERNEL_VIRT_BASE }, + { L"hal.dll", "hal.dll", NULL, 0 /* Calculated dynamically */ }, + }; + + for (int i = 0; i < 2; i++) { + Print(L"Loading %s...\n", core[i].path); + UINTN rawSize; + UINT8* rawBuf = LoadFile(core[i].path, &rawSize); + if (!rawBuf) { + Print(L"MISSING: %s\n", core[i].path); + while(1); + return EFI_NOT_FOUND; + } + + // Map sections and apply base relocations + EFI_PHYSICAL_ADDRESS physBase; + EFI_STATUS status = LoadPeImage(rawBuf, virtCursor, &physBase); + if (EFI_ERROR(status)) { + Print(L"PE Load Error: %r\n", status); + while(1); + return status; + } + + // Store locations for the Import Resolver + core[i].physBase = (UINT8*)physBase; + core[i].virtBase = virtCursor; + + // Map the pages into the new PML4 + // We need the SizeOfImage from the mapped headers + UINT32 peOff = *(UINT32*)(rawBuf + 0x3C); + UINT32 imgLen = *(UINT32*)(rawBuf + peOff + 4 + 20 + 56); // SizeOfImage + imgLen = (imgLen + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); + + for (UINT64 off = 0; off < imgLen; off += PAGE_SIZE) { + MapPage(virtCursor + off, physBase + off, 0x03 /* P|W */); + } + + // Fill BOOT_INFO + AsciiStrCpyS(bi->Modules[bi->ModuleCount].Name, 32, core[i].name); + bi->Modules[bi->ModuleCount].VirtBase = virtCursor; + bi->Modules[bi->ModuleCount].ImageSize = imgLen; + bi->ModuleCount++; + + // Increment cursor (1MB alignment for safety) + virtCursor = (virtCursor + imgLen + 0xFFFFF) & ~0xFFFFF; + + // We can free the raw file buffer now; sections are in physBase + FreePool(rawBuf); + } + + if (EFI_ERROR(ResolveImports(core[0].physBase, core[1].physBase, core[1].virtBase))) { + Print(L"Failed to resolve imports. System halted.\n"); + while(1); + } + + Print(L"5\n"); + + // Load driver .sys files. + for (int i = 0; i < ps.driverCount; i++) { + CHAR16 path[128]; + UnicodeSPrint(path, sizeof(path), L"drivers\\%s", ps.drivers[i]); + UINTN imgSz; + UINT8* buf = LoadFile(path, &imgSz); + if (!buf) { Print(L"Driver not found: %s\n", ps.drivers[i]); continue; } + + UINT32 stored = *(UINT32 *)(buf + *(UINT32 *)(buf + 0x3C) + 4 + 20 + 64); + UINT32 computed = ComputePeChecksum(buf, imgSz); + if (stored && computed != stored) { + Print(L"Checksum mismatch: %s\n", ps.drivers[i]); + FreePool(buf); continue; + } + + UINT32 peOff = *(UINT32 *)(buf + 0x3C); + UINT32 imgLen = *(UINT32 *)(buf + peOff + 4 + 20 + 56); + imgLen = (imgLen + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); + + EFI_PHYSICAL_ADDRESS phys; + EFI_STATUS status = LoadPeImage(buf, virtCursor, &phys); + if (EFI_ERROR(status)) { + Print(L"Driver PE load failed: %s\n", ps.drivers[i]); + FreePool(buf); + continue; + } + + UINT64 virt = virtCursor; + for (UINT64 off = 0; off < imgLen; off += PAGE_SIZE) + MapPage(virt + off, phys + off, 0x03); + + char name[32]; + UnicodeStrToAsciiStrS(ps.drivers[i], name, 32); + AsciiStrCpyS(bi->Modules[bi->ModuleCount].Name, 32, name); + bi->Modules[bi->ModuleCount].VirtBase = virt; + bi->Modules[bi->ModuleCount].ImageSize = imgLen; + bi->ModuleCount++; + virtCursor = (virtCursor + imgLen + 0xFFFFF) & ~0xFFFFF; + FreePool(buf); + } + + Print(L"6\n"); + + // Query GOP FIRST, before the GetMemoryMap loop + EFI_GRAPHICS_OUTPUT_PROTOCOL* gop; + if (!EFI_ERROR(gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&gop))) { + bi->FramebufferBase = gop->Mode->FrameBufferBase; + bi->FramebufferWidth = gop->Mode->Info->HorizontalResolution; + bi->FramebufferHeight = gop->Mode->Info->VerticalResolution; + bi->FramebufferStride = gop->Mode->Info->PixelsPerScanLine; + + // FrameBufferSize is a lie - EFI reports it as Width*Height*4. + // The ACTUAL consumed bytes are Stride*Height*4. + // Add one extra page as a safety margin. + UINT64 fbBytes = (UINT64)gop->Mode->Info->PixelsPerScanLine + * (UINT64)gop->Mode->Info->VerticalResolution + * 4 + PAGE_SIZE; + fbBytes = (fbBytes + PAGE_SIZE - 1) & ~(UINT64)(PAGE_SIZE - 1); + + for (UINT64 i = 0; i < fbBytes; i += PAGE_SIZE) { + UINT64 phys = gop->Mode->FrameBufferBase + i; + MapPage(PHYS_MAP_BASE + phys, phys, 0x13); // P|W|PCD (write-combined MMIO) + MapPage(phys, phys, 0x13); + } + } + + Print(L"7\n"); + + // --- Map physical RAM as direct window AND identity map --- + UINTN mapSize = 0, descSz = 0, mapKey; UINT32 descVer; + gBS->GetMemoryMap(&mapSize, NULL, &mapKey, &descSz, &descVer); + mapSize += 8 * descSz; + EFI_MEMORY_DESCRIPTOR* efiMap = AllocatePool(mapSize); + gBS->GetMemoryMap(&mapSize, efiMap, &mapKey, &descSz, &descVer); + { + for (UINTN i = 0; i < mapSize / descSz; i++) { + EFI_MEMORY_DESCRIPTOR* desc = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)efiMap + i * descSz); + + // Map everything except unusable memory to the Physical Window + if (desc->Type != EfiUnusableMemory && desc->Type != EfiMemoryMappedIOPortSpace) { + UINT64 start = desc->PhysicalStart; + UINT64 end = start + (desc->NumberOfPages * PAGE_SIZE); + + // CRITICAL FIX: Add 2 pages (8KB) of padding to the end of the region. + // This catches ACPI tables that cross page boundaries into unmapped + // memory because of buggy UEFI size reporting. + end += 2 * PAGE_SIZE; + + for (UINT64 phys = start; phys < end; phys += PAGE_SIZE) { + MapPage(phys, phys, 0x03); // Identity + MapPage(PHYS_MAP_BASE + phys, phys, 0x03); // High-half + } + } + } + } + FreePool(efiMap); + + // ------------------------------------------------------------------------- + // Explicitly Map Standard Architectural MMIO + // ------------------------------------------------------------------------- + // Motherboards frequently omit the APIC/IOAPIC/HPET from the UEFI memory map. + // We explicitly map the region from 0xFEC00000 up through 0xFEE00FFF + // to guarantee the HAL can access them via the physical window. + for (UINT64 phys = 0xFEC00000; phys < 0xFEE01000; phys += PAGE_SIZE) { + // In a production OS you'd use Cache-Disable flags (0x13 or 0x1B), + // but 0x03 is fine for hobby OS initialization before PAT is set up. + MapPage(phys, phys, 0x03); // Identity Map + MapPage(PHYS_MAP_BASE + phys, phys, 0x03); // Physical Window Map + } + + Print(L"8\n"); + + // --- Convert EFI memory map -> MEMORY_MAP --- + ConvertMemoryMap(&bi->MemoryMap); + + // --- Locate ACPI RSDP --- + // Define the standard UEFI ACPI GUIDs + EFI_GUID acpi2Guid = { 0x8868e871, 0xe4f1, 0x11d3, {0xbc, 0x22, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81} }; + EFI_GUID acpi1Guid = { 0xeb9d2d30, 0x2d88, 0x11d3, {0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} }; + + bi->RsdpPhysical = 0; + void* acpi1Table = NULL; + + // Search the UEFI Configuration Table + for (UINTN i = 0; i < SystemTable->NumberOfTableEntries; i++) { + EFI_GUID* vendorGuid = &SystemTable->ConfigurationTable[i].VendorGuid; + + // Check for ACPI 2.0 (Preferred) + if (vendorGuid->Data1 == acpi2Guid.Data1 && + vendorGuid->Data2 == acpi2Guid.Data2 && + vendorGuid->Data3 == acpi2Guid.Data3 && + vendorGuid->Data4[0] == acpi2Guid.Data4[0] && + vendorGuid->Data4[7] == acpi2Guid.Data4[7]) + { + bi->RsdpPhysical = (UINT64)SystemTable->ConfigurationTable[i].VendorTable; + break; // Found the best one, stop searching + } + + // Check for ACPI 1.0 (Fallback) + if (vendorGuid->Data1 == acpi1Guid.Data1 && + vendorGuid->Data2 == acpi1Guid.Data2 && + vendorGuid->Data3 == acpi1Guid.Data3 && + vendorGuid->Data4[0] == acpi1Guid.Data4[0] && + vendorGuid->Data4[7] == acpi1Guid.Data4[7]) + { + acpi1Table = SystemTable->ConfigurationTable[i].VendorTable; + } + } + + // Fallback to ACPI 1.0 if ACPI 2.0 wasn't found + if (bi->RsdpPhysical == 0 && acpi1Table != NULL) { + bi->RsdpPhysical = (UINT64)acpi1Table; + } + + // Print it out to verify the bootloader actually found it before launching the kernel + Print(L"Found RSDP at: 0x%llx\n", bi->RsdpPhysical); + + bi->PhysicalMapBase = PHYS_MAP_BASE; + bi->DebugEnabled = (UINT32)ps.debug; + + Print(L"9\n"); + + // --- ExitBootServices --- + gBS->GetMemoryMap(&mapSize, NULL, &mapKey, &descSz, &descVer); + gBS->ExitBootServices(ImageHandle, mapKey); + + // --- Load minimal GDT / IDT, enable NXE, set CR3 --- + // (These are inline since we have no runtime services after ExitBootServices.) + // GDT is set up by the kernel's KeInitializeGdt; we just need a valid one to + // reach KernelMain. The bootloader installed a flat 64-bit GDT earlier via + // EDK2, which is fine for the jump. + + // Enable NXE bit in EFER. + UINT64 efer = __readmsr(0xC0000080); + __writemsr(0xC0000080, efer | (1ULL << 11)); + + // Switch to our new PML4. + __writecr3((UINT64)gPml4); + + // --- Jump to KernelMain --- + typedef void (*KERNEL_ENTRY)(BOOT_INFO *); + KERNEL_ENTRY KernelMain = (KERNEL_ENTRY)bi->Modules[0].VirtBase; + + // The PE entry point is at VirtBase + AddressOfEntryPoint. + UINT32 epOff = *(UINT32 *)(bi->Modules[0].VirtBase + *(UINT32 *)(bi->Modules[0].VirtBase + 0x3C) + 4 + 20 + 16); + KernelMain = (KERNEL_ENTRY)(bi->Modules[0].VirtBase + epOff); + KernelMain(bi); + + // Never returns. + _disable(); __halt(); + return EFI_SUCCESS; +} diff --git a/code/drivers/ahci/ahci.c b/code/drivers/ahci/ahci.c new file mode 100644 index 0000000..2d3857f --- /dev/null +++ b/code/drivers/ahci/ahci.c @@ -0,0 +1,159 @@ +// ahci.c - AHCI SATA driver (basic PRDT, 1 slot, port 0) +#include +#include +#include +#include +#include +#include +#include + +// AHCI generic host control registers (BAR5 offsets). +#define AHCI_GHC 0x04 // Global Host Control +#define AHCI_PI 0x0C // Ports Implemented +#define AHCI_PORT_BASE(p) (0x100 + (p) * 0x80) + +// Port registers (relative to port base). +#define P_CLB 0x00 // Command List Base Address +#define P_FB 0x08 // FIS Base Address +#define P_IS 0x10 // Interrupt Status +#define P_CMD 0x18 // Command and Status +#define P_TFD 0x20 // Task File Data +#define P_SIG 0x24 // Signature +#define P_SSTS 0x28 // SATA Status +#define P_CI 0x38 // Command Issue + +#define CMD_ST (1 << 0) +#define CMD_FRE (1 << 4) + +#pragma pack(push, 1) +typedef struct { uint8_t cfl:5,a:1,w:1,p:1; uint8_t pmport:4,r:1,b:1,c:1,rsvd:1; uint16_t prdtl; + uint32_t prdbc; uint64_t ctba; uint32_t rsvd2[4]; } HBA_CMD_HEADER; +typedef struct { uint64_t dba; uint32_t rsvd; uint32_t dbc:22, rsvd2:9, i:1; } HBA_PRDT; +typedef struct { uint8_t cfis[64]; uint8_t acmd[16]; uint8_t rsvd[48]; HBA_PRDT prdt[1]; } HBA_CMD_TABLE; +#pragma pack(pop) + +static const HAL_API* gHal; +static volatile uint32_t* gAhci = (volatile uint32_t *)0; +static HBA_CMD_HEADER* gCmdList = (HBA_CMD_HEADER *)0; +static HBA_CMD_TABLE* gCmdTable = (HBA_CMD_TABLE *)0; +static uint8_t* gFisBuf = (uint8_t *)0; +static uint8_t gPort = 0; +static uint64_t gSectors = 0; + +static inline uint32_t PRd(uint32_t off) { + return *(volatile uint32_t *)((uint8_t *)gAhci + off); +} +static inline void PWr(uint32_t off, uint32_t v) { + *(volatile uint32_t *)((uint8_t *)gAhci + off) = v; +} +static inline uint32_t PortRd(uint8_t p, uint32_t off) { + return PRd(AHCI_PORT_BASE(p) + off); +} +static inline void PortWr(uint8_t p, uint32_t off, uint32_t v) { + PWr(AHCI_PORT_BASE(p) + off, v); +} + +static void AhciIssueCmd(uint8_t fis[20], void* buf, uint32_t bytes, int write) { + // Fill FIS in command table. + memcpy(gCmdTable->cfis, fis, 20); + gCmdTable->prdt[0].dba = MmGetPhysicalAddress((uintptr_t)buf); + gCmdTable->prdt[0].dbc = bytes - 1; + gCmdTable->prdt[0].i = 1; + + gCmdList[0].cfl = 5; // FIS length in DWORDs + gCmdList[0].w = write ? 1 : 0; + gCmdList[0].prdtl = 1; + gCmdList[0].prdbc = 0; + gCmdList[0].ctba = MmGetPhysicalAddress((uintptr_t)gCmdTable); + + PortWr(gPort, P_CI, 1); + while (PortRd(gPort, P_CI) & 1) _mm_pause(); +} + +static KSTATUS AhciRead(uint64_t lba, uint32_t count, void* buf) { + uint8_t fis[20] = {0}; + fis[0] = 0x27; fis[1] = 0x80; // H2D, C=1 + fis[2] = 0x25; // READ DMA EXT + fis[4] = (uint8_t)lba; + fis[5] = (uint8_t)(lba >> 8); + fis[6] = (uint8_t)(lba >> 16); + fis[7] = 0x40; // LBA mode + fis[8] = (uint8_t)(lba >> 24); + fis[9] = (uint8_t)(lba >> 32); + fis[10]= (uint8_t)(lba >> 40); + fis[12]= (uint8_t)count; + fis[13]= (uint8_t)(count >> 8); + AhciIssueCmd(fis, buf, count * 512, 0); + return STATUS_SUCCESS; +} + +static KSTATUS AhciWrite(uint64_t lba, uint32_t count, const void* buf) { + uint8_t fis[20] = {0}; + fis[0] = 0x27; fis[1] = 0x80; + fis[2] = 0x35; // WRITE DMA EXT + fis[4] = (uint8_t)lba; + fis[5] = (uint8_t)(lba >> 8); + fis[6] = (uint8_t)(lba >> 16); + fis[7] = 0x40; + fis[8] = (uint8_t)(lba >> 24); + fis[9] = (uint8_t)(lba >> 32); + fis[10]= (uint8_t)(lba >> 40); + fis[12]= (uint8_t)count; + fis[13]= (uint8_t)(count >> 8); + AhciIssueCmd(fis, (void *)buf, count * 512, 1); + return STATUS_SUCCESS; +} + +KSTATUS DriverEntry(const HAL_API* hal) { + DbgPrint("AHCI: Init\n"); + gHal = hal; + uint8_t bus, dev, fn; + if (!hal->Pci.FindClass(0x01, 0x06, &bus, &dev, &fn)) + return STATUS_NOT_FOUND; // no AHCI controller + + // BAR5 = AHCI base address. + uint32_t bar5 = hal->Pci.ConfigRead32(bus, dev, fn, 0x24) & ~0xFU; + if (!bar5) return STATUS_NOT_FOUND; + + gAhci = (volatile uint32_t *)(gHal->PhysToVirt(bar5)); + + // Enable AHCI mode. + PWr(AHCI_GHC, PRd(AHCI_GHC) | (1 << 31)); + + // Find a port with a connected device. + uint32_t pi = PRd(AHCI_PI); + for (int p = 0; p < 32; p++) { + if (!(pi & (1 << p))) continue; + uint32_t ssts = PortRd((uint8_t)p, P_SSTS); + if ((ssts & 0xF) != 3) continue; // DET: device present + PHY + if (PortRd((uint8_t)p, P_SIG) != 0x00000101) continue; // SATA + gPort = (uint8_t)p; + goto found; + } + return STATUS_NOT_FOUND; +found: + // Allocate command list (1 header), FIS buffer, command table. + gCmdList = (HBA_CMD_HEADER *)MmAllocatePool(4096); + gFisBuf = (uint8_t *)MmAllocatePool(4096); + gCmdTable = (HBA_CMD_TABLE *)MmAllocatePool(4096); + if (!gCmdList || !gFisBuf || !gCmdTable) return STATUS_NO_MEMORY; + memset(gCmdList, 0, 4096); + memset(gFisBuf, 0, 4096); + memset(gCmdTable,0, 4096); + + PortWr(gPort, P_CLB, (uint32_t)(MmGetPhysicalAddress((uintptr_t)gCmdList))); + PortWr(gPort, P_FB, (uint32_t)(MmGetPhysicalAddress((uintptr_t)gFisBuf))); + PortWr(gPort, P_CMD, PortRd(gPort, P_CMD) | CMD_FRE | CMD_ST); + + // Identify to get sector count. + uint8_t fis[20] = {0}; + fis[0] = 0x27; fis[1] = 0x80; fis[2] = 0xEC; + uint16_t ident[256]; + memset(ident, 0, sizeof(ident)); + AhciIssueCmd(fis, ident, 512, 0); + gSectors = *(uint64_t *)(&ident[100]); + if (!gSectors) gSectors = ((uint32_t)ident[61] << 16) | ident[60]; + + DISK_DRIVER drv = { AhciRead, AhciWrite, gSectors }; + return IoRegisterDisk(1, &drv); // drive 1; drive 0 = IDE +} diff --git a/code/drivers/drivers.ini b/code/drivers/drivers.ini new file mode 100644 index 0000000..6c261fe --- /dev/null +++ b/code/drivers/drivers.ini @@ -0,0 +1,6 @@ +[boot] +ide.sys +fat32.sys + +[runtime] +usb.sys diff --git a/code/drivers/fat32/fat32.c b/code/drivers/fat32/fat32.c new file mode 100644 index 0000000..9937a4c --- /dev/null +++ b/code/drivers/fat32/fat32.c @@ -0,0 +1,591 @@ +// fat32.c - FAT32 filesystem driver +// Registers itself via IoRegisterFilesystem after finding a FAT32 partition. +// Supports read-only access; write support is not implemented. +#include +#include +#include +#include +#include +#include +#include +#include + +// --------------------------------------------------------------------------- +// On-disk structures +// --------------------------------------------------------------------------- +#pragma pack(push, 1) + +typedef struct { + uint8_t Jump[3]; + char OemId[8]; + uint16_t BytesPerSector; + uint8_t SectorsPerCluster; + uint16_t ReservedSectors; + uint8_t NumFats; + uint16_t RootEntryCount; // 0 for FAT32 + uint16_t TotalSectors16; + uint8_t MediaType; + uint16_t FatSize16; // 0 for FAT32 + uint16_t SectorsPerTrack; + uint16_t NumHeads; + uint32_t HiddenSectors; + uint32_t TotalSectors32; + // FAT32 extended BPB + uint32_t FatSize32; + uint16_t ExtFlags; + uint16_t FsVersion; + uint32_t RootCluster; + uint16_t FsInfoSector; + uint16_t BackupBootSector; + uint8_t Reserved[12]; + uint8_t DriveNumber; + uint8_t Reserved1; + uint8_t BootSignature; + uint32_t VolumeId; + char VolumeLabel[11]; + char FsType[8]; +} BPB; + +typedef struct { + char Name[8]; + char Ext[3]; + uint8_t Attr; + uint8_t Reserved; + uint8_t CrtTimeTenth; + uint16_t CrtTime; + uint16_t CrtDate; + uint16_t LastAccDate; + uint16_t FirstClusterHi; + uint16_t WrtTime; + uint16_t WrtDate; + uint16_t FirstClusterLo; + uint32_t FileSize; +} DIRENT; + +typedef struct { + uint8_t Order; + uint16_t Name1[5]; + uint8_t Attr; // 0x0F + uint8_t Type; + uint8_t Checksum; + uint16_t Name2[6]; + uint16_t FirstCluster; + uint16_t Name3[2]; +} LFN_ENTRY; + +// GPT Structures +typedef struct { + uint32_t Data1; + uint16_t Data2; + uint16_t Data3; + uint8_t Data4[8]; +} EFI_GUID; + +typedef struct { + char Signature[8]; // "EFI PART" + uint32_t Revision; + uint32_t HeaderSize; + uint32_t HeaderCRC32; + uint32_t Reserved; + uint64_t MyLBA; + uint64_t AlternateLBA; + uint64_t FirstUsableLBA; + uint64_t LastUsableLBA; + EFI_GUID DiskGUID; + uint64_t PartitionEntryLBA; + uint32_t NumberOfPartitionEntries; + uint32_t SizeOfPartitionEntry; + uint32_t PartitionEntryArrayCRC32; +} GPT_HEADER; + +typedef struct { + EFI_GUID PartitionTypeGUID; + EFI_GUID UniquePartitionGUID; + uint64_t StartingLBA; + uint64_t EndingLBA; + uint64_t Attributes; + uint16_t PartitionName[36]; +} GPT_ENTRY; + +#pragma pack(pop) + +#define ATTR_DIRECTORY 0x10 +#define ATTR_LFN 0x0F +#define FAT32_EOC 0x0FFFFFF8 + +// --------------------------------------------------------------------------- +// Driver state +// --------------------------------------------------------------------------- +typedef struct { + uint8_t DriveIndex; + uint32_t PartitionLba; // LBA of the partition's first sector + uint32_t BytesPerSector; + uint32_t SectorsPerCluster; + uint32_t BytesPerCluster; + uint32_t ReservedSectors; + uint32_t NumFats; + uint32_t FatSize; // in sectors + uint32_t RootCluster; + uint32_t DataStart; // LBA of cluster 2 + const HAL_API* Hal; +} FAT32_VOL; + +typedef struct { + uint32_t StartCluster; + uint32_t FileSize; + FAT32_VOL* Vol; +} FAT32_FILE; + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- +static KSTATUS ReadSectors(FAT32_VOL* v, uint64_t lba, + uint32_t count, void* buf) { + if (!v || !v->Hal || !v->Hal->Disk.ReadSectors) { + return STATUS_INVALID_PARAMETER; + } + return v->Hal->Disk.ReadSectors(v->DriveIndex, lba, count, buf); +} + +static uint64_t ClusterToLba(FAT32_VOL* v, uint32_t cluster) { + return v->DataStart + (uint64_t)(cluster - 2) * v->SectorsPerCluster; +} + +// Read the FAT entry for a given cluster. Returns 0 on error. +static uint32_t FatEntry(FAT32_VOL* v, uint32_t cluster) { + uint32_t fatOffset = cluster * 4; + uint32_t sector = v->PartitionLba + v->ReservedSectors + + fatOffset / v->BytesPerSector; + uint32_t offInSec = fatOffset % v->BytesPerSector; + + uint8_t* sec = (uint8_t *)MmAllocatePool(v->BytesPerSector); + if (!sec) return 0; + if (!KSUCCESS(ReadSectors(v, sector, 1, sec))) { + DbgPrint("fat32: FatEntry: ReadSectors failed!\n"); + } + uint32_t val = *(uint32_t *)(sec + offInSec) & 0x0FFFFFFF; + MmFreePool(sec); + return val; +} + +// --------------------------------------------------------------------------- +// 8.3 name matching +// --------------------------------------------------------------------------- +static int MatchName83(const char* dirName, const char* dirExt, + const char* want) { + char buf[13]; + int n = 0; + for (int i = 0; i < 8 && dirName[i] != ' '; i++) { + buf[n++] = (char)(dirName[i] >= 'A' && dirName[i] <= 'Z' + ? dirName[i] + 32 : dirName[i]); + } + if (dirExt[0] != ' ') { + buf[n++] = '.'; + for (int i = 0; i < 3 && dirExt[i] != ' '; i++) { + buf[n++] = (char)(dirExt[i] >= 'A' && dirExt[i] <= 'Z' + ? dirExt[i] + 32 : dirExt[i]); + } + } + buf[n] = '\0'; + + const char* p = buf; + while (*want && *p) { + char a = *p++, b = *want++; + if (a >= 'A' && a <= 'Z') a += 32; + if (b >= 'A' && b <= 'Z') b += 32; + if (a != b) return 0; + } + return* want == '\0' && *p == '\0'; +} + +// --------------------------------------------------------------------------- +// LFN name assembly +// --------------------------------------------------------------------------- +#define MAX_LFN 256 + +static void LfnAppend(char* lfn, const LFN_ENTRY* e) { + int seq = (e->Order & 0x3F) - 1; + if (seq < 0 || seq >= (MAX_LFN / 13)) return; + + int pos = seq * 13; + uint16_t chars[13]; + int idx = 0; + + for (int i = 0; i < 5; i++) chars[idx++] = e->Name1[i]; + for (int i = 0; i < 6; i++) chars[idx++] = e->Name2[i]; + for (int i = 0; i < 2; i++) chars[idx++] = e->Name3[i]; + + for (int i = 0; i < 13 && pos < MAX_LFN - 1; i++, pos++) { + uint16_t c = chars[i]; + if (c == 0x0000 || c == 0xFFFF) { lfn[pos] = '\0'; break; } + lfn[pos] = (char)(c & 0x7F); + } +} + +static int LfnMatch(const char* lfn, const char* want) { + while (*lfn && *want) { + char a = *lfn++, b = *want++; + if (a >= 'A' && a <= 'Z') a += 32; + if (b >= 'A' && b <= 'Z') b += 32; + if (a != b) return 0; + } + return* lfn == '\0' && *want == '\0'; +} + +// --------------------------------------------------------------------------- +// Directory search +// --------------------------------------------------------------------------- +static int SearchDir(FAT32_VOL* v, uint32_t dirCluster, + const char* name, + uint32_t* outCluster, uint32_t* outSize, + uint8_t* outAttr) { + uint8_t* clusterBuf = (uint8_t *)MmAllocatePool(v->BytesPerCluster); + if (!clusterBuf) return 0; + + char lfn[MAX_LFN]; + int hasLfn = 0; + memset(lfn, 0, sizeof(lfn)); + + uint32_t cluster = dirCluster; + while (cluster < FAT32_EOC) { + if (!KSUCCESS(ReadSectors(v, ClusterToLba(v, cluster), + v->SectorsPerCluster, clusterBuf))) { + break; + } + + uint32_t entries = v->BytesPerCluster / sizeof(DIRENT); + DIRENT* dir = (DIRENT *)clusterBuf; + + for (uint32_t i = 0; i < entries; i++) { + if (dir[i].Name[0] == 0x00) goto done; // end of directory + if ((uint8_t)dir[i].Name[0] == 0xE5) { // deleted + hasLfn = 0; memset(lfn, 0, sizeof(lfn)); + continue; + } + if (dir[i].Attr == ATTR_LFN) { + LfnAppend(lfn, (LFN_ENTRY *)&dir[i]); + hasLfn = 1; + continue; + } + + int match = 0; + if (hasLfn && lfn[0]) { + match = LfnMatch(lfn, name); + } + if (!match) { + match = MatchName83(dir[i].Name, dir[i].Ext, name); + } + + hasLfn = 0; memset(lfn, 0, sizeof(lfn)); + + if (match) { + *outCluster = ((uint32_t)dir[i].FirstClusterHi << 16) | dir[i].FirstClusterLo; + *outSize = dir[i].FileSize; + *outAttr = dir[i].Attr; + MmFreePool(clusterBuf); + return 1; + } + } + cluster = FatEntry(v, cluster); + } +done: + MmFreePool(clusterBuf); + return 0; +} + +// --------------------------------------------------------------------------- +// Path traversal +// --------------------------------------------------------------------------- +static KSTATUS Traverse(FAT32_VOL* v, const char* path, + uint32_t* outCluster, uint32_t* outSize) { + uint32_t cluster = v->RootCluster; + uint32_t size = 0; + uint8_t attr = ATTR_DIRECTORY; + + char component[256]; + const char* p = path; + + while (*p) { + while (*p == '\\' || *p == '/') p++; + if (!*p) break; + + int len = 0; + while (*p && *p != '\\' && *p != '/' && len < 255) + component[len++] = *p++; + component[len] = '\0'; + if (!len) break; + + if (!(attr & ATTR_DIRECTORY)) return STATUS_NOT_FOUND; + + uint32_t childCluster, childSize; + uint8_t childAttr; + if (!SearchDir(v, cluster, component, &childCluster, &childSize, &childAttr)) + return STATUS_NOT_FOUND; + + cluster = childCluster; + size = childSize; + attr = childAttr; + } + + *outCluster = cluster; + *outSize = size; + return STATUS_SUCCESS; +} + +// --------------------------------------------------------------------------- +// IO_FILESYSTEM vtable implementations +// --------------------------------------------------------------------------- +static KSTATUS Fat32Open(IO_FILESYSTEM* fs, const char* path, void **fileCtx) { + FAT32_VOL* v = (FAT32_VOL *)fs->DriverCtx; + uint32_t cluster, size; + KSTATUS s = Traverse(v, path, &cluster, &size); + if (!KSUCCESS(s)) return s; + + FAT32_FILE* f = (FAT32_FILE *)MmAllocatePool(sizeof(FAT32_FILE)); + if (!f) return STATUS_NO_MEMORY; + f->StartCluster = cluster; + f->FileSize = size; + f->Vol = v; + + *fileCtx = f; + return STATUS_SUCCESS; +} + +static KSTATUS Fat32Read(IO_FILESYSTEM* fs, void* fileCtx, + uint64_t offset, void* buf, + size_t size, size_t* bytesRead) { + (void)fs; + FAT32_FILE* f = (FAT32_FILE *)fileCtx; + FAT32_VOL* v = f->Vol; + + if (offset >= f->FileSize) { *bytesRead = 0; return STATUS_SUCCESS; } + if (offset + size > f->FileSize) size = (size_t)(f->FileSize - offset); + + uint8_t* clusterBuf = (uint8_t *)MmAllocatePool(v->BytesPerCluster); + if (!clusterBuf) return STATUS_NO_MEMORY; + + size_t totalRead = 0; + uint8_t* out = (uint8_t *)buf; + + uint32_t skipClusters = (uint32_t)(offset / v->BytesPerCluster); + uint32_t offsetInCluster = (uint32_t)(offset % v->BytesPerCluster); + uint32_t cluster = f->StartCluster; + + for (uint32_t i = 0; i < skipClusters && cluster < FAT32_EOC; i++) + cluster = FatEntry(v, cluster); + + while (size > 0 && cluster < FAT32_EOC) { + if (!KSUCCESS(ReadSectors(v, ClusterToLba(v, cluster), + v->SectorsPerCluster, clusterBuf))) { + break; + } + + size_t avail = v->BytesPerCluster - offsetInCluster; + size_t copy = avail < size ? avail : size; + + memcpy(out, clusterBuf + offsetInCluster, copy); + out += copy; + totalRead += copy; + size -= copy; + offsetInCluster = 0; + + cluster = FatEntry(v, cluster); + } + + MmFreePool(clusterBuf); + *bytesRead = totalRead; + return STATUS_SUCCESS; +} + +static uint64_t Fat32GetSize(IO_FILESYSTEM* fs, void* fileCtx) { + (void)fs; + return ((FAT32_FILE *)fileCtx)->FileSize; +} + +static void Fat32Close(IO_FILESYSTEM* fs, void* fileCtx) { + (void)fs; + MmFreePool(fileCtx); +} + +// --------------------------------------------------------------------------- +// Partition scan - Supports MBR and GPT +// --------------------------------------------------------------------------- +static const EFI_GUID GUID_EFI_SYSTEM = { + 0xC12A7328, 0xF81F, 0x11D2, {0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B} +}; +static const EFI_GUID GUID_MS_BASIC_DATA = { + 0xEBD0A0A2, 0xB9E5, 0x4433, {0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7} +}; +static const EFI_GUID GUID_LINUX_BASIC_DATA = { + 0x0FC63DAF, 0x8483, 0x4772, {0x8E, 0x79, 0x3D, 0x69, 0xD8, 0x47, 0x7D, 0xE4} +}; + +// Validates whether the VBR actually contains a FAT32 BPB +static int IsFat32Vbr(FAT32_VOL* v, uint32_t lba) { + uint8_t sector[512]; + if (!KSUCCESS(ReadSectors(v, lba, 1, sector))) return 0; + + if (sector[510] != 0x55 || sector[511] != 0xAA) return 0; + + BPB* bpb = (BPB *)sector; + if (bpb->FatSize16 != 0 || bpb->RootEntryCount != 0) return 0; + if (bpb->FatSize32 == 0) return 0; + + return 1; +} + +static uint32_t FindFat32Partition(FAT32_VOL* v) { + uint8_t mbr[512]; + + KSTATUS s = ReadSectors(v, 0, 1, mbr); + if (!KSUCCESS(s)) { + DbgPrint("FAT32: [DEBUG] ReadSectors for MBR failed.\n"); + return 0; + } + + if (mbr[510] != 0x55 || mbr[511] != 0xAA) { + DbgPrint("FAT32: [DEBUG] Invalid signature at LBA 0.\n"); + return 0; + } + + // Check for GPT Protective MBR (Type 0xEE) + int isGpt = 0; + for (int i = 0; i < 4; i++) { + if (mbr[0x1BE + i * 16 + 4] == 0xEE) { + isGpt = 1; + break; + } + } + + if (isGpt) { + DbgPrint("FAT32: [DEBUG] Protective MBR found. Parsing GPT...\n"); + uint8_t gptSector[512]; + if (!KSUCCESS(ReadSectors(v, 1, 1, gptSector))) return 0; + + GPT_HEADER* gpt = (GPT_HEADER *)gptSector; + if (memcmp(gpt->Signature, "EFI PART", 8) != 0) { + DbgPrint("FAT32: [DEBUG] Invalid GPT signature.\n"); + return 0; + } + + uint64_t entryLBA = gpt->PartitionEntryLBA; + uint32_t numEntries = gpt->NumberOfPartitionEntries; + uint32_t entrySize = gpt->SizeOfPartitionEntry; + + if (entrySize < sizeof(GPT_ENTRY)) return 0; + + uint32_t entriesPerSector = 512 / entrySize; + uint8_t entrySector[512]; + + for (uint32_t i = 0; i < numEntries; i++) { + if (i % entriesPerSector == 0) { + if (!KSUCCESS(ReadSectors(v, entryLBA + (i / entriesPerSector), 1, entrySector))) { + return 0; + } + } + + GPT_ENTRY* entry = (GPT_ENTRY *)(entrySector + (i % entriesPerSector) * entrySize); + + static const EFI_GUID emptyGuid = {0}; + if (memcmp(&entry->PartitionTypeGUID, &emptyGuid, sizeof(EFI_GUID)) == 0) continue; + + // Microsoft Basic Data maps to FAT, NTFS, and exFAT. VBR validation checks true FAT32 nature. + if (memcmp(&entry->PartitionTypeGUID, &GUID_EFI_SYSTEM, sizeof(EFI_GUID)) == 0 || + memcmp(&entry->PartitionTypeGUID, &GUID_MS_BASIC_DATA, sizeof(EFI_GUID)) == 0 || + memcmp(&entry->PartitionTypeGUID, &GUID_LINUX_BASIC_DATA, sizeof(EFI_GUID)) == 0) { + + uint32_t lba = (uint32_t)entry->StartingLBA; + if (IsFat32Vbr(v, lba)) { + DbgPrint("FAT32: [DEBUG] Found FAT32 partition via GPT at LBA %u\n", lba); + return lba; + } + } + } + DbgPrint("FAT32: [DEBUG] No FAT32 partition found in GPT.\n"); + return 0; + } + + // Fallback: MBR Parsing + for (int i = 0; i < 4; i++) { + uint8_t* entry = mbr + 0x1BE + i * 16; + uint8_t type = entry[4]; + + if (type == 0x0B || type == 0x0C) { + uint32_t lba = *(uint32_t *)(entry + 8); + if (IsFat32Vbr(v, lba)) { + DbgPrint("FAT32: [DEBUG] Found FAT32 partition via MBR at LBA %u\n", lba); + return lba; + } + } + } + + DbgPrint("FAT32: [DEBUG] No FAT32 partition found in MBR.\n"); + return 0; +} + +// --------------------------------------------------------------------------- +// DriverEntry +// --------------------------------------------------------------------------- +static FAT32_VOL gVol; +static IO_FILESYSTEM gFs; + +KSTATUS DriverEntry(const HAL_API* hal) { + DbgPrint("FAT32: Init\n"); + if (!hal) return STATUS_INVALID_PARAMETER; + + gVol.Hal = hal; + gVol.DriveIndex = 0; + + uint32_t partLba = FindFat32Partition(&gVol); + if (partLba == 0) { + DbgPrint("FAT32: [DEBUG] Could not locate a valid FAT32 volume.\n"); + return STATUS_NOT_SUPPORTED; + } + + gVol.PartitionLba = partLba; + + uint8_t sector[512]; + if (!KSUCCESS(ReadSectors(&gVol, partLba, 1, sector))) { + DbgPrint("FAT32: [DEBUG] ReadSectors FAILED!\n"); + return STATUS_DEVICE_ERROR; + } + + BPB* bpb = (BPB *)sector; + + // IsFat32Vbr guarantees these pass, but retained for absolute sanity checking. + if (bpb->FatSize16 != 0 || bpb->RootEntryCount != 0) { + DbgPrint("FAT32: [DEBUG] Validation failed - Not a FAT32 volume.\n"); + return STATUS_NOT_SUPPORTED; + } + + gVol.BytesPerSector = bpb->BytesPerSector; + gVol.SectorsPerCluster = bpb->SectorsPerCluster; + gVol.BytesPerCluster = bpb->BytesPerSector * bpb->SectorsPerCluster; + gVol.ReservedSectors = bpb->ReservedSectors; + gVol.NumFats = bpb->NumFats; + gVol.FatSize = bpb->FatSize32; + gVol.RootCluster = bpb->RootCluster; + gVol.DataStart = partLba + + bpb->ReservedSectors + + bpb->NumFats * bpb->FatSize32; + + gFs.Open = Fat32Open; + gFs.Read = Fat32Read; + gFs.GetSize = Fat32GetSize; + gFs.Close = Fat32Close; + gFs.DriverCtx = &gVol; + + // Populate IO_VOLUME_PARAMS + IO_VOLUME_PARAMS volParams; + volParams.DiskIndex = gVol.DriveIndex; + volParams.PartitionLba = partLba; + // FAT32 sizes are stored in TotalSectors32 if TotalSectors16 is 0 + volParams.PartitionSize = (bpb->TotalSectors16 != 0) ? bpb->TotalSectors16 : bpb->TotalSectors32; + + // Pass the new volParams structure + KSTATUS status = IoRegisterFilesystem(gVol.DriveIndex, &gFs, &volParams); + DbgPrint("FAT32: [DEBUG] pIoRegisterFilesystem returned: %d\n", status); + + DbgPrint("FAT32: Init complete.\n"); + return STATUS_SUCCESS; +} diff --git a/code/drivers/ide/ide.c b/code/drivers/ide/ide.c new file mode 100644 index 0000000..f2724b3 --- /dev/null +++ b/code/drivers/ide/ide.c @@ -0,0 +1,179 @@ +// ide.c - PIO-mode IDE driver (legacy 28-bit LBA) +#include +#include +#include +#include +#include +#include + +// Primary channel I/O ports. +#define IDE_DATA 0x1F0 +#define IDE_ERR 0x1F1 +#define IDE_SECCNT 0x1F2 +#define IDE_LBA0 0x1F3 +#define IDE_LBA1 0x1F4 +#define IDE_LBA2 0x1F5 +#define IDE_DRIVE 0x1F6 // 0xE0=master 0xF0=slave +#define IDE_STATUS 0x1F7 +#define IDE_CMD 0x1F7 +#define IDE_ALT 0x3F6 + +#define IDE_BUSY 0x80 +#define IDE_READY 0x40 +#define IDE_ERR_F 0x01 +#define IDE_DRQ 0x08 + +#define CMD_READ 0x20 +#define CMD_WRITE 0x30 +#define CMD_IDENT 0xEC + +static const HAL_API* gHal; +static DISK_DRIVER gDrv; +static uint64_t gSectorCount = 0; + +static void IdeWait(void) { + while (__inbyte(IDE_STATUS) & IDE_BUSY) _mm_pause(); +} + +static KSTATUS IdeWaitData(void) { + // Read the Alternate Status port 4 times to waste 400ns + for (int i = 0; i < 4; i++) { + __inbyte(IDE_ALT); + } + + // Wait until the drive is not busy AND data is requested (DRQ) + while (1) { + uint8_t st = __inbyte(IDE_STATUS); + if (st & IDE_ERR_F) return STATUS_DEVICE_ERROR; + if (!(st & IDE_BUSY) && (st & IDE_DRQ)) return STATUS_SUCCESS; + _mm_pause(); + } +} + +static KSTATUS IdeRead(uint64_t lba, uint32_t count, void* buf) { + if (lba + count > gSectorCount) return STATUS_INVALID_PARAMETER; + uint16_t* p = (uint16_t *)buf; + + for (uint32_t i = 0; i < count; i++, lba++) { + IdeWait(); // Wait for drive to be ready for commands + __outbyte(IDE_DRIVE, 0xE0 | ((lba >> 24) & 0xF)); + __outbyte(IDE_SECCNT, 1); + __outbyte(IDE_LBA0, (uint8_t)lba); + __outbyte(IDE_LBA1, (uint8_t)(lba >> 8)); + __outbyte(IDE_LBA2, (uint8_t)(lba >> 16)); + __outbyte(IDE_CMD, CMD_READ); + + // Use the delay/DRQ wait + if (IdeWaitData() != STATUS_SUCCESS) return STATUS_DEVICE_ERROR; + + for (int w = 0; w < 256; w++) *p++ = __inword(IDE_DATA); + } + return STATUS_SUCCESS; +} + +static KSTATUS IdeWrite(uint64_t lba, uint32_t count, const void* buf) { + if (lba + count > gSectorCount) return STATUS_INVALID_PARAMETER; + const uint16_t* p = (const uint16_t *)buf; + + for (uint32_t i = 0; i < count; i++, lba++) { + IdeWait(); + __outbyte(IDE_DRIVE, 0xE0 | ((lba >> 24) & 0xF)); + __outbyte(IDE_SECCNT, 1); + __outbyte(IDE_LBA0, (uint8_t)lba); + __outbyte(IDE_LBA1, (uint8_t)(lba >> 8)); + __outbyte(IDE_LBA2, (uint8_t)(lba >> 16)); + __outbyte(IDE_CMD, CMD_WRITE); + IdeWait(); + for (int w = 0; w < 256; w++) __outword(IDE_DATA, *p++); + __outbyte(IDE_ALT, 0); // flush cache + if (IdeWaitData() != STATUS_SUCCESS) return STATUS_DEVICE_ERROR; + } + return STATUS_SUCCESS; +} + +KSTATUS DriverEntry(const HAL_API* hal) { + DbgPrint("IDE: Init\n"); + gHal = hal; + uint8_t status; + int timeout; + + // 1. Select Primary Master Drive (0xA0) + __outbyte(IDE_DRIVE, 0xA0); + + // Waste 400ns to let the drive selection settle on the bus + for(int i=0; i<4; i++) __inbyte(IDE_ALT); + + // 2. Zero out the LBA and Sector Count registers + __outbyte(IDE_SECCNT, 0); + __outbyte(IDE_LBA0, 0); + __outbyte(IDE_LBA1, 0); + __outbyte(IDE_LBA2, 0); + + // 3. Send the IDENTIFY command + DbgPrint("IDE: Sending CMD_IDENT (0xEC)...\n"); + __outbyte(IDE_CMD, CMD_IDENT); + + // 4. Read status immediately. If it's 0, the drive doesn't exist at all. + status = __inbyte(IDE_STATUS); + // DbgPrint("IDE: Initial status after IDENTIFY: 0x%02X\n", status); + if (status == 0) { + DbgPrint("IDE ERROR: Drive does not exist (Status 0).\n"); + return STATUS_NOT_FOUND; + } + + // 5. Wait for BSY (Busy) to clear, WITH A TIMEOUT + timeout = 100000; + while (__inbyte(IDE_STATUS) & IDE_BUSY) { + if (--timeout == 0) { + DbgPrint("IDE ERROR: Timeout waiting for BSY to clear!\n"); + return STATUS_DEVICE_ERROR; + } + } + + // 6. Check for ATAPI (CD-ROM) or SATA signatures. + // If these registers aren't 0 after BSY clears, it's NOT a standard ATA disk! + uint8_t lba1 = __inbyte(IDE_LBA1); + uint8_t lba2 = __inbyte(IDE_LBA2); + if (lba1 != 0 || lba2 != 0) { + DbgPrint("IDE ERROR: Not an ATA drive! Signatures: LBA1=0x%02X, LBA2=0x%02X\n", lba1, lba2); + // (ATAPI CD-ROMs usually show LBA1=0x14, LBA2=0xEB) + return STATUS_NOT_SUPPORTED; + } + + // 7. Wait for DRQ (Data Request) or ERR (Error) + timeout = 100000; + while (1) { + status = __inbyte(IDE_STATUS); + if (status & IDE_ERR_F) { + DbgPrint("IDE ERROR: Drive returned an error! Status: 0x%02X\n", status); + return STATUS_DEVICE_ERROR; + } + if (status & IDE_DRQ) { + break; // Data is ready! + } + if (--timeout == 0) { + DbgPrint("IDE ERROR: Timeout waiting for DRQ! Status: 0x%02X\n", status); + return STATUS_DEVICE_ERROR; + } + } + + // 8. Success! Read the 256 words (512 bytes) of IDENTIFY data + // DbgPrint("IDE: DRQ set! Reading 256 words...\n"); + uint16_t ident[256]; + for (int i = 0; i < 256; i++) { + ident[i] = __inword(IDE_DATA); + } + + // 9. Extract and print the sector count (Words 60 and 61 for 28-bit LBA) + gSectorCount = ((uint32_t)ident[61] << 16) | ident[60]; + DbgPrint("IDE: SUCCESS: Disk found! Sector count: %u\n", (uint32_t)gSectorCount); + + if (gSectorCount == 0) return STATUS_NOT_FOUND; + + // Register driver globally (from the previous fix!) + gDrv.ReadSectors = IdeRead; + gDrv.WriteSectors = IdeWrite; + gDrv.SectorCount = gSectorCount; + + return IoRegisterDisk(0, &gDrv); +} diff --git a/code/drivers/usb/usb.c b/code/drivers/usb/usb.c new file mode 100644 index 0000000..13ec507 --- /dev/null +++ b/code/drivers/usb/usb.c @@ -0,0 +1,9 @@ +#include +#include +#include + +KSTATUS DriverEntry(const HAL_API* hal) { + (void)hal; + DbgPrint("Test runtime driver\n"); + return STATUS_SUCCESS; +} \ No newline at end of file diff --git a/code/hal/font8x16.h b/code/hal/font8x16.h new file mode 100644 index 0000000..ddd46a5 --- /dev/null +++ b/code/hal/font8x16.h @@ -0,0 +1,199 @@ +#pragma once +// font8x16.h - embedded 8x16 VGA bitmap font, printable ASCII (0x20–0x7E) +// 95 glyphs × 16 bytes = 1520 bytes total. +// Each byte is one scanline; bit 7 = leftmost pixel. +#include + +static const uint8_t Font8x16[95 * 16] = { + // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x21 '!' + 0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, + // 0x22 '"' + 0x00,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x23 '#' + 0x00,0x36,0x36,0x7F,0x36,0x36,0x36,0x7F,0x36,0x36,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x24 '$' + 0x18,0x18,0x3E,0x63,0x03,0x03,0x1E,0x30,0x30,0x63,0x3E,0x18,0x18,0x00,0x00,0x00, + // 0x25 '%' + 0x00,0x00,0x63,0x33,0x18,0x0C,0x06,0x31,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x26 '&' + 0x00,0x1C,0x36,0x1C,0x0E,0x3B,0x33,0x33,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x27 '\'' + 0x00,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x28 '(' + 0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x29 ')' + 0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x2A '*' + 0x00,0x00,0x00,0x33,0x1E,0xFF,0x1E,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x2B '+' + 0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x08,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x2F '/' + 0x00,0x60,0x30,0x18,0x0C,0x06,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x30 '0' + 0x00,0x3C,0x66,0x66,0x76,0x6E,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x31 '1' + 0x00,0x18,0x1C,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x32 '2' + 0x00,0x3C,0x66,0x60,0x30,0x18,0x0C,0x66,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x33 '3' + 0x00,0x3C,0x66,0x60,0x38,0x60,0x60,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x34 '4' + 0x00,0x30,0x38,0x3C,0x36,0x33,0x7F,0x30,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x35 '5' + 0x00,0x7E,0x06,0x06,0x3E,0x60,0x60,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x36 '6' + 0x00,0x38,0x0C,0x06,0x3E,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x37 '7' + 0x00,0x7E,0x60,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x38 '8' + 0x00,0x3C,0x66,0x66,0x3C,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x39 '9' + 0x00,0x3C,0x66,0x66,0x7C,0x60,0x30,0x18,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x3A ':' + 0x00,0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x3B ';' + 0x00,0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x3C '<' + 0x00,0x60,0x30,0x18,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x3D '=' + 0x00,0x00,0x00,0x7E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x3E '>' + 0x00,0x06,0x0C,0x18,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x3F '?' + 0x00,0x3C,0x66,0x60,0x30,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x40 '@' + 0x00,0x3E,0x63,0x7B,0x7B,0x7B,0x3B,0x03,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x41 'A' + 0x00,0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x42 'B' + 0x00,0x3E,0x66,0x66,0x3E,0x66,0x66,0x66,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x43 'C' + 0x00,0x3C,0x66,0x06,0x06,0x06,0x06,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x44 'D' + 0x00,0x1E,0x36,0x66,0x66,0x66,0x66,0x36,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x45 'E' + 0x00,0x7E,0x06,0x06,0x3E,0x06,0x06,0x06,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x46 'F' + 0x00,0x7E,0x06,0x06,0x3E,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x47 'G' + 0x00,0x3C,0x66,0x06,0x06,0x76,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x48 'H' + 0x00,0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x49 'I' + 0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x4A 'J' + 0x00,0x78,0x30,0x30,0x30,0x30,0x36,0x36,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x4B 'K' + 0x00,0x66,0x36,0x1E,0x0E,0x1E,0x36,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x4C 'L' + 0x00,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x4D 'M' + 0x00,0x63,0x77,0x7F,0x6B,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x4E 'N' + 0x00,0x63,0x67,0x6F,0x7B,0x73,0x63,0x63,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x4F 'O' + 0x00,0x3C,0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x50 'P' + 0x00,0x3E,0x66,0x66,0x3E,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x51 'Q' + 0x00,0x3C,0x66,0x66,0x66,0x66,0x6E,0x3C,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x52 'R' + 0x00,0x3E,0x66,0x66,0x3E,0x36,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x53 'S' + 0x00,0x3C,0x66,0x06,0x1C,0x30,0x60,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x54 'T' + 0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x55 'U' + 0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x56 'V' + 0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x57 'W' + 0x00,0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x58 'X' + 0x00,0x66,0x66,0x3C,0x18,0x3C,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x59 'Y' + 0x00,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x5A 'Z' + 0x00,0x7E,0x60,0x30,0x18,0x0C,0x06,0x06,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x5B '[' + 0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x5C '\' + 0x00,0x03,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x5D ']' + 0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x5E '^' + 0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x60 '`' + 0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x61–0x7A lowercase - condensed to save space, using same shapes as upper offset by 32 + // 0x61 'a' + 0x00,0x00,0x00,0x1C,0x30,0x3C,0x33,0x33,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x62 'b' + 0x00,0x06,0x06,0x1E,0x36,0x66,0x66,0x66,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x63 'c' + 0x00,0x00,0x00,0x3C,0x06,0x06,0x06,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x64 'd' + 0x00,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x65 'e' + 0x00,0x00,0x00,0x3C,0x66,0x7E,0x06,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x66 'f' + 0x00,0x38,0x0C,0x0C,0x3E,0x0C,0x0C,0x0C,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x67 'g' + 0x00,0x00,0x7C,0x66,0x66,0x66,0x7C,0x60,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x68 'h' + 0x00,0x06,0x06,0x3E,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x69 'i' + 0x00,0x18,0x00,0x1C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x6A 'j' + 0x00,0x30,0x00,0x38,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x6B 'k' + 0x00,0x06,0x06,0x66,0x36,0x1E,0x36,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x6C 'l' + 0x00,0x1C,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x6D 'm' + 0x00,0x00,0x00,0x37,0x7F,0x6B,0x6B,0x6B,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x6E 'n' + 0x00,0x00,0x00,0x1E,0x36,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x6F 'o' + 0x00,0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x70 'p' + 0x00,0x00,0x3E,0x66,0x66,0x3E,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x71 'q' + 0x00,0x00,0x7C,0x66,0x66,0x7C,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x72 'r' + 0x00,0x00,0x00,0x3E,0x06,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x73 's' + 0x00,0x00,0x00,0x3C,0x06,0x1C,0x30,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x74 't' + 0x00,0x0C,0x0C,0x3E,0x0C,0x0C,0x0C,0x0C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x75 'u' + 0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x76 'v' + 0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x77 'w' + 0x00,0x00,0x00,0x63,0x6B,0x6B,0x7F,0x77,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x78 'x' + 0x00,0x00,0x00,0x66,0x3C,0x18,0x3C,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x79 'y' + 0x00,0x00,0x66,0x66,0x66,0x7C,0x60,0x30,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x7A 'z' + 0x00,0x00,0x00,0x7E,0x30,0x18,0x0C,0x06,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x7B '{' + 0x00,0x30,0x18,0x18,0x0C,0x18,0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x7C '|' + 0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x7D '}' + 0x00,0x0C,0x18,0x18,0x30,0x18,0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x7E '~' + 0x00,0x6E,0x3B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; diff --git a/code/hal/hal_api.h b/code/hal/hal_api.h new file mode 100644 index 0000000..f367b45 --- /dev/null +++ b/code/hal/hal_api.h @@ -0,0 +1,95 @@ +#pragma once +// hal_api.h - HAL interface table exported as HalGetApi() +#include +#include +#include +#include "ke_status.h" + +typedef struct BOOT_INFO BOOT_INFO; + +typedef struct HAL_SCREEN { + void (*Clear)(uint32_t color); + void (*PutPixel)(int x, int y, uint32_t color); + void (*Blit)(int x, int y, int w, int h, const uint32_t* pixels); + void (*GetSize)(int* width, int* height); + void (*Scroll)(int lines); + void (*PutChar)(char c, int x, int y, uint32_t fg, uint32_t bg); + void (*PrintChar)(char c, uint32_t fg, uint32_t bg); +} HAL_SCREEN; + +typedef struct HAL_KEYBOARD { + bool (*Poll)(void); + uint8_t (*ReadScancode)(void); + char (*ReadChar)(void); + void (*SetCallback)(void (*cb)(uint8_t scancode)); + void (*Isr)(void); + uint8_t IrqNumber; +} HAL_KEYBOARD; + +typedef struct HAL_DISK { + KSTATUS (*ReadSectors)(uint8_t drive, uint64_t lba, + uint32_t count, void* buf); + KSTATUS (*WriteSectors)(uint8_t drive, uint64_t lba, + uint32_t count, const void* buf); + bool (*DrivePresent)(uint8_t drive); + uint64_t (*DriveSectorCount)(uint8_t drive); +} HAL_DISK; + +typedef struct HAL_TIMER { + uint64_t (*QueryTicks)(void); + void (*Stall)(uint32_t us); + void (*Isr)(void); + uint8_t IrqNumber; +} HAL_TIMER; + +typedef struct HAL_PCI { + uint32_t (*ConfigRead32)(uint8_t bus, uint8_t dev, + uint8_t fn, uint8_t reg); + void (*ConfigWrite32)(uint8_t bus, uint8_t dev, + uint8_t fn, uint8_t reg, uint32_t val); + bool (*FindDevice)(uint16_t vendor, uint16_t device, + uint8_t* bus, uint8_t* dev, uint8_t* fn); + bool (*FindClass)(uint8_t classCode, uint8_t subclass, + uint8_t* bus, uint8_t* dev, uint8_t* fn); +} HAL_PCI; + +typedef struct HAL_INTC { + void (*RouteIrq)(uint8_t irq); + void (*MaskIrq)(uint8_t irq); + void (*UnmaskIrq)(uint8_t irq); + void (*SendEoi)(void); +} HAL_INTC; + +typedef struct HAL_API { + uint32_t Version; + void *(*PhysToVirt)(uint64_t physAddr); + HAL_SCREEN Screen; + HAL_KEYBOARD Keyboard; + HAL_DISK Disk; + HAL_TIMER Timer; + HAL_PCI Pci; + HAL_INTC Intc; +} HAL_API; + +typedef struct HAL_INIT_PARAMS { + // Framebuffer + uintptr_t FramebufferBase; + uint32_t FramebufferWidth; + uint32_t FramebufferHeight; + uint32_t FramebufferStride; + + // ACPI + uintptr_t RsdpPhysical; + + // Memory + uint64_t PhysicalWindowBase; + + // Debug + int DebugEnabled; +} HAL_INIT_PARAMS; + +#define HAL_API_VERSION 1 + +const HAL_API* HalGetApi(void); +void HalRegisterScheduler(void (*pKeSchedulerTick)(void)); +KSTATUS HalInitialize(const HAL_INIT_PARAMS* params); diff --git a/code/hal/hal_apic.c b/code/hal/hal_apic.c new file mode 100644 index 0000000..13403c9 --- /dev/null +++ b/code/hal/hal_apic.c @@ -0,0 +1,74 @@ +// hal_apic.c - Local APIC + I/O APIC +#include "hal_apic.h" +#include "hal_api.h" +#include + +extern HAL_API gApi; + +// ---- Local APIC ---- +static volatile uint32_t* gLapic = (volatile uint32_t *)0; +#define LAPIC_REG(off) (*(volatile uint32_t *)((uint8_t *)gLapic + (off))) +#define LAPIC_EOI 0x0B0 +#define LAPIC_SPURIOUS 0x0F0 +#define LAPIC_ENABLE 0x100 // bit in spurious vector register + +// ---- I/O APIC ---- +static volatile uint32_t* gIoapic = (volatile uint32_t *)0; +#define IOAPIC_IDX 0x00 +#define IOAPIC_DATA 0x10 + +static uint32_t IoapicRead(uint8_t reg) { + *(volatile uint32_t *)((uint8_t *)gIoapic + IOAPIC_IDX) = reg; + return *(volatile uint32_t *)((uint8_t *)gIoapic + IOAPIC_DATA); +} +static void IoapicWrite(uint8_t reg, uint32_t val) { + *(volatile uint32_t *)((uint8_t *)gIoapic + IOAPIC_IDX) = reg; + *(volatile uint32_t *)((uint8_t *)gIoapic + IOAPIC_DATA) = val; +} + +// IRQ n -> redirection table at register 0x10 + 2*n (low), 0x11 + 2*n (high). +#define IOREDTBL_LO(n) (0x10 + 2*(n)) +#define IOREDTBL_HI(n) (0x11 + 2*(n)) +// Interrupt vector base: IRQ 0 -> vector 0x20, IRQ 1 -> 0x21, ... +#define IRQ_VECTOR_BASE 0x20 + +void HalApicRouteIrq(uint8_t irq) { + // Full initial setup of the redirection entry. + // Sets the vector and clears the mask bit in one write. + uint32_t vector = IRQ_VECTOR_BASE + irq; // e.g. IRQ 1 -> vector 0x21 + IoapicWrite(IOREDTBL_LO(irq), vector); // unmasked (bit 16 = 0), edge, fixed + IoapicWrite(IOREDTBL_HI(irq), 0); // deliver to LAPIC id 0 +} + +void HalApicMaskIrq(uint8_t irq) { + uint32_t lo = IoapicRead(IOREDTBL_LO(irq)); + lo |= (1 << 16); + IoapicWrite(IOREDTBL_LO(irq), lo); +} + +void HalApicUnmaskIrq(uint8_t irq) { + uint32_t lo = IoapicRead(IOREDTBL_LO(irq)); + lo &= ~(1 << 16); // clear mask bit + lo = (lo & ~0xFF) | (IRQ_VECTOR_BASE + irq); + IoapicWrite(IOREDTBL_LO(irq), lo); + IoapicWrite(IOREDTBL_HI(irq), 0); // LAPIC id 0 +} + +void HalApicSendEoi(void) { + LAPIC_REG(LAPIC_EOI) = 0; +} + +void HalApicInitialize(uintptr_t lapicPhys, uintptr_t ioapicPhys) { + gLapic = (volatile uint32_t *)(gApi.PhysToVirt(lapicPhys)); + gIoapic = (volatile uint32_t *)(gApi.PhysToVirt(ioapicPhys)); + + // Enable Local APIC, set spurious vector to 0xFF. + LAPIC_REG(LAPIC_SPURIOUS) = LAPIC_ENABLE | 0xFF; + + // Mask all IOAPIC lines initially. + uint32_t maxRedir = (IoapicRead(1) >> 16) & 0xFF; + for (uint8_t i = 0; i <= maxRedir; i++) { + IoapicWrite(IOREDTBL_LO(i), (1 << 16) | (IRQ_VECTOR_BASE + i)); + IoapicWrite(IOREDTBL_HI(i), 0); + } +} diff --git a/code/hal/hal_apic.h b/code/hal/hal_apic.h new file mode 100644 index 0000000..b0339e4 --- /dev/null +++ b/code/hal/hal_apic.h @@ -0,0 +1,9 @@ +// hal_apic.h +#pragma once +#include + +void HalApicRouteIrq(uint8_t irq); +void HalApicMaskIrq(uint8_t irq); +void HalApicUnmaskIrq(uint8_t irq); +void HalApicSendEoi(void); +void HalApicInitialize(uintptr_t lapicPhys, uintptr_t ioapicPhys); diff --git a/code/hal/hal_debug.h b/code/hal/hal_debug.h new file mode 100644 index 0000000..b081c15 --- /dev/null +++ b/code/hal/hal_debug.h @@ -0,0 +1,4 @@ +#pragma once +// hal_debug.h - HAL debug output function +// Do not include outside HAL. +void HalDbgPrint(const char* fmt, ...); \ No newline at end of file diff --git a/code/hal/hal_disk.c b/code/hal/hal_disk.c new file mode 100644 index 0000000..72e857c --- /dev/null +++ b/code/hal/hal_disk.c @@ -0,0 +1,43 @@ +// hal_disk.c - drive registry; drivers register themselves via IoRegisterDisk +#include "hal_api.h" +#include "io_driver.h" +#include +#include + +#define MAX_DRIVES 8 + +static DISK_DRIVER gDrives[MAX_DRIVES]; +static bool gPresent[MAX_DRIVES]; + +KSTATUS IoRegisterDisk(uint8_t index, const DISK_DRIVER* driver) { + if (index >= MAX_DRIVES || !driver) return STATUS_INVALID_PARAMETER; + if (gPresent[index]) return STATUS_ALREADY_EXISTS; + gDrives[index] = *driver; + gPresent[index] = true; + return STATUS_SUCCESS; +} + +static KSTATUS DiskRead(uint8_t drive, uint64_t lba, + uint32_t count, void* buf) { + if (drive >= MAX_DRIVES || !gPresent[drive]) return STATUS_NOT_FOUND; + return gDrives[drive].ReadSectors(lba, count, buf); +} +static KSTATUS DiskWrite(uint8_t drive, uint64_t lba, + uint32_t count, const void* buf) { + if (drive >= MAX_DRIVES || !gPresent[drive]) return STATUS_NOT_FOUND; + return gDrives[drive].WriteSectors(lba, count, buf); +} +static bool DiskPresent(uint8_t drive) { + return drive < MAX_DRIVES && gPresent[drive]; +} +static uint64_t DiskSectorCount(uint8_t drive) { + if (drive >= MAX_DRIVES || !gPresent[drive]) return 0; + return gDrives[drive].SectorCount; +} + +void HalDiskInitialize(HAL_DISK* out) { + out->ReadSectors = DiskRead; + out->WriteSectors = DiskWrite; + out->DrivePresent = DiskPresent; + out->DriveSectorCount = DiskSectorCount; +} diff --git a/code/hal/hal_keyboard.c b/code/hal/hal_keyboard.c new file mode 100644 index 0000000..11bee3e --- /dev/null +++ b/code/hal/hal_keyboard.c @@ -0,0 +1,71 @@ +// hal_keyboard.c - PS/2 keyboard, interrupt-driven, 256-entry ring buffer +#include "hal_api.h" +#include "hal_apic.h" +#include +#include +#include + +#define PS2_DATA 0x60 +#define PS2_STAT 0x64 +#define PS2_CMD 0x64 + +#define KBD_BUF_SIZE 256 + +static uint8_t gBuf[KBD_BUF_SIZE]; +static volatile int gHead = 0, gTail = 0; +static void (*gCallback)(uint8_t) = (void *)0; + +// Minimal Set-2 to ASCII translation (unshifted only). +static const char gScanToAscii[128] = { + 0,0,'1','2','3','4','5','6','7','8','9','0','-','=','\b', + '\t','q','w','e','r','t','y','u','i','o','p','[',']','\n', + 0,'a','s','d','f','g','h','j','k','l',';','\'','`', + 0,'\\','z','x','c','v','b','n','m',',','.','/',0,'*', + 0,' ',0,0,0,0,0,0,0,0,0,0,0,0,0, + '7','8','9','-','4','5','6','+','1','2','3','0','.',0,0,0, +}; + +static void KbdIsr(void) { + uint8_t sc = __inbyte(PS2_DATA); + if (sc & 0x80) return; // key-up, ignore + int next = (gTail + 1) % KBD_BUF_SIZE; + if (next != gHead) { + gBuf[gTail] = sc; + gTail = next; + } + if (gCallback) gCallback(sc); +} + +static bool KbdPoll(void) { + return gHead != gTail; +} + +static uint8_t KbdReadScancode(void) { + while (gHead == gTail) { _mm_pause(); } + uint8_t sc = gBuf[gHead]; + gHead = (gHead + 1) % KBD_BUF_SIZE; + return sc; +} + +static char KbdReadChar(void) { + if (gHead == gTail) return 0; + uint8_t sc = KbdReadScancode(); + if (sc < 128) return gScanToAscii[sc]; + return 0; +} + +static void KbdSetCallback(void (*cb)(uint8_t sc)) { + gCallback = cb; +} + +void HalKeyboardInitialize(HAL_KEYBOARD *out) { + // Flush PS/2 output buffer + while (__inbyte(PS2_STAT) & 1) __inbyte(PS2_DATA); + + out->Poll = KbdPoll; + out->ReadScancode = KbdReadScancode; + out->ReadChar = KbdReadChar; + out->SetCallback = KbdSetCallback; + out->Isr = KbdIsr; + out->IrqNumber = 1; +} diff --git a/code/hal/hal_main.c b/code/hal/hal_main.c new file mode 100644 index 0000000..d10593b --- /dev/null +++ b/code/hal/hal_main.c @@ -0,0 +1,250 @@ +// hal_main.c - HAL initialisation and HalGetApi +#include "hal_api.h" +#include "hal_apic.h" +#include +#include +#include +#include "printf.h" + +// Declared in other hal_*.c files: +void HalScreenInitialize(uintptr_t fb, int w, int h, int stride, HAL_SCREEN* out); +void HalKeyboardInitialize(HAL_KEYBOARD* out); +KSTATUS HalTimerInitialize(uintptr_t lapicPhys, uintptr_t hpetPhys, HAL_TIMER *out); +void HalPciInitialize(HAL_PCI* out); +void HalDiskInitialize(HAL_DISK* out); +extern void HalSetDebugEnabled(int v); + +// Defined in mm_virt.c - HAL needs it for MMIO window access. +static uint64_t gPhysBase = 0xFFFF880000000000ULL; + +HAL_API gApi; +static int gInitialised = 0; +extern void (*gTimerCallback)(void); + +// --------------------------------------------------------------------------- +// ACPI table walker - minimal, just enough to find APIC and HPET addresses. +// --------------------------------------------------------------------------- +#define ACPI_SIG(a,b,c,d) ((uint32_t)(a)|((uint32_t)(b)<<8)|((uint32_t)(c)<<16)|((uint32_t)(d)<<24)) + +#pragma pack(push, 1) +#pragma warning(disable : 4200) + +// ACPI RSDP (Root System Description Pointer) +typedef struct { + char Signature[8]; + uint8_t Checksum; + char OEMID[6]; + uint8_t Revision; + uint32_t RsdtAddress; + uint32_t Length; + uint64_t XsdtAddress; + uint8_t ExtendedChecksum; + uint8_t Reserved[3]; +} RSDP; + +// ACPI SDT Header +typedef struct { + char Signature[4]; + uint32_t Length; + uint8_t Revision; + uint8_t Checksum; + char OEMID[6]; + char OEMTableID[8]; + uint32_t OEMRevision; + uint32_t CreatorID; + uint32_t CreatorRevision; +} ACPISDTHeader; + +// RSDT (Root System Description Table) +typedef struct { + ACPISDTHeader Header; + uint32_t PointerToOtherSDT[]; +} RSDT; + +// XSDT (Extended System Description Table) +typedef struct { + ACPISDTHeader Header; + uint64_t PointerToOtherSDT[]; +} XSDT; + +// MADT (Multiple APIC Description Table) +typedef struct { + ACPISDTHeader Header; + uint32_t LocalAPICAddress; + uint32_t Flags; + uint8_t Entries[]; +} MADT; + +#pragma pack(pop) + +static uintptr_t gLapicPhys = 0xFEE00000; +static uintptr_t gIoapicPhys = 0xFEC00000; +static uintptr_t gHpetPhys = 0xFED00000; + +int debugEnabled = 0; +int _fltused; // fuckass +static void hal_putchar(char c) { + gApi.Screen.PrintChar(c, 0x00FF00, 0x000000); +} +void HalDbgPrint(const char* fmt, ...) { + if (!debugEnabled) return; + + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); +} + +static void *HalPhysToVirt(uint64_t phys) { + return (void *)(phys + gPhysBase); +} + +static void ParseMadt(MADT* madt) { + gLapicPhys = madt->LocalAPICAddress; + uint8_t* p = (uint8_t *)(madt + 1); + uint8_t* end = (uint8_t *)madt + madt->Header.Length; + while (p < end) { + uint8_t type = p[0], len = p[1]; + if (type == 1) { // I/O APIC entry + gIoapicPhys = *(uint32_t *)(p + 4); + } + p += len ? len : 1; + } +} + +static int validate_checksum(void* table, uint32_t length) { + uint8_t sum = 0; + uint8_t* bytes = (uint8_t*)table; + for (uint32_t i = 0; i < length; i++) { + sum += bytes[i]; + } + return sum == 0; +} + +static void WalkAcpi(uintptr_t rsdpPhys) { + if (!rsdpPhys) return; + + // Map RSDP into virtual memory + RSDP* rsdp = (RSDP*)(rsdpPhys + gPhysBase); + + if (memcmp(rsdp->Signature, "RSD PTR ", 8) != 0) { + HalDbgPrint("HAL: Invalid RSDP signature!\n"); + return; + } + + ACPISDTHeader* sdtHeader = NULL; + uint32_t count = 0; + int isXsdt = 0; + + // Safely find and validate the XSDT (ACPI 2.0+) + if (rsdp->Revision >= 2 && rsdp->XsdtAddress != 0) { + XSDT* xsdt = (XSDT*)(rsdp->XsdtAddress + gPhysBase); + + if (validate_checksum(xsdt, xsdt->Header.Length) && + memcmp(xsdt->Header.Signature, "XSDT", 4) == 0) { + + sdtHeader = &xsdt->Header; + count = (xsdt->Header.Length - sizeof(ACPISDTHeader)) / 8; + isXsdt = 1; + } + } + + // Fallback to safely finding and validating the RSDT (ACPI 1.0) + if (sdtHeader == NULL && rsdp->RsdtAddress != 0) { + RSDT* rsdt = (RSDT*)((uintptr_t)rsdp->RsdtAddress + gPhysBase); + + if (validate_checksum(rsdt, rsdt->Header.Length) && + memcmp(rsdt->Header.Signature, "RSDT", 4) == 0) { + + sdtHeader = &rsdt->Header; + count = (rsdt->Header.Length - sizeof(ACPISDTHeader)) / 4; + isXsdt = 0; + } + } + + if (sdtHeader == NULL) { + HalDbgPrint("HAL: No valid XSDT or RSDT found!\n"); + return; + } + + // Walk the tables + for (uint32_t i = 0; i < count; i++) { + uintptr_t tablePhys = 0; + + if (isXsdt) { + tablePhys = ((XSDT*)sdtHeader)->PointerToOtherSDT[i]; + } else { + tablePhys = ((RSDT*)sdtHeader)->PointerToOtherSDT[i]; + } + + // Paranoid alignment check to reject firmware garbage pointers + if (!tablePhys || (tablePhys & 3) != 0) continue; + + ACPISDTHeader* header = (ACPISDTHeader*)(tablePhys + gPhysBase); + + // Ensure the table isn't corrupt before parsing + if (!validate_checksum(header, header->Length)) continue; + + // Parse MADT + if (memcmp(header->Signature, "APIC", 4) == 0) { + ParseMadt((MADT*)header); + } + // Parse HPET + else if (memcmp(header->Signature, "HPET", 4) == 0) { + // HPET base address block is located at offset 44 + // (which is 8 bytes past the 36-byte ACPISDTHeader) + gHpetPhys = *(uint64_t*)((uint8_t*)header + 44) & ~0xFFFULL; + } + } +} + +// --------------------------------------------------------------------------- +KSTATUS HalInitialize(const HAL_INIT_PARAMS* initParams) { + if (gInitialised) return STATUS_ALREADY_EXISTS; + gPhysBase = initParams->PhysicalWindowBase; + gApi.PhysToVirt = HalPhysToVirt; + debugEnabled = initParams->DebugEnabled; + + // Screen first so DbgPrint works immediately. + HalScreenInitialize(initParams->FramebufferBase + initParams->PhysicalWindowBase, + (int)initParams->FramebufferWidth, + (int)initParams->FramebufferHeight, + (int)initParams->FramebufferStride, + &gApi.Screen); + + printf_set_putchar(hal_putchar); + + HalDbgPrint("HAL: screen %dx%d\n", + initParams->FramebufferWidth, initParams->FramebufferHeight); + + // Parse ACPI to find LAPIC / IOAPIC / HPET addresses. + if (initParams->RsdpPhysical) WalkAcpi(initParams->RsdpPhysical); + HalDbgPrint("HAL: LAPIC=%016llx IOAPIC=%016llx HPET=%016llx\n", + gLapicPhys, gIoapicPhys, gHpetPhys); + + HalApicInitialize(gLapicPhys, gIoapicPhys); + HalKeyboardInitialize(&gApi.Keyboard); + + KSTATUS ts = HalTimerInitialize(gLapicPhys, gHpetPhys, &gApi.Timer); + if (!KSUCCESS(ts)) HalDbgPrint("HAL: HPET unavailable, using fallback\n"); + + HalPciInitialize(&gApi.Pci); + HalDiskInitialize(&gApi.Disk); + + gApi.Intc.RouteIrq = HalApicRouteIrq; + gApi.Intc.MaskIrq = HalApicMaskIrq; + gApi.Intc.UnmaskIrq = HalApicUnmaskIrq; + gApi.Intc.SendEoi = HalApicSendEoi; + + gApi.Version = HAL_API_VERSION; + gInitialised = 1; + + HalDbgPrint("HAL: initialisation complete.\n"); + return STATUS_SUCCESS; +} + +void HalRegisterScheduler(void (*pKeSchedulerTick)(void)) { + gTimerCallback = pKeSchedulerTick; +} + +const HAL_API* HalGetApi(void) { return &gApi; } diff --git a/code/hal/hal_pci.c b/code/hal/hal_pci.c new file mode 100644 index 0000000..90f1a72 --- /dev/null +++ b/code/hal/hal_pci.c @@ -0,0 +1,63 @@ +// hal_pci.c - PCI configuration space via Mechanism 1 port I/O +#include "hal_api.h" +#include + +#define PCI_CONFIG_ADDR 0xCF8 +#define PCI_CONFIG_DATA 0xCFC + +static uint32_t MakeAddr(uint8_t bus, uint8_t dev, uint8_t fn, uint8_t reg) { + return 0x80000000UL + | ((uint32_t)bus << 16) + | ((uint32_t)(dev & 0x1F) << 11) + | ((uint32_t)(fn & 0x07) << 8) + | (reg & 0xFC); +} + +static uint32_t PciRead32(uint8_t bus, uint8_t dev, uint8_t fn, uint8_t reg) { + __outdword(PCI_CONFIG_ADDR, MakeAddr(bus, dev, fn, reg)); + return __indword(PCI_CONFIG_DATA); +} + +static void PciWrite32(uint8_t bus, uint8_t dev, uint8_t fn, + uint8_t reg, uint32_t val) { + __outdword(PCI_CONFIG_ADDR, MakeAddr(bus, dev, fn, reg)); + __outdword(PCI_CONFIG_DATA, val); +} + +static bool PciFindDevice(uint16_t vendor, uint16_t device, + uint8_t* outBus, uint8_t* outDev, uint8_t* outFn) { + for (int bus = 0; bus < 256; bus++) + for (int dev = 0; dev < 32; dev++) + for (int fn = 0; fn < 8; fn++) { + uint32_t id = PciRead32((uint8_t)bus, (uint8_t)dev, (uint8_t)fn, 0); + if ((id & 0xFFFF) == vendor && (id >> 16) == device) { + *outBus = (uint8_t)bus; *outDev = (uint8_t)dev; *outFn = (uint8_t)fn; + return true; + } + } + return false; +} + +static bool PciFindClass(uint8_t classCode, uint8_t subclass, + uint8_t* outBus, uint8_t* outDev, uint8_t* outFn) { + for (int bus = 0; bus < 256; bus++) + for (int dev = 0; dev < 32; dev++) + for (int fn = 0; fn < 8; fn++) { + uint32_t id = PciRead32((uint8_t)bus,(uint8_t)dev,(uint8_t)fn,0); + if ((id & 0xFFFF) == 0xFFFF) continue; // no device + uint32_t cc = PciRead32((uint8_t)bus,(uint8_t)dev,(uint8_t)fn,8); + if (((cc >> 24) & 0xFF) == classCode && + ((cc >> 16) & 0xFF) == subclass) { + *outBus = (uint8_t)bus; *outDev = (uint8_t)dev; *outFn = (uint8_t)fn; + return true; + } + } + return false; +} + +void HalPciInitialize(HAL_PCI* out) { + out->ConfigRead32 = PciRead32; + out->ConfigWrite32 = PciWrite32; + out->FindDevice = PciFindDevice; + out->FindClass = PciFindClass; +} diff --git a/code/hal/hal_screen.c b/code/hal/hal_screen.c new file mode 100644 index 0000000..7343d47 --- /dev/null +++ b/code/hal/hal_screen.c @@ -0,0 +1,118 @@ +// hal_screen.c - GOP framebuffer screen driver with embedded 8x16 font +// +// The 8x16 bitmap font is a standard VGA/PC font. We embed just the +// printable ASCII range (0x20–0x7E). Each glyph is 16 bytes; bit 7 of +// each byte is the leftmost pixel. +#include "hal_api.h" +#include +#include +#include + +static uint32_t* gFb = (uint32_t *)0; +static int gWidth = 0; +static int gHeight = 0; +static int gStride = 0; // pixels per row +static int gCursorX = 0, gCursorY = 0; + +#define FONT_W 8 +#define FONT_H 16 + +// --------------------------------------------------------------------------- +// 8x16 VGA font - printable ASCII only (glyph 0 = space = 0x20) +// --------------------------------------------------------------------------- +#include "font8x16.h" // see font8x16.h below + +// --------------------------------------------------------------------------- +// Internals +// --------------------------------------------------------------------------- +static inline void PutPixelRaw(int x, int y, uint32_t color) { + if ((unsigned)x < (unsigned)gWidth && (unsigned)y < (unsigned)gHeight) + gFb[y * gStride + x] = color; +} + +// --------------------------------------------------------------------------- +// HAL_SCREEN implementations +// --------------------------------------------------------------------------- +static void ScreenClear(uint32_t color) { + for (int y = 0; y < gHeight; y++) + for (int x = 0; x < gWidth; x++) + gFb[y * gStride + x] = color; + gCursorX = 0; gCursorY = 0; +} + +static void ScreenPutPixel(int x, int y, uint32_t color) { + PutPixelRaw(x, y, color); +} + +static void ScreenBlit(int x, int y, int w, int h, const uint32_t* pixels) { + for (int row = 0; row < h; row++) + for (int col = 0; col < w; col++) + PutPixelRaw(x + col, y + row, pixels[row * w + col]); +} + +static void ScreenGetSize(int* w, int* h) { *w = gWidth; *h = gHeight; } + +static void ScreenScroll(int lines) { + if (lines <= 0 || lines >= gHeight) { ScreenClear(0); return; } + int rowBytes = gStride * sizeof(uint32_t); + memmove(gFb, gFb + lines * gStride, + (size_t)(gHeight - lines) * rowBytes); + // Clear the revealed rows at the bottom. + memset(gFb + (gHeight - lines) * gStride, 0, + (size_t)lines * rowBytes); +} + +static void ScreenPutChar(char c, int x, int y, uint32_t fg, uint32_t bg) { + if ((unsigned char)c < 0x20 || (unsigned char)c > 0x7E) c = '?'; + const uint8_t* glyph = Font8x16 + ((unsigned char)c - 0x20) * 16; + for (int row = 0; row < 16; row++) { + uint8_t bits = glyph[row]; + for (int col = 0; col < 8; col++) { + uint32_t color = (bits & (1 << col)) ? fg : bg; // i don't know why, i don't want to know why, i shouldn't have to wonder why but the font is backwards unless we do this terriblness + PutPixelRaw(x + col, y + row, color); + } + } +} + +static void ScreenPrintChar(char c, uint32_t fg, uint32_t bg) { + int cols = gWidth / FONT_W; + int rows = gHeight / FONT_H; + + // Mirror to serial + while ((__inbyte(0x3FD) & 0x20) == 0); + if (c == '\n') __outbyte(0x3F8, '\r'); + __outbyte(0x3F8, c); + + if (c == '\n') { + gCursorX = 0; + gCursorY++; + } else if (c == '\r') { + gCursorX = 0; + } else { + ScreenPutChar(c, gCursorX * FONT_W, gCursorY * FONT_H, fg, bg); + if (++gCursorX >= cols) { gCursorX = 0; gCursorY++; } + } + if (gCursorY >= rows) { + ScreenScroll(FONT_H); + gCursorY = rows - 1; + } +} + +// --------------------------------------------------------------------------- +// Populate the HAL_SCREEN vtable +// --------------------------------------------------------------------------- +void HalScreenInitialize(uintptr_t fb, int w, int h, int stride, + HAL_SCREEN* out) { + gFb = (uint32_t *)fb; + gWidth = w; + gHeight = h; + gStride = stride; + out->Clear = ScreenClear; + out->PutPixel = ScreenPutPixel; + out->Blit = ScreenBlit; + out->GetSize = ScreenGetSize; + out->Scroll = ScreenScroll; + out->PutChar = ScreenPutChar; + out->PrintChar = ScreenPrintChar; + ScreenClear(0x000000); +} diff --git a/code/hal/hal_timer.c b/code/hal/hal_timer.c new file mode 100644 index 0000000..47bd507 --- /dev/null +++ b/code/hal/hal_timer.c @@ -0,0 +1,136 @@ +// hal_timer.c - Local APIC timer, calibrated against PIT channel 2 +#include "hal_api.h" +#include "hal_apic.h" +#include "hal_debug.h" +#include +#include + +#define LAPIC_TIMER_LVT 0x320 +#define LAPIC_TIMER_INIT 0x380 +#define LAPIC_TIMER_CUR 0x390 +#define LAPIC_TIMER_DIV 0x3E0 + +#define TIMER_VECTOR 0x20 // vector 0x20 = IRQ 0 slot in IDT +#define TIMER_PERIODIC (1 << 17) +#define TIMER_MASKED (1 << 16) +#define TIMER_DIV16 0x3 + +#define QUANTUM_MS 10 +#define PIT_HZ 1193182UL + +extern HAL_API gApi; +static volatile uint32_t* gLapic = NULL; +#define LAPIC_REG(off) (*(volatile uint32_t *)((uint8_t *)gLapic + (off))) + +static volatile uint64_t gTicks = 0; +void (*gTimerCallback)(void) = NULL; + +static inline void outb(uint16_t port, uint8_t val) { __outbyte(port, val); } +static inline uint8_t inb(uint16_t port) { return __inbyte(port); } + +static void TimerIsr(void) { + gTicks++; + if (gTimerCallback) gTimerCallback(); + // EOI is sent by KeIrqDispatch after this returns +} + +static uint64_t QueryTicks(void) { return gTicks; } + +static void Stall(uint32_t us) { + uint64_t start = gTicks; + uint64_t ms = (us + 999) / 1000; + while ((gTicks - start) < ms) _mm_pause(); +} + +// Returns HPET ticks/second, or 0 if HPET is unavailable. +static uint64_t HpetInit(uintptr_t hpetPhys) { + // HPET register block, accessed through physical window + volatile uint64_t *hpet = (volatile uint64_t *)gApi.PhysToVirt(hpetPhys); + + // General Capabilities register (offset 0): + // Bits 63:32 = counter clock period in femtoseconds + uint64_t caps = hpet[0]; + uint32_t periodFs = (uint32_t)(caps >> 32); + if (!periodFs) return 0; + + // Enable the HPET main counter (General Configuration, offset 0x10, bit 0) + hpet[2] |= 1; // offset 0x10 / 8 = index 2 + + return (uint64_t)1e15 / periodFs; // ticks per second +} + +// Use PIT channel 2 one-shot to measure how many APIC ticks elapse in 10 ms, then return ticks/ms. +static uint32_t CalibrateApicTimerViaPit(void) { + // Divide by 16 + LAPIC_REG(LAPIC_TIMER_DIV) = TIMER_DIV16; + // Mask, set vector - leave masked during calibration + LAPIC_REG(LAPIC_TIMER_LVT) = TIMER_MASKED | TIMER_VECTOR; + // Load max count + LAPIC_REG(LAPIC_TIMER_INIT) = 0xFFFFFFFF; + + // PIT channel 2: one-shot, ~10 ms + uint16_t pit_count = (uint16_t)(PIT_HZ / 100); // 11931 ≈ 10 ms + outb(0x61, (inb(0x61) & ~0x02) | 0x01); // gate on, speaker off + outb(0x43, 0xB0); // ch2, lo/hi, mode 0, binary + outb(0x42, (uint8_t)(pit_count & 0xFF)); + outb(0x42, (uint8_t)(pit_count >> 8)); + + // Wait for OUT2 (bit 5 of port 0x61) to go high + while (!(inb(0x61) & 0x20)) _mm_pause(); + + uint32_t elapsed = 0xFFFFFFFF - LAPIC_REG(LAPIC_TIMER_CUR); + return elapsed / 10; // ticks per ms +} + +// Use HPET main counter to measure how many APIC ticks elapse in 10 ms, then return ticks/ms. +static uint32_t CalibrateApicTimerViaHpet(uintptr_t hpetPhys) { + volatile uint64_t *hpet = (volatile uint64_t *)gApi.PhysToVirt(hpetPhys); + uint64_t hpetHz = HpetInit(hpetPhys); + if (!hpetHz) return 0; + + // Ticks in 10 ms = hpetHz / 100 + uint64_t ticksFor10ms = hpetHz / 100; + + LAPIC_REG(LAPIC_TIMER_DIV) = TIMER_DIV16; + LAPIC_REG(LAPIC_TIMER_LVT) = TIMER_MASKED | TIMER_VECTOR; + LAPIC_REG(LAPIC_TIMER_INIT) = 0xFFFFFFFF; + + // HPET main counter is at offset 0xF0, index 0xF0/8 = 30 + uint64_t hpetStart = hpet[30]; + while ((hpet[30] - hpetStart) < ticksFor10ms) _mm_pause(); + + uint32_t elapsed = 0xFFFFFFFF - LAPIC_REG(LAPIC_TIMER_CUR); + return elapsed / 10; // APIC ticks per ms +} + +KSTATUS HalTimerInitialize(uintptr_t lapicPhys, uintptr_t hpetPhys, HAL_TIMER *out) { + gLapic = (volatile uint32_t *)gApi.PhysToVirt(lapicPhys); + HalDbgPrint("HAL: lapicPhys=0x%llX, lapicVirt=0x%llX, hpetPhys=0x%llX\n", lapicPhys, (uintptr_t)gLapic, hpetPhys); + + uint32_t ticksPerMs = 0; + if (hpetPhys) { + HalDbgPrint("HAL: Attempting to calibrate APIC timer via HPET...\n"); + ticksPerMs = CalibrateApicTimerViaHpet(hpetPhys); + } + if (!ticksPerMs) { + HalDbgPrint("HAL: HPET unavailable or calibration failed. Falling back to PIT...\n"); + ticksPerMs = CalibrateApicTimerViaPit(); + } + if (!ticksPerMs) { + HalDbgPrint("HAL: APIC calibration failed. How?\n"); + return STATUS_DEVICE_ERROR; + } + + HalDbgPrint("HAL: APIC timer: %u ticks/ms\n", ticksPerMs); + + // Configure LAPIC timer in periodic mode + LAPIC_REG(LAPIC_TIMER_DIV) = TIMER_DIV16; + LAPIC_REG(LAPIC_TIMER_LVT) = TIMER_PERIODIC | TIMER_VECTOR; + LAPIC_REG(LAPIC_TIMER_INIT) = ticksPerMs * QUANTUM_MS; + + out->QueryTicks = QueryTicks; + out->Stall = Stall; + out->Isr = TimerIsr; + out->IrqNumber = 0; + return STATUS_SUCCESS; +} diff --git a/code/hal/io_driver.h b/code/hal/io_driver.h new file mode 100644 index 0000000..5c4550c --- /dev/null +++ b/code/hal/io_driver.h @@ -0,0 +1,17 @@ +#pragma once +// io_driver.h - driver-side interface for registering disk controllers +#include "hal_api.h" +#include "ke_status.h" +#include "../kernel/io_file.h" +#include + +typedef KSTATUS (*DRIVER_ENTRY_FN)(const HAL_API* hal); +typedef void (*DRIVER_UNLOAD_FN)(void); + +typedef struct DISK_DRIVER { + KSTATUS (*ReadSectors)(uint64_t lba, uint32_t count, void* buf); + KSTATUS (*WriteSectors)(uint64_t lba, uint32_t count, const void* buf); + uint64_t SectorCount; +} DISK_DRIVER; + +KSTATUS IoRegisterDisk(uint8_t driveIndex, const DISK_DRIVER* driver); diff --git a/code/ini_parser.c b/code/ini_parser.c new file mode 100644 index 0000000..adbd93b --- /dev/null +++ b/code/ini_parser.c @@ -0,0 +1,53 @@ +// ini_parser.c - minimal [section] key=value parser +// Used by the bootloader to read boot.ini and drivers/drivers.ini. +// No heap; caller provides fixed-size output buffers. +#include "ini_parser.h" +#include + +static inline int IsWs(char c) { return c == ' ' || c == '\t' || c == '\r'; } + +static char* TrimLeft(char* s) { + while (*s && IsWs(*s)) s++; + return s; +} + +static void TrimRight(char* s) { + char* e = s + strlen(s); + while (e > s && IsWs(*(e-1))) *--e = '\0'; +} + +// Parse 'buf' (null-terminated) for [section] / key=value. +// Calls cb(section, key, value, userdata) for each key found. +void IniParse(char* buf, IniCallback cb, void* userdata) { + char section[64] = ""; + char* line = buf; + + while (*line) { + char* end = line; + while (*end && *end != '\n') end++; + char saved = *end; + *end = '\0'; + + char* p = TrimLeft(line); + if (*p == '[') { + p++; + char* close = strchr(p, ']'); + if (close) { *close = '\0'; strncpy(section, p, 63); section[63] = '\0'; } + } else if (*p && *p != ';' && *p != '#') { + char* eq = strchr(p, '='); + if (eq) { + *eq = '\0'; + char* key = p; TrimRight(key); + char* val = TrimLeft(eq + 1); TrimRight(val); + cb(section, key, val, userdata); + } else { + // Key with no value (e.g., a driver filename in drivers.ini). + TrimRight(p); + if (*p) cb(section, p, "", userdata); + } + } + + *end = saved; + line = end + (*end ? 1 : 0); + } +} diff --git a/code/kernel/boot_info.h b/code/kernel/boot_info.h new file mode 100644 index 0000000..4186585 --- /dev/null +++ b/code/kernel/boot_info.h @@ -0,0 +1,45 @@ +#pragma once +// boot_info.h - shared between bootx64.efi and kernel.exe +// The bootloader fills this structure and passes a pointer to KernelMain. +#include +#include "memory_map.h" + +#define BOOT_INFO_MAGIC 0x424F4F54494E464FULL /* 'BOOTINFO' */ +#define MAX_BOOT_MODULES 32 + +typedef struct BOOT_MODULE { + char Name[32]; /* e.g. "hal.dll", "ide.sys" */ + uintptr_t VirtBase; /* where it was mapped */ + size_t ImageSize; +} BOOT_MODULE; + +typedef struct BOOT_INFO { + uint64_t Magic; + + /* Physical memory. */ + MEMORY_MAP MemoryMap; + + /* GOP framebuffer. */ + uintptr_t FramebufferBase; + uint32_t FramebufferWidth; + uint32_t FramebufferHeight; + uint32_t FramebufferStride; /* pixels per row */ + uint32_t _pad0; + + /* Loaded modules. */ + BOOT_MODULE Modules[MAX_BOOT_MODULES]; + uint32_t ModuleCount; + uint32_t _pad1; + + char CommandLine[64]; + + /* ACPI RSDP physical address (for APIC, HPET). */ + uintptr_t RsdpPhysical; + + /* Direct physical window base - always 0xFFFF880000000000. */ + uintptr_t PhysicalMapBase; + + /* From boot.ini */ + uint32_t DebugEnabled; + uint32_t _pad2; +} BOOT_INFO; diff --git a/code/kernel/ini_parser.h b/code/kernel/ini_parser.h new file mode 100644 index 0000000..a169759 --- /dev/null +++ b/code/kernel/ini_parser.h @@ -0,0 +1,4 @@ +#pragma once +typedef void (*IniCallback)(const char* section, const char* key, + const char* value, void* userdata); +void IniParse(char* buf, IniCallback cb, void* userdata); diff --git a/code/kernel/io_file.c b/code/kernel/io_file.c new file mode 100644 index 0000000..cdaecc7 --- /dev/null +++ b/code/kernel/io_file.c @@ -0,0 +1,113 @@ +// io_file.c - VFS dispatch layer +#include "ke_list.h" +#include "io_file.h" +#include "mm_virt.h" +#include "ob_object.h" +#include + +#define MAX_DRIVES 8 + +typedef struct { + IO_FILESYSTEM *Fs; + IO_VOLUME_PARAMS Vol; +} VOLUME_ENTRY; + +static VOLUME_ENTRY gVolumes[MAX_DRIVES]; + +// --------------------------------------------------------------------------- +// Registration +// --------------------------------------------------------------------------- +KSTATUS IoRegisterFilesystem(uint8_t volumeIndex, + IO_FILESYSTEM *fs, + const IO_VOLUME_PARAMS *vol) { + if (volumeIndex >= MAX_DRIVES || !fs || !vol) + return STATUS_INVALID_PARAMETER; + if (gVolumes[volumeIndex].Fs) + return STATUS_ALREADY_EXISTS; + gVolumes[volumeIndex].Fs = fs; + gVolumes[volumeIndex].Vol = *vol; + return STATUS_SUCCESS; +} + +// --------------------------------------------------------------------------- +// Path parsing - "0:\apps\shell.exe" or just "apps\shell.exe" (drive 0) +// --------------------------------------------------------------------------- +static uint8_t ParseDrive(const char* path, const char **pathOut) { + // Accept "N:\..." prefix, otherwise default to drive 0. + if (path[0] >= '0' && path[0] <= '7' && + path[1] == ':' && (path[2] == '\\' || path[2] == '/')) { + *pathOut = path + 3; + return (uint8_t)(path[0] - '0'); + } + *pathOut = path; + return 0; +} + +// --------------------------------------------------------------------------- +// Destructor +// --------------------------------------------------------------------------- +static void FileDestroy(OBJECT* obj) { + FILE_OBJECT* f = CONTAINING_RECORD(obj, FILE_OBJECT, Header); + if (f->Fs && f->FileCtx) f->Fs->Close(f->Fs, f->FileCtx); +} + +// --------------------------------------------------------------------------- +// IoOpenFile +// --------------------------------------------------------------------------- +KSTATUS IoOpenFile(const char* path, FILE_OBJECT **out) { + if (!path || !out) return STATUS_INVALID_PARAMETER; + + const char* relPath; + uint8_t drive = ParseDrive(path, &relPath); + + IO_FILESYSTEM* fs = gVolumes[drive].Fs; + if (!fs) return STATUS_NOT_FOUND; + + void* fileCtx; + KSTATUS s = fs->Open(fs, relPath, &fileCtx); + if (!KSUCCESS(s)) return s; + + FILE_OBJECT* f = (FILE_OBJECT *)ObAllocateObject(ObjectTypeFile /* reuse slot */, + sizeof(FILE_OBJECT)); + if (!f) { fs->Close(fs, fileCtx); return STATUS_NO_MEMORY; } + f->Header.Destroy = FileDestroy; + f->Fs = fs; + f->FileCtx = fileCtx; + f->Size = fs->GetSize(fs, fileCtx); + f->Offset = 0; + + *out = f; + return STATUS_SUCCESS; +} + +// --------------------------------------------------------------------------- +// IoReadFile - sequential read at current offset +// --------------------------------------------------------------------------- +KSTATUS IoReadFile(FILE_OBJECT* file, void* buf, size_t size, size_t* bytesRead) { + if (!file || !buf) return STATUS_INVALID_PARAMETER; + if (file->Offset >= file->Size) { *bytesRead = 0; return STATUS_SUCCESS; } + + // Clamp to remaining bytes. + size_t remaining = (size_t)(file->Size - file->Offset); + if (size > remaining) size = remaining; + + KSTATUS s = file->Fs->Read(file->Fs, file->FileCtx, + file->Offset, buf, size, bytesRead); + if (KSUCCESS(s)) file->Offset += *bytesRead; + return s; +} + +// --------------------------------------------------------------------------- +KSTATUS IoSeekFile(FILE_OBJECT* file, uint64_t offset) { + if (!file) return STATUS_INVALID_PARAMETER; + file->Offset = offset; + return STATUS_SUCCESS; +} + +uint64_t IoGetFileSize(FILE_OBJECT* file) { + return file ? file->Size : 0; +} + +void IoCloseFile(FILE_OBJECT* file) { + if (file) ObDereferenceObject(&file->Header); +} diff --git a/code/kernel/io_file.h b/code/kernel/io_file.h new file mode 100644 index 0000000..c85c558 --- /dev/null +++ b/code/kernel/io_file.h @@ -0,0 +1,66 @@ +#pragma once +// io_file.h - VFS layer +// Filesystem drivers register an IO_FILESYSTEM vtable via IoRegisterFilesystem. +// Kernel and user code open files through IoOpenFile. +#include "ke_status.h" +#include "ob_object.h" +#include +#include + +// --------------------------------------------------------------------------- +// Filesystem driver vtable - filled in by fat32.sys (or any future fs driver) +// --------------------------------------------------------------------------- +typedef struct IO_FILESYSTEM { + // Open a file by absolute path (e.g. "apps\\shell.exe"). + // Returns an opaque per-file driver cookie in* fileCtx. + KSTATUS (*Open)(struct IO_FILESYSTEM* fs, + const char* path, void **fileCtx); + + // Read up to 'size' bytes at 'offset' into 'buf'. + // Sets* bytesRead to actual bytes copied. + KSTATUS (*Read)(struct IO_FILESYSTEM* fs, void* fileCtx, + uint64_t offset, void* buf, + size_t size, size_t* bytesRead); + + // Return the file size in bytes. + uint64_t (*GetSize)(struct IO_FILESYSTEM* fs, void* fileCtx); + + // Release any resources the driver allocated for fileCtx. + void (*Close)(struct IO_FILESYSTEM* fs, void* fileCtx); + + // Optional driver-private data. + void* DriverCtx; +} IO_FILESYSTEM; + +// --------------------------------------------------------------------------- +// FILE_OBJECT - the kernel object returned to callers +// --------------------------------------------------------------------------- +typedef struct FILE_OBJECT { + OBJECT Header; // must be first + IO_FILESYSTEM* Fs; + void* FileCtx; // driver cookie + uint64_t Size; + uint64_t Offset; // current position for sequential reads +} FILE_OBJECT; + +typedef struct IO_VOLUME_PARAMS { + uint8_t DiskIndex; // which disk in HAL_DISK table + uint64_t PartitionLba; // starting LBA of this partition + uint64_t PartitionSize; // sectors, for bounds checking +} IO_VOLUME_PARAMS; + +// --------------------------------------------------------------------------- +// Registration - called by fat32.sys from DriverEntry +// --------------------------------------------------------------------------- +// driveIndex matches the index passed to IoRegisterDisk. +KSTATUS IoRegisterFilesystem(uint8_t driveIndex, IO_FILESYSTEM* fs, const IO_VOLUME_PARAMS *vol); + +// --------------------------------------------------------------------------- +// Kernel-side API +// --------------------------------------------------------------------------- +KSTATUS IoOpenFile(const char* path, FILE_OBJECT **out); +KSTATUS IoReadFile(FILE_OBJECT* file, void* buf, + size_t size, size_t* bytesRead); +KSTATUS IoSeekFile(FILE_OBJECT* file, uint64_t offset); +uint64_t IoGetFileSize(FILE_OBJECT* file); +void IoCloseFile(FILE_OBJECT* file); diff --git a/code/kernel/ke_debug.c b/code/kernel/ke_debug.c new file mode 100644 index 0000000..7f0405c --- /dev/null +++ b/code/kernel/ke_debug.c @@ -0,0 +1,29 @@ +// ke_debug.c - debugging utilities +#include "hal_api.h" +#include +#include +#include +#include "printf.h" +int _fltused; // fuckass + +int gDebugEnabled = 0; +void (*PrintChar)(char, uint32_t, uint32_t); + +void kernel_putchar(char c) { + PrintChar(c, 0x00FF00, 0x000000); +} + +void DbgPrint(const char* fmt, ...) { + if (!gDebugEnabled) return; + + va_list va; + va_start(va, fmt); + vprintf(fmt, va); + va_end(va); +} + +void KeInitDebug(void (*PrintPtr)(char, uint32_t, uint32_t), int v) { + gDebugEnabled = v; + PrintChar = PrintPtr; + printf_set_putchar(kernel_putchar); +} diff --git a/code/kernel/ke_debug.h b/code/kernel/ke_debug.h new file mode 100644 index 0000000..179dd42 --- /dev/null +++ b/code/kernel/ke_debug.h @@ -0,0 +1,9 @@ +#ifndef KE_DEBUG_H +#define KE_DEBUG_H + +#include + +void KeInitDebug(void (*PrintPtr)(char, uint32_t, uint32_t), int v); +void DbgPrint(const char* fmt, ...); + +#endif // KE_DEBUG_H \ No newline at end of file diff --git a/code/kernel/ke_event.c b/code/kernel/ke_event.c new file mode 100644 index 0000000..2a08505 --- /dev/null +++ b/code/kernel/ke_event.c @@ -0,0 +1,72 @@ +// ke_event.c - synchronisation events +#include "ke_event.h" +#include "ke_thread.h" +#include "ke_sched.h" +#include "ob_object.h" + +static void EventDestroy(OBJECT* obj) { (void)obj; } + +KSTATUS KeEventCreate(EVENT_TYPE type, uint32_t initialState, EVENT **out) { + if (!out) return STATUS_INVALID_PARAMETER; + EVENT* e = (EVENT *)ObAllocateObject(ObjectTypeEvent, sizeof(EVENT)); + if (!e) return STATUS_NO_MEMORY; + e->Header.Destroy = EventDestroy; + e->Lock = (SPINLOCK)SPINLOCK_INIT; + e->Type = type; + e->Signaled = initialState ? 1 : 0; + LIST_INIT(&e->WaitList); + *out = e; + return STATUS_SUCCESS; +} + +void KeSignalEvent(EVENT* event) { + if (!event) return; + KeAcquireSpinlock(&event->Lock); + + if (event->Type == EventManualReset) { + // Wake all waiters. + event->Signaled = 1; + while (!LIST_IS_EMPTY(&event->WaitList)) { + LIST_ENTRY* node = ListPopHead(&event->WaitList); + THREAD* t = CONTAINING_RECORD(node, THREAD, SchedulerLink); + KeReleaseSpinlock(&event->Lock); + KeUnblockThread(t); + KeAcquireSpinlock(&event->Lock); + } + } else { + // Auto-reset: wake one waiter or set the flag for the next waiter. + if (!LIST_IS_EMPTY(&event->WaitList)) { + LIST_ENTRY* node = ListPopHead(&event->WaitList); + THREAD* t = CONTAINING_RECORD(node, THREAD, SchedulerLink); + KeReleaseSpinlock(&event->Lock); + KeUnblockThread(t); + return; + } + event->Signaled = 1; + } + KeReleaseSpinlock(&event->Lock); +} + +void KeClearEvent(EVENT* event) { + if (!event) return; + KeAcquireSpinlock(&event->Lock); + event->Signaled = 0; + KeReleaseSpinlock(&event->Lock); +} + +KSTATUS KeWaitForEvent(EVENT* event) { + if (!event) return STATUS_INVALID_PARAMETER; + THREAD* self = KeCurrentThread(); + + for (;;) { + KeAcquireSpinlock(&event->Lock); + if (event->Signaled) { + if (event->Type == EventAutoReset) event->Signaled = 0; + KeReleaseSpinlock(&event->Lock); + return STATUS_SUCCESS; + } + ListInsertTail(&event->WaitList, &self->SchedulerLink); + KeReleaseSpinlock(&event->Lock); + KeBlockThread(self, &event->Header); + } +} diff --git a/code/kernel/ke_event.h b/code/kernel/ke_event.h new file mode 100644 index 0000000..1549570 --- /dev/null +++ b/code/kernel/ke_event.h @@ -0,0 +1,22 @@ +#pragma once +// ke_event.h - auto-reset and manual-reset events +#include "ob_object.h" +#include "ke_spinlock.h" +#include "ke_list.h" +#include "ke_status.h" +#include + +typedef enum EVENT_TYPE { EventAutoReset, EventManualReset } EVENT_TYPE; + +typedef struct EVENT { + OBJECT Header; + SPINLOCK Lock; + EVENT_TYPE Type; + uint32_t Signaled; + LIST_ENTRY WaitList; +} EVENT; + +KSTATUS KeEventCreate(EVENT_TYPE type, uint32_t initialState, EVENT **out); +void KeSignalEvent(EVENT* event); +void KeClearEvent(EVENT* event); +KSTATUS KeWaitForEvent(EVENT* event); diff --git a/code/kernel/ke_gdt_reload.asm b/code/kernel/ke_gdt_reload.asm new file mode 100644 index 0000000..aa7c11d --- /dev/null +++ b/code/kernel/ke_gdt_reload.asm @@ -0,0 +1,45 @@ +; ke_helpers.asm +.code + +; void KeFlushGdt(GDTR* pGdtr, uint16_t codeSel, uint16_t dataSel, uint16_t tssSel); +KeFlushGdt PROC + ; RCX = pGdtr (pointer to limit/base struct) + ; RDX = codeSel + ; R8 = dataSel + ; R9 = tssSel + + ; 1. Load the GDT + lgdt fword ptr [rcx] + + ; 2. Reload Data Segments + mov ax, r8w + mov ds, ax + mov es, ax + mov ss, ax + mov fs, ax + mov gs, ax + + ; 3. Load Task Register + mov ax, r9w + ltr ax + + ; 4. Reload Code Segment (Far Return) + ; In MASM64, use OFFSET to get the address of the label. + ; We push the selector, then the offset, then issue retff / retfq. + + push rdx ; Push new Code Selector (RDX) + lea rax, [reload_cs] ; RIP-relative address of the label + push rax ; Push "return" address + db 048h, 0CBh ; rex_w retf (effectively retfq) + +reload_cs: + ret +KeFlushGdt ENDP + +; void KeFlushIdt(IDTR* pIdtr); +KeFlushIdt PROC + lidt fword ptr [rcx] + ret +KeFlushIdt ENDP + +END diff --git a/code/kernel/ke_idt.c b/code/kernel/ke_idt.c new file mode 100644 index 0000000..d2a2d13 --- /dev/null +++ b/code/kernel/ke_idt.c @@ -0,0 +1,175 @@ +// ke_idt.c - GDT, IDT, and TSS initialisation +// +// GDT layout (matches segment selectors in ke_switch.asm / ke_syscall.asm): +// 0x00 null +// 0x08 ring-0 code (64-bit) +// 0x10 ring-0 data +// 0x18 ring-3 code (64-bit, DPL=3) +// 0x20 ring-3 data (DPL=3) - note: 0x1B/0x23 = 0x18|3 / 0x20|3 +// 0x28 TSS low +// 0x30 TSS high +#include "ke_idt.h" +#include +#include + +// External assembly procedures +extern void KeFlushGdt(void* pGdtr, uint16_t codeSel, uint16_t dataSel, uint16_t tssSel); +extern void KeFlushIdt(void* pIdtr); + +extern void KeIrqStub0(void); +extern void KeIrqStub1(void); +extern void KeIrqStub2(void); +extern void KeIrqStub3(void); +extern void KeIrqStub4(void); +extern void KeIrqStub5(void); +extern void KeIrqStub6(void); +extern void KeIrqStub7(void); +extern void KeIrqStub8(void); +extern void KeIrqStub9(void); +extern void KeIrqStub10(void); +extern void KeIrqStub11(void); +extern void KeIrqStub12(void); +extern void KeIrqStub13(void); +extern void KeIrqStub14(void); +extern void KeIrqStub15(void); +extern void KeIrqStub16(void); +extern void KeIrqStub17(void); +extern void KeIrqStub18(void); +extern void KeIrqStub19(void); +extern void KeIrqStub20(void); +extern void KeIrqStub21(void); +extern void KeIrqStub22(void); +extern void KeIrqStub23(void); + +#define NUM_IRQS 24 + +// --------------------------------------------------------------------------- +// GDT +// --------------------------------------------------------------------------- +#define GDT_ENTRIES 8 +#define KERNEL_IST_STACK_SIZE 0x4000 + +static uint64_t gGdt[GDT_ENTRIES]; +static uint8_t gKernelStack[KERNEL_IST_STACK_SIZE]; + +#pragma pack(push, 1) +typedef struct { uint16_t Limit; uint64_t Base; } GDTR; +#pragma pack(pop) + +static void GdtSetEntry(int idx, uint32_t base, uint32_t limit, + uint8_t access, uint8_t flags) { + gGdt[idx] = + ((uint64_t)(limit & 0xFFFF)) | + ((uint64_t)(base & 0xFFFFFF) << 16) | + ((uint64_t)access << 40) | + ((uint64_t)(limit >> 16 & 0xF)<< 48) | + ((uint64_t)(flags & 0xF) << 52) | + ((uint64_t)(base >> 24 & 0xFF)<< 56); +} + +static void GdtSetTss(int idx, uintptr_t base, uint32_t limit) { + // TSS descriptor is 16 bytes (two GDT slots). + gGdt[idx] = 0; + gGdt[idx+1] = 0; + + gGdt[idx] = + ((uint64_t)(limit & 0xFFFF)) | + ((uint64_t)(base & 0xFFFFFF) << 16) | + (0x89ULL << 40) | // P=1,DPL=0,type=TSS64 avail + ((uint64_t)((limit>>16)&0xF) << 48) | + ((uint64_t)(base>>24 & 0xFF) << 56); + + gGdt[idx+1] = (base >> 32); +} + +TSS64 gTssStruct; +TSS64* gTss = &gTssStruct; + +void KeInitializeGdt(void) { + memset(gGdt, 0, sizeof(gGdt)); + memset(&gTssStruct, 0, sizeof(gTssStruct)); + + // 0x00: Null + GdtSetEntry(0, 0, 0, 0, 0); + // 0x08: Ring-0 Code (Access 0x9A, Flags 0xA for 64-bit) + GdtSetEntry(1, 0, 0xFFFFF, 0x9A, 0xA); + // 0x10: Ring-0 Data + GdtSetEntry(2, 0, 0xFFFFF, 0x92, 0xC); + // 0x18: Ring-3 Code + GdtSetEntry(3, 0, 0xFFFFF, 0xFA, 0xA); + // 0x20: Ring-3 Data + GdtSetEntry(4, 0, 0xFFFFF, 0xF2, 0xC); + + // 0x28: TSS (Occupies two slots: 0x28 and 0x30) + gTssStruct.IoMapBase = sizeof(TSS64); + gTssStruct.RSP0 = (uint64_t)(gKernelStack + KERNEL_IST_STACK_SIZE); // top of stack + + GdtSetTss(5, (uintptr_t)&gTssStruct, sizeof(TSS64) - 1); + + GDTR gdtr = { sizeof(gGdt) - 1, (uint64_t)gGdt }; + + // Call the MASM64 proc to reload everything + // Selectors: CS=0x08, Data=0x10, TSS=0x28 + KeFlushGdt(&gdtr, 0x08, 0x10, 0x28); +} + +// --------------------------------------------------------------------------- +// IDT +// --------------------------------------------------------------------------- +#define IDT_ENTRIES 256 + +#pragma pack(push, 1) +typedef struct { + uint16_t OffsetLow; + uint16_t Selector; + uint8_t Ist; + uint8_t TypeAttr; + uint16_t OffsetMid; + uint32_t OffsetHigh; + uint32_t Reserved; +} IDT_ENTRY; +#pragma pack(pop) + +static IDT_ENTRY gIdt[IDT_ENTRIES]; + +#pragma pack(push, 1) +typedef struct { uint16_t Limit; uint64_t Base; } IDTR; +#pragma pack(pop) + +static void IdtSetGate(int vec, uintptr_t handler, + uint8_t typeAttr, uint8_t ist) { + gIdt[vec].OffsetLow = (uint16_t)(handler & 0xFFFF); + gIdt[vec].Selector = 0x08; // ring-0 code segment + gIdt[vec].Ist = ist; + gIdt[vec].TypeAttr = typeAttr; + gIdt[vec].OffsetMid = (uint16_t)((handler >> 16) & 0xFFFF); + gIdt[vec].OffsetHigh = (uint32_t)((handler >> 32) & 0xFFFFFFFF); + gIdt[vec].Reserved = 0; +} + +void KeInitializeIdt(void) { + memset(gIdt, 0, sizeof(gIdt)); + + IdtSetGate(0, (uintptr_t)KeFaultDE, 0x8E, 0); + IdtSetGate(13, (uintptr_t)KeFaultGP, 0x8E, 0); + IdtSetGate(14, (uintptr_t)KeFaultPF, 0x8E, 0); + IdtSetGate(0x40, (uintptr_t)KeSyscallEntry, 0xEE, 0); + + static void *irqStubs[NUM_IRQS] = { + (void*)KeIrqStub0, (void*)KeIrqStub1, (void*)KeIrqStub2, + (void*)KeIrqStub3, (void*)KeIrqStub4, (void*)KeIrqStub5, + (void*)KeIrqStub6, (void*)KeIrqStub7, (void*)KeIrqStub8, + (void*)KeIrqStub9, (void*)KeIrqStub10, (void*)KeIrqStub11, + (void*)KeIrqStub12, (void*)KeIrqStub13, (void*)KeIrqStub14, + (void*)KeIrqStub15, (void*)KeIrqStub16, (void*)KeIrqStub17, + (void*)KeIrqStub18, (void*)KeIrqStub19, (void*)KeIrqStub20, + (void*)KeIrqStub21, (void*)KeIrqStub22, (void*)KeIrqStub23, + }; + for (int i = 0; i < NUM_IRQS; i++) + IdtSetGate(0x20 + i, (uintptr_t)irqStubs[i], 0x8E, 0); + + IDTR idtr = { sizeof(gIdt) - 1, (uint64_t)gIdt }; + + // Call the MASM64 proc to load IDT + KeFlushIdt(&idtr); +} diff --git a/code/kernel/ke_idt.h b/code/kernel/ke_idt.h new file mode 100644 index 0000000..cd495b4 --- /dev/null +++ b/code/kernel/ke_idt.h @@ -0,0 +1,34 @@ +#pragma once +// ke_idt.h - IDT, GDT, and TSS setup +#include + +// 64-bit TSS - minimal; we only care about RSP0. +#pragma pack(push, 1) +typedef struct TSS64 { + uint32_t Reserved0; + uint64_t RSP0; // loaded into RSP on ring-0 entry + uint64_t RSP1; + uint64_t RSP2; + uint64_t Reserved1; + uint64_t IST[7]; + uint64_t Reserved2; + uint16_t Reserved3; + uint16_t IoMapBase; +} TSS64; +#pragma pack(pop) + +extern TSS64* gTss; + +void KeInitializeGdt(void); +void KeInitializeIdt(void); + +// Called from hal_timer.c after HPET/APIC timer fires. +void KeTimerInterrupt(void); + +// Syscall entry - implemented in ke_syscall.asm. +extern void KeSyscallEntry(void); + +// Fault stubs installed by KeInitializeIdt. +extern void KeFaultDE(void); // #DE divide error +extern void KeFaultGP(void); // #GP general protection +extern void KeFaultPF(void); // #PF page fault diff --git a/code/kernel/ke_irq.c b/code/kernel/ke_irq.c new file mode 100644 index 0000000..31227d4 --- /dev/null +++ b/code/kernel/ke_irq.c @@ -0,0 +1,26 @@ +// ke_irq.c — IRQ dispatch, kernel-side +#include "ke_irq.h" +#include "hal_api.h" + +#define MAX_IRQS 24 + +static void (*gIrqHandlers[MAX_IRQS])(void); +static const HAL_API *gHal; + +void KeIrqInitialize(const HAL_API *hal) { + gHal = hal; +} + +void KeIrqRegister(uint8_t irq, void (*handler)(void)) { + if (irq >= MAX_IRQS || !handler) return; + gIrqHandlers[irq] = handler; + gHal->Intc.RouteIrq(irq); // programs IOAPIC, clears mask bit +} + +// Called from KeIrqCommon in assembly - this is the only symbol +// the assembly needs to know. +void KeIrqDispatch(uint8_t irq) { + gHal->Intc.SendEoi(); + if (irq < MAX_IRQS && gIrqHandlers[irq]) + gIrqHandlers[irq](); +} diff --git a/code/kernel/ke_irq.h b/code/kernel/ke_irq.h new file mode 100644 index 0000000..ba87dae --- /dev/null +++ b/code/kernel/ke_irq.h @@ -0,0 +1,7 @@ +#pragma once +#include "hal_api.h" +#include + +void KeIrqInitialize(const HAL_API *hal); +void KeIrqRegister(uint8_t irq, void (*handler)(void)); +void KeIrqDispatch(uint8_t irq); // called from ke_syscall.asm diff --git a/code/kernel/ke_list.h b/code/kernel/ke_list.h new file mode 100644 index 0000000..02f8324 --- /dev/null +++ b/code/kernel/ke_list.h @@ -0,0 +1,44 @@ +#pragma once +// ke_list.h - intrusive doubly-linked list +// Used throughout the kernel for run queues, wait lists, thread lists, etc. +#include + +typedef struct LIST_ENTRY { + struct LIST_ENTRY* Fwd; + struct LIST_ENTRY* Bwd; +} LIST_ENTRY; + +#define LIST_INIT(head) ((head)->Fwd = (head)->Bwd = (head)) +#define LIST_IS_EMPTY(head) ((head)->Fwd == (head)) + +// Recover the containing struct pointer from an embedded LIST_ENTRY. +#define CONTAINING_RECORD(ptr, type, member) \ + ((type *)((char *)(ptr) - offsetof(type, member))) + +static inline void ListInsertTail(LIST_ENTRY* head, LIST_ENTRY* node) { + node->Bwd = head->Bwd; + node->Fwd = head; + head->Bwd->Fwd = node; + head->Bwd = node; +} + +static inline void ListInsertHead(LIST_ENTRY* head, LIST_ENTRY* node) { + node->Fwd = head->Fwd; + node->Bwd = head; + head->Fwd->Bwd = node; + head->Fwd = node; +} + +static inline void ListRemove(LIST_ENTRY* node) { + node->Bwd->Fwd = node->Fwd; + node->Fwd->Bwd = node->Bwd; + node->Fwd = node->Bwd = node; /* self-loop: poison against double-remove */ +} + +// Pop the first entry off the list, or NULL if empty. +static inline LIST_ENTRY* ListPopHead(LIST_ENTRY* head) { + if (LIST_IS_EMPTY(head)) return (LIST_ENTRY *)0; + LIST_ENTRY* node = head->Fwd; + ListRemove(node); + return node; +} diff --git a/code/kernel/ke_mutex.c b/code/kernel/ke_mutex.c new file mode 100644 index 0000000..9e77a6b --- /dev/null +++ b/code/kernel/ke_mutex.c @@ -0,0 +1,69 @@ +// ke_mutex.c - binary ownership mutex +#include "ke_mutex.h" +#include "ke_thread.h" +#include "ke_sched.h" +#include "mm_virt.h" +#include "ob_object.h" + +static void MutexDestroy(OBJECT* obj) { (void)obj; } + +KSTATUS MutexCreate(MUTEX **out) { + if (!out) return STATUS_INVALID_PARAMETER; + MUTEX* m = (MUTEX *)ObAllocateObject(ObjectTypeMutex, sizeof(MUTEX)); + if (!m) return STATUS_NO_MEMORY; + m->Header.Destroy = MutexDestroy; + m->Lock = (SPINLOCK)SPINLOCK_INIT; + m->Owner = (struct THREAD *)0; + LIST_INIT(&m->WaitList); + *out = m; + return STATUS_SUCCESS; +} + +KSTATUS KeAcquireMutex(MUTEX* mutex) { + if (!mutex) return STATUS_INVALID_PARAMETER; + THREAD* self = KeCurrentThread(); + + for (;;) { + KeAcquireSpinlock(&mutex->Lock); + if (!mutex->Owner) { + mutex->Owner = self; + KeReleaseSpinlock(&mutex->Lock); + return STATUS_SUCCESS; + } + // Already owned - add self to wait list and block. + ListInsertTail(&mutex->WaitList, &self->SchedulerLink); + KeReleaseSpinlock(&mutex->Lock); + KeBlockThread(self, &mutex->Header); + // KeBlockThread calls KeYield; when we return here we've been + // unblocked by KeReleaseMutex - loop back and try to own it. + } +} + +KSTATUS KeTryAcquireMutex(MUTEX* mutex) { + if (!mutex) return STATUS_INVALID_PARAMETER; + THREAD* self = KeCurrentThread(); + KeAcquireSpinlock(&mutex->Lock); + if (!mutex->Owner) { + mutex->Owner = self; + KeReleaseSpinlock(&mutex->Lock); + return STATUS_SUCCESS; + } + KeReleaseSpinlock(&mutex->Lock); + return STATUS_FAILURE; +} + +void KeReleaseMutex(MUTEX* mutex) { + if (!mutex) return; + KeAcquireSpinlock(&mutex->Lock); + mutex->Owner = (struct THREAD *)0; + + // Wake the first waiter, if any. + if (!LIST_IS_EMPTY(&mutex->WaitList)) { + LIST_ENTRY* node = ListPopHead(&mutex->WaitList); + THREAD* waiter = CONTAINING_RECORD(node, THREAD, SchedulerLink); + KeReleaseSpinlock(&mutex->Lock); + KeUnblockThread(waiter); + return; + } + KeReleaseSpinlock(&mutex->Lock); +} diff --git a/code/kernel/ke_mutex.h b/code/kernel/ke_mutex.h new file mode 100644 index 0000000..cb2e843 --- /dev/null +++ b/code/kernel/ke_mutex.h @@ -0,0 +1,18 @@ +#pragma once +// ke_mutex.h - binary ownership mutex +#include "ob_object.h" +#include "ke_spinlock.h" +#include "ke_list.h" +#include "ke_status.h" + +typedef struct MUTEX { + OBJECT Header; + SPINLOCK Lock; + struct THREAD* Owner; /* NULL if unowned */ + LIST_ENTRY WaitList; +} MUTEX; + +KSTATUS MutexCreate(MUTEX **out); +KSTATUS KeAcquireMutex(MUTEX* mutex); +KSTATUS KeTryAcquireMutex(MUTEX* mutex); +void KeReleaseMutex(MUTEX* mutex); diff --git a/code/kernel/ke_process.c b/code/kernel/ke_process.c new file mode 100644 index 0000000..ef755fc --- /dev/null +++ b/code/kernel/ke_process.c @@ -0,0 +1,143 @@ +// ke_process.c - process model +#include "ke_process.h" +#include "ke_thread.h" // KeExitThread (forward declared below) +#include "mm_virt.h" +#include "ob_object.h" +#include +#include + +// --------------------------------------------------------------------------- +// Global process list +// --------------------------------------------------------------------------- +static LIST_ENTRY gProcessList; +static SPINLOCK gProcessListLock; +static uint32_t gNextProcessId = 1; + +static void ProcessInit(void) { + static int inited = 0; + if (!inited) { + LIST_INIT(&gProcessList); + gProcessListLock = (SPINLOCK)SPINLOCK_INIT; + inited = 1; + } +} + +LIST_ENTRY* KeGetProcessList(void) { + return &gProcessList; +} + +// --------------------------------------------------------------------------- +// Destructor (called by ObDereferenceObject when RefCount hits zero) +// --------------------------------------------------------------------------- +static void ProcessDestroy(OBJECT* obj) { + PROCESS* proc = CONTAINING_RECORD(obj, PROCESS, Header); + + // Release all remaining handles. + for (int i = 1; i < HANDLE_TABLE_SIZE; i++) { + if (proc->Handles[i]) { + ObDereferenceObject(proc->Handles[i]); + proc->Handles[i] = (OBJECT *)0; + } + } + + // Remove from global list. + KeAcquireSpinlock(&gProcessListLock); + ListRemove(&proc->GlobalLink); + KeReleaseSpinlock(&gProcessListLock); + + // Memory for the struct itself is freed by ObDereferenceObject after + // Destroy returns. +} + +// --------------------------------------------------------------------------- +// KeCreateProcess +// --------------------------------------------------------------------------- +KSTATUS KeCreateProcess(const char* name, PROCESS **out) { + ProcessInit(); + + if (!name || !out) return STATUS_INVALID_PARAMETER; + + PROCESS* proc = (PROCESS *)ObAllocateObject(ObjectTypeProcess, sizeof(PROCESS)); + if (!proc) return STATUS_NO_MEMORY; + + proc->Header.Destroy = ProcessDestroy; + + proc->ProcessId = _InterlockedExchangeAdd((volatile long *)&gNextProcessId, 1); + strncpy(proc->Name, name, PROCESS_NAME_MAX - 1); + proc->Name[PROCESS_NAME_MAX - 1] = '\0'; + + LIST_INIT(&proc->ThreadList); + proc->ThreadCount = 0; + proc->HandleLock = (SPINLOCK)SPINLOCK_INIT; + proc->ExitCode = 0; + + // Slot 0 is the invalid handle - leave it NULL. + memset(proc->Handles, 0, sizeof(proc->Handles)); + + LIST_INIT(&proc->GlobalLink); + + KeAcquireSpinlock(&gProcessListLock); + ListInsertTail(&gProcessList, &proc->GlobalLink); + KeReleaseSpinlock(&gProcessListLock); + + *out = proc; + return STATUS_SUCCESS; +} + +// --------------------------------------------------------------------------- +// KeExitProcess +// --------------------------------------------------------------------------- +void KeExitProcess(PROCESS* process, int exitCode) { + if (!process) return; + process->ExitCode = exitCode; + // The last thread exiting via KeExitThread will drop the process refcount. + // This function is a policy hook; actual cleanup is in ProcessDestroy. + ObDereferenceObject(&process->Header); +} + +// --------------------------------------------------------------------------- +// Handle table +// --------------------------------------------------------------------------- +KSTATUS KeAllocateHandle(PROCESS* process, OBJECT* object, uint32_t* handleOut) { + if (!process || !object || !handleOut) return STATUS_INVALID_PARAMETER; + + KeAcquireSpinlock(&process->HandleLock); + + for (int i = 1; i < HANDLE_TABLE_SIZE; i++) { + if (!process->Handles[i]) { + ObReferenceObject(object); + process->Handles[i] = object; + *handleOut = (uint32_t)i; + KeReleaseSpinlock(&process->HandleLock); + return STATUS_SUCCESS; + } + } + + KeReleaseSpinlock(&process->HandleLock); + return STATUS_NO_MEMORY; +} + +void KeCloseHandle(PROCESS* process, uint32_t handle) { + if (!process || handle == 0 || handle >= HANDLE_TABLE_SIZE) return; + + KeAcquireSpinlock(&process->HandleLock); + OBJECT* obj = process->Handles[handle]; + if (obj) { + process->Handles[handle] = (OBJECT *)0; + KeReleaseSpinlock(&process->HandleLock); + ObDereferenceObject(obj); + return; + } + KeReleaseSpinlock(&process->HandleLock); +} + +OBJECT* KeLookupHandle(PROCESS* process, uint32_t handle) { + if (!process || handle == 0 || handle >= HANDLE_TABLE_SIZE) + return (OBJECT *)0; + + KeAcquireSpinlock(&process->HandleLock); + OBJECT* obj = process->Handles[handle]; + if (obj) ObReferenceObject(obj); + KeReleaseSpinlock(&process->HandleLock); + return obj; +} diff --git a/code/kernel/ke_process.h b/code/kernel/ke_process.h new file mode 100644 index 0000000..34420e4 --- /dev/null +++ b/code/kernel/ke_process.h @@ -0,0 +1,41 @@ +#pragma once +// ke_process.h - process model +// A process owns a handle table and a list of threads. +// There is one shared address space - processes do not own one. +#include "ob_object.h" +#include "ke_list.h" +#include "ke_spinlock.h" + +#define PROCESS_NAME_MAX 64 +#define HANDLE_TABLE_SIZE 256 + +typedef struct PROCESS { + OBJECT Header; /* must be first */ + + uint32_t ProcessId; + char Name[PROCESS_NAME_MAX]; /* UTF-8 */ + + /* Thread list. */ + LIST_ENTRY ThreadList; /* links THREAD.ProcessLink */ + uint32_t ThreadCount; + + /* Handle table. + Index 0 is always NULL (the invalid handle). + Entries are OBJECT pointers, each holding a reference. */ + OBJECT* Handles[HANDLE_TABLE_SIZE]; + SPINLOCK HandleLock; + + int ExitCode; + LIST_ENTRY GlobalLink; /* node in the global process list */ +} PROCESS; + +KSTATUS KeCreateProcess(const char* name, PROCESS **out); +void KeExitProcess(PROCESS* process, int exitCode); + +/* Handle table operations. */ +KSTATUS KeAllocateHandle(PROCESS* process, OBJECT* object, uint32_t* handleOut); +void KeCloseHandle(PROCESS* process, uint32_t handle); +OBJECT* KeLookupHandle(PROCESS* process, uint32_t handle); + +/* Return the global process list head (kernel-internal). */ +LIST_ENTRY* KeGetProcessList(void); diff --git a/code/kernel/ke_queue.c b/code/kernel/ke_queue.c new file mode 100644 index 0000000..12c266b --- /dev/null +++ b/code/kernel/ke_queue.c @@ -0,0 +1,85 @@ +// ke_queue.c - ring-buffer message queue +#include "ke_queue.h" +#include "ke_thread.h" +#include "ke_sched.h" +#include "ob_object.h" +#include + +static void QueueDestroy(OBJECT* obj) { (void)obj; } + +KSTATUS QueueCreate(QUEUE **out) { + if (!out) return STATUS_INVALID_PARAMETER; + QUEUE* q = (QUEUE *)ObAllocateObject(ObjectTypeQueue, sizeof(QUEUE)); + if (!q) return STATUS_NO_MEMORY; + q->Header.Destroy = QueueDestroy; + q->Lock = (SPINLOCK)SPINLOCK_INIT; + q->Head = q->Tail = q->Count = 0; + LIST_INIT(&q->SendWaiters); + LIST_INIT(&q->RecvWaiters); + *out = q; + return STATUS_SUCCESS; +} + +KSTATUS KeSendMessage(QUEUE* queue, const QUEUE_MESSAGE* msg, bool blocking) { + if (!queue || !msg) return STATUS_INVALID_PARAMETER; + THREAD* self = KeCurrentThread(); + + for (;;) { + KeAcquireSpinlock(&queue->Lock); + if (queue->Count < QUEUE_DEPTH) { + queue->Ring[queue->Tail] = *msg; + queue->Tail = (queue->Tail + 1) % QUEUE_DEPTH; + queue->Count++; + + // Wake a receiver if one is waiting. + if (!LIST_IS_EMPTY(&queue->RecvWaiters)) { + LIST_ENTRY* node = ListPopHead(&queue->RecvWaiters); + THREAD* t = CONTAINING_RECORD(node, THREAD, SchedulerLink); + KeReleaseSpinlock(&queue->Lock); + KeUnblockThread(t); + } else { + KeReleaseSpinlock(&queue->Lock); + } + return STATUS_SUCCESS; + } + if (!blocking) { + KeReleaseSpinlock(&queue->Lock); + return STATUS_QUEUE_FULL; + } + ListInsertTail(&queue->SendWaiters, &self->SchedulerLink); + KeReleaseSpinlock(&queue->Lock); + KeBlockThread(self, &queue->Header); + } +} + +KSTATUS KeReceiveMessage(QUEUE* queue, QUEUE_MESSAGE* msg, bool blocking) { + if (!queue || !msg) return STATUS_INVALID_PARAMETER; + THREAD* self = KeCurrentThread(); + + for (;;) { + KeAcquireSpinlock(&queue->Lock); + if (queue->Count > 0) { + *msg = queue->Ring[queue->Head]; + queue->Head = (queue->Head + 1) % QUEUE_DEPTH; + queue->Count--; + + // Wake a sender if one is waiting. + if (!LIST_IS_EMPTY(&queue->SendWaiters)) { + LIST_ENTRY* node = ListPopHead(&queue->SendWaiters); + THREAD* t = CONTAINING_RECORD(node, THREAD, SchedulerLink); + KeReleaseSpinlock(&queue->Lock); + KeUnblockThread(t); + } else { + KeReleaseSpinlock(&queue->Lock); + } + return STATUS_SUCCESS; + } + if (!blocking) { + KeReleaseSpinlock(&queue->Lock); + return STATUS_QUEUE_EMPTY; + } + ListInsertTail(&queue->RecvWaiters, &self->SchedulerLink); + KeReleaseSpinlock(&queue->Lock); + KeBlockThread(self, &queue->Header); + } +} diff --git a/code/kernel/ke_queue.h b/code/kernel/ke_queue.h new file mode 100644 index 0000000..aafd8d2 --- /dev/null +++ b/code/kernel/ke_queue.h @@ -0,0 +1,32 @@ +#pragma once +// ke_queue.h - fixed-depth message queue +// Processes share an address space, so a pointer in Param[] is valid +// on both sides. The queue is only a synchronisation and ordering tool. +#include "ob_object.h" +#include "ke_spinlock.h" +#include "ke_list.h" +#include "ke_status.h" +#include +#include + +#define QUEUE_MESSAGE_SIZE 64 /* bytes, fixed */ +#define QUEUE_DEPTH 256 + +typedef struct QUEUE_MESSAGE { + uint32_t Type; + uint32_t Flags; + uint64_t Param[6]; /* 48 bytes of payload */ +} QUEUE_MESSAGE; /* total: 64 bytes */ + +typedef struct QUEUE { + OBJECT Header; + SPINLOCK Lock; + QUEUE_MESSAGE Ring[QUEUE_DEPTH]; + uint32_t Head, Tail, Count; + LIST_ENTRY SendWaiters; + LIST_ENTRY RecvWaiters; +} QUEUE; + +KSTATUS QueueCreate(QUEUE **out); +KSTATUS KeSendMessage(QUEUE* queue, const QUEUE_MESSAGE* msg, bool blocking); +KSTATUS KeReceiveMessage(QUEUE* queue, QUEUE_MESSAGE* msg, bool blocking); diff --git a/code/kernel/ke_sched.c b/code/kernel/ke_sched.c new file mode 100644 index 0000000..473fb34 --- /dev/null +++ b/code/kernel/ke_sched.c @@ -0,0 +1,202 @@ +// ke_sched.c - MLFQ scheduler +// +// Three queues: PriorityHigh(2), PriorityNormal(1), PriorityLow(0). +// Dispatch always picks the highest non-empty queue. +// Within a queue: strict round-robin. +// +// Demotion threshold: a thread that consumes DEMOTION_QUANTA consecutive +// ticks without blocking drops one level (floor PriorityLow). +// Promotion: a thread that unblocks is bumped one level (ceiling PriorityHigh). +// +// The idle thread (created by KeInitializeScheduler) runs at PriorityLow +// when nothing else is runnable. +#include "ke_sched.h" +#include "ke_thread.h" +#include "ke_spinlock.h" +#include "ke_list.h" +#include "mm_virt.h" +#include + +#define DEMOTION_QUANTA 4 /* ticks at a level before demotion */ + +// --------------------------------------------------------------------------- +// Run queues +// --------------------------------------------------------------------------- +static LIST_ENTRY gRunQueue[PriorityCount]; // [0]=Low [1]=Normal [2]=High +static SPINLOCK gSchedLock; + +// The currently running thread (also in GS:[0] for fast access). +// On a single-core system this is the only "per-CPU" slot we need. +static THREAD* gCurrentThread; +static THREAD* gIdleThread; + +// --------------------------------------------------------------------------- +// GS:[0] helpers - implemented in ke_switch.asm +// (On single-core we just use a global; SMP would use per-core GS.) +// --------------------------------------------------------------------------- +THREAD* KeCurrentThread(void) { return gCurrentThread; } +void KeSetCurrentThread(THREAD* t){ gCurrentThread = t; } + +// --------------------------------------------------------------------------- +// Idle thread body - runs in ring 0 when every other thread is blocked. +// --------------------------------------------------------------------------- +static void IdleLoop(void) { + for (;;) { __halt(); } +} + +// --------------------------------------------------------------------------- +// Init +// --------------------------------------------------------------------------- +void KeInitializeScheduler(void) { + for (int i = 0; i < PriorityCount; i++) LIST_INIT(&gRunQueue[i]); + gSchedLock = (SPINLOCK)SPINLOCK_INIT; + + // Create the idle process / thread. + // We call the internal alloc directly to avoid the full KeCreateThread + // path (no user stack, no ring-3 entry - the idle thread never leaves + // ring 0 and never calls KeExitThread). + extern KSTATUS KeCreateProcess(const char *, PROCESS **); + PROCESS* idleProc; + KeCreateProcess("idle", &idleProc); + + THREAD* idle = (THREAD *)ObAllocateObject(ObjectTypeThread, sizeof(THREAD)); + idle->Header.Destroy = (void *)0; + idle->ThreadId = 0; + idle->State = ThreadReady; + idle->Priority = PriorityLow; + idle->QuantaConsumed = 0; + idle->Owner = idleProc; + idle->WaitObject = (OBJECT *)0; + + void* kstack = MmAllocatePool(KSTACK_SIZE); + idle->KernelStackBase = kstack; + idle->KernelStackTop = (uintptr_t)kstack + KSTACK_SIZE; + idle->TssRsp0 = idle->KernelStackTop; + + // Initial context: RSP at top of kstack, Rip = IdleLoop. + uintptr_t* ksp = (uintptr_t *)idle->KernelStackTop; + ksp -= sizeof(KCONTEXT) / sizeof(uintptr_t); + KCONTEXT* ctx = (KCONTEXT *)ksp; + __stosq((unsigned __int64 *)ctx, 0, sizeof(KCONTEXT) / 8); + ctx->Rip = (uint64_t)IdleLoop; + idle->SavedContext = ctx; + + gIdleThread = idle; + gCurrentThread = idle; + + // Don't add idle to the run queue here; KeSchedulerTick falls back to it. +} + +// --------------------------------------------------------------------------- +// Run-queue management +// --------------------------------------------------------------------------- +void KeReadyThread(THREAD* thread) { + if (!thread) return; + thread->State = ThreadReady; + int p = (int)thread->Priority; + if (p < 0) p = 0; + if (p >= PriorityCount) p = PriorityCount - 1; + + KeAcquireSpinlock(&gSchedLock); + ListInsertTail(&gRunQueue[p], &thread->SchedulerLink); + KeReleaseSpinlock(&gSchedLock); +} + +void KeUnreadyThread(THREAD* thread) { + if (!thread) return; + KeAcquireSpinlock(&gSchedLock); + ListRemove(&thread->SchedulerLink); + KeReleaseSpinlock(&gSchedLock); +} + +// --------------------------------------------------------------------------- +// Pick the highest-priority runnable thread (caller holds gSchedLock). +// Returns gIdleThread if all queues are empty. +// --------------------------------------------------------------------------- +static THREAD* PickNext(void) { + for (int p = PriorityCount - 1; p >= 0; p--) { + if (!LIST_IS_EMPTY(&gRunQueue[p])) { + LIST_ENTRY* node = gRunQueue[p].Fwd; + ListRemove(node); + return CONTAINING_RECORD(node, THREAD, SchedulerLink); + } + } + return gIdleThread; +} + +// --------------------------------------------------------------------------- +// KeSchedulerTick - called from the timer ISR every QUANTUM_MS +// --------------------------------------------------------------------------- +void KeSchedulerTick(void) { + THREAD* cur = gCurrentThread; + if (!cur) return; + + KeAcquireSpinlock(&gSchedLock); + + cur->QuantaConsumed++; + + // Demotion: CPU-bound thread exhausted its quanta budget. + if (cur != gIdleThread && cur->QuantaConsumed >= DEMOTION_QUANTA) { + cur->QuantaConsumed = 0; + if (cur->Priority > PriorityLow) { + cur->Priority = (THREAD_PRIORITY)(cur->Priority - 1); + } + } + + // Check if a higher-priority thread is waiting. + THREAD* next = PickNext(); + if (next == cur) { + // Re-insert ourselves and continue. + if (cur != gIdleThread) { + ListInsertTail(&gRunQueue[cur->Priority], &cur->SchedulerLink); + } + KeReleaseSpinlock(&gSchedLock); + return; + } + + // Switch. + cur->State = (cur == gIdleThread) ? ThreadReady : ThreadReady; + next->State = ThreadRunning; + gCurrentThread = next; + + // Re-queue the outgoing thread if it is still runnable. + if (cur != gIdleThread && cur->State == ThreadReady) { + ListInsertTail(&gRunQueue[cur->Priority], &cur->SchedulerLink); + } + + KeReleaseSpinlock(&gSchedLock); + KeSwitchContext(cur, next); +} + +// --------------------------------------------------------------------------- +// KeYield +// --------------------------------------------------------------------------- +void KeYield(void) { + THREAD* cur = gCurrentThread; + if (!cur) return; + + KeAcquireSpinlock(&gSchedLock); + + // Voluntary block → promote one level. + if (cur != gIdleThread && cur->Priority < PriorityHigh) { + cur->Priority = (THREAD_PRIORITY)(cur->Priority + 1); + cur->QuantaConsumed = 0; + } + + THREAD* next = PickNext(); + if (next == cur) { + if (cur != gIdleThread) + ListInsertTail(&gRunQueue[cur->Priority], &cur->SchedulerLink); + KeReleaseSpinlock(&gSchedLock); + return; + } + + next->State = ThreadRunning; + gCurrentThread = next; + + if (cur != gIdleThread && cur->State == ThreadReady) + ListInsertTail(&gRunQueue[cur->Priority], &cur->SchedulerLink); + + KeReleaseSpinlock(&gSchedLock); + KeSwitchContext(cur, next); +} diff --git a/code/kernel/ke_sched.h b/code/kernel/ke_sched.h new file mode 100644 index 0000000..ee1328c --- /dev/null +++ b/code/kernel/ke_sched.h @@ -0,0 +1,25 @@ +#pragma once +// ke_sched.h - Multi-Level Feedback Queue scheduler +// Three run queues (Low / Normal / High). IRQ 0 drives KeSchedulerTick. +#include "ke_thread.h" + +#define QUANTUM_MS 10 /* base time slice in milliseconds */ + +// Called once by KernelMain before any threads are created. +void KeInitializeScheduler(void); + +// Add / remove a thread from the run queues. +void KeReadyThread(THREAD* thread); +void KeUnreadyThread(THREAD* thread); + +// Called from the timer ISR every QUANTUM_MS. +void KeSchedulerTick(void); + +// Voluntarily yield the CPU. Picks the next runnable thread immediately. +void KeYield(void); + +// Returns the thread currently running on this CPU (reads GS:[0]). +THREAD* KeCurrentThread(void); + +// Set the current-thread GS slot. Called once per CPU at boot. +void KeSetCurrentThread(THREAD* thread); diff --git a/code/kernel/ke_semaphore.c b/code/kernel/ke_semaphore.c new file mode 100644 index 0000000..d9f6e87 --- /dev/null +++ b/code/kernel/ke_semaphore.c @@ -0,0 +1,64 @@ +// ke_semaphore.c - counting semaphore +#include "ke_semaphore.h" +#include "ke_thread.h" +#include "ke_sched.h" +#include "ob_object.h" + +static void SemDestroy(OBJECT* obj) { (void)obj; } + +KSTATUS SemaphoreCreate(int32_t initial, int32_t max, SEMAPHORE **out) { + if (!out || initial < 0 || max < 1 || initial > max) + return STATUS_INVALID_PARAMETER; + SEMAPHORE* s = (SEMAPHORE *)ObAllocateObject(ObjectTypeSemaphore, sizeof(SEMAPHORE)); + if (!s) return STATUS_NO_MEMORY; + s->Header.Destroy = SemDestroy; + s->Lock = (SPINLOCK)SPINLOCK_INIT; + s->Count = initial; + s->MaxCount = max; + LIST_INIT(&s->WaitList); + *out = s; + return STATUS_SUCCESS; +} + +KSTATUS KeWaitSemaphore(SEMAPHORE* sem) { + if (!sem) return STATUS_INVALID_PARAMETER; + THREAD* self = KeCurrentThread(); + + for (;;) { + KeAcquireSpinlock(&sem->Lock); + if (sem->Count > 0) { + sem->Count--; + KeReleaseSpinlock(&sem->Lock); + return STATUS_SUCCESS; + } + ListInsertTail(&sem->WaitList, &self->SchedulerLink); + KeReleaseSpinlock(&sem->Lock); + KeBlockThread(self, &sem->Header); + } +} + +KSTATUS KeTrySemaphore(SEMAPHORE* sem) { + if (!sem) return STATUS_INVALID_PARAMETER; + KeAcquireSpinlock(&sem->Lock); + if (sem->Count > 0) { + sem->Count--; + KeReleaseSpinlock(&sem->Lock); + return STATUS_SUCCESS; + } + KeReleaseSpinlock(&sem->Lock); + return STATUS_FAILURE; +} + +void KeSignalSemaphore(SEMAPHORE* sem) { + if (!sem) return; + KeAcquireSpinlock(&sem->Lock); + if (!LIST_IS_EMPTY(&sem->WaitList)) { + LIST_ENTRY* node = ListPopHead(&sem->WaitList); + THREAD* waiter = CONTAINING_RECORD(node, THREAD, SchedulerLink); + KeReleaseSpinlock(&sem->Lock); + KeUnblockThread(waiter); + return; + } + if (sem->Count < sem->MaxCount) sem->Count++; + KeReleaseSpinlock(&sem->Lock); +} diff --git a/code/kernel/ke_semaphore.h b/code/kernel/ke_semaphore.h new file mode 100644 index 0000000..1d6f9f2 --- /dev/null +++ b/code/kernel/ke_semaphore.h @@ -0,0 +1,20 @@ +#pragma once +// ke_semaphore.h - counting semaphore +#include "ob_object.h" +#include "ke_spinlock.h" +#include "ke_list.h" +#include "ke_status.h" +#include + +typedef struct SEMAPHORE { + OBJECT Header; + SPINLOCK Lock; + int32_t Count; + int32_t MaxCount; + LIST_ENTRY WaitList; +} SEMAPHORE; + +KSTATUS SemaphoreCreate(int32_t initial, int32_t max, SEMAPHORE **out); +KSTATUS KeWaitSemaphore(SEMAPHORE* semaphore); +KSTATUS KeTrySemaphore(SEMAPHORE* semaphore); +void KeSignalSemaphore(SEMAPHORE* semaphore); diff --git a/code/kernel/ke_spinlock.h b/code/kernel/ke_spinlock.h new file mode 100644 index 0000000..bb159d7 --- /dev/null +++ b/code/kernel/ke_spinlock.h @@ -0,0 +1,24 @@ +#pragma once +// ke_spinlock.h - spinlock for short, non-sleeping critical sections +// Uses MSVC interlocked intrinsics. Never hold across a scheduling boundary. +#include +#include + +typedef struct SPINLOCK { + volatile long Locked; +} SPINLOCK; + +#define SPINLOCK_INIT { 0 } + +static __forceinline void KeAcquireSpinlock(SPINLOCK* sl) { + while (_InterlockedCompareExchange(&sl->Locked, 1, 0) != 0) + _mm_pause(); +} + +static __forceinline void KeReleaseSpinlock(SPINLOCK* sl) { + _InterlockedExchange(&sl->Locked, 0); +} + +static __forceinline int KeTryAcquireSpinlock(SPINLOCK* sl) { + return _InterlockedCompareExchange(&sl->Locked, 1, 0) == 0; +} diff --git a/code/kernel/ke_status.h b/code/kernel/ke_status.h new file mode 100644 index 0000000..2ec3e5e --- /dev/null +++ b/code/kernel/ke_status.h @@ -0,0 +1,25 @@ +#pragma once +// ke_status.h - kernel status codes +// All fallible kernel functions return KSTATUS. +// Success is always zero; failures are positive named constants. +#include + +typedef uint32_t KSTATUS; + +#define STATUS_SUCCESS ((KSTATUS)0x00000000) +#define STATUS_FAILURE ((KSTATUS)0x00000001) +#define STATUS_INVALID_PARAMETER ((KSTATUS)0x00000002) +#define STATUS_NO_MEMORY ((KSTATUS)0x00000003) +#define STATUS_NOT_FOUND ((KSTATUS)0x00000004) +#define STATUS_ACCESS_DENIED ((KSTATUS)0x00000005) +#define STATUS_ALREADY_EXISTS ((KSTATUS)0x00000006) +#define STATUS_NOT_SUPPORTED ((KSTATUS)0x00000007) +#define STATUS_TIMEOUT ((KSTATUS)0x00000008) +#define STATUS_BUFFER_TOO_SMALL ((KSTATUS)0x00000009) +#define STATUS_DEVICE_ERROR ((KSTATUS)0x0000000A) +#define STATUS_OBJECT_DEAD ((KSTATUS)0x0000000B) +#define STATUS_QUEUE_FULL ((KSTATUS)0x0000000C) +#define STATUS_QUEUE_EMPTY ((KSTATUS)0x0000000D) +#define STATUS_CHECKSUM_MISMATCH ((KSTATUS)0x0000000E) + +#define KSUCCESS(s) ((s) == STATUS_SUCCESS) diff --git a/code/kernel/ke_switch.asm b/code/kernel/ke_switch.asm new file mode 100644 index 0000000..fa5a826 --- /dev/null +++ b/code/kernel/ke_switch.asm @@ -0,0 +1,72 @@ +; ke_switch.asm - context switch and thread entry stubs (MASM64 / ML64) +; +; Generated struct offsets (regenerate with gen_offsets.exe if structs change): +; sizeof(OBJECT) = 16 (type:4, refcount:4, destroy:8) +; THREAD.SavedContext offset = 88 +; THREAD.TssRsp0 offset = 104 +; TSS64.RSP0 offset = 4 +; +THREAD_SavedContext EQU 88 +THREAD_TssRsp0 EQU 104 +TSS_RSP0_OFFSET EQU 4 + +EXTERN gTss:QWORD ; address of the single TSS, exported from ke_idt.c + +.CODE + +; ------------------------------------------------------------------------- +; void KeSwitchContext(THREAD* from, THREAD* to) +; RCX = from, RDX = to (Microsoft x64) +; ------------------------------------------------------------------------- +KeSwitchContext PROC + ; Save non-volatile registers onto the current (outgoing) kernel stack. + push rbx + push rbp + push r12 + push r13 + push r14 + push r15 + + ; from->SavedContext = rsp + mov [rcx + THREAD_SavedContext], rsp + + ; rsp = to->SavedContext + mov rsp, [rdx + THREAD_SavedContext] + + ; Update TSS.RSP0 so that the next interrupt/syscall uses the + ; incoming thread's kernel stack top. + mov rax, [rdx + THREAD_TssRsp0] + mov r8, gTss + mov qword ptr [r8 + TSS_RSP0_OFFSET], rax + + ; Restore non-volatile registers of the incoming thread. + pop r15 + pop r14 + pop r13 + pop r12 + pop rbp + pop rbx + ret +KeSwitchContext ENDP + +; ------------------------------------------------------------------------- +; KeThreadEntry - landing pad for brand-new threads. +; +; Stack layout when we arrive here (set up by KeCreateThread): +; [rsp+00] = KCONTEXT (already popped by KeSwitchContext ret) +; After ret from KeSwitchContext RSP points here: +; [rsp+00] = user RCX arg +; [rsp+08] = user RIP +; [rsp+16] = user CS (0x1B) +; [rsp+24] = RFLAGS (0x202) +; [rsp+32] = user RSP +; [rsp+40] = user SS (0x23) +; +; We load RCX from the stack (first arg per MS x64), then IRETQ. +; ------------------------------------------------------------------------- +KeThreadEntry PROC + pop rcx ; user arg + iretq ; pops RIP, CS, RFLAGS, RSP, SS -> ring 3 +KeThreadEntry ENDP + +END diff --git a/code/kernel/ke_syscall.asm b/code/kernel/ke_syscall.asm new file mode 100644 index 0000000..f572b95 --- /dev/null +++ b/code/kernel/ke_syscall.asm @@ -0,0 +1,140 @@ +; ke_syscall.asm - INT 0x2E kernel entry (MASM64) +; +; On entry the CPU has pushed (ring-3 -> ring-0 transition): +; SS, RSP, RFLAGS, CS, RIP (on the kernel stack via TSS.RSP0) +; RAX = syscall number +; RCX, RDX, R8, R9 = args 0-3 (MS x64) +; R10, R11 = args 4-5 (our extension) + +EXTERN KeSyscallDispatch:PROC + +.CODE + +KeSyscallEntry PROC + sub rsp, 8 ; 16-byte align the stack frame + + ; We need to allocate 32 bytes for shadow space, plus 24 bytes for + ; the 3 stack arguments (a3, a4, a5), plus 8 bytes of padding to keep + ; the stack 16-byte aligned. Total = 64. + sub rsp, 64 + + ; Place the 5th, 6th, and 7th arguments onto the stack for KeSyscallDispatch + mov [rsp + 32], r9 ; a3 + mov [rsp + 40], r10 ; a4 + mov [rsp + 48], r11 ; a5 + + ; Shift the first 4 registers down one slot + mov r9, r8 ; a2 + mov r8, rdx ; a1 + mov rdx, rcx ; a0 + mov rcx, rax ; nr (syscall number) + + ; Call the C dispatcher + call KeSyscallDispatch + + add rsp, 72 ; Clean up (64 + 8) + iretq +KeSyscallEntry ENDP + +; --------------------------------------------------------------------------- +; Fault stubs - print a message and halt. A real kernel would do a bugcheck. +; --------------------------------------------------------------------------- +EXTERN DbgPrint:PROC + +FaultMsg DB "KERNEL FAULT: vector %d at RIP %016llx", 0Ah, 0 + +KeFaultDE PROC + sub rsp, 28h + lea rcx, FaultMsg + mov rdx, 0 + pop r8 ; RIP from the fault frame + call DbgPrint + add rsp, 28h +@@: hlt + jmp @B +KeFaultDE ENDP + +KeFaultGP PROC + sub rsp, 28h + lea rcx, FaultMsg + mov rdx, 13 + pop rax ; error code + pop r8 ; RIP + call DbgPrint + add rsp, 28h +@@: hlt + jmp @B +KeFaultGP ENDP + +KeFaultPF PROC + sub rsp, 28h + lea rcx, FaultMsg + mov rdx, 14 + pop rax ; error code + pop r8 ; RIP + call DbgPrint + add rsp, 28h +@@: hlt + jmp @B +KeFaultPF ENDP + +EXTERN KeIrqDispatch:PROC + +IrqStub MACRO num +PUBLIC KeIrqStub&num +KeIrqStub&num PROC + push rax + mov al, num + jmp KeIrqCommon +KeIrqStub&num ENDP +ENDM + +IrqStub 0 +IrqStub 1 +IrqStub 2 +IrqStub 3 +IrqStub 4 +IrqStub 5 +IrqStub 6 +IrqStub 7 +IrqStub 8 +IrqStub 9 +IrqStub 10 +IrqStub 11 +IrqStub 12 +IrqStub 13 +IrqStub 14 +IrqStub 15 +IrqStub 16 +IrqStub 17 +IrqStub 18 +IrqStub 19 +IrqStub 20 +IrqStub 21 +IrqStub 22 +IrqStub 23 + +KeIrqCommon PROC + ; al = irq number, rax saved on stack + ; Build a minimal calling-convention-safe frame + push rcx + push rdx + push r8 + push r9 + push r10 + push r11 + movzx ecx, al ; first arg = irq number (rcx, Win64 ABI) + sub rsp, 32 ; shadow space + call KeIrqDispatch + add rsp, 32 + pop r11 + pop r10 + pop r9 + pop r8 + pop rdx + pop rcx + pop rax + iretq +KeIrqCommon ENDP + +END diff --git a/code/kernel/ke_syscall.c b/code/kernel/ke_syscall.c new file mode 100644 index 0000000..cec46f0 --- /dev/null +++ b/code/kernel/ke_syscall.c @@ -0,0 +1,377 @@ +// ke_syscall.c - syscall dispatch +// +// KeSyscallEntry (MASM64) pushes all arguments onto the kernel stack and +// calls KeSyscallDispatch. We read them from the stack frame. +//#include "ke_syscall.h" +#include "ke_thread.h" +#include "ke_sched.h" +#include "ke_process.h" +#include "ke_mutex.h" +#include "ke_semaphore.h" +#include "ke_event.h" +#include "ke_queue.h" +#include "ke_debug.h" +#include "mm_virt.h" +#include "syscall_nr.h" +#include "hal_api.h" +#include "io_file.h" +#include +#include + +// hal pointer set at boot +static const HAL_API* gHal; +void KeSyscallSetHal(const HAL_API* hal) { gHal = hal; } + +// --------------------------------------------------------------------------- +// Individual syscall handlers +// --------------------------------------------------------------------------- + +static uint64_t SyscallExitThread(uint64_t code, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + KeExitThread(KeCurrentThread(), (int)code); + return STATUS_SUCCESS; +} + +static uint64_t SyscallExitProcess(uint64_t code, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + THREAD* t = KeCurrentThread(); + if (t && t->Owner) KeExitProcess(t->Owner, (int)code); + KeExitThread(t, (int)code); + return STATUS_SUCCESS; +} + +static uint64_t SyscallYield(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + KeYield(); + return STATUS_SUCCESS; +} + +static uint64_t SyscallSleep(uint64_t ms, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + // Simple busy-wait sleep via HAL timer. + if (gHal) { + uint64_t start = gHal->Timer.QueryTicks(); + while (gHal->Timer.QueryTicks() - start < ms) KeYield(); + } + return STATUS_SUCCESS; +} + +static uint64_t SyscallAlloc(uint64_t size, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + return (uint64_t)MmAllocateUserMemory((size_t)size); +} + +static uint64_t SyscallFree(uint64_t ptr, uint64_t size, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a2; (void)a3; (void)a4; (void)a5; + MmFreeUserMemory((void *)ptr, (size_t)size); + return STATUS_SUCCESS; +} + +static uint64_t SyscallCreateThread(uint64_t entry, uint64_t arg, + uint64_t priority, uint64_t a3, + uint64_t a4, uint64_t a5) { + (void)a3; (void)a4; (void)a5; + THREAD* cur = KeCurrentThread(); + if (!cur || !cur->Owner) return (uint64_t)STATUS_FAILURE; + THREAD* newThread; + KSTATUS s = KeCreateThread(cur->Owner, entry, arg, + (THREAD_PRIORITY)priority, &newThread); + if (!KSUCCESS(s)) return (uint64_t)s; + uint32_t handle; + KeAllocateHandle(cur->Owner, &newThread->Header, &handle); + return (uint64_t)handle; +} + +static uint64_t SyscallCloseHandle(uint64_t handle, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + THREAD* cur = KeCurrentThread(); + if (!cur || !cur->Owner) return STATUS_FAILURE; + KeCloseHandle(cur->Owner, (uint32_t)handle); + return STATUS_SUCCESS; +} + +static uint64_t SyscallDbgPrint(uint64_t strPtr, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + const char* s = (const char *)(uintptr_t)strPtr; + DbgPrint(s); + return STATUS_SUCCESS; +} + +static uint64_t SyscallMutexCreate(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + THREAD* cur = KeCurrentThread(); + if (!cur || !cur->Owner) return 0; + MUTEX* m; if (!KSUCCESS(MutexCreate(&m))) return 0; + uint32_t h; KeAllocateHandle(cur->Owner, &m->Header, &h); + ObDereferenceObject(&m->Header); // handle holds the ref + return h; +} + +static uint64_t SyscallMutexAcquire(uint64_t handle, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + THREAD* cur = KeCurrentThread(); + if (!cur || !cur->Owner) return STATUS_FAILURE; + OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); + if (!obj || obj->Type != ObjectTypeMutex) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; } + KSTATUS s = KeAcquireMutex((MUTEX *)obj); + ObDereferenceObject(obj); + return s; +} + +static uint64_t SyscallMutexRelease(uint64_t handle, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + THREAD* cur = KeCurrentThread(); + if (!cur || !cur->Owner) return STATUS_FAILURE; + OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); + if (!obj || obj->Type != ObjectTypeMutex) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; } + KeReleaseMutex((MUTEX *)obj); + ObDereferenceObject(obj); + return STATUS_SUCCESS; +} + +static uint64_t SyscallSemCreate(uint64_t initial, uint64_t max, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a2; (void)a3; (void)a4; (void)a5; + THREAD* cur = KeCurrentThread(); + if (!cur || !cur->Owner) return 0; + SEMAPHORE* s; if (!KSUCCESS(SemaphoreCreate((int32_t)initial,(int32_t)max,&s))) return 0; + uint32_t h; KeAllocateHandle(cur->Owner, &s->Header, &h); + ObDereferenceObject(&s->Header); + return h; +} + +static uint64_t SyscallSemWait(uint64_t handle, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + THREAD* cur = KeCurrentThread(); + if (!cur || !cur->Owner) return STATUS_FAILURE; + OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); + if (!obj || obj->Type != ObjectTypeSemaphore) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; } + KSTATUS s = KeWaitSemaphore((SEMAPHORE *)obj); + ObDereferenceObject(obj); + return s; +} + +static uint64_t SyscallSemSignal(uint64_t handle, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + THREAD* cur = KeCurrentThread(); + if (!cur || !cur->Owner) return STATUS_FAILURE; + OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); + if (!obj || obj->Type != ObjectTypeSemaphore) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; } + KeSignalSemaphore((SEMAPHORE *)obj); + ObDereferenceObject(obj); + return STATUS_SUCCESS; +} + +static uint64_t SyscallEventCreate(uint64_t manualReset, uint64_t initial, + uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a2; (void)a3; (void)a4; (void)a5; + THREAD* cur = KeCurrentThread(); + if (!cur || !cur->Owner) return 0; + EVENT* e; + EVENT_TYPE t = manualReset ? EventManualReset : EventAutoReset; + if (!KSUCCESS(KeEventCreate(t, (uint32_t)initial, &e))) return 0; + uint32_t h; KeAllocateHandle(cur->Owner, &e->Header, &h); + ObDereferenceObject(&e->Header); + return h; +} + +static uint64_t SyscallEventSet(uint64_t handle, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + THREAD* cur = KeCurrentThread(); + if (!cur || !cur->Owner) return STATUS_FAILURE; + OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); + if (!obj || obj->Type != ObjectTypeEvent) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; } + KeSignalEvent((EVENT *)obj); + ObDereferenceObject(obj); + return STATUS_SUCCESS; +} + +static uint64_t SyscallEventWait(uint64_t handle, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + THREAD* cur = KeCurrentThread(); + if (!cur || !cur->Owner) return STATUS_FAILURE; + OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); + if (!obj || obj->Type != ObjectTypeEvent) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; } + KSTATUS s = KeWaitForEvent((EVENT *)obj); + ObDereferenceObject(obj); + return s; +} + +static uint64_t SyscallQueueCreate(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + THREAD* cur = KeCurrentThread(); + if (!cur || !cur->Owner) return 0; + QUEUE* q; if (!KSUCCESS(QueueCreate(&q))) return 0; + uint32_t h; KeAllocateHandle(cur->Owner, &q->Header, &h); + ObDereferenceObject(&q->Header); + return h; +} + +static uint64_t SyscallQueueSend(uint64_t handle, uint64_t msgPtr, + uint64_t blocking, uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a3; (void)a4; (void)a5; + THREAD* cur = KeCurrentThread(); + if (!cur || !cur->Owner) return STATUS_FAILURE; + OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); + if (!obj || obj->Type != ObjectTypeQueue) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; } + KSTATUS s = KeSendMessage((QUEUE *)obj, (const QUEUE_MESSAGE *)msgPtr, (bool)blocking); + ObDereferenceObject(obj); + return s; +} + +static uint64_t SyscallQueueRecv(uint64_t handle, uint64_t msgPtr, + uint64_t blocking, uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a3; (void)a4; (void)a5; + THREAD* cur = KeCurrentThread(); + if (!cur || !cur->Owner) return STATUS_FAILURE; + OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); + if (!obj || obj->Type != ObjectTypeQueue) { if(obj) ObDereferenceObject(obj); return STATUS_INVALID_PARAMETER; } + KSTATUS s = KeReceiveMessage((QUEUE *)obj, (QUEUE_MESSAGE *)msgPtr, (bool)blocking); + ObDereferenceObject(obj); + return s; +} + +static uint64_t SyscallScreenBlit(uint64_t x, uint64_t y, uint64_t w, + uint64_t h, uint64_t pixels, uint64_t a5) { + (void)a5; + if (gHal) { + gHal->Screen.Blit((int)x, (int)y, (int)w, (int)h, (const uint32_t *)pixels); + return STATUS_SUCCESS; + } + DbgPrint("!! SyscallScreenBlit: what?\n"); + return STATUS_FAILURE; +} + +static uint64_t SyscallGetTick(uint64_t a0, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + return gHal ? gHal->Timer.QueryTicks() : 0; +} + +static uint64_t SyscallOpen(uint64_t pathPtr, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + THREAD* cur = KeCurrentThread(); + if (!cur || !cur->Owner) return 0; + + FILE_OBJECT* f; + KSTATUS s = IoOpenFile((const char *)pathPtr, &f); + if (!KSUCCESS(s)) return 0; + + uint32_t handle; + s = KeAllocateHandle(cur->Owner, &f->Header, &handle); + ObDereferenceObject(&f->Header); // handle holds the ref now + if (!KSUCCESS(s)) return 0; + return (uint64_t)handle; +} + +static uint64_t SyscallRead(uint64_t handle, uint64_t bufPtr, uint64_t size, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a3; (void)a4; (void)a5; + THREAD* cur = KeCurrentThread(); + if (!cur || !cur->Owner) return 0; + + OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); + if (!obj) return 0; + // FILE_OBJECT reuses ObjectTypeQueue slot - check it holds a Fs pointer. + FILE_OBJECT* f = (FILE_OBJECT *)obj; + size_t bytesRead = 0; + IoReadFile(f, (void *)bufPtr, (size_t)size, &bytesRead); + ObDereferenceObject(obj); + return (uint64_t)bytesRead; +} + +static uint64_t SyscallFClose(uint64_t handle, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + THREAD* cur = KeCurrentThread(); + if (!cur || !cur->Owner) return STATUS_FAILURE; + KeCloseHandle(cur->Owner, (uint32_t)handle); + return STATUS_SUCCESS; +} + +static uint64_t SyscallFSeek(uint64_t handle, uint64_t offset, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a2; (void)a3; (void)a4; (void)a5; + THREAD* cur = KeCurrentThread(); + if (!cur || !cur->Owner) return STATUS_FAILURE; + OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); + if (!obj) return STATUS_NOT_FOUND; + KSTATUS s = IoSeekFile((FILE_OBJECT *)obj, offset); + ObDereferenceObject(obj); + return s; +} + +static uint64_t SyscallFSize(uint64_t handle, uint64_t a1, uint64_t a2, + uint64_t a3, uint64_t a4, uint64_t a5) { + (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; + THREAD* cur = KeCurrentThread(); + if (!cur || !cur->Owner) return 0; + OBJECT* obj = KeLookupHandle(cur->Owner, (uint32_t)handle); + if (!obj) return 0; + uint64_t sz = IoGetFileSize((FILE_OBJECT *)obj); + ObDereferenceObject(obj); + return sz; +} + +// --------------------------------------------------------------------------- +// Dispatch table +// --------------------------------------------------------------------------- +typedef uint64_t (*SYSCALL_FN)(uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t, uint64_t); + +static const SYSCALL_FN gSyscallTable[SYS_MAX] = { + [SYS_EXIT_THREAD] = SyscallExitThread, + [SYS_EXIT_PROCESS] = SyscallExitProcess, + [SYS_SPAWN] = (SYSCALL_FN)0, // TODO: process spawn + [SYS_SLEEP] = SyscallSleep, + [SYS_YIELD] = SyscallYield, + [SYS_ALLOC] = SyscallAlloc, + [SYS_FREE] = SyscallFree, + [SYS_CREATE_THREAD]= SyscallCreateThread, + [SYS_OPEN_HANDLE] = (SYSCALL_FN)0, // TODO + [SYS_CLOSE_HANDLE] = SyscallCloseHandle, + [SYS_DBG_PRINT] = SyscallDbgPrint, + [SYS_MUTEX_CREATE] = SyscallMutexCreate, + [SYS_MUTEX_ACQUIRE]= SyscallMutexAcquire, + [SYS_MUTEX_RELEASE]= SyscallMutexRelease, + [SYS_SEM_CREATE] = SyscallSemCreate, + [SYS_SEM_WAIT] = SyscallSemWait, + [SYS_SEM_SIGNAL] = SyscallSemSignal, + [SYS_EVENT_CREATE] = SyscallEventCreate, + [SYS_EVENT_SET] = SyscallEventSet, + [SYS_EVENT_WAIT] = SyscallEventWait, + [SYS_QUEUE_CREATE] = SyscallQueueCreate, + [SYS_QUEUE_SEND] = SyscallQueueSend, + [SYS_QUEUE_RECV] = SyscallQueueRecv, + [SYS_SCREEN_BLIT] = SyscallScreenBlit, + [SYS_GET_TICK] = SyscallGetTick, + [SYS_OPEN] = SyscallOpen, + [SYS_READ] = SyscallRead, + [SYS_FCLOSE] = SyscallFClose, + [SYS_FSEEK] = SyscallFSeek, + [SYS_FSIZE] = SyscallFSize, +}; + +// Called from ke_syscall.asm - args already on the stack in order. +uint64_t KeSyscallDispatch(uint64_t nr, uint64_t a0, uint64_t a1, + uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { + if (nr >= SYS_MAX || !gSyscallTable[nr]) return (uint64_t)STATUS_NOT_SUPPORTED; + return gSyscallTable[nr](a0, a1, a2, a3, a4, a5); +} diff --git a/code/kernel/ke_syscall.h b/code/kernel/ke_syscall.h new file mode 100644 index 0000000..bbe73bb --- /dev/null +++ b/code/kernel/ke_syscall.h @@ -0,0 +1,11 @@ +#pragma once + +#include +#include "hal_api.h" + +// Set the HAL API pointer for syscalls +void KeSyscallSetHal(const HAL_API* hal); + +// Syscall dispatcher, called from assembly entry point +uint64_t KeSyscallDispatch(uint64_t nr, uint64_t a0, uint64_t a1, + uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5); diff --git a/code/kernel/ke_thread.c b/code/kernel/ke_thread.c new file mode 100644 index 0000000..fcf1bcb --- /dev/null +++ b/code/kernel/ke_thread.c @@ -0,0 +1,157 @@ +// ke_thread.c - thread model +#include "ke_thread.h" +#include "ke_sched.h" +#include "mm_virt.h" +#include "ob_object.h" +#include +#include + +static uint32_t gNextThreadId = 1; + +// --------------------------------------------------------------------------- +// Initial kernel-side entry point for a new user thread +// +// When KeSwitchContext restores a brand-new thread, execution lands here. +// We set up RFLAGS (enable interrupts) and IRETQ into ring 3. +// --------------------------------------------------------------------------- +// Declared in ke_thread_entry.asm - see that file for the implementation. +extern void KeThreadEntry(void); + +// --------------------------------------------------------------------------- +// Destructor +// --------------------------------------------------------------------------- +static void ThreadDestroy(OBJECT* obj) { + THREAD* thread = CONTAINING_RECORD(obj, THREAD, Header); + + // Detach from owner process. + if (thread->Owner) { + KeAcquireSpinlock(&thread->Owner->HandleLock); + ListRemove(&thread->ProcessLink); + thread->Owner->ThreadCount--; + KeReleaseSpinlock(&thread->Owner->HandleLock); + ObDereferenceObject(&thread->Owner->Header); + thread->Owner = (PROCESS *)0; + } + + // Free kernel stack. + if (thread->KernelStackBase) { + MmFreePool(thread->KernelStackBase); + thread->KernelStackBase = (void *)0; + } + // User stack was allocated from user heap - it is up to the process to + // track and free it. For now we leave it (shared heap, no per-process VA). +} + +// --------------------------------------------------------------------------- +// KeCreateThread +// --------------------------------------------------------------------------- +KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, uintptr_t arg, + THREAD_PRIORITY priority, THREAD **out) { + if (!owner || !out) return STATUS_INVALID_PARAMETER; + if (priority >= PriorityCount) return STATUS_INVALID_PARAMETER; + + THREAD* thread = (THREAD *)ObAllocateObject(ObjectTypeThread, sizeof(THREAD)); + if (!thread) return STATUS_NO_MEMORY; + + thread->Header.Destroy = ThreadDestroy; + thread->ThreadId = _InterlockedExchangeAdd((volatile long *)&gNextThreadId, 1); + thread->State = ThreadReady; + thread->Priority = priority; + thread->QuantaConsumed = 0; + thread->WaitObject = (OBJECT *)0; + + // Allocate kernel stack. + void* kstack = MmAllocatePool(KSTACK_SIZE); + if (!kstack) { + ObDereferenceObject(&thread->Header); + return STATUS_NO_MEMORY; + } + memset(kstack, 0, KSTACK_SIZE); + thread->KernelStackBase = kstack; + thread->KernelStackTop = (uintptr_t)kstack + KSTACK_SIZE; + thread->TssRsp0 = thread->KernelStackTop; + + // Allocate user stack in the shared user heap. + void* ustack = MmAllocateUserMemory(USTACK_SIZE); + if (!ustack) { + MmFreePool(kstack); + ObDereferenceObject(&thread->Header); + return STATUS_NO_MEMORY; + } + uintptr_t userStackTop = (uintptr_t)ustack + USTACK_SIZE; + + thread->UserEntry = entry; + thread->UserArg = arg; + + // Set up the initial KCONTEXT so that when KeSwitchContext restores + // this thread, execution lands in KeThreadEntry (in ke_switch.asm), + // which will IRETQ into ring 3 at UserEntry. + // The KCONTEXT sits at the top of the kernel stack. + uintptr_t* ksp = (uintptr_t *)thread->KernelStackTop; + + // Push user RSP so KeThreadEntry can find it. + *(--ksp) = userStackTop; + + // Push the IRETQ frame: RIP, CS (ring3), RFLAGS, RSP, SS (ring3). + // Segment selector values: 0x1B = ring-3 code, 0x23 = ring-3 data. + *(--ksp) = 0x23ULL; // SS + *(--ksp) = userStackTop; // RSP (already set above but IRETQ needs it) + *(--ksp) = 0x202ULL; // RFLAGS: IF=1, reserved bit 1 + *(--ksp) = 0x1BULL; // CS + *(--ksp) = entry; // RIP + // RCX = arg (first argument per MS x64 ABI). + *(--ksp) = arg; // RCX placeholder - KeThreadEntry loads it + + // Now build the KCONTEXT that KeSwitchContext will restore. + // Rip points to KeThreadEntry; all other regs zero; RSP = ksp. + ksp -= sizeof(KCONTEXT) / sizeof(uintptr_t); + KCONTEXT* ctx = (KCONTEXT *)ksp; + memset(ctx, 0, sizeof(KCONTEXT)); + ctx->Rip = (uint64_t)KeThreadEntry; + thread->SavedContext = ctx; + + // Link into the owner process. + ObReferenceObject(&owner->Header); + thread->Owner = owner; + KeAcquireSpinlock(&owner->HandleLock); + ListInsertTail(&owner->ThreadList, &thread->ProcessLink); + owner->ThreadCount++; + KeReleaseSpinlock(&owner->HandleLock); + + // Hand the thread to the scheduler. + KeReadyThread(thread); + + *out = thread; + return STATUS_SUCCESS; +} + +// --------------------------------------------------------------------------- +// KeExitThread +// --------------------------------------------------------------------------- +void KeExitThread(THREAD* thread, int code) { + (void)code; + if (!thread) return; + + thread->State = ThreadDead; + KeUnreadyThread(thread); + ObDereferenceObject(&thread->Header); + + // Yield - the scheduler will never pick this thread again. + KeYield(); +} + +// --------------------------------------------------------------------------- +// Block / unblock +// --------------------------------------------------------------------------- +void KeBlockThread(THREAD* thread, OBJECT* waitObject) { + thread->State = ThreadWaiting; + thread->WaitObject = waitObject; + KeUnreadyThread(thread); + KeYield(); +} + +void KeUnblockThread(THREAD* thread) { + thread->WaitObject = (OBJECT *)0; + thread->State = ThreadReady; + KeReadyThread(thread); +} diff --git a/code/kernel/ke_thread.h b/code/kernel/ke_thread.h new file mode 100644 index 0000000..03e33b7 --- /dev/null +++ b/code/kernel/ke_thread.h @@ -0,0 +1,77 @@ +#pragma once +// ke_thread.h - thread model +// A THREAD is the unit of scheduling. Every thread belongs to exactly one process. +#include "ob_object.h" +#include "ke_list.h" +#include "ke_process.h" +#include + +#define KSTACK_SIZE (64 * 1024) /* 64 KB kernel stack */ +#define USTACK_SIZE (512 * 1024) /* 512 KB user stack */ + +typedef enum THREAD_PRIORITY { + PriorityLow = 0, + PriorityNormal = 1, + PriorityHigh = 2, + PriorityCount = 3, +} THREAD_PRIORITY; + +typedef enum THREAD_STATE { + ThreadReady = 0, + ThreadRunning = 1, + ThreadWaiting = 2, + ThreadDead = 3, +} THREAD_STATE; + +// Saved register context - matches the layout pushed by KeSwitchContext. +// The saved RSP points to this structure on the kernel stack. +typedef struct KCONTEXT { + uint64_t R15, R14, R13, R12; + uint64_t Rbp, Rbx; + uint64_t Rip; /* return address back into KeSwitchContext */ +} KCONTEXT; + +typedef struct THREAD { + OBJECT Header; /* must be first */ + + uint32_t ThreadId; + THREAD_STATE State; + THREAD_PRIORITY Priority; + + // Quanta consumed without blocking - used by the MLFQ for demotion. + uint32_t QuantaConsumed; + + struct PROCESS* Owner; + LIST_ENTRY ProcessLink; /* node in Owner->ThreadList */ + LIST_ENTRY SchedulerLink; /* node in run queue or wait list */ + + // Kernel stack - never PAGE_USER, pointed to by TssRsp0. + void* KernelStackBase; + uintptr_t KernelStackTop; + + // Saved context pointer - set by KeSwitchContext. + KCONTEXT* SavedContext; + + // Non-NULL while State == ThreadWaiting. + OBJECT* WaitObject; + + // Updated on every context switch so the CPU loads the right kernel stack. + uintptr_t TssRsp0; + + // Ring-3 entry point and argument for newly created threads. + uintptr_t UserEntry; + uintptr_t UserArg; +} THREAD; + +KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, uintptr_t arg, + THREAD_PRIORITY priority, THREAD **out); + +// Mark a thread dead and deschedule it permanently. +void KeExitThread(THREAD* thread, int code); + +// Block / unblock primitives used by sync objects. +void KeBlockThread(THREAD* thread, OBJECT* waitObject); +void KeUnblockThread(THREAD* thread); + +// Assembly stub - implemented in ke_switch.asm. +void KeSwitchContext(THREAD* from, THREAD* to); diff --git a/code/kernel/kmain.c b/code/kernel/kmain.c new file mode 100644 index 0000000..de8ddc8 --- /dev/null +++ b/code/kernel/kmain.c @@ -0,0 +1,414 @@ +// main.c - kernel entry point +#include "boot_info.h" +#include "mm_phys.h" +#include "mm_virt.h" +#include "ob_object.h" +#include "ke_process.h" +#include "ke_thread.h" +#include "ke_sched.h" +#include "ke_idt.h" +#include "ke_irq.h" +#include "ke_syscall.h" +#include "ke_debug.h" +#include "ldr_image.h" +#include "hal_api.h" +#include "io_file.h" +#include "ini_parser.h" +#include +#include +#include + +// dynamic arrays bitch +typedef struct { + size_t count; + size_t capacity; +} Header; + +#define ARR_INIT_CAPACITY 1 + +#define _arr_header(arr) ((Header*)(arr) - 1) + +#define _arr_maybe_grow(arr) \ + do { \ + if (!(arr)) { \ + Header* h = MmAllocatePool(sizeof(Header) + sizeof(*(arr)) * ARR_INIT_CAPACITY); \ + h->count = 0; \ + h->capacity = ARR_INIT_CAPACITY; \ + (arr) = (void*)(h + 1); \ + } \ + Header* h = _arr_header(arr); \ + if (h->count >= h->capacity) { \ + h->capacity *= 2; \ + h = MmReallocatePool(h, sizeof(Header) + sizeof(*(arr)) * h->capacity); \ + (arr) = (void*)(h + 1); \ + } \ + } while (0) + +#define arr_push(arr, x) \ + do { \ + _arr_maybe_grow(arr); \ + (arr)[_arr_header(arr)->count++] = (x); \ + } while (0) + +#define arr_push_front(arr, x) \ + do { \ + _arr_maybe_grow(arr); \ + Header* h = _arr_header(arr); \ + memmove(&(arr)[1], &(arr)[0], sizeof(*(arr)) * h->count); \ + (arr)[0] = (x); \ + h->count++; \ + } while (0) + +#define arr_remove(arr, index) \ + do { \ + if ((arr) && (index) < arr_len(arr)) { \ + Header* h = _arr_header(arr); \ + memmove(&(arr)[index], &(arr)[index + 1], sizeof(*(arr)) * (h->count - (index) - 1)); \ + h->count--; \ + } \ + } while (0) + +#define arr_len(arr) ((Header*)(arr) - 1)->count + +#define arr_free(arr) MmFreePool((Header*)(arr) - 1) + +typedef KSTATUS (*DRIVER_ENTRY_FN)(const HAL_API *); + +// --------------------------------------------------------------------------- +// Phase Helper: Resolve Imports for all registered modules +// --------------------------------------------------------------------------- +static void ResolveSystemImports(BOOT_INFO* bootInfo) { + // Resolve imports for all loaded modules (drivers may import from hal.dll, + // win32.dll imports from syscall.dll, etc). + // Starting at 2 to skip the kernel and HAL base images, as per your design. + for (uint32_t i = 2; i < bootInfo->ModuleCount; i++) { + LdrResolveImports(bootInfo->Modules[i].VirtBase); + } +} + +// --------------------------------------------------------------------------- +// Phase Helper: Initialize dynamically loaded .sys drivers +// --------------------------------------------------------------------------- +static void DriversIniCb(const char* section, const char* key, + const char* val, void* ud) { + (void)val; + if (!strcmp(section, "runtime")) { + char*** pArray = (char***)ud; + size_t len = strlen(key) + 1; + char* keyCopy = MmAllocatePool(len); + if (keyCopy) { + memcpy(keyCopy, key, len); + arr_push(*pArray, keyCopy); + } + } +} + +static void InitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) { + DbgPrint("KernelMain: Initializing drivers...\n"); + + // boot drivers (provided by the bootloader) + for (uint32_t i = 0; i < bootInfo->ModuleCount; i++) { + const char* name = bootInfo->Modules[i].Name; + + // Identify .sys files by extension + size_t len = strlen(name); + if (len < 4 || strcmp(name + len - 4, ".sys") != 0) continue; + + DbgPrint("KernelMain: Executing DriverEntry for %s\n", name); + + DRIVER_ENTRY_FN entry = (DRIVER_ENTRY_FN)(LdrGetEntryPoint(bootInfo->Modules[i].VirtBase)); + + KSTATUS ds = entry(hal); + if (!KSUCCESS(ds)) { + DbgPrint("KernelMain: Driver %s failed to init!\n", name); + } + } + + // runtime drivers + KSTATUS s; + FILE_OBJECT* f; + + s = IoOpenFile("drivers\\drivers.ini", &f); + if (s != STATUS_SUCCESS) { + DbgPrint("KernelMain: Failed to open drivers.ini\n"); + _disable(); while(1) __halt(); + } + + uint64_t size = IoGetFileSize(f) + 1; + char* mem = MmAllocatePool(size); + size_t got; + if (!KSUCCESS(IoReadFile(f, mem, size, &got))) { + DbgPrint("KernelMain: Failed to read drivers.ini\n"); + IoCloseFile(f); + _disable(); while(1) __halt(); + } + mem[got] = '\0'; + + IoCloseFile(f); + + char** runtimeKeys = NULL; + IniParse(mem, DriversIniCb, &runtimeKeys); + + for (uint32_t i = 0; i < arr_len(runtimeKeys); i++) { + DbgPrint("Found runtime driver: %s\n", runtimeKeys[i]); + + // Load the driver + size_t len = strlen(runtimeKeys[i]); + char* path = MmAllocatePool(len + 10); + if (!path) { + DbgPrint("KernelMain: Failed to allocate memory for driver path. How?\n"); + continue; + } + + // memcpy manouvers + memcpy(path, "drivers\\", 8); + memcpy(path + 8, runtimeKeys[i], len + 1); + + s = IoOpenFile(path, &f); + if (s != STATUS_SUCCESS) { + DbgPrint("KernelMain: Failed to open runtime driver: %s\n", runtimeKeys[i]); + continue; // Skip this driver but keep going with others + } + + MmFreePool(path); + + uint64_t drvSize = IoGetFileSize(f); + void* drvMem = MmAllocatePool(drvSize); + if (!KSUCCESS(IoReadFile(f, drvMem, drvSize, &got))) { + DbgPrint("KernelMain: Failed to read runtime driver: %s\n", runtimeKeys[i]); + IoCloseFile(f); + continue; + } + IoCloseFile(f); + + uintptr_t mappedBase = 0; + if (!KSUCCESS(LdrLoadImage(drvMem, drvSize, &mappedBase, false))) { // Load into kernel space + DbgPrint("KernelMain: Failed to load runtime driver: %s\n", runtimeKeys[i]); + continue; + } + + DRIVER_ENTRY_FN entry = (DRIVER_ENTRY_FN)(LdrGetEntryPoint(mappedBase)); + + KSTATUS ds = entry(hal); + if (!KSUCCESS(ds)) { + DbgPrint("KernelMain: Driver %s failed to init!\n", runtimeKeys[i]); + } + } + + // Free the individual strings allocated via strdup in the callback + if (runtimeKeys) { + for (uint32_t i = 0; i < arr_len(runtimeKeys); i++) { + if (runtimeKeys[i]) { + MmFreePool(runtimeKeys[i]); + } + } + // Free the dynamic array structure itself + arr_free(runtimeKeys); + } + + // Free the file buffer + MmFreePool(mem); +} + +// --------------------------------------------------------------------------- +// Phase Helper: Load a DLL from disk and register it as a system module +// --------------------------------------------------------------------------- +static void LoadAndRegisterDll(const char* filename) { + KSTATUS s; + FILE_OBJECT* f; + + // Read the DLL from disk + s = IoOpenFile(filename, &f); + if (s != STATUS_SUCCESS) { + DbgPrint("KernelMain: Failed to open critical system DLL: %s\n", filename); + _disable(); while(1) __halt(); + } + + uint64_t size = IoGetFileSize(f); + void* mem = MmAllocatePool(size); // Temporary pool for the raw file + size_t got; + if (!KSUCCESS(IoReadFile(f, mem, size, &got))) { + DbgPrint("KernelMain: Failed to read %s\n", filename); + IoCloseFile(f); + _disable(); while(1) __halt(); + } + IoCloseFile(f); + + // Map the DLL into memory + // Passing 'true' for user-mode so init.exe can access its code + uintptr_t mappedBase = 0; + s = LdrLoadImage(mem, size, &mappedBase, true); + if (!KSUCCESS(s)) { + DbgPrint("KernelMain: Failed to map %s\n", filename); + _disable(); while(1) __halt(); + } + + MmFreePool(mem); // Free the raw file buffer, we only need the mapped image now + + LdrRegisterModule(filename, mappedBase); // Register the module +} + +// --------------------------------------------------------------------------- +// Phase Helper: Load and launch the init process from the filesystem +// --------------------------------------------------------------------------- +static void LaunchInitProcess(BOOT_INFO* bootInfo) { + KSTATUS s; + FILE_OBJECT* f; + + // Read the executable file into a raw buffer + s = IoOpenFile(bootInfo->CommandLine, &f); + DbgPrint("KernelMain: IoOpenFile: %d\n", s); + if (s != STATUS_SUCCESS) { + DbgPrint("Failed to load file: \"%s\"!\n", bootInfo->CommandLine); + _disable(); while(1) __halt(); + } + + uint64_t size = IoGetFileSize(f); + DbgPrint("KernelMain: IoGetFileSize: %llu\n", size); + + void* mem = MmAllocateUserMemory(size); + DbgPrint("KernelMain: MmAllocateUserMemory: 0x%llX\n", mem); + + size_t got; + s = IoReadFile(f, mem, size, &got); + DbgPrint("KernelMain: IoReadFile: %d\n", s); + IoCloseFile(f); + DbgPrint("KernelMain: IoCloseFile\n"); + + // Create the process object + PROCESS* proc; + THREAD* thread; + + s = KeCreateProcess("init", &proc); + if (!KSUCCESS(s)) { + DbgPrint("Failed to create init process. System halted.\n"); + _disable(); while(1) __halt(); + } + DbgPrint("Created init process (PID %u) with command line: %s\n", proc->ProcessId, bootInfo->CommandLine); + + // Parse the raw PE file and map it into executable memory + uintptr_t entryPoint = 0; + s = LdrLoadImage(mem, size, &entryPoint, true); + if (!KSUCCESS(s)) { + DbgPrint("KernelMain: LdrLoadImage failed with status: %d\n", s); + _disable(); while(1) __halt(); + } + DbgPrint("KernelMain: PE Image mapped! Entry point at 0x%llX\n", (void*)entryPoint); + + // Create the main thread, pointing it to the PE Entry Point + s = KeCreateThread(proc, (uintptr_t)entryPoint, 0, PriorityNormal, &thread); + if (!KSUCCESS(s)) { + DbgPrint("KernelMain: Failed to create init thread. Status: %d\n", s); + _disable(); while(1) __halt(); + } + DbgPrint("KernelMain: Thread created and queued!\n"); +} + +static void PrintProcessList() { + LIST_ENTRY* listHead = KeGetProcessList(); + LIST_ENTRY* current; + + DbgPrint("\nPID | Name | Threads | ExitCode\n"); + DbgPrint("---------------------------------------------\n"); + + for (current = listHead->Fwd; current != listHead; current = current->Fwd) { + // Translate the list entry back to the PROCESS structure + PROCESS* proc = CONTAINING_RECORD(current, PROCESS, GlobalLink); + + DbgPrint("%-5u | %-16s | %-7u | %d\n", + proc->ProcessId, + proc->Name, + proc->ThreadCount, + proc->ExitCode); + } +} + +// --------------------------------------------------------------------------- +// Main Kernel Entry +// --------------------------------------------------------------------------- +extern void KernelMain(BOOT_INFO* bootInfo) { + // + // Physical & Virtual Memory initialization + // + MmInitializePhysical(&bootInfo->MemoryMap, bootInfo->PhysicalMapBase); + PHYSICAL_ADDRESS pml4 = (PHYSICAL_ADDRESS)__readcr3(); + MmInitializeVirtual(pml4, 4 * 1024 * 1024 /* 4 MB initial pool */); + + // + // CPU Architecture setup (GDT/IDT/Faults) + // + KeInitializeGdt(); + KeInitializeIdt(); + + // + // Register boot modules (Allows LdrGetExport to work for drivers and the HAL) + // Note: Kept to a single call here to avoid the duplicate in your original code. + // + LdrRegisterModulesFromBootInfo(bootInfo); + + // + // HAL Initialization + // + HAL_INIT_PARAMS halParams = { + .PhysicalWindowBase = bootInfo->PhysicalMapBase, + .FramebufferBase = bootInfo->FramebufferBase, + .FramebufferWidth = bootInfo->FramebufferWidth, + .FramebufferHeight = bootInfo->FramebufferHeight, + .FramebufferStride = bootInfo->FramebufferStride, + .RsdpPhysical = bootInfo->RsdpPhysical, + .DebugEnabled = bootInfo->DebugEnabled + }; + KSTATUS s = HalInitialize(&halParams); + if (!KSUCCESS(s)) for (;;) __halt(); // there's nothing we can do. + const HAL_API* hal = HalGetApi(); + + KeInitDebug(hal->Screen.PrintChar, bootInfo->DebugEnabled); // Enable debug + + KeIrqInitialize(hal); + + KeIrqRegister(hal->Timer.IrqNumber, hal->Timer.Isr); + KeIrqRegister(hal->Keyboard.IrqNumber, hal->Keyboard.Isr); + + HalRegisterScheduler(KeSchedulerTick); + + KeSyscallSetHal(hal); + + // + // Dynamic Linking & Driver Execution + // + ResolveSystemImports(bootInfo); + InitializeDrivers(bootInfo, hal); + + // + // Scheduler Prep & Status Update + // + KeInitializeScheduler(); + // hal->Screen.Clear(0x000000); + DbgPrint("KernelMain: initialisation complete. %u MB free.\n", + (unsigned)(MmFreeFrameCount() * PAGE_SIZE / (1024 * 1024))); + + DbgPrint("KernelMain: Loading system DLLs...\n"); + LoadAndRegisterDll("syscall.dll"); + LoadAndRegisterDll("win32.dll"); + + // Now that they are in memory and registered, we link them together + // (e.g., win32.dll resolving its imports against syscall.dll) + ResolveSystemImports(bootInfo); + + // + // User-Mode Launch + // + LaunchInitProcess(bootInfo); + + // + // Ignite the System + // + DbgPrint("KernelMain: Starting scheduler... Handing over control.\n"); + _enable(); + + while (1) { + DbgPrint("KernelMain: Idle loop. Free memory: %u MB\n", + (unsigned)(MmFreeFrameCount() * PAGE_SIZE / (1024 * 1024))); + __halt(); // nothing to do + } +} diff --git a/code/kernel/ldr_image.c b/code/kernel/ldr_image.c new file mode 100644 index 0000000..8437ae8 --- /dev/null +++ b/code/kernel/ldr_image.c @@ -0,0 +1,301 @@ +// ldr_image.c - PE32+ loader and export resolver +// +// At boot all images are already mapped by the bootloader; LdrLoadImage is +// used for any image loaded later (currently unused - all modules come in via +// BOOT_INFO). LdrGetExport scans the PE export directory of a registered module. +#include "ldr_image.h" +#include "boot_info.h" +#include "mm_virt.h" +#include "ke_debug.h" +#include +#include + +// --------------------------------------------------------------------------- +// PE32+ structures (just what we need) +// --------------------------------------------------------------------------- +#define PE_SIGNATURE 0x00004550UL // 'PE\0\0' +#define IMAGE_FILE_MACHINE_AMD64 0x8664 + +#pragma pack(push, 1) +typedef struct { + uint16_t Magic; + uint8_t MajorLinkerVersion; + uint8_t MinorLinkerVersion; + uint32_t SizeOfCode; + uint32_t SizeOfInitializedData; + uint32_t SizeOfUninitializedData; + uint32_t AddressOfEntryPoint; + uint32_t BaseOfCode; + uint64_t ImageBase; + uint32_t SectionAlignment; + uint32_t FileAlignment; + uint16_t MajorOSVersion; + uint16_t MinorOSVersion; + uint16_t MajorImageVersion; + uint16_t MinorImageVersion; + uint16_t MajorSubsystemVersion; + uint16_t MinorSubsystemVersion; + uint32_t Win32VersionValue; + uint32_t SizeOfImage; + uint32_t SizeOfHeaders; + uint32_t CheckSum; + uint16_t Subsystem; + uint16_t DllCharacteristics; + uint64_t SizeOfStackReserve; + uint64_t SizeOfStackCommit; + uint64_t SizeOfHeapReserve; + uint64_t SizeOfHeapCommit; + uint32_t LoaderFlags; + uint32_t NumberOfRvaAndSizes; + struct { uint32_t VirtualAddress; uint32_t Size; } DataDirectory[16]; +} OPT_HEADER64; + +typedef struct { + uint32_t Signature; + uint16_t Machine; + uint16_t NumberOfSections; + uint32_t TimeDateStamp; + uint32_t PointerToSymbolTable; + uint32_t NumberOfSymbols; + uint16_t SizeOfOptionalHeader; + uint16_t Characteristics; + OPT_HEADER64 OptionalHeader; +} PE_HEADER; + +typedef struct { + char Name[8]; + uint32_t VirtualSize; + uint32_t VirtualAddress; + uint32_t SizeOfRawData; + uint32_t PointerToRawData; + uint32_t PointerToRelocations; + uint32_t PointerToLinenumbers; + uint16_t NumberOfRelocations; + uint16_t NumberOfLinenumbers; + uint32_t Characteristics; +} SECTION_HEADER; + +typedef struct { + uint32_t Characteristics; + uint32_t TimeDateStamp; + uint16_t MajorVersion; + uint16_t MinorVersion; + uint32_t Name; + uint32_t Base; + uint32_t NumberOfFunctions; + uint32_t NumberOfNames; + uint32_t AddressOfFunctions; + uint32_t AddressOfNames; + uint32_t AddressOfNameOrdinals; +} EXPORT_DIR; + +typedef struct { + uint32_t OriginalFirstThunk; + uint32_t TimeDateStamp; + uint32_t ForwarderChain; + uint32_t Name; + uint32_t FirstThunk; +} IMPORT_DESC; + +typedef struct { + uint32_t VirtualAddress; + uint32_t SizeOfBlock; +} BASE_RELOC; +#pragma pack(pop) + +#define IMAGE_REL_BASED_DIR64 10 + +// --------------------------------------------------------------------------- +// Module registry +// --------------------------------------------------------------------------- +#define MAX_MODULES 32 + +typedef struct { + char Name[32]; + uintptr_t Base; +} MODULE_ENTRY; + +static MODULE_ENTRY gModules[MAX_MODULES]; +static int gModuleCount = 0; + +void LdrRegisterModulesFromBootInfo(const BOOT_INFO* bootInfo) { + for (uint32_t i = 0; i < bootInfo->ModuleCount && i < MAX_MODULES; i++) { + strncpy(gModules[gModuleCount].Name, bootInfo->Modules[i].Name, 31); + gModules[gModuleCount].Base = bootInfo->Modules[i].VirtBase; + gModuleCount++; + } +} + +void LdrRegisterModule(const char* name, uintptr_t base) { + if (gModuleCount < MAX_MODULES) { + strncpy(gModules[gModuleCount].Name, name, 31); + gModules[gModuleCount].Base = base; + gModuleCount++; + } +} + +static uintptr_t FindModuleBase(const char* name) { + for (int i = 0; i < gModuleCount; i++) { + if (_stricmp(gModules[i].Name, name) == 0) return gModules[i].Base; + } + return 0; +} + +// --------------------------------------------------------------------------- +// Export lookup +// --------------------------------------------------------------------------- +void* LdrGetExport(const char* moduleName, const char* functionName) { + uintptr_t base = FindModuleBase(moduleName); + if (!base) return (void *)0; + + uint32_t peOffset = *(uint32_t *)(base + 0x3C); + PE_HEADER* pe = (PE_HEADER *)(base + peOffset); + if (pe->Signature != PE_SIGNATURE) return (void *)0; + + OPT_HEADER64* opt = &pe->OptionalHeader; + if (opt->NumberOfRvaAndSizes < 1) return (void *)0; + + uint32_t expRva = opt->DataDirectory[0].VirtualAddress; + if (!expRva) return (void *)0; + + EXPORT_DIR* exp = (EXPORT_DIR *)(base + expRva); + uint32_t* names = (uint32_t *)(base + exp->AddressOfNames); + uint16_t* ordinals = (uint16_t *)(base + exp->AddressOfNameOrdinals); + uint32_t* functions = (uint32_t *)(base + exp->AddressOfFunctions); + + for (uint32_t i = 0; i < exp->NumberOfNames; i++) { + const char* name = (const char *)(base + names[i]); + if (strcmp(name, functionName) == 0) { + uint16_t ord = ordinals[i]; + return (void *)(base + functions[ord]); + } + } + return (void *)0; +} + +// --------------------------------------------------------------------------- +// Entry point lookup +// --------------------------------------------------------------------------- +uintptr_t LdrGetEntryPoint(uintptr_t base) { + uint32_t pe_offset = *(uint32_t*)(base + 0x3C); + uint32_t entry_rva = *(uint32_t*)(base + pe_offset + 0x28); + return base + entry_rva; +} + +// --------------------------------------------------------------------------- +// Base Relocation +// --------------------------------------------------------------------------- +static KSTATUS LdrApplyRelocations(uintptr_t base, uintptr_t delta) { + uint32_t peOffset = *(uint32_t *)(base + 0x3C); + PE_HEADER* pe = (PE_HEADER *)(base + peOffset); + OPT_HEADER64* opt = &pe->OptionalHeader; + + if (opt->NumberOfRvaAndSizes < 6) return STATUS_SUCCESS; + uint32_t relocRva = opt->DataDirectory[5].VirtualAddress; + uint32_t relocSize = opt->DataDirectory[5].Size; + if (!relocRva || !relocSize) return STATUS_SUCCESS; + + BASE_RELOC* block = (BASE_RELOC *)(base + relocRva); + uintptr_t end = (uintptr_t)block + relocSize; + + while ((uintptr_t)block < end && block->SizeOfBlock > 0) { + uint32_t count = (block->SizeOfBlock - sizeof(BASE_RELOC)) / sizeof(uint16_t); + uint16_t* entries = (uint16_t *)(block + 1); + + for (uint32_t i = 0; i < count; i++) { + int type = entries[i] >> 12; + int offset = entries[i] & 0xFFF; + + // For 64-bit PEs, we mostly care about DIR64 (Type 10) + if (type == IMAGE_REL_BASED_DIR64) { + uint64_t* ptr = (uint64_t *)(base + block->VirtualAddress + offset); + *ptr += delta; + } + } + block = (BASE_RELOC *)((uint8_t *)block + block->SizeOfBlock); + } + return STATUS_SUCCESS; +} + +// --------------------------------------------------------------------------- +// Import resolution +// --------------------------------------------------------------------------- +KSTATUS LdrResolveImports(uintptr_t imageBase) { + uint32_t peOffset = *(uint32_t *)(imageBase + 0x3C); + PE_HEADER* pe = (PE_HEADER *)(imageBase + peOffset); + OPT_HEADER64* opt = &pe->OptionalHeader; + + if (opt->NumberOfRvaAndSizes < 2) return STATUS_SUCCESS; // no imports + uint32_t impRva = opt->DataDirectory[1].VirtualAddress; + if (!impRva) return STATUS_SUCCESS; + + IMPORT_DESC* imp = (IMPORT_DESC *)(imageBase + impRva); + while (imp->Name) { + const char* dllName = (const char *)(imageBase + imp->Name); + uint64_t* thunk = (uint64_t *)(imageBase + imp->FirstThunk); + uint64_t* origThunk = (uint64_t *)(imageBase + (imp->OriginalFirstThunk + ? imp->OriginalFirstThunk + : imp->FirstThunk)); + while (*origThunk) { + if (*origThunk & (1ULL << 63)) { + // Import by ordinal - not supported. + DbgPrint("LdrResolveImports: Ordinal imports not supported! (%s)\n", dllName); + return STATUS_NOT_SUPPORTED; + } + const char* funcName = (const char *)(imageBase + (*origThunk & 0xFFFFFFFF) + 2); + void* addr = LdrGetExport(dllName, funcName); + if (!addr) { + DbgPrint("LdrResolveImports: Function not found! (%s)\n", funcName); + return STATUS_NOT_FOUND; + } + *thunk = (uint64_t)addr; + thunk++; + origThunk++; + } + imp++; + } + return STATUS_SUCCESS; +} + +// LdrLoadImage - load a PE from a raw buffer into virtual space. +KSTATUS LdrLoadImage(const void* buffer, size_t size, uintptr_t* baseOut, bool user) { + if (!buffer || !size || !baseOut) return STATUS_INVALID_PARAMETER; + + uint32_t peOffset = *(uint32_t *)((uint8_t *)buffer + 0x3C); + PE_HEADER* pe = (PE_HEADER *)((uint8_t *)buffer + peOffset); + if (pe->Signature != PE_SIGNATURE) return STATUS_FAILURE; + + OPT_HEADER64* opt = &pe->OptionalHeader; + size_t imageSize = opt->SizeOfImage; + + void* mem = user ? MmAllocateUserMemory(imageSize) : MmAllocatePool(imageSize); + if (!mem) return STATUS_NO_MEMORY; + memset(mem, 0, imageSize); + + // Copy headers and sections + memcpy(mem, buffer, opt->SizeOfHeaders); + SECTION_HEADER* sec = (SECTION_HEADER *)((uint8_t *)&pe->OptionalHeader + pe->SizeOfOptionalHeader); + for (int i = 0; i < pe->NumberOfSections; i++) { + void* dst = (uint8_t *)mem + sec[i].VirtualAddress; + const void* src = (const uint8_t *)buffer + sec[i].PointerToRawData; + if (sec[i].SizeOfRawData) { + memcpy(dst, src, sec[i].SizeOfRawData < sec[i].VirtualSize ? sec[i].SizeOfRawData : sec[i].VirtualSize); + } + + uint64_t prot = PAGE_PRESENT | PAGE_WRITE | (user ? PAGE_USER : 0); + MmSetPageProtect((uintptr_t)mem + sec[i].VirtualAddress, sec[i].VirtualSize, prot); + } + + // Apply Relocations + uintptr_t delta = (uintptr_t)mem - opt->ImageBase; + if (delta != 0) { + LdrApplyRelocations((uintptr_t)mem, delta); + } + + // Resolve Imports + KSTATUS status = LdrResolveImports((uintptr_t)mem); + if (status != STATUS_SUCCESS) return status; + + *baseOut = (uintptr_t)mem + opt->AddressOfEntryPoint; + return STATUS_SUCCESS; +} diff --git a/code/kernel/ldr_image.h b/code/kernel/ldr_image.h new file mode 100644 index 0000000..a6490bc --- /dev/null +++ b/code/kernel/ldr_image.h @@ -0,0 +1,27 @@ +#pragma once +// ldr_image.h - minimal PE32+ loader +// Loads an already-mapped PE image and resolves its imports. +#include "ke_status.h" +#include +#include +#include + +// Map a PE32+ image from 'buffer' into the kernel virtual address space. +// On success, *baseOut receives the virtual base address. +KSTATUS LdrLoadImage(const void* buffer, size_t size, uintptr_t* baseOut, bool user); + +// Look up a named export in a loaded module. +// 'moduleName' must match a name in BOOT_INFO.Modules (e.g., "hal.dll"). +void* LdrGetExport(const char* moduleName, const char* functionName); + +// Get the entry point address of a loaded image. +uintptr_t LdrGetEntryPoint(uintptr_t base); + +// Resolve the import table of an already-loaded image. +KSTATUS LdrResolveImports(uintptr_t imageBase); + +// Called by KernelMain to register all modules from BOOT_INFO so that +// LdrGetExport can find them. +struct BOOT_INFO; // forward declare for the compiler to shut the fuck up +void LdrRegisterModulesFromBootInfo(const struct BOOT_INFO* bootInfo); +void LdrRegisterModule(const char* name, uintptr_t base); diff --git a/code/kernel/memory_map.h b/code/kernel/memory_map.h new file mode 100644 index 0000000..4881c30 --- /dev/null +++ b/code/kernel/memory_map.h @@ -0,0 +1,30 @@ +#pragma once +// memory_map.h - shared between bootx64.efi and kernel.exe +// Describes physical memory layout passed from bootloader to kernel. +#include + +#define MEMORY_MAP_MAGIC 0x4D454D4D41500000ULL /* 'MEMMAP\0\0' */ +#define MEMORY_MAX_REGIONS 256 + +typedef enum MEMORY_TYPE { + MemoryUsable = 0, /* free RAM, available to the PMM */ + MemoryReserved = 1, /* firmware-reserved, do not touch */ + MemoryMappedIO = 2, /* device MMIO regions */ + MemoryFramebuffer = 3, /* GOP framebuffer */ + MemoryBootloader = 4, /* bootloader code/data (reclaimable) */ + MemoryKernel = 5, /* kernel + HAL + drivers image pages */ +} MEMORY_TYPE; + +typedef struct MEMORY_REGION { + uint64_t Base; + uint64_t Length; /* in bytes, always page-aligned */ + MEMORY_TYPE Type; + uint32_t _pad; +} MEMORY_REGION; + +typedef struct MEMORY_MAP { + uint64_t Magic; + uint32_t RegionCount; + uint32_t _pad; + MEMORY_REGION Regions[MEMORY_MAX_REGIONS]; +} MEMORY_MAP; diff --git a/code/kernel/mm_phys.c b/code/kernel/mm_phys.c new file mode 100644 index 0000000..9810053 --- /dev/null +++ b/code/kernel/mm_phys.c @@ -0,0 +1,162 @@ +// mm_phys.c - physical memory manager +// +// The free-frame stack is a flat array of PHYSICAL_ADDRESS values carved out of +// the first suitable usable region before any allocation is served. All access +// to physical memory goes through the direct physical window established by the +// bootloader at PhysicalWindowBase (always 0xFFFF880000000000). +// +// Lock: a single spinlock guards Push/Pop. O(1) for both operations. +#include "mm_phys.h" +#include "ke_spinlock.h" +#include +#include + +// --------------------------------------------------------------------------- +// Physical-to-virtual translation via the direct map window. +// --------------------------------------------------------------------------- +static uint64_t gPhysBase = 0; // set by MmInitializePhysical + +static inline void* PhysToVirt(PHYSICAL_ADDRESS phys) { + return (void *)(phys + gPhysBase); +} + +// --------------------------------------------------------------------------- +// Frame stack +// --------------------------------------------------------------------------- +#define MAX_FRAMES (256ULL * 1024) // up to 1 GB worth of 4 KB frames + +typedef struct { + PHYSICAL_ADDRESS* Stack; // pointer into physical window + size_t Top; // index of next free slot (stack grows up) + size_t Capacity; + size_t Total; // total frames ever pushed + SPINLOCK Lock; +} FRAME_STACK; + +static FRAME_STACK gFrameStack; + +// Push a physical frame address onto the stack. +static void PushFrame(PHYSICAL_ADDRESS frame) { + KeAcquireSpinlock(&gFrameStack.Lock); + if (gFrameStack.Top < gFrameStack.Capacity) { + gFrameStack.Stack[gFrameStack.Top++] = frame; + } + KeReleaseSpinlock(&gFrameStack.Lock); +} + +// --------------------------------------------------------------------------- +// Initialisation +// --------------------------------------------------------------------------- +void MmInitializePhysical(const MEMORY_MAP* map, uint64_t physicalWindowBase) { + gPhysBase = physicalWindowBase; + + // --- Phase 1: Find a region large enough to hold the stack array. --- + // We need MAX_FRAMES * sizeof(PHYSICAL_ADDRESS) = 2 MB worst-case. + // Take the first usable region that is large enough. + const size_t stackBytes = MAX_FRAMES * sizeof(PHYSICAL_ADDRESS); + PHYSICAL_ADDRESS stackPhys = 0; + + for (uint32_t i = 0; i < map->RegionCount; i++) { + const MEMORY_REGION* r = &map->Regions[i]; + if (r->Type == MemoryUsable && r->Length >= stackBytes + PAGE_SIZE) { + stackPhys = r->Base; + break; + } + } + + if (!stackPhys) { + // Should never happen on any machine with >= 4 MB RAM. + // Hang - there is nothing else we can do. + for (;;) { __halt(); } + } + + gFrameStack.Stack = (PHYSICAL_ADDRESS *)PhysToVirt(stackPhys); + gFrameStack.Top = 0; + gFrameStack.Capacity = MAX_FRAMES; + gFrameStack.Total = 0; + gFrameStack.Lock = (SPINLOCK)SPINLOCK_INIT; + + // --- Phase 2: Push all free 4 KB frames from MemoryUsable regions. --- + // Skip the pages occupied by the stack itself. + const PHYSICAL_ADDRESS stackEnd = + stackPhys + ((stackBytes + PAGE_SIZE - 1) & PAGE_MASK); + + for (uint32_t i = 0; i < map->RegionCount; i++) { + const MEMORY_REGION* r = &map->Regions[i]; + if (r->Type != MemoryUsable) continue; + + PHYSICAL_ADDRESS base = r->Base; + PHYSICAL_ADDRESS end = r->Base + r->Length; + + for (PHYSICAL_ADDRESS frame = base; frame < end; frame += PAGE_SIZE) { + // Skip the frames reserved for our own stack. + if (frame >= stackPhys && frame < stackEnd) continue; + if (gFrameStack.Top < gFrameStack.Capacity) { + gFrameStack.Stack[gFrameStack.Top++] = frame; + gFrameStack.Total++; + } + } + } +} + +// --------------------------------------------------------------------------- +// Public API +// --------------------------------------------------------------------------- +PHYSICAL_ADDRESS MmAllocateFrame(void) { + KeAcquireSpinlock(&gFrameStack.Lock); + if (gFrameStack.Top == 0) { + KeReleaseSpinlock(&gFrameStack.Lock); + return (PHYSICAL_ADDRESS)0; + } + PHYSICAL_ADDRESS frame = gFrameStack.Stack[--gFrameStack.Top]; + KeReleaseSpinlock(&gFrameStack.Lock); + return frame; +} + +void MmFreeFrame(PHYSICAL_ADDRESS frame) { + if (!frame || (frame & (PAGE_SIZE - 1))) return; // must be page-aligned + PushFrame(frame); +} + +PHYSICAL_ADDRESS MmAllocateContiguous(size_t count) { + if (!count) return (PHYSICAL_ADDRESS)0; + + // Brute-force: scan the stack for 'count' consecutive frames. + // Acceptable for small DMA buffers; not for general use. + KeAcquireSpinlock(&gFrameStack.Lock); + + // Build a temporary sorted view - too expensive; instead do a simple + // linear scan for a contiguous run already on the stack (lucky case), + // or fall back to pulling frames one by one and checking adjacency. + // For now: pull 'count' frames and verify they are contiguous. + // If not, return them all and report failure. + if (gFrameStack.Top < count) { + KeReleaseSpinlock(&gFrameStack.Lock); + return (PHYSICAL_ADDRESS)0; + } + + // Attempt: take the top 'count' entries and check. + PHYSICAL_ADDRESS base = gFrameStack.Stack[gFrameStack.Top - 1]; + int ok = 1; + for (size_t i = 0; i < count; i++) { + PHYSICAL_ADDRESS f = gFrameStack.Stack[gFrameStack.Top - 1 - i]; + if (f != base + i * PAGE_SIZE) { ok = 0; break; } + } + + if (ok) { + gFrameStack.Top -= count; + KeReleaseSpinlock(&gFrameStack.Lock); + return base; + } + + KeReleaseSpinlock(&gFrameStack.Lock); + return (PHYSICAL_ADDRESS)0; // caller should retry or fail gracefully +} + +size_t MmFreeFrameCount(void) { + return gFrameStack.Top; +} + +size_t MmTotalFrameCount(void) { + return gFrameStack.Total; +} diff --git a/code/kernel/mm_phys.h b/code/kernel/mm_phys.h new file mode 100644 index 0000000..fc0c8b9 --- /dev/null +++ b/code/kernel/mm_phys.h @@ -0,0 +1,27 @@ +#pragma once +// mm_phys.h - physical memory manager (PMM) +// Stack allocator over 4 KB frames, seeded from MEMORY_MAP. +#include +#include +#include "memory_map.h" + +#define PAGE_SIZE 4096ULL +#define PAGE_MASK (~(PAGE_SIZE - 1)) + +typedef uint64_t PHYSICAL_ADDRESS; + +// Called once by KernelMain with the MEMORY_MAP from BOOT_INFO. +void MmInitializePhysical(const MEMORY_MAP* map, + uint64_t physicalWindowBase); + +// Allocate / free a single 4 KB frame. +// MmAllocateFrame returns 0 on failure. +PHYSICAL_ADDRESS MmAllocateFrame(void); +void MmFreeFrame(PHYSICAL_ADDRESS frame); + +// Allocate 'count' physically contiguous 4 KB frames. +// Returns 0 on failure. Use sparingly (DMA, page tables). +PHYSICAL_ADDRESS MmAllocateContiguous(size_t count); + +size_t MmFreeFrameCount(void); +size_t MmTotalFrameCount(void); diff --git a/code/kernel/mm_virt.c b/code/kernel/mm_virt.c new file mode 100644 index 0000000..ebb5c48 --- /dev/null +++ b/code/kernel/mm_virt.c @@ -0,0 +1,445 @@ +// mm_virt.c - virtual memory manager +// +// Page tables: +// One PML4 shared by all processes. +// Upper half (bit 47 set) has U/S = 0 - ring-3 access always faults. +// Lower half pages are PAGE_USER. +// +// Kernel pool: +// A boundary-tag (header + footer) free-list allocator starting at POOL_BASE. +// Pages are committed on demand from the PMM. +// +// User heap: +// A single best-fit free list in the lower half. +// Backed on demand from the PMM. No per-process heaps. +#include "mm_virt.h" +#include "ke_spinlock.h" +#include +#include + +// --------------------------------------------------------------------------- +// Helpers - physical window access +// --------------------------------------------------------------------------- +static uint64_t gPhysBase = PHYS_MAP_BASE; + +static inline void* PhysToVirt(PHYSICAL_ADDRESS p) { + return (void *)(p + gPhysBase); +} +static inline uint64_t* PtePtr(PHYSICAL_ADDRESS tablePhys, unsigned idx) { + return (uint64_t *)PhysToVirt(tablePhys) + idx; +} + +// --------------------------------------------------------------------------- +// PML4 / page-table helpers +// --------------------------------------------------------------------------- +static PHYSICAL_ADDRESS gPml4Phys = 0; + +// Extract the page-table index for each level from a virtual address. +#define PML4_IDX(va) (((va) >> 39) & 0x1FF) +#define PDPT_IDX(va) (((va) >> 30) & 0x1FF) +#define PDT_IDX(va) (((va) >> 21) & 0x1FF) +#define PT_IDX(va) (((va) >> 12) & 0x1FF) + +// Ensure a page-table entry at 'parentPhys[index]' points to a child table. +// Allocates and zeros a new frame if the entry is not present. +// Returns the physical address of the child table, or 0 on OOM. +static PHYSICAL_ADDRESS EnsureTable(PHYSICAL_ADDRESS parentPhys, + unsigned index, uint64_t extraFlags) { + uint64_t* entry = PtePtr(parentPhys, index); + if (*entry & PAGE_PRESENT) { + *entry |= extraFlags; + return* entry & ~0xFFFULL; + } + PHYSICAL_ADDRESS childPhys = MmAllocateFrame(); + if (!childPhys) return 0; + memset(PhysToVirt(childPhys), 0, PAGE_SIZE); + *entry = childPhys | PAGE_PRESENT | PAGE_WRITE | extraFlags; + return childPhys; +} + +// --------------------------------------------------------------------------- +// Public mapping +// --------------------------------------------------------------------------- +KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags) { + unsigned userFlag = (flags & PAGE_USER) ? PAGE_USER : 0; + + PHYSICAL_ADDRESS pdpt = EnsureTable(gPml4Phys, PML4_IDX(virt), userFlag); + if (!pdpt) return STATUS_NO_MEMORY; + PHYSICAL_ADDRESS pdt = EnsureTable(pdpt, PDPT_IDX(virt), userFlag); + if (!pdt) return STATUS_NO_MEMORY; + PHYSICAL_ADDRESS pt = EnsureTable(pdt, PDT_IDX(virt), userFlag); + if (!pt) return STATUS_NO_MEMORY; + + uint64_t* pte = PtePtr(pt, PT_IDX(virt)); + *pte = phys | flags; + __invlpg((void *)virt); + return STATUS_SUCCESS; +} + +KSTATUS MmUnmapPage(uintptr_t virt) { + uint64_t* e4 = PtePtr(gPml4Phys, PML4_IDX(virt)); + if (!(*e4 & PAGE_PRESENT)) return STATUS_NOT_FOUND; + uint64_t* e3 = PtePtr(*e4 & ~0xFFFULL, PDPT_IDX(virt)); + if (!(*e3 & PAGE_PRESENT)) return STATUS_NOT_FOUND; + uint64_t* e2 = PtePtr(*e3 & ~0xFFFULL, PDT_IDX(virt)); + if (!(*e2 & PAGE_PRESENT)) return STATUS_NOT_FOUND; + uint64_t* pte = PtePtr(*e2 & ~0xFFFULL, PT_IDX(virt)); + *pte = 0; + __invlpg((void *)virt); + return STATUS_SUCCESS; +} + +KSTATUS MmSetPageProtect(uintptr_t virt, size_t size, uint64_t flags) { + if (!size) return STATUS_SUCCESS; + + // Round down to page boundary, round size up. + uintptr_t base = virt & PAGE_MASK; + uintptr_t end = (virt + size + PAGE_SIZE - 1) & PAGE_MASK; + + for (uintptr_t va = base; va < end; va += PAGE_SIZE) { + uint64_t* e4 = PtePtr(gPml4Phys, PML4_IDX(va)); + if (!(*e4 & PAGE_PRESENT)) return STATUS_NOT_FOUND; + uint64_t* e3 = PtePtr(*e4 & ~0xFFFULL, PDPT_IDX(va)); + if (!(*e3 & PAGE_PRESENT)) return STATUS_NOT_FOUND; + uint64_t* e2 = PtePtr(*e3 & ~0xFFFULL, PDT_IDX(va)); + if (!(*e2 & PAGE_PRESENT)) return STATUS_NOT_FOUND; + uint64_t* pte = PtePtr(*e2 & ~0xFFFULL, PT_IDX(va)); + if (!(*pte & PAGE_PRESENT)) return STATUS_NOT_FOUND; + + // Preserve the physical address, replace everything else. + PHYSICAL_ADDRESS phys = *pte & ~0xFFFULL & ~PAGE_NX; + *pte = phys | flags; + __invlpg((void *)va); + } + + return STATUS_SUCCESS; +} + +PHYSICAL_ADDRESS MmGetPhysicalAddress(uintptr_t virt) { + if (!gPml4Phys) return 0; // Not initialized + + uint64_t pml4_idx = (virt >> 39) & 0x1FF; + uint64_t pdpt_idx = (virt >> 30) & 0x1FF; + uint64_t pd_idx = (virt >> 21) & 0x1FF; + uint64_t pt_idx = (virt >> 12) & 0x1FF; + + uint64_t* pml4 = PhysToVirt(gPml4Phys); + if (!(pml4[pml4_idx] & PAGE_PRESENT)) return 0; + + uint64_t* pdpt = PhysToVirt(pml4[pml4_idx] & ~0xFFFULL); + if (!(pdpt[pdpt_idx] & PAGE_PRESENT)) return 0; + + // Check for 1GB huge pages (bit 7 - PS) + if (pdpt[pdpt_idx] & 0x80) { + return (pdpt[pdpt_idx] & 0x000FFFFFC0000000ULL) + (virt & 0x3FFFFFFF); + } + + uint64_t* pd = PhysToVirt(pdpt[pdpt_idx] & ~0xFFFULL); + if (!(pd[pd_idx] & PAGE_PRESENT)) return 0; + + // Check for 2MB huge pages (bit 7 - PS) + if (pd[pd_idx] & 0x80) { + return (pd[pd_idx] & 0x000FFFFFFFE00000ULL) + (virt & 0x1FFFFF); + } + + uint64_t* pt = PhysToVirt(pd[pd_idx] & ~0xFFFULL); + if (!(pt[pt_idx] & PAGE_PRESENT)) return 0; + + // Extract the physical frame and add the offset within the page + return (pt[pt_idx] & ~0xFFFULL) + (virt & 0xFFF); +} + +// --------------------------------------------------------------------------- +// Boundary-tag allocator (used for both pool and user heap) +// --------------------------------------------------------------------------- +// Each allocation has a BLOCK_HDR immediately before the user data, and a +// BLOCK_FTR immediately after. Both carry the block size and a 'free' flag. +// This allows O(1) coalescing of adjacent free blocks. + +#define BLOCK_MAGIC 0xB10CB10CUL + +typedef struct BLOCK_HDR { + uint32_t Magic; + uint32_t Free; // 1 = free, 0 = used + size_t Size; // usable bytes (excludes header + footer) + struct BLOCK_HDR* PrevFree; + struct BLOCK_HDR* NextFree; +} BLOCK_HDR; + +typedef struct BLOCK_FTR { + size_t Size; + uint32_t Free; + uint32_t Magic; +} BLOCK_FTR; + +#define HDR_SIZE (sizeof(BLOCK_HDR)) +#define FTR_SIZE (sizeof(BLOCK_FTR)) +#define OVERHEAD (HDR_SIZE + FTR_SIZE) +#define MIN_BLOCK (OVERHEAD + sizeof(void*)) + +static inline BLOCK_FTR* HdrToFtr(BLOCK_HDR* h) { + return (BLOCK_FTR *)((char *)h + HDR_SIZE + h->Size); +} +static inline BLOCK_HDR* FtrToHdr(BLOCK_FTR* f) { + return (BLOCK_HDR *)((char *)f - HDR_SIZE - f->Size); +} +static inline BLOCK_HDR* NextBlock(BLOCK_HDR* h) { + return (BLOCK_HDR *)((char *)h + HDR_SIZE + h->Size + FTR_SIZE); +} +static inline BLOCK_FTR* PrevFtr(BLOCK_HDR* h) { + return (BLOCK_FTR *)((char *)h - FTR_SIZE); +} + +typedef struct HEAP { + BLOCK_HDR* FreeList; // doubly-linked list of free blocks + uintptr_t Start; // virtual base of the arena + uintptr_t Brk; // current committed end (page-aligned) + uintptr_t Limit; // hard upper bound + uint64_t MapFlags; // PAGE_* flags for new committed pages + SPINLOCK Lock; +} HEAP; + +// Extend heap by at least 'need' bytes (rounded up to page boundary). +static int HeapGrow(HEAP* h, size_t need) { + size_t grow = (need + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); + if (h->Brk + grow > h->Limit) return 0; + + for (uintptr_t va = h->Brk; va < h->Brk + grow; va += PAGE_SIZE) { + PHYSICAL_ADDRESS frame = MmAllocateFrame(); + if (!frame) return 0; + if (!KSUCCESS(MmMapPage(va, frame, h->MapFlags))) { + MmFreeFrame(frame); + return 0; + } + memset((void *)va, 0, PAGE_SIZE); + } + + // Make the new pages a single free block. + BLOCK_HDR* blk = (BLOCK_HDR *)h->Brk; + blk->Magic = BLOCK_MAGIC; + blk->Free = 1; + blk->Size = grow - OVERHEAD; + blk->PrevFree = (BLOCK_HDR *)0; + blk->NextFree = h->FreeList; + if (h->FreeList) h->FreeList->PrevFree = blk; + h->FreeList = blk; + HdrToFtr(blk)->Magic = BLOCK_MAGIC; + HdrToFtr(blk)->Free = 1; + HdrToFtr(blk)->Size = blk->Size; + + h->Brk += grow; + return 1; +} + +// Unlink a free block from the free list. +static void FreeListRemove(HEAP* h, BLOCK_HDR* blk) { + if (blk->PrevFree) blk->PrevFree->NextFree = blk->NextFree; + else h->FreeList = blk->NextFree; + if (blk->NextFree) blk->NextFree->PrevFree = blk->PrevFree; + blk->PrevFree = blk->NextFree = (BLOCK_HDR *)0; +} + +static void* HeapAlloc(HEAP* h, size_t size) { + if (!size) return (void *)0; + size = (size + 7) & ~7ULL; // 8-byte align + + KeAcquireSpinlock(&h->Lock); + + // Best-fit search. + BLOCK_HDR* best = (BLOCK_HDR *)0; + for (BLOCK_HDR* cur = h->FreeList; cur; cur = cur->NextFree) { + if (cur->Size >= size) { + if (!best || cur->Size < best->Size) best = cur; + if (best->Size == size) break; + } + } + + if (!best) { + if (!HeapGrow(h, size + OVERHEAD)) { + KeReleaseSpinlock(&h->Lock); + return (void *)0; + } + // Re-search; HeapGrow inserted at the front. + best = h->FreeList; + while (best && best->Size < size) best = best->NextFree; + if (!best) { + KeReleaseSpinlock(&h->Lock); + return (void *)0; + } + } + + FreeListRemove(h, best); + + // Split the block if the remainder is big enough. + if (best->Size >= size + OVERHEAD + sizeof(void*)) { + BLOCK_HDR* rem = (BLOCK_HDR *)((char *)best + HDR_SIZE + size + FTR_SIZE); + rem->Magic = BLOCK_MAGIC; + rem->Free = 1; + rem->Size = best->Size - size - OVERHEAD; + rem->PrevFree = (BLOCK_HDR *)0; + rem->NextFree = h->FreeList; + if (h->FreeList) h->FreeList->PrevFree = rem; + h->FreeList = rem; + HdrToFtr(rem)->Magic = BLOCK_MAGIC; + HdrToFtr(rem)->Free = 1; + HdrToFtr(rem)->Size = rem->Size; + + best->Size = size; + } + + best->Free = 0; + HdrToFtr(best)->Free = 0; + HdrToFtr(best)->Magic = BLOCK_MAGIC; + HdrToFtr(best)->Size = best->Size; + + KeReleaseSpinlock(&h->Lock); + return (char *)best + HDR_SIZE; +} + +static void HeapFree(HEAP* h, void* ptr) { + if (!ptr) return; + BLOCK_HDR* blk = (BLOCK_HDR *)((char *)ptr - HDR_SIZE); + if (blk->Magic != BLOCK_MAGIC || blk->Free) return; // double-free / corrupt + + KeAcquireSpinlock(&h->Lock); + + blk->Free = 1; + + // Coalesce with next block if it is free. + BLOCK_HDR* next = NextBlock(blk); + if ((uintptr_t)next < h->Brk && next->Magic == BLOCK_MAGIC && next->Free) { + FreeListRemove(h, next); + blk->Size += OVERHEAD + next->Size; + HdrToFtr(blk)->Size = blk->Size; + HdrToFtr(blk)->Magic = BLOCK_MAGIC; + HdrToFtr(blk)->Free = 1; + } + + // Coalesce with previous block if it is free. + if ((uintptr_t)blk > h->Start) { + BLOCK_FTR* prevFtr = PrevFtr(blk); + if (prevFtr->Magic == BLOCK_MAGIC && prevFtr->Free) { + BLOCK_HDR* prev = FtrToHdr(prevFtr); + FreeListRemove(h, prev); + prev->Size += OVERHEAD + blk->Size; + HdrToFtr(prev)->Size = prev->Size; + HdrToFtr(prev)->Magic = BLOCK_MAGIC; + HdrToFtr(prev)->Free = 1; + blk = prev; + } + } + + // Insert at head of free list. + blk->PrevFree = (BLOCK_HDR *)0; + blk->NextFree = h->FreeList; + if (h->FreeList) h->FreeList->PrevFree = blk; + h->FreeList = blk; + + HdrToFtr(blk)->Free = 1; + HdrToFtr(blk)->Magic = BLOCK_MAGIC; + + KeReleaseSpinlock(&h->Lock); +} + +static void* HeapRealloc(HEAP* h, void* ptr, size_t new_size) { + // If ptr is NULL, realloc acts like malloc + if (!ptr) { + return HeapAlloc(h, new_size); + } + + // If size is 0, realloc acts like free + if (new_size == 0) { + HeapFree(h, ptr); + return (void*)0; + } + + // Retrieve the header of the existing block + BLOCK_HDR* blk = (BLOCK_HDR *)((char *)ptr - HDR_SIZE); + + // Sanity checks to prevent operating on corrupted or already-freed pointers + if (blk->Magic != BLOCK_MAGIC || blk->Free) { + return (void*)0; + } + + // Align the requested size (matches HeapAlloc 8-byte alignment) + size_t aligned_size = (new_size + 7) & ~7ULL; + + // If the current block is already big enough, we can reuse it in-place. + // (Note: To save space, you could optionally split the block here if + // the new size is significantly smaller, similar to HeapAlloc's logic). + if (blk->Size >= aligned_size) { + return ptr; + } + + // The block is too small. Allocate a new, larger block. + void* new_ptr = HeapAlloc(h, aligned_size); + if (!new_ptr) { + return (void*)0; // Out of memory, original block is left untouched + } + + // Copy the old data to the new block. + // We only copy up to the old block's usable size. + memcpy(new_ptr, ptr, blk->Size); + + // Free the old block + HeapFree(h, ptr); + + return new_ptr; +} + +// --------------------------------------------------------------------------- +// Kernel pool +// --------------------------------------------------------------------------- +static HEAP gPoolHeap; + +// --------------------------------------------------------------------------- +// User heap +// --------------------------------------------------------------------------- +static HEAP gUserHeap; + +// --------------------------------------------------------------------------- +// Module init +// --------------------------------------------------------------------------- +void MmInitializeVirtual(PHYSICAL_ADDRESS bootPml4Phys, size_t poolSize) { + gPml4Phys = bootPml4Phys; + + // Kernel pool heap. + gPoolHeap.FreeList = (BLOCK_HDR *)0; + gPoolHeap.Start = POOL_BASE; + gPoolHeap.Brk = POOL_BASE; + gPoolHeap.Limit = POOL_LIMIT; + gPoolHeap.MapFlags = PAGE_PRESENT | PAGE_WRITE | PAGE_NX; + gPoolHeap.Lock = (SPINLOCK)SPINLOCK_INIT; + + // Pre-commit the requested pool size. + if (poolSize) { + poolSize = (poolSize + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); + HeapGrow(&gPoolHeap, poolSize); + } + + // User heap. + gUserHeap.FreeList = (BLOCK_HDR *)0; + gUserHeap.Start = USER_BASE; + gUserHeap.Brk = USER_BASE; + gUserHeap.Limit = USER_LIMIT; + gUserHeap.MapFlags = PAGE_PRESENT | PAGE_WRITE | PAGE_USER; + gUserHeap.Lock = (SPINLOCK)SPINLOCK_INIT; +} + +void MmActivate(void) { + __writecr3(gPml4Phys); +} + +// --------------------------------------------------------------------------- +// Public pool API +// --------------------------------------------------------------------------- +void* MmAllocatePool(size_t size) { return HeapAlloc(&gPoolHeap, size); } +void MmFreePool(void* ptr) { HeapFree(&gPoolHeap, ptr); } +void* MmReallocatePool(void* ptr, size_t newSize) { return HeapRealloc(&gPoolHeap, ptr, newSize); } + +// --------------------------------------------------------------------------- +// Public user heap API +// --------------------------------------------------------------------------- +void* MmAllocateUserMemory(size_t size) { return HeapAlloc(&gUserHeap, size); } +void MmFreeUserMemory(void* ptr, size_t size) { (void)size; HeapFree(&gUserHeap, ptr); } +void* MmReallocateUserMemory(void* ptr, size_t newSize) { return HeapRealloc(&gUserHeap, ptr, newSize); } diff --git a/code/kernel/mm_virt.h b/code/kernel/mm_virt.h new file mode 100644 index 0000000..9bda186 --- /dev/null +++ b/code/kernel/mm_virt.h @@ -0,0 +1,70 @@ +#pragma once +// mm_virt.h - virtual memory manager (VMM) +// Manages the single shared PML4, kernel pool, and user heap. +#include +#include +#include "mm_phys.h" +#include "ke_status.h" + +// --------------------------------------------------------------------------- +// Page flags (x86-64 PTE bits) +// --------------------------------------------------------------------------- +#define PAGE_PRESENT (1ULL << 0) +#define PAGE_WRITE (1ULL << 1) +#define PAGE_USER (1ULL << 2) +#define PAGE_NOCACHE (1ULL << 4) +#define PAGE_NX (1ULL << 63) + +// --------------------------------------------------------------------------- +// Virtual address space constants +// --------------------------------------------------------------------------- +#define USER_BASE 0x0000000000001000ULL +#define USER_LIMIT 0x00007FFFFFFFF000ULL + +#define KERNEL_BASE 0xFFFF800000000000ULL +#define PHYS_MAP_BASE 0xFFFF880000000000ULL +#define POOL_BASE 0xFFFFC00000000000ULL +#define POOL_LIMIT 0xFFFFE00000000000ULL + +// --------------------------------------------------------------------------- +// Initialisation +// --------------------------------------------------------------------------- +// Called by KernelMain after MmInitializePhysical. +// bootPml4Phys: the PML4 set up by the bootloader. +// poolSize: initial reservation for kernel pool (bytes, page-aligned). +void MmInitializeVirtual(PHYSICAL_ADDRESS bootPml4Phys, size_t poolSize); + +// Install the shared PML4 into CR3. Called once at the end of KernelMain init. +void MmActivate(void); + +// --------------------------------------------------------------------------- +// Page mapping +// --------------------------------------------------------------------------- +KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags); +KSTATUS MmUnmapPage(uintptr_t virt); + +// Modify protection flags on an already-mapped virtual range. +// 'flags' is the complete new set of PAGE_* bits - it replaces the old flags +// entirely (except the physical address, which is preserved). +// Returns STATUS_NOT_FOUND if any page in the range is not mapped. +KSTATUS MmSetPageProtect(uintptr_t virt, size_t size, uint64_t flags); + +// Walk the page tables to translate a virtual address to physical. +// Returns 0 if the address is not mapped. +PHYSICAL_ADDRESS MmGetPhysicalAddress(uintptr_t virt); + +// --------------------------------------------------------------------------- +// Kernel pool - ring 0 only, never PAGE_USER. +// Best-fit free-list allocator, thread-safe via spinlock. +// --------------------------------------------------------------------------- +void* MmAllocatePool(size_t size); +void MmFreePool(void* ptr); +void* MmReallocatePool(void* ptr, size_t newSize); + +// --------------------------------------------------------------------------- +// User heap - shared flat space, ring 3 accessible. +// All allocations are PAGE_PRESENT | PAGE_WRITE | PAGE_USER. +// --------------------------------------------------------------------------- +void* MmAllocateUserMemory(size_t size); +void MmFreeUserMemory(void* ptr, size_t size); +void* MmReallocateUserMemory(void* ptr, size_t newSize); diff --git a/code/kernel/ob_object.c b/code/kernel/ob_object.c new file mode 100644 index 0000000..6b86572 --- /dev/null +++ b/code/kernel/ob_object.c @@ -0,0 +1,35 @@ +// ob_object.c - executive object manager +#include "ob_object.h" +#include "mm_virt.h" // MmAllocatePool / MmFreePool +#include +#include + +OBJECT* ObAllocateObject(OBJECT_TYPE type, size_t size) { + if (size < sizeof(OBJECT)) size = sizeof(OBJECT); + + OBJECT* obj = (OBJECT *)MmAllocatePool(size); + if (!obj) return (OBJECT *)0; + + memset(obj, 0, size); + obj->Type = type; + obj->RefCount = 1; + obj->Destroy = (void *)0; /* caller fills this in */ + return obj; +} + +void ObReferenceObject(OBJECT* object) { + if (!object) return; + _InterlockedIncrement(&object->RefCount); +} + +void ObDereferenceObject(OBJECT* object) { + if (!object) return; + long prev = _InterlockedDecrement(&object->RefCount); + if (prev == 0) { + /* Reference count hit zero - run the destructor then free. */ + if (object->Destroy) { + object->Destroy(object); + } + MmFreePool(object); + } +} diff --git a/code/kernel/ob_object.h b/code/kernel/ob_object.h new file mode 100644 index 0000000..478d3b7 --- /dev/null +++ b/code/kernel/ob_object.h @@ -0,0 +1,33 @@ +#pragma once +// ob_object.h - executive object model +// Every resource the kernel tracks is a typed, reference-counted OBJECT. +// The OBJECT header must be the first member of any derived struct. +#include +#include +#include "ke_status.h" + +typedef enum OBJECT_TYPE { + ObjectTypeProcess = 1, + ObjectTypeThread = 2, + ObjectTypeMutex = 3, + ObjectTypeSemaphore = 4, + ObjectTypeEvent = 5, + ObjectTypeQueue = 6, + ObjectTypeFile = 7, +} OBJECT_TYPE; + +typedef struct OBJECT { + OBJECT_TYPE Type; + volatile long RefCount; /* interlocked; long = 4 bytes on MSVC x64 */ + void (*Destroy)(struct OBJECT* self); +} OBJECT; + +// Increment the reference count. Call whenever ownership is shared. +void ObReferenceObject(OBJECT* object); + +// Decrement. Calls Destroy() and frees the object when count reaches zero. +void ObDereferenceObject(OBJECT* object); + +// Allocate a zeroed object of the given size from kernel pool. +// Caller must fill Type and Destroy before publishing the pointer. +OBJECT* ObAllocateObject(OBJECT_TYPE type, size_t size); diff --git a/code/kernel/printf.h b/code/kernel/printf.h new file mode 100644 index 0000000..1cf58b6 --- /dev/null +++ b/code/kernel/printf.h @@ -0,0 +1,119 @@ +/////////////////////////////////////////////////////////////////////////////// +// \author (c) Marco Paland (info@paland.com) +// 2014-2019, PALANDesign Hannover, Germany +// +// \license The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on +// embedded systems with a very limited resources. +// Use this instead of bloated standard/newlib printf. +// These routines are thread safe and reentrant. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _PRINTF_H_ +#define _PRINTF_H_ + +#include +#include + +// maksw: yeah that hack i mentioned earlier +void printf_set_putchar(void (*fn)(char)); + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Output a character to a custom device like UART, used by the printf() function + * This function is declared here only. You have to write your custom implementation somewhere + * \param character Character to output + */ +//void _putchar(char character); + + +/** + * Tiny printf implementation + * You have to implement _putchar if you use printf() + * To avoid conflicts with the regular printf() API it is overridden by macro defines + * and internal underscore-appended functions like printf_() are used + * \param format A string that specifies the format of the output + * \return The number of characters that are written into the array, not counting the terminating null character + */ +#define printf printf_ +int printf_(const char* format, ...); + + +/** + * Tiny sprintf implementation + * Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING (V)SNPRINTF INSTEAD! + * \param buffer A pointer to the buffer where to store the formatted string. MUST be big enough to store the output! + * \param format A string that specifies the format of the output + * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character + */ +#define sprintf sprintf_ +int sprintf_(char* buffer, const char* format, ...); + + +/** + * Tiny snprintf/vsnprintf implementation + * \param buffer A pointer to the buffer where to store the formatted string + * \param count The maximum number of characters to store in the buffer, including a terminating null character + * \param format A string that specifies the format of the output + * \param va A value identifying a variable arguments list + * \return The number of characters that COULD have been written into the buffer, not counting the terminating + * null character. A value equal or larger than count indicates truncation. Only when the returned value + * is non-negative and less than count, the string has been completely written. + */ +#define snprintf snprintf_ +#define vsnprintf vsnprintf_ +int snprintf_(char* buffer, size_t count, const char* format, ...); +int vsnprintf_(char* buffer, size_t count, const char* format, va_list va); + + +/** + * Tiny vprintf implementation + * \param format A string that specifies the format of the output + * \param va A value identifying a variable arguments list + * \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character + */ +#define vprintf vprintf_ +int vprintf_(const char* format, va_list va); + + +/** + * printf with output function + * You may use this as dynamic alternative to printf() with its fixed _putchar() output + * \param out An output function which takes one character and an argument pointer + * \param arg An argument pointer for user data passed to output function + * \param format A string that specifies the format of the output + * \return The number of characters that are sent to the output function, not counting the terminating null character + */ +int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...); + + +#ifdef __cplusplus +} +#endif + + +#endif // _PRINTF_H_ diff --git a/code/kernel/syscall_nr.h b/code/kernel/syscall_nr.h new file mode 100644 index 0000000..1521c58 --- /dev/null +++ b/code/kernel/syscall_nr.h @@ -0,0 +1,37 @@ +#pragma once +// syscall_nr.h - system call numbers +// Shared between kernel (ke_syscall.c) and user mode (syscall.dll). +// Keep in sync with the dispatch table in ke_syscall.c. + +#define SYS_EXIT_THREAD 0 +#define SYS_EXIT_PROCESS 1 +#define SYS_SPAWN 2 +#define SYS_SLEEP 3 +#define SYS_YIELD 4 +#define SYS_ALLOC 5 +#define SYS_FREE 6 +#define SYS_CREATE_THREAD 7 +#define SYS_OPEN_HANDLE 8 +#define SYS_CLOSE_HANDLE 9 +#define SYS_DBG_PRINT 10 +#define SYS_MUTEX_CREATE 11 +#define SYS_MUTEX_ACQUIRE 12 +#define SYS_MUTEX_RELEASE 13 +#define SYS_SEM_CREATE 14 +#define SYS_SEM_WAIT 15 +#define SYS_SEM_SIGNAL 16 +#define SYS_EVENT_CREATE 17 +#define SYS_EVENT_SET 18 +#define SYS_EVENT_WAIT 19 +#define SYS_QUEUE_CREATE 20 +#define SYS_QUEUE_SEND 21 +#define SYS_QUEUE_RECV 22 +#define SYS_SCREEN_BLIT 23 +#define SYS_GET_TICK 24 +#define SYS_OPEN 25 +#define SYS_READ 26 +#define SYS_FCLOSE 27 +#define SYS_FSEEK 28 +#define SYS_FSIZE 29 + +#define SYS_MAX 30 diff --git a/code/libc.c b/code/libc.c new file mode 100644 index 0000000..08e106c --- /dev/null +++ b/code/libc.c @@ -0,0 +1,64 @@ +// everyone needs a little libc +#include +#include + +char* strcpy(char* dest, const char* src) { + char* d = dest; + while (*src) *d++ = *src++; + *d = 0; + return dest; +} + +char* strncpy(char* dest, const char* src, size_t n) { + size_t i; + for (i = 0; i < n && src[i]; i++) dest[i] = src[i]; + for (; i < n; i++) dest[i] = 0; + return dest; +} + +int strcmp(const char* s1, const char* s2) { + while (*s1 && *s1 == *s2) s1++, s2++; + return (unsigned char)*s1 - (unsigned char)*s2; +} + +int _stricmp(const char* s1, const char* s2) { + // 0x20 (32) is the bit that differs between 'A' and 'a' + while (*s1 && ((*s1 | 0x20) == (*s2 | 0x20))) { + s1++, s2++; + } + return (unsigned char)(*s1 | 0x20) - (unsigned char)(*s2 | 0x20); +} + +size_t strlen(const char* s) { + size_t n = 0; + while (*s++) n++; + return n; +} + +char* strchr(const char* s, int c) { + while (*s) { + if (*s == (char)c) return (char *)s; + s++; + } + return NULL; +} + +void* memmove(void* dest, const void* src, size_t n) { + uint8_t* d = (uint8_t *)dest; + const uint8_t* s = (const uint8_t *)src; + if (d < s) { + for (size_t i = 0; i < n; i++) d[i] = s[i]; + } else if (d > s) { + for (size_t i = n; i > 0; i--) d[i - 1] = s[i - 1]; + } + return dest; +} + +int memcmp(const void* s1, const void* s2, size_t n) { + const uint8_t* a = (const uint8_t *)s1; + const uint8_t* b = (const uint8_t *)s2; + for (size_t i = 0; i < n; i++) { + if (a[i] != b[i]) return a[i] - b[i]; + } + return 0; +} diff --git a/code/printf.c b/code/printf.c new file mode 100644 index 0000000..27b232f --- /dev/null +++ b/code/printf.c @@ -0,0 +1,920 @@ +/////////////////////////////////////////////////////////////////////////////// +// \author (c) Marco Paland (info@paland.com) +// 2014-2019, PALANDesign Hannover, Germany +// +// \license The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on +// embedded systems with a very limited resources. These routines are thread +// safe and reentrant! +// Use this instead of the bloated standard/newlib printf cause these use +// malloc for printf (and may not be thread safe). +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "printf.h" + + +// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the +// printf_config.h header file +// default: undefined +#ifdef PRINTF_INCLUDE_CONFIG_H +#include "printf_config.h" +#endif + + +// 'ntoa' conversion buffer size, this must be big enough to hold one converted +// numeric number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_NTOA_BUFFER_SIZE +#define PRINTF_NTOA_BUFFER_SIZE 32U +#endif + +// 'ftoa' conversion buffer size, this must be big enough to hold one converted +// float number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_FTOA_BUFFER_SIZE +#define PRINTF_FTOA_BUFFER_SIZE 32U +#endif + +// support for the floating point type (%f) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_FLOAT +#define PRINTF_SUPPORT_FLOAT +#endif + +// support for exponential floating point notation (%e/%g) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL +#define PRINTF_SUPPORT_EXPONENTIAL +#endif + +// define the default floating point precision +// default: 6 digits +#ifndef PRINTF_DEFAULT_FLOAT_PRECISION +#define PRINTF_DEFAULT_FLOAT_PRECISION 6U +#endif + +// define the largest float suitable to print with %f +// default: 1e9 +#ifndef PRINTF_MAX_FLOAT +#define PRINTF_MAX_FLOAT 1e9 +#endif + +// support for the long long types (%llu or %p) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG +#define PRINTF_SUPPORT_LONG_LONG +#endif + +// support for the ptrdiff_t type (%t) +// ptrdiff_t is normally defined in as long or long long type +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T +#define PRINTF_SUPPORT_PTRDIFF_T +#endif + +/////////////////////////////////////////////////////////////////////////////// + +// internal flag definitions +#define FLAGS_ZEROPAD (1U << 0U) +#define FLAGS_LEFT (1U << 1U) +#define FLAGS_PLUS (1U << 2U) +#define FLAGS_SPACE (1U << 3U) +#define FLAGS_HASH (1U << 4U) +#define FLAGS_UPPERCASE (1U << 5U) +#define FLAGS_CHAR (1U << 6U) +#define FLAGS_SHORT (1U << 7U) +#define FLAGS_LONG (1U << 8U) +#define FLAGS_LONG_LONG (1U << 9U) +#define FLAGS_PRECISION (1U << 10U) +#define FLAGS_ADAPT_EXP (1U << 11U) + + +// import float.h for DBL_MAX +#if defined(PRINTF_SUPPORT_FLOAT) +#include +#endif + + +// output function type +typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen); + + +// wrapper (used as buffer) for output function type +typedef struct { + void (*fct)(char character, void* arg); + void* arg; +} out_fct_wrap_type; + + +// internal buffer output +static inline void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen) +{ + if (idx < maxlen) { + ((char*)buffer)[idx] = character; + } +} + + +// internal null output +static inline void _out_null(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)character; (void)buffer; (void)idx; (void)maxlen; +} + +// maksw: hack around putchar, hal and kernel +static void (*g_putchar_fn)(char) = 0; + +void printf_set_putchar(void (*fn)(char)) { + g_putchar_fn = fn; +} + +// internal _putchar wrapper +static inline void _out_char(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)buffer; (void)idx; (void)maxlen; + if (character) { + if (g_putchar_fn) g_putchar_fn(character); + } +} + + +// internal output function wrapper +static inline void _out_fct(char character, void* buffer, size_t idx, size_t maxlen) +{ + (void)idx; (void)maxlen; + if (character) { + // buffer is the output fct pointer + ((out_fct_wrap_type*)buffer)->fct(character, ((out_fct_wrap_type*)buffer)->arg); + } +} + + +// internal secure strlen +// \return The length of the string (excluding the terminating 0) limited by 'maxsize' +static inline unsigned int _strnlen_s(const char* str, size_t maxsize) +{ + const char* s; + for (s = str; *s && maxsize--; ++s); + return (unsigned int)(s - str); +} + + +// internal test if char is a digit (0-9) +// \return true if char is a digit +static inline bool _is_digit(char ch) +{ + return (ch >= '0') && (ch <= '9'); +} + + +// internal ASCII string to unsigned int conversion +static unsigned int _atoi(const char** str) +{ + unsigned int i = 0U; + while (_is_digit(**str)) { + i = i * 10U + (unsigned int)(*((*str)++) - '0'); + } + return i; +} + + +// output the specified string in reverse, taking care of any zero-padding +static size_t _out_rev(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, unsigned int width, unsigned int flags) +{ + const size_t start_idx = idx; + + // pad spaces up to given width + if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { + for (size_t i = len; i < width; i++) { + out(' ', buffer, idx++, maxlen); + } + } + + // reverse string + while (len) { + out(buf[--len], buffer, idx++, maxlen); + } + + // append pad spaces up to given width + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) { + out(' ', buffer, idx++, maxlen); + } + } + + return idx; +} + + +// internal itoa format +static size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen, char* buf, size_t len, bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags) +{ + // pad leading zeros + if (!(flags & FLAGS_LEFT)) { + if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + // handle hash + if (flags & FLAGS_HASH) { + if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) { + len--; + if (len && (base == 16U)) { + len--; + } + } + if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'x'; + } + else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'X'; + } + else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'b'; + } + if (len < PRINTF_NTOA_BUFFER_SIZE) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_NTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } + else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } + else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + + +// internal itoa for 'long' type +static size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // no hash for 0 values + if (!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} + + +// internal itoa for 'long long' type +#if defined(PRINTF_SUPPORT_LONG_LONG) +static size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_NTOA_BUFFER_SIZE]; + size_t len = 0U; + + // no hash for 0 values + if (!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || value) { + do { + const char digit = (char)(value % base); + buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} +#endif // PRINTF_SUPPORT_LONG_LONG + + +#if defined(PRINTF_SUPPORT_FLOAT) + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +// forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT +static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags); +#endif + + +// internal ftoa for fixed decimal floating point +static size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) +{ + char buf[PRINTF_FTOA_BUFFER_SIZE]; + size_t len = 0U; + double diff = 0.0; + + // powers of 10 + static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + + // test for special values + if (value != value) + return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags); + if (value < -DBL_MAX) + return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags); + if (value > DBL_MAX) + return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags); + + // test for very large values + // standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad + if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) { +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + return _etoa(out, buffer, idx, maxlen, value, prec, width, flags); +#else + return 0U; +#endif + } + + // test for negative + bool negative = false; + if (value < 0) { + negative = true; + value = 0 - value; + } + + // set default precision, if not set explicitly + if (!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + // limit precision to 9, cause a prec >= 10 can lead to overflow errors + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) { + buf[len++] = '0'; + prec--; + } + + int whole = (int)value; + double tmp = (value - whole) * pow10[prec]; + unsigned long frac = (unsigned long)tmp; + diff = tmp - frac; + + if (diff > 0.5) { + ++frac; + // handle rollover, e.g. case 0.99 with prec 1 is 1.0 + if (frac >= pow10[prec]) { + frac = 0; + ++whole; + } + } + else if (diff < 0.5) { + } + else if ((frac == 0U) || (frac & 1U)) { + // if halfway, round up if odd OR if last digit is 0 + ++frac; + } + + if (prec == 0U) { + diff = value - (double)whole; + if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) { + // exactly 0.5 and ODD, then round up + // 1.5 -> 2, but 2.5 -> 2 + ++whole; + } + } + else { + unsigned int count = prec; + // now do fractional part, as an unsigned number + while (len < PRINTF_FTOA_BUFFER_SIZE) { + --count; + buf[len++] = (char)(48U + (frac % 10U)); + if (!(frac /= 10U)) { + break; + } + } + // add extra 0s + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) { + buf[len++] = '0'; + } + if (len < PRINTF_FTOA_BUFFER_SIZE) { + // add decimal + buf[len++] = '.'; + } + } + + // do whole part, number is reversed + while (len < PRINTF_FTOA_BUFFER_SIZE) { + buf[len++] = (char)(48 + (whole % 10)); + if (!(whole /= 10)) { + break; + } + } + + // pad leading zeros + if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) { + if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_FTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } + else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } + else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags); +} + + +#if defined(PRINTF_SUPPORT_EXPONENTIAL) +// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse +static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags) +{ + // check for NaN and special values + if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) { + return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags); + } + + // determine the sign + const bool negative = value < 0; + if (negative) { + value = -value; + } + + // default precision + if (!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + + // determine the decimal exponent + // based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c) + union { + uint64_t U; + double F; + } conv; + + conv.F = value; + int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2 + conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2) + // now approximate log10 from the log2 integer part and an expansion of ln around 1.5 + int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168); + // now we want to compute 10^expval but we want to be sure it won't overflow + exp2 = (int)(expval * 3.321928094887362 + 0.5); + const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453; + const double z2 = z * z; + conv.U = (uint64_t)(exp2 + 1023) << 52U; + // compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex + conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14))))); + // correct for rounding errors + if (value < conv.F) { + expval--; + conv.F /= 10; + } + + // the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters + unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U; + + // in "%g" mode, "prec" is the number of* significant figures* not decimals + if (flags & FLAGS_ADAPT_EXP) { + // do we want to fall-back to "%f" mode? + if ((value >= 1e-4) && (value < 1e6)) { + if ((int)prec > expval) { + prec = (unsigned)((int)prec - expval - 1); + } + else { + prec = 0; + } + flags |= FLAGS_PRECISION; // make sure _ftoa respects precision + // no characters in exponent + minwidth = 0U; + expval = 0; + } + else { + // we use one sigfig for the whole part + if ((prec > 0) && (flags & FLAGS_PRECISION)) { + --prec; + } + } + } + + // will everything fit? + unsigned int fwidth = width; + if (width > minwidth) { + // we didn't fall-back so subtract the characters required for the exponent + fwidth -= minwidth; + } else { + // not enough characters, so go back to default sizing + fwidth = 0U; + } + if ((flags & FLAGS_LEFT) && minwidth) { + // if we're padding on the right, DON'T pad the floating part + fwidth = 0U; + } + + // rescale the float value + if (expval) { + value /= conv.F; + } + + // output the floating part + const size_t start_idx = idx; + idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP); + + // output the exponent part + if (minwidth) { + // output the exponential symbol + out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen); + // output the exponent value + idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth-1, FLAGS_ZEROPAD | FLAGS_PLUS); + // might need to right-pad spaces + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) out(' ', buffer, idx++, maxlen); + } + } + return idx; +} +#endif // PRINTF_SUPPORT_EXPONENTIAL +#endif // PRINTF_SUPPORT_FLOAT + + +// internal vsnprintf +static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va) +{ + unsigned int flags, width, precision, n; + size_t idx = 0U; + + if (!buffer) { + // use null output function + out = _out_null; + } + + while (*format) + { + // format specifier? %[flags][width][.precision][length] + if (*format != '%') { + // no + out(*format, buffer, idx++, maxlen); + format++; + continue; + } + else { + // yes, evaluate it + format++; + } + + // evaluate flags + flags = 0U; + do { + switch (*format) { + case '0': flags |= FLAGS_ZEROPAD; format++; n = 1U; break; + case '-': flags |= FLAGS_LEFT; format++; n = 1U; break; + case '+': flags |= FLAGS_PLUS; format++; n = 1U; break; + case ' ': flags |= FLAGS_SPACE; format++; n = 1U; break; + case '#': flags |= FLAGS_HASH; format++; n = 1U; break; + default : n = 0U; break; + } + } while (n); + + // evaluate width field + width = 0U; + if (_is_digit(*format)) { + width = _atoi(&format); + } + else if (*format == '*') { + const int w = va_arg(va, int); + if (w < 0) { + flags |= FLAGS_LEFT; // reverse padding + width = (unsigned int)-w; + } + else { + width = (unsigned int)w; + } + format++; + } + + // evaluate precision field + precision = 0U; + if (*format == '.') { + flags |= FLAGS_PRECISION; + format++; + if (_is_digit(*format)) { + precision = _atoi(&format); + } + else if (*format == '*') { + const int prec = (int)va_arg(va, int); + precision = prec > 0 ? (unsigned int)prec : 0U; + format++; + } + } + + // evaluate length field + switch (*format) { + case 'l' : + flags |= FLAGS_LONG; + format++; + if (*format == 'l') { + flags |= FLAGS_LONG_LONG; + format++; + } + break; + case 'h' : + flags |= FLAGS_SHORT; + format++; + if (*format == 'h') { + flags |= FLAGS_CHAR; + format++; + } + break; +#if defined(PRINTF_SUPPORT_PTRDIFF_T) + case 't' : + flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; +#endif + case 'j' : + flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + case 'z' : + flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + default : + break; + } + + // evaluate specifier + switch (*format) { + case 'd' : + case 'i' : + case 'u' : + case 'x' : + case 'X' : + case 'o' : + case 'b' : { + // set the base + unsigned int base; + if (*format == 'x' || *format == 'X') { + base = 16U; + } + else if (*format == 'o') { + base = 8U; + } + else if (*format == 'b') { + base = 2U; + } + else { + base = 10U; + flags &= ~FLAGS_HASH; // no hash for dec format + } + // uppercase + if (*format == 'X') { + flags |= FLAGS_UPPERCASE; + } + + // no plus or space flag for u, x, X, o, b + if ((*format != 'i') && (*format != 'd')) { + flags &= ~(FLAGS_PLUS | FLAGS_SPACE); + } + + // ignore '0' flag when precision is given + if (flags & FLAGS_PRECISION) { + flags &= ~FLAGS_ZEROPAD; + } + + // convert the integer + if ((*format == 'i') || (*format == 'd')) { + // signed + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + const long long value = va_arg(va, long long); + idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); +#endif + } + else if (flags & FLAGS_LONG) { + const long value = va_arg(va, long); + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); + } + else { + const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int); + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags); + } + } + else { + // unsigned + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags); +#endif + } + else if (flags & FLAGS_LONG) { + idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags); + } + else { + const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int); + idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags); + } + } + format++; + break; + } +#if defined(PRINTF_SUPPORT_FLOAT) + case 'f' : + case 'F' : + if (*format == 'F') flags |= FLAGS_UPPERCASE; + idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); + format++; + break; +#if defined(PRINTF_SUPPORT_EXPONENTIAL) + case 'e': + case 'E': + case 'g': + case 'G': + if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP; + if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE; + idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); + format++; + break; +#endif // PRINTF_SUPPORT_EXPONENTIAL +#endif // PRINTF_SUPPORT_FLOAT + case 'c' : { + unsigned int l = 1U; + // pre padding + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // char output + out((char)va_arg(va, int), buffer, idx++, maxlen); + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 's' : { + const char* p = va_arg(va, char*); + unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1); + // pre padding + if (flags & FLAGS_PRECISION) { + l = (l < precision ? l : precision); + } + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // string output + while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) { + out(*(p++), buffer, idx++, maxlen); + } + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 'p' : { + width = sizeof(void*) * 2U; + flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE; +#if defined(PRINTF_SUPPORT_LONG_LONG) + const bool is_ll = sizeof(uintptr_t) == sizeof(long long); + if (is_ll) { + idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void*), false, 16U, precision, width, flags); + } + else { +#endif + idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void*)), false, 16U, precision, width, flags); +#if defined(PRINTF_SUPPORT_LONG_LONG) + } +#endif + format++; + break; + } + + case '%' : + out('%', buffer, idx++, maxlen); + format++; + break; + + default : + out(*format, buffer, idx++, maxlen); + format++; + break; + } + } + + // termination + out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen); + + // return written chars without terminating \0 + return (int)idx; +} + + +/////////////////////////////////////////////////////////////////////////////// + +int printf_(const char* format, ...) +{ + va_list va; + va_start(va, format); + char buffer[1]; + const int ret = _vsnprintf(_out_char, buffer, (size_t)-1, format, va); + va_end(va); + return ret; +} + + +int sprintf_(char* buffer, const char* format, ...) +{ + va_list va; + va_start(va, format); + const int ret = _vsnprintf(_out_buffer, buffer, (size_t)-1, format, va); + va_end(va); + return ret; +} + + +int snprintf_(char* buffer, size_t count, const char* format, ...) +{ + va_list va; + va_start(va, format); + const int ret = _vsnprintf(_out_buffer, buffer, count, format, va); + va_end(va); + return ret; +} + + +int vprintf_(const char* format, va_list va) +{ + char buffer[1]; + return _vsnprintf(_out_char, buffer, (size_t)-1, format, va); +} + + +int vsnprintf_(char* buffer, size_t count, const char* format, va_list va) +{ + return _vsnprintf(_out_buffer, buffer, count, format, va); +} + + +int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...) +{ + va_list va; + va_start(va, format); + const out_fct_wrap_type out_fct_wrap = { out, arg }; + const int ret = _vsnprintf(_out_fct, (char*)(uintptr_t)&out_fct_wrap, (size_t)-1, format, va); + va_end(va); + return ret; +} diff --git a/code/shell/shell.c b/code/shell/shell.c new file mode 100644 index 0000000..5c99d31 --- /dev/null +++ b/code/shell/shell.c @@ -0,0 +1,47 @@ +#include +#include + +void BitBlt(int x, int y, int w, int h, const uint32_t* pixels); +void* HeapAlloc(void* heap, unsigned long flags, size_t size); +int HeapFree(void* heap, unsigned long flags, void* mem); +_Noreturn void ExitProcess(unsigned int code); +_Noreturn void ExitThread(unsigned long code); +void OutputDebugStringA(const char* s); + +int main() { + OutputDebugStringA("Hello from the shell!\n"); + int width = 300; + int height = 300; + + // Allocate space for uint32_t (4 bytes per pixel) + uint32_t* image = (uint32_t *)HeapAlloc(NULL, 0, width * height * sizeof(uint32_t)); + + int tileSize = 8; + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + uint32_t color1 = 0xFFFFFFFF; // White + uint32_t color2 = 0xFF000000; // Black + + int tileX = x / tileSize; + int tileY = y / tileSize; + + if ((tileX + tileY) % 2 == 0) { + image[y * width + x] = color1; + } else { + image[y * width + x] = color2; + } + } + } + + // Pass the 32-bit buffer directly to BitBlt + BitBlt(600, 400, width, height, image); + + for (size_t i = 0; i < 1000000000; i++) { + // burn! + } + + OutputDebugStringA("Goodbye from the shell!\n"); + + ExitProcess(0); +} diff --git a/code/syscall/syscall_nr.inc b/code/syscall/syscall_nr.inc new file mode 100644 index 0000000..ad45840 --- /dev/null +++ b/code/syscall/syscall_nr.inc @@ -0,0 +1,32 @@ +; syscall_nr.inc - assembled from syscall_nr.h for use in .asm files +SYS_EXIT_THREAD EQU 0 +SYS_EXIT_PROCESS EQU 1 +SYS_SPAWN EQU 2 +SYS_SLEEP EQU 3 +SYS_YIELD EQU 4 +SYS_ALLOC EQU 5 +SYS_FREE EQU 6 +SYS_CREATE_THREAD EQU 7 +SYS_OPEN_HANDLE EQU 8 +SYS_CLOSE_HANDLE EQU 9 +SYS_DBG_PRINT EQU 10 +SYS_MUTEX_CREATE EQU 11 +SYS_MUTEX_ACQUIRE EQU 12 +SYS_MUTEX_RELEASE EQU 13 +SYS_SEM_CREATE EQU 14 +SYS_SEM_WAIT EQU 15 +SYS_SEM_SIGNAL EQU 16 +SYS_EVENT_CREATE EQU 17 +SYS_EVENT_SET EQU 18 +SYS_EVENT_WAIT EQU 19 +SYS_QUEUE_CREATE EQU 20 +SYS_QUEUE_SEND EQU 21 +SYS_QUEUE_RECV EQU 22 +SYS_SCREEN_BLIT EQU 23 +SYS_GET_TICK EQU 24 +SYS_OPEN EQU 25 +SYS_READ EQU 26 +SYS_FCLOSE EQU 27 +SYS_FSEEK EQU 28 +SYS_FSIZE EQU 29 +SYS_MAX EQU 30 diff --git a/code/syscall/syscall_stubs.asm b/code/syscall/syscall_stubs.asm new file mode 100644 index 0000000..12bce77 --- /dev/null +++ b/code/syscall/syscall_stubs.asm @@ -0,0 +1,180 @@ +; syscall_stubs.asm - user-mode INT 0x2E stubs exported by syscall.dll (MASM64) +; Microsoft x64 ABI: args in RCX, RDX, R8, R9; args 5+6 in R10, R11. + +INCLUDE syscall_nr.inc ; SYS_* constants + +.CODE + +SysExitThread PROC + mov rax, SYS_EXIT_THREAD + int 40h + ret +SysExitThread ENDP + +SysExitProcess PROC + mov rax, SYS_EXIT_PROCESS + int 40h + ret +SysExitProcess ENDP + +SysYield PROC + mov rax, SYS_YIELD + int 40h + ret +SysYield ENDP + +SysSleep PROC ; RCX = milliseconds + mov rax, SYS_SLEEP + int 40h + ret +SysSleep ENDP + +SysAlloc PROC ; RCX = size -> RAX = ptr + mov rax, SYS_ALLOC + int 40h + ret +SysAlloc ENDP + +SysFree PROC ; RCX = ptr, RDX = size + mov rax, SYS_FREE + int 40h + ret +SysFree ENDP + +SysCreateThread PROC ; RCX=entry, RDX=arg, R8=priority -> RAX=handle + mov rax, SYS_CREATE_THREAD + int 40h + ret +SysCreateThread ENDP + +SysCloseHandle PROC ; RCX = handle + mov rax, SYS_CLOSE_HANDLE + int 40h + ret +SysCloseHandle ENDP + +SysDbgPrint PROC ; RCX = string ptr + mov rax, SYS_DBG_PRINT + int 40h + ret +SysDbgPrint ENDP + +SysMutexCreate PROC ; -> RAX = handle + mov rax, SYS_MUTEX_CREATE + int 40h + ret +SysMutexCreate ENDP + +SysMutexAcquire PROC ; RCX = handle + mov rax, SYS_MUTEX_ACQUIRE + int 40h + ret +SysMutexAcquire ENDP + +SysMutexRelease PROC ; RCX = handle + mov rax, SYS_MUTEX_RELEASE + int 40h + ret +SysMutexRelease ENDP + +SysSemCreate PROC ; RCX=initial, RDX=max -> RAX=handle + mov rax, SYS_SEM_CREATE + int 40h + ret +SysSemCreate ENDP + +SysSemWait PROC ; RCX = handle + mov rax, SYS_SEM_WAIT + int 40h + ret +SysSemWait ENDP + +SysSemSignal PROC ; RCX = handle + mov rax, SYS_SEM_SIGNAL + int 40h + ret +SysSemSignal ENDP + +SysEventCreate PROC ; RCX=manualReset, RDX=initialState -> RAX=handle + mov rax, SYS_EVENT_CREATE + int 40h + ret +SysEventCreate ENDP + +SysEventSet PROC ; RCX = handle + mov rax, SYS_EVENT_SET + int 40h + ret +SysEventSet ENDP + +SysEventWait PROC ; RCX = handle + mov rax, SYS_EVENT_WAIT + int 40h + ret +SysEventWait ENDP + +SysQueueCreate PROC ; -> RAX = handle + mov rax, SYS_QUEUE_CREATE + int 40h + ret +SysQueueCreate ENDP + +SysQueueSend PROC ; RCX=handle, RDX=*msg, R8=blocking + mov rax, SYS_QUEUE_SEND + int 40h + ret +SysQueueSend ENDP + +SysQueueRecv PROC ; RCX=handle, RDX=*msg, R8=blocking + mov rax, SYS_QUEUE_RECV + int 40h + ret +SysQueueRecv ENDP + +SysScreenBlit PROC + ; RCX=x, RDX=y, R8=w, R9=h + ; The 5th arg (pixels) is on the stack above the 32-byte shadow space and return address. + mov r10, [rsp + 40] + + mov rax, SYS_SCREEN_BLIT + int 40h + ret +SysScreenBlit ENDP + +SysGetTick PROC ; -> RAX = milliseconds + mov rax, SYS_GET_TICK + int 40h + ret +SysGetTick ENDP + +SysOpen PROC ; RCX = *path -> RAX = handle (0 = failure) + mov rax, SYS_OPEN + int 40h + ret +SysOpen ENDP + +SysRead PROC ; RCX = handle, RDX = *buf, R8 = size -> RAX = bytes read + mov rax, SYS_READ + int 40h + ret +SysRead ENDP + +SysFClose PROC ; RCX = handle + mov rax, SYS_FCLOSE + int 40h + ret +SysFClose ENDP + +SysFSeek PROC ; RCX = handle, RDX = offset + mov rax, SYS_FSEEK + int 40h + ret +SysFSeek ENDP + +SysFSize PROC ; RCX = handle -> RAX = size in bytes + mov rax, SYS_FSIZE + int 40h + ret +SysFSize ENDP + +END diff --git a/code/win32/kernel32.c b/code/win32/kernel32.c new file mode 100644 index 0000000..0a56911 --- /dev/null +++ b/code/win32/kernel32.c @@ -0,0 +1,131 @@ +// kernel32.c - Win32 personality: process, thread, memory, sync +// Thin wrappers over syscall.dll stubs. Provides a familiar API for +// user-mode code that was originally written for Windows. +#include +#include +#include + +// Forward declarations of syscall stubs (from syscall.dll). +extern uint64_t SysAlloc(size_t size); +extern void SysFree(void* ptr, size_t size); +extern void SysYield(void); +extern void SysSleep(uint64_t ms); +extern void SysExitProcess(int code); +extern void SysExitThread(int code); +extern uint64_t SysCreateThread(uintptr_t entry, uintptr_t arg, uint32_t priority); +extern void SysCloseHandle(uint32_t handle); +extern void SysDbgPrint(const char* s); +extern uint64_t SysMutexCreate(void); +extern void SysMutexAcquire(uint32_t handle); +extern void SysMutexRelease(uint32_t handle); +extern uint64_t SysEventCreate(uint32_t manualReset, uint32_t initial); +extern void SysEventSet(uint32_t handle); +extern void SysEventWait(uint32_t handle); +extern uint64_t SysGetTick(void); + +#define INVALID_HANDLE_VALUE ((void *)(intptr_t)-1) +#define WAIT_OBJECT_0 0 + +// --------------------------------------------------------------------------- +// Heap +// --------------------------------------------------------------------------- +void* HeapAlloc(void* heap, unsigned long flags, size_t size) { + (void)heap; (void)flags; + return (void *)SysAlloc(size); +} +void* HeapReAlloc(void* heap, unsigned long flags, void* mem, size_t size) { + (void)heap; (void)flags; + // No in-place resize; alloc + copy + free. + void* n = (void *)SysAlloc(size); + if (!n) return (void *)0; + // We don't track sizes, so copy a conservative max. + // In practice callers should use a custom heap. + SysFree(mem, 0); + return n; +} +int HeapFree(void* heap, unsigned long flags, void* mem) { + (void)heap; (void)flags; + SysFree(mem, 0); + return 1; +} + +// --------------------------------------------------------------------------- +// Process / Thread +// --------------------------------------------------------------------------- +void ExitProcess(unsigned int code) { SysExitProcess((int)code); } +void ExitThread(unsigned long code) { SysExitThread((int)code); } + +typedef unsigned long (*LPTHREAD_START_ROUTINE)(void *); + +void* CreateThread(void* attr, size_t stackSize, + LPTHREAD_START_ROUTINE fn, void* arg, + unsigned long flags, unsigned long* tid) { + (void)attr; (void)stackSize; (void)flags; (void)tid; + uint64_t h = SysCreateThread((uintptr_t)fn, (uintptr_t)arg, 1 /* Normal */); + if (!h) return INVALID_HANDLE_VALUE; + return (void *)(uintptr_t)h; +} + +void Sleep(unsigned long ms) { SysSleep((uint64_t)ms); } +void SwitchToThread(void) { SysYield(); } + +// --------------------------------------------------------------------------- +// Synchronisation +// --------------------------------------------------------------------------- +void* CreateMutex(void* attr, int initialOwner, const char* name) { + (void)attr; (void)initialOwner; (void)name; + uint64_t h = SysMutexCreate(); + if (!h) return INVALID_HANDLE_VALUE; + return (void *)(uintptr_t)h; +} + +unsigned long WaitForSingleObject(void* handle, unsigned long ms) { + (void)ms; // Timeout not supported - always blocking for now. + uint32_t h = (uint32_t)(uintptr_t)handle; + // We need to know if this is a mutex, event, etc. + // For simplicity, try event wait; syscall layer validates the type. + SysEventWait(h); + return WAIT_OBJECT_0; +} + +int ReleaseMutex(void* handle) { + extern void SysMutexRelease(uint32_t); + SysMutexRelease((uint32_t)(uintptr_t)handle); + return 1; +} + +void* CreateEvent(void* attr, int manualReset, int initialState, const char* name) { + (void)attr; (void)name; + uint64_t h = SysEventCreate((uint32_t)manualReset, (uint32_t)initialState); + if (!h) return INVALID_HANDLE_VALUE; + return (void *)(uintptr_t)h; +} + +int SetEvent(void* handle) { + SysEventSet((uint32_t)(uintptr_t)handle); + return 1; +} + +int CloseHandle(void* handle) { + SysCloseHandle((uint32_t)(uintptr_t)handle); + return 1; +} + +void OutputDebugStringA(const char* s) { + SysDbgPrint(s); +} + +// --------------------------------------------------------------------------- +// Time +// --------------------------------------------------------------------------- +unsigned long long GetTickCount64(void) { return SysGetTick(); } +unsigned long GetTickCount(void) { return (unsigned long)SysGetTick(); } + +// --------------------------------------------------------------------------- +// String helpers (no CRT dependency) +// --------------------------------------------------------------------------- +int lstrlenA(const char* s) { + int n = 0; + while (*s++) n++; + return n; +} diff --git a/code/win32/ole32.c b/code/win32/ole32.c new file mode 100644 index 0000000..b008b5c --- /dev/null +++ b/code/win32/ole32.c @@ -0,0 +1,2 @@ +// ole32.c - stub; no COM at this stage. +static void stub(void) { } diff --git a/code/win32/user32.c b/code/win32/user32.c new file mode 100644 index 0000000..25089ba --- /dev/null +++ b/code/win32/user32.c @@ -0,0 +1,20 @@ +// user32.c - minimal user32 stubs (no window manager yet) +#include + +// Screen blit is the only graphical primitive available at this stage. +extern void SysScreenBlit(int x, int y, int w, int h, const uint32_t* pixels); + +// syscall.dll +extern void SysYield(void); + +void BitBlt(int x, int y, int w, int h, const uint32_t* pixels) { + SysScreenBlit(x, y, w, h, pixels); +} + +// Message loop stubs - always return 0. +int GetMessage(void* msg, void* hwnd, unsigned int min, unsigned int max) { + (void)msg; (void)hwnd; (void)min; (void)max; + SysYield(); + return 0; +} +int DispatchMessage(const void* msg) { (void)msg; return 0; } diff --git a/code/win32/winmm.c b/code/win32/winmm.c new file mode 100644 index 0000000..5155621 --- /dev/null +++ b/code/win32/winmm.c @@ -0,0 +1,2 @@ +// winmm.c - stub; no multimedia at this stage. +static void stub(void) { } diff --git a/run.bat b/run.bat new file mode 100644 index 0000000..34a2c91 --- /dev/null +++ b/run.bat @@ -0,0 +1 @@ +@start qemu-system-x86_64 -drive if=pflash,format=raw,readonly=on,file=OVMF\OVMF_CODE_4M.fd -drive if=pflash,format=raw,file=OVMF\OVMF_VARS_4M.fd -drive format=raw,file=\\.\PhysicalDrive7 -serial stdio diff --git a/rund.bat b/rund.bat new file mode 100644 index 0000000..4c5cff4 --- /dev/null +++ b/rund.bat @@ -0,0 +1 @@ +@start qemu-system-x86_64 -drive if=pflash,format=raw,readonly=on,file=OVMF\OVMF_CODE_4M.fd -drive if=pflash,format=raw,file=OVMF\OVMF_VARS_4M.fd -drive format=raw,file=\\.\PhysicalDrive7 -m 4G -serial stdio -d in_asm,cpu_reset,int -D qemu.log -no-reboot -no-shutdown