//! 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 = 1; /// 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 (lossy is impossible: lines are always UTF-8). 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 { /// A line is available (see `out`). Line, /// Input exhausted. Eof, /// Aborted (^C or upstream killed); stop immediately. Abort, } // --------------------------------------------------------------------------- // Exports table — v1 // --------------------------------------------------------------------------- /// 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) ---- /// Print one line to the command's output stream. /// Returns false when the consumer says stop (pager quit / head limit / /// ^C) — the binary should wrap up promptly. pub put_line: fn(line: Line) -> bool, /// Read one line from the command's input stream (only meaningful for /// input consumers like cat/hexdump; otherwise returns Eof). /// `out` receives the line when the result is `StreamResult::Line`. pub get_line: fn(out: &mut Line) -> StreamResult, // ---- lifecycle (v1) ---- /// Log one line to the kernel log ring (/dev/klog). pub log_line: fn(line: Line), /// Exit code for the completion message to the spawner. /// (Calling this is optional; returning from the entry point exits 0.) pub exit: fn(code: i32) -> !, }