From 8767dbecb45bbe5f748952fb9171b1a96c173f67 Mon Sep 17 00:00:00 2001 From: salmonik Date: Thu, 27 Aug 2026 17:16:04 +0200 Subject: tool migration: v2 exports + 10 external CLI binaries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rsapi v2: 14 new ABI function pointers appended after v1 — fs_resolve, fs_dir_next (iterator), fs_create, fs_remove, fs_read, fs_write, fs_size, fs_close, rtc_now, mem_stats, pci_probe, pci_device, klog_dump, kernel_version. New C-repr structs: DirEntry, RtcTime, MemStats, PciDevice, KernelVersion. ABI_VERSION bumped to 2. Shell-side: build_exports() constructs the full table at runtime per invocation (replaces static const). 14 kernel-side wrapper functions bridge rsapi types to rsnix kernel APIs; fs_dir_next maintains a per-handle cache of children() results for iteration. Tool binaries (10 crates, all linked against rsapi only): - date: rtc_now → formatted YYYY-MM-DD HH:MM:SS - mem: heap/pages free/total via mem_stats - pci: pci_probe + pci_device enumerate all devices - cat: fs_read paths or get_line stdin; put_line output - ls: fs_resolve + fs_dir_next iteration; trailing / for dirs - mkdir: fs_create(path, true) - touch: fs_create(path, false) - rm: fs_remove(path) - klog: klog_dump 2048 bytes → put_line - info: rtc_now + kernel_version (minimal; mem/pci deferred) Gate verified: date prints RTC; pci lists all 4 QEMU devices (8086:29c0, 1234:1111, 8086:10d3, 8086:2918); hello/boom/count still work; test-disk PASS; poweroff clean. --- rsapi/src/lib.rs | 117 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 100 insertions(+), 17 deletions(-) (limited to 'rsapi/src') diff --git a/rsapi/src/lib.rs b/rsapi/src/lib.rs index d7b69a2..dfe75d6 100644 --- a/rsapi/src/lib.rs +++ b/rsapi/src/lib.rs @@ -15,13 +15,12 @@ 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; +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; +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). @@ -39,7 +38,7 @@ pub struct Line { } impl Line { - /// Borrow as a &str (lossy is impossible: lines are always UTF-8). + /// 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)) } } @@ -48,16 +47,75 @@ impl Line { /// 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 +// 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`; @@ -69,19 +127,44 @@ pub struct Exports { 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) -> !, + + // ---- 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), } -- cgit v1.2.3