//! 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, } /// 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), }