//! rsapi — the kernel↔binary ABI (ADR 0006). //! //! One versioned `Exports` table is constructed per invocation and handed //! to the binary's entry point. The header starts with a magic and a //! `version: u32` so a future kernel can keep old binaries working //! (dispatch on the version, never on struct layout). //! //! Everything here is `no_std`-clean: plain structs and function pointers, //! no allocation, no rsnix dependency — binaries link only this crate. #![no_std] /// Table magic: "RSEX". pub const EXPORTS_MAGIC: u32 = 0x5245_5853; /// ABI revision. Bump on any signature change; the kernel refuses to run /// binaries whose required major exceeds its own. pub const ABI_VERSION: u32 = 2; /// Entry-point signature. `extern "C"` on the x86_64-unknown-uefi /// target is the Win64 convention: the three arguments arrive in /// RCX/RDX/R8 on both sides of the table. pub type EntryPoint = extern "C" fn(exports: &'static Exports, argc: usize, argv: *const Arg) -> i32; /// One C-style argv element: pointer + length (rs-dos strings are not /// NUL-terminated in memory). #[derive(Clone, Copy)] pub struct Arg { pub ptr: *const u8, pub len: usize, } /// A line of text handed across the ABI (stream I/O). #[derive(Clone, Copy)] pub struct Line { pub ptr: *const u8, pub len: usize, } impl Line { /// Borrow as a &str. pub fn as_str(&self) -> &'static str { unsafe { core::str::from_utf8_unchecked(core::slice::from_raw_parts(self.ptr, self.len)) } } } /// Outcome of `get_line`. #[derive(Clone, Copy, PartialEq, Eq)] pub enum StreamResult { Line, Eof, Abort, } // --------------------------------------------------------------------------- // v2 types // --------------------------------------------------------------------------- /// Opaque file/directory handle returned by `fs_resolve` / `fs_create`. pub type FsHandle = i32; /// One directory entry returned by `fs_dir_next`. #[repr(C)] #[derive(Clone, Copy)] pub struct DirEntry { pub name: Line, pub is_dir: bool, pub _pad: u8, pub size: u64, } /// Real-time clock snapshot. #[repr(C)] #[derive(Clone, Copy)] pub struct RtcTime { pub year: u16, pub month: u8, pub day: u8, pub hour: u8, pub minute: u8, pub second: u8, pub _pad: u8, } /// Memory statistics (heap + page allocator). #[repr(C)] #[derive(Clone, Copy)] pub struct MemStats { pub heap_total: u64, pub heap_free: u64, pub pages_total: u64, pub pages_free: u64, } /// One PCI device discovered at probe time. #[repr(C)] #[derive(Clone, Copy)] pub struct PciDevice { pub bus: u8, pub device: u8, pub function: u8, pub class: u8, pub subclass: u8, pub vendor: u16, pub device_id: u16, } // ---- GUI types (v2 window/event) ---- /// Window buffer info returned by wm_buffer. #[repr(C)] #[derive(Clone, Copy)] pub struct WindowInfo { pub ptr: *mut u32, pub w: u32, pub h: u32, } /// Key event kind (flattened for ABI stability). #[repr(u8)] #[derive(Clone, Copy, PartialEq, Eq)] pub enum WmKeyKind { Char = 0, Enter = 1, Backspace = 2, Tab = 3, Escape = 4, CtrlC = 5, ArrowUp = 10, ArrowDown = 11, ArrowLeft = 12, ArrowRight = 13, Home = 14, End = 15, PageUp = 16, PageDown = 17, Delete = 18, F1 = 20, F2 = 21, F3 = 22, F4 = 23, Unknown = 255, } /// Mouse button state. #[repr(C)] #[derive(Clone, Copy)] pub struct WmMouseEvent { pub x: i32, pub y: i32, pub buttons: u8, } /// One window manager event delivered to a GUI binary. #[repr(C)] #[derive(Clone, Copy)] pub struct WmEvent { pub kind: u8, // 0=key, 1=mouse, 2=focus, 3=close pub key_kind: WmKeyKind, pub key_char: u8, pub mouse: WmMouseEvent, pub focused: bool, pub _pad: [u8; 4], } /// Kernel version information. #[derive(Clone, Copy)] pub struct KernelVersion { pub name: Line, pub major: u16, pub minor: u16, pub patch: u16, } // --------------------------------------------------------------------------- // Exports table — v2 // --------------------------------------------------------------------------- /// The function table a binary receives. Layout is fixed by `version`; /// new functions are appended, existing ones never move. #[repr(C)] pub struct Exports { // ---- header ---- pub magic: u32, pub version: u32, // ---- console / streams (v1) ---- pub put_line: fn(line: Line) -> bool, pub get_line: fn(out: &mut Line) -> StreamResult, // ---- lifecycle (v1) ---- pub log_line: fn(line: Line), pub exit: fn(code: i32) -> !, // ---- filesystem queries (v2) ---- /// Resolve a path to a handle; returns -1 on error. pub fs_resolve: fn(path: Line) -> FsHandle, /// Iterate directory entries: returns true and fills `out` while /// entries remain; returns false when exhausted. Resets position. pub fs_dir_next: fn(handle: FsHandle, out: &mut DirEntry) -> bool, /// Create a file (is_dir=false) or directory (is_dir=true) at path. /// Returns 0 on success, -1 on error. pub fs_create: fn(path: Line, is_dir: bool) -> i32, /// Remove a file or empty directory. Returns 0 on success. pub fs_remove: fn(path: Line) -> i32, /// Read `len` bytes from `handle` at `pos`. Returns bytes actually /// read, or -1 on error. pub fs_read: fn(handle: FsHandle, buf: *mut u8, pos: u64, len: u64) -> i64, /// Write `len` bytes to `handle` at `pos`. Returns bytes written. pub fs_write: fn(handle: FsHandle, buf: *const u8, pos: u64, len: u64) -> i64, /// Get file/directory size in bytes. pub fs_size: fn(handle: FsHandle) -> u64, /// Close a handle (currently a no-op; reserved for future fd mgmt). pub fs_close: fn(handle: FsHandle), // ---- hardware queries (v2) ---- pub rtc_now: fn(out: &mut RtcTime), pub mem_stats: fn(out: &mut MemStats), /// Enumerate PCI: returns number of devices discovered. pub pci_probe: fn() -> u32, /// Get one PCI device by index (0-based). Returns true on success. pub pci_device: fn(index: u32, out: &mut PciDevice) -> bool, /// Copy up to `cap` bytes of the kernel log ring into `buf`. /// Returns bytes copied. pub klog_dump: fn(buf: *mut u8, cap: u64) -> u64, /// Fill `out` with kernel version info. pub kernel_version: fn(out: &mut KernelVersion), // ---- window/events (v2 GUI) ---- /// Create a window; returns window id or -1. pub wm_create: fn(title: Line, w: u32, h: u32) -> i32, /// Get the window's pixel buffer info. pub wm_buffer: fn(id: i32, out: &mut WindowInfo) -> bool, /// Composite the window to screen. pub wm_flush: fn(id: i32), /// Destroy a window. pub wm_destroy: fn(id: i32), /// Non-blocking: receive one event. Returns true if an event was delivered. pub wm_recv: fn(out: &mut WmEvent) -> bool, }