1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
|
//! 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,
}
|