diff options
| author | salmonik <salmonik@tuta.io> | 2026-08-27 17:16:04 +0200 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-08-27 17:16:04 +0200 |
| commit | 8767dbecb45bbe5f748952fb9171b1a96c173f67 (patch) | |
| tree | c10a66c91a53522feb980d8b59aa8c87293537f8 /rsapi/src | |
| parent | streams: per-invocation channel, pumping mode, filter pipeline wiring (diff) | |
| download | rs-dos-8767dbecb45bbe5f748952fb9171b1a96c173f67.tar.gz rs-dos-8767dbecb45bbe5f748952fb9171b1a96c173f67.zip | |
tool migration: v2 exports + 10 external CLI binaries
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.
Diffstat (limited to 'rsapi/src')
| -rw-r--r-- | rsapi/src/lib.rs | 117 |
1 files changed, 100 insertions, 17 deletions
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; | |||
| 15 | 15 | ||
| 16 | /// ABI revision. Bump on any signature change; the kernel refuses to run | 16 | /// ABI revision. Bump on any signature change; the kernel refuses to run |
| 17 | /// binaries whose required major exceeds its own. | 17 | /// binaries whose required major exceeds its own. |
| 18 | pub const ABI_VERSION: u32 = 1; | 18 | pub const ABI_VERSION: u32 = 2; |
| 19 | 19 | ||
| 20 | /// Entry-point signature. `extern "C"` on the x86_64-unknown-uefi | 20 | /// Entry-point signature. `extern "C"` on the x86_64-unknown-uefi |
| 21 | /// target is the Win64 convention: the three arguments arrive in | 21 | /// target is the Win64 convention: the three arguments arrive in |
| 22 | /// RCX/RDX/R8 on both sides of the table. | 22 | /// RCX/RDX/R8 on both sides of the table. |
| 23 | pub type EntryPoint = | 23 | pub type EntryPoint = extern "C" fn(exports: &'static Exports, argc: usize, argv: *const Arg) -> i32; |
| 24 | extern "C" fn(exports: &'static Exports, argc: usize, argv: *const Arg) -> i32; | ||
| 25 | 24 | ||
| 26 | /// One C-style argv element: pointer + length (rs-dos strings are not | 25 | /// One C-style argv element: pointer + length (rs-dos strings are not |
| 27 | /// NUL-terminated in memory). | 26 | /// NUL-terminated in memory). |
| @@ -39,7 +38,7 @@ pub struct Line { | |||
| 39 | } | 38 | } |
| 40 | 39 | ||
| 41 | impl Line { | 40 | impl Line { |
| 42 | /// Borrow as a &str (lossy is impossible: lines are always UTF-8). | 41 | /// Borrow as a &str. |
| 43 | pub fn as_str(&self) -> &'static str { | 42 | pub fn as_str(&self) -> &'static str { |
| 44 | unsafe { core::str::from_utf8_unchecked(core::slice::from_raw_parts(self.ptr, self.len)) } | 43 | unsafe { core::str::from_utf8_unchecked(core::slice::from_raw_parts(self.ptr, self.len)) } |
| 45 | } | 44 | } |
| @@ -48,16 +47,75 @@ impl Line { | |||
| 48 | /// Outcome of `get_line`. | 47 | /// Outcome of `get_line`. |
| 49 | #[derive(Clone, Copy, PartialEq, Eq)] | 48 | #[derive(Clone, Copy, PartialEq, Eq)] |
| 50 | pub enum StreamResult { | 49 | pub enum StreamResult { |
| 51 | /// A line is available (see `out`). | ||
| 52 | Line, | 50 | Line, |
| 53 | /// Input exhausted. | ||
| 54 | Eof, | 51 | Eof, |
| 55 | /// Aborted (^C or upstream killed); stop immediately. | ||
| 56 | Abort, | 52 | Abort, |
| 57 | } | 53 | } |
| 58 | 54 | ||
| 59 | // --------------------------------------------------------------------------- | 55 | // --------------------------------------------------------------------------- |
| 60 | // Exports table — v1 | 56 | // v2 types |
| 57 | // --------------------------------------------------------------------------- | ||
| 58 | |||
| 59 | /// Opaque file/directory handle returned by `fs_resolve` / `fs_create`. | ||
| 60 | pub type FsHandle = i32; | ||
| 61 | |||
| 62 | /// One directory entry returned by `fs_dir_next`. | ||
| 63 | #[repr(C)] | ||
| 64 | #[derive(Clone, Copy)] | ||
| 65 | pub struct DirEntry { | ||
| 66 | pub name: Line, | ||
| 67 | pub is_dir: bool, | ||
| 68 | pub _pad: u8, | ||
| 69 | pub size: u64, | ||
| 70 | } | ||
| 71 | |||
| 72 | /// Real-time clock snapshot. | ||
| 73 | #[repr(C)] | ||
| 74 | #[derive(Clone, Copy)] | ||
| 75 | pub struct RtcTime { | ||
| 76 | pub year: u16, | ||
| 77 | pub month: u8, | ||
| 78 | pub day: u8, | ||
| 79 | pub hour: u8, | ||
| 80 | pub minute: u8, | ||
| 81 | pub second: u8, | ||
| 82 | pub _pad: u8, | ||
| 83 | } | ||
| 84 | |||
| 85 | /// Memory statistics (heap + page allocator). | ||
| 86 | #[repr(C)] | ||
| 87 | #[derive(Clone, Copy)] | ||
| 88 | pub struct MemStats { | ||
| 89 | pub heap_total: u64, | ||
| 90 | pub heap_free: u64, | ||
| 91 | pub pages_total: u64, | ||
| 92 | pub pages_free: u64, | ||
| 93 | } | ||
| 94 | |||
| 95 | /// One PCI device discovered at probe time. | ||
| 96 | #[repr(C)] | ||
| 97 | #[derive(Clone, Copy)] | ||
| 98 | pub struct PciDevice { | ||
| 99 | pub bus: u8, | ||
| 100 | pub device: u8, | ||
| 101 | pub function: u8, | ||
| 102 | pub class: u8, | ||
| 103 | pub subclass: u8, | ||
| 104 | pub vendor: u16, | ||
| 105 | pub device_id: u16, | ||
| 106 | } | ||
| 107 | |||
| 108 | /// Kernel version information. | ||
| 109 | #[derive(Clone, Copy)] | ||
| 110 | pub struct KernelVersion { | ||
| 111 | pub name: Line, | ||
| 112 | pub major: u16, | ||
| 113 | pub minor: u16, | ||
| 114 | pub patch: u16, | ||
| 115 | } | ||
| 116 | |||
| 117 | // --------------------------------------------------------------------------- | ||
| 118 | // Exports table — v2 | ||
| 61 | // --------------------------------------------------------------------------- | 119 | // --------------------------------------------------------------------------- |
| 62 | 120 | ||
| 63 | /// The function table a binary receives. Layout is fixed by `version`; | 121 | /// The function table a binary receives. Layout is fixed by `version`; |
| @@ -69,19 +127,44 @@ pub struct Exports { | |||
| 69 | pub version: u32, | 127 | pub version: u32, |
| 70 | 128 | ||
| 71 | // ---- console / streams (v1) ---- | 129 | // ---- console / streams (v1) ---- |
| 72 | /// Print one line to the command's output stream. | ||
| 73 | /// Returns false when the consumer says stop (pager quit / head limit / | ||
| 74 | /// ^C) — the binary should wrap up promptly. | ||
| 75 | pub put_line: fn(line: Line) -> bool, | 130 | pub put_line: fn(line: Line) -> bool, |
| 76 | /// Read one line from the command's input stream (only meaningful for | ||
| 77 | /// input consumers like cat/hexdump; otherwise returns Eof). | ||
| 78 | /// `out` receives the line when the result is `StreamResult::Line`. | ||
| 79 | pub get_line: fn(out: &mut Line) -> StreamResult, | 131 | pub get_line: fn(out: &mut Line) -> StreamResult, |
| 80 | 132 | ||
| 81 | // ---- lifecycle (v1) ---- | 133 | // ---- lifecycle (v1) ---- |
| 82 | /// Log one line to the kernel log ring (/dev/klog). | ||
| 83 | pub log_line: fn(line: Line), | 134 | pub log_line: fn(line: Line), |
| 84 | /// Exit code for the completion message to the spawner. | ||
| 85 | /// (Calling this is optional; returning from the entry point exits 0.) | ||
| 86 | pub exit: fn(code: i32) -> !, | 135 | pub exit: fn(code: i32) -> !, |
| 136 | |||
| 137 | // ---- filesystem queries (v2) ---- | ||
| 138 | /// Resolve a path to a handle; returns -1 on error. | ||
| 139 | pub fs_resolve: fn(path: Line) -> FsHandle, | ||
| 140 | /// Iterate directory entries: returns true and fills `out` while | ||
| 141 | /// entries remain; returns false when exhausted. Resets position. | ||
| 142 | pub fs_dir_next: fn(handle: FsHandle, out: &mut DirEntry) -> bool, | ||
| 143 | /// Create a file (is_dir=false) or directory (is_dir=true) at path. | ||
| 144 | /// Returns 0 on success, -1 on error. | ||
| 145 | pub fs_create: fn(path: Line, is_dir: bool) -> i32, | ||
| 146 | /// Remove a file or empty directory. Returns 0 on success. | ||
| 147 | pub fs_remove: fn(path: Line) -> i32, | ||
| 148 | /// Read `len` bytes from `handle` at `pos`. Returns bytes actually | ||
| 149 | /// read, or -1 on error. | ||
| 150 | pub fs_read: fn(handle: FsHandle, buf: *mut u8, pos: u64, len: u64) -> i64, | ||
| 151 | /// Write `len` bytes to `handle` at `pos`. Returns bytes written. | ||
| 152 | pub fs_write: fn(handle: FsHandle, buf: *const u8, pos: u64, len: u64) -> i64, | ||
| 153 | /// Get file/directory size in bytes. | ||
| 154 | pub fs_size: fn(handle: FsHandle) -> u64, | ||
| 155 | /// Close a handle (currently a no-op; reserved for future fd mgmt). | ||
| 156 | pub fs_close: fn(handle: FsHandle), | ||
| 157 | |||
| 158 | // ---- hardware queries (v2) ---- | ||
| 159 | pub rtc_now: fn(out: &mut RtcTime), | ||
| 160 | pub mem_stats: fn(out: &mut MemStats), | ||
| 161 | /// Enumerate PCI: returns number of devices discovered. | ||
| 162 | pub pci_probe: fn() -> u32, | ||
| 163 | /// Get one PCI device by index (0-based). Returns true on success. | ||
| 164 | pub pci_device: fn(index: u32, out: &mut PciDevice) -> bool, | ||
| 165 | /// Copy up to `cap` bytes of the kernel log ring into `buf`. | ||
| 166 | /// Returns bytes copied. | ||
| 167 | pub klog_dump: fn(buf: *mut u8, cap: u64) -> u64, | ||
| 168 | /// Fill `out` with kernel version info. | ||
| 169 | pub kernel_version: fn(out: &mut KernelVersion), | ||
| 87 | } | 170 | } |
