summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--rsnix/src/font.rs (renamed from src/font.rs)0
-rw-r--r--rsnix/src/gop.rs (renamed from src/gop.rs)0
-rw-r--r--rsnix/src/interrupts.rs (renamed from src/interrupts.rs)4
-rw-r--r--rsnix/src/memory.rs (renamed from src/memory.rs)2
-rw-r--r--rsnix/src/ps2.rs (renamed from src/ps2.rs)5
-rw-r--r--rsnix/src/serial.rs (renamed from src/serial.rs)0
-rw-r--r--rsnix/src/uefi.rs (renamed from src/uefi.rs)0
-rw-r--r--shell/src/lib.rs (renamed from src/shell.rs)42
-rw-r--r--src/main.rs186
9 files changed, 31 insertions, 208 deletions
diff --git a/src/font.rs b/rsnix/src/font.rs
index e188513..e188513 100644
--- a/src/font.rs
+++ b/rsnix/src/font.rs
diff --git a/src/gop.rs b/rsnix/src/gop.rs
index 9645bb0..9645bb0 100644
--- a/src/gop.rs
+++ b/rsnix/src/gop.rs
diff --git a/src/interrupts.rs b/rsnix/src/interrupts.rs
index 90d5bbb..8f2acd7 100644
--- a/src/interrupts.rs
+++ b/rsnix/src/interrupts.rs
@@ -174,7 +174,7 @@ impl KeyBuf {
174 let h = self.head.load(Ordering::Acquire); 174 let h = self.head.load(Ordering::Acquire);
175 let next = t.wrapping_add(1); 175 let next = t.wrapping_add(1);
176 // Full if the distance between head and tail == capacity (256). 176 // Full if the distance between head and tail == capacity (256).
177 if next.wrapping_sub(h) as u16 > 255 { 177 if next.wrapping_sub(h) > 255 {
178 return; // drop — ring is full 178 return; // drop — ring is full
179 } 179 }
180 unsafe { 180 unsafe {
@@ -362,7 +362,7 @@ pub fn init() {
362 362
363 // Build the IDTR pseudo-descriptor. 363 // Build the IDTR pseudo-descriptor.
364 IDTR = [ 364 IDTR = [
365 (256u16 * 16 - 1) as u16, // limit = 256*16 - 1 365 ((256u16 * 16 - 1)), // limit = 256*16 - 1
366 idt_ptr as u16, // base lo 366 idt_ptr as u16, // base lo
367 (idt_ptr as u64 >> 16) as u16, // base mid 367 (idt_ptr as u64 >> 16) as u16, // base mid
368 (idt_ptr as u64 >> 32) as u16, // base hi 368 (idt_ptr as u64 >> 32) as u16, // base hi
diff --git a/src/memory.rs b/rsnix/src/memory.rs
index d223f69..39fd88d 100644
--- a/src/memory.rs
+++ b/rsnix/src/memory.rs
@@ -85,7 +85,7 @@ pub fn capture_memory_map(bs: &BootServices) -> Result<usize, Status> {
85 } 85 }
86 86
87 // Round up to desc_size alignment 87 // Round up to desc_size alignment
88 let buf_size = (buf_size + desc_size - 1) / desc_size * desc_size; 88 let buf_size = buf_size.div_ceil(desc_size) * desc_size;
89 89
90 // If our static buffer is too small, fall back to pool (rare) 90 // If our static buffer is too small, fall back to pool (rare)
91 if buf_size > unsafe { MAP_WORK_BUF.len() } { 91 if buf_size > unsafe { MAP_WORK_BUF.len() } {
diff --git a/src/ps2.rs b/rsnix/src/ps2.rs
index 4ea8b7a..b83a4e0 100644
--- a/src/ps2.rs
+++ b/rsnix/src/ps2.rs
@@ -346,11 +346,10 @@ fn update_modifiers(scancode: u8, pressed: bool, e0: bool) {
346 (0x1D, true) => set_mod(state, MOD_RCTRL, pressed), 346 (0x1D, true) => set_mod(state, MOD_RCTRL, pressed),
347 (0x38, false) => set_mod(state, MOD_LALT, pressed), 347 (0x38, false) => set_mod(state, MOD_LALT, pressed),
348 (0x38, true) => set_mod(state, MOD_RALT, pressed), 348 (0x38, true) => set_mod(state, MOD_RALT, pressed),
349 (0x3A, false) => { 349 (0x3A, false)
350 if pressed { 350 if pressed => {
351 state.modifiers ^= MOD_CAPS; 351 state.modifiers ^= MOD_CAPS;
352 } 352 }
353 }
354 _ => {} 353 _ => {}
355 } 354 }
356} 355}
diff --git a/src/serial.rs b/rsnix/src/serial.rs
index 03fa570..03fa570 100644
--- a/src/serial.rs
+++ b/rsnix/src/serial.rs
diff --git a/src/uefi.rs b/rsnix/src/uefi.rs
index 2e3ed6b..2e3ed6b 100644
--- a/src/uefi.rs
+++ b/rsnix/src/uefi.rs
diff --git a/src/shell.rs b/shell/src/lib.rs
index 8e4cb62..bdd79c6 100644
--- a/src/shell.rs
+++ b/shell/src/lib.rs
@@ -1,14 +1,24 @@
1#![no_std]
2
3extern crate alloc;
4
1/// Minimal command shell — reads from PS/2 keyboard, writes to GOP + serial. 5/// Minimal command shell — reads from PS/2 keyboard, writes to GOP + serial.
2use crate::ps2::{self, KeyEvent}; 6use rsnix::ps2::{self, KeyEvent};
3use crate::{gop_print, gop_println, serial_print, serial_println}; 7use rsnix::{gop_print, gop_println, serial_print, serial_println};
4 8
5/// Maximum input line length. 9/// Maximum input line length.
6const LINE_BUF_SIZE: usize = 256; 10const LINE_BUF_SIZE: usize = 256;
7 11
8/// Run the shell forever. 12/// Run the shell forever.
9pub fn run() -> ! { 13pub fn run() -> ! {
10 gop_println!("raisernics v{} — type 'help' for commands", env!("CARGO_PKG_VERSION")); 14 gop_println!(
11 serial_println!("========== raisernics v{} ==========", env!("CARGO_PKG_VERSION")); 15 "rs-dos v{} — type 'help' for commands",
16 env!("CARGO_PKG_VERSION")
17 );
18 serial_println!(
19 "========== rs-dos v{} ==========",
20 env!("CARGO_PKG_VERSION")
21 );
12 22
13 loop { 23 loop {
14 // Print prompt 24 // Print prompt
@@ -53,32 +63,32 @@ fn read_line() -> heapless_str::String<LINE_BUF_SIZE> {
53 loop { 63 loop {
54 match ps2::poll_key() { 64 match ps2::poll_key() {
55 KeyEvent::Enter => { 65 KeyEvent::Enter => {
56 crate::gop::put_char('\n'); 66 rsnix::gop::put_char('\n');
57 crate::serial::write_str("\r\n"); 67 rsnix::serial::write_str("\r\n");
58 return buf; 68 return buf;
59 } 69 }
60 KeyEvent::Char(c) if c.is_ascii_graphic() || c == ' ' => { 70 KeyEvent::Char(c) if c.is_ascii_graphic() || c == ' ' => {
61 if buf.push(c).is_ok() { 71 if buf.push(c).is_ok() {
62 crate::gop::put_char(c); 72 rsnix::gop::put_char(c);
63 // Echo to serial too 73 // Echo to serial too
64 let mut s = [0u8; 4]; 74 let mut s = [0u8; 4];
65 let s = c.encode_utf8(&mut s); 75 let s = c.encode_utf8(&mut s);
66 crate::serial::write_str(s); 76 rsnix::serial::write_str(s);
67 } 77 }
68 } 78 }
69 KeyEvent::Backspace => { 79 KeyEvent::Backspace => {
70 if buf.pop().is_some() { 80 if buf.pop().is_some() {
71 // GOP backspace: move cursor back and erase 81 // GOP backspace: move cursor back and erase
72 crate::gop::put_char('\x08'); 82 rsnix::gop::put_char('\x08');
73 // Serial backspace: send BS SP BS (standard terminal protocol) 83 // Serial backspace: send BS SP BS (standard terminal protocol)
74 crate::serial::write_str("\x08 \x08"); 84 rsnix::serial::write_str("\x08 \x08");
75 } 85 }
76 } 86 }
77 KeyEvent::Tab => { 87 KeyEvent::Tab => {
78 for _ in 0..4 { 88 for _ in 0..4 {
79 if buf.push(' ').is_ok() { 89 if buf.push(' ').is_ok() {
80 crate::gop::put_char(' '); 90 rsnix::gop::put_char(' ');
81 crate::serial::write_str(" "); 91 rsnix::serial::write_str(" ");
82 } 92 }
83 } 93 }
84 } 94 }
@@ -120,14 +130,14 @@ fn cmd_echo(args: &str) {
120} 130}
121 131
122fn cmd_clear() { 132fn cmd_clear() {
123 crate::gop::clear_screen(); 133 rsnix::gop::clear_screen();
124} 134}
125 135
126fn cmd_info() { 136fn cmd_info() {
127 // Test that the global allocator works: build a String on the heap 137 // Test that the global allocator works: build a String on the heap
128 let mut s = alloc::string::String::from("raisernics v"); 138 let mut s = alloc::string::String::from("rs-dos v");
129 s.push_str(env!("CARGO_PKG_VERSION")); 139 s.push_str(env!("CARGO_PKG_VERSION"));
130 s.push_str(" — RNG custom kernel"); 140 s.push_str(" — rsnix kernel");
131 gop_println!("{}", s); 141 gop_println!("{}", s);
132 gop_println!("arch: x86_64, freestanding, no userspace"); 142 gop_println!("arch: x86_64, freestanding, no userspace");
133 serial_println!("{}", s); 143 serial_println!("{}", s);
@@ -136,7 +146,7 @@ fn cmd_info() {
136} 146}
137 147
138fn cmd_mem() { 148fn cmd_mem() {
139 let (map, key) = crate::memory::get_map(); 149 let (map, key) = rsnix::memory::get_map();
140 150
141 let mut total_kb = 0u64; 151 let mut total_kb = 0u64;
142 let mut conventional_kb = 0u64; 152 let mut conventional_kb = 0u64;
diff --git a/src/main.rs b/src/main.rs
deleted file mode 100644
index 9a901f5..0000000
--- a/src/main.rs
+++ /dev/null
@@ -1,186 +0,0 @@
1#![no_std]
2#![no_main]
3#![allow(static_mut_refs, unsafe_code, dead_code, unused_doc_comments)]
4
5// SAFETY: single-core kernel, no preemption — static mut access is sound
6// Toy kernel: dead code and unused items during active development
7
8extern crate alloc;
9
10mod font;
11mod gop;
12mod interrupts;
13mod memory;
14mod ps2;
15mod serial;
16mod shell;
17mod uefi;
18
19use core::panic::PanicInfo;
20use uefi::*;
21
22// ---------------------------------------------------------------------------
23// Panic handler
24// ---------------------------------------------------------------------------
25#[panic_handler]
26fn panic(info: &PanicInfo) -> ! {
27 use core::fmt::Write;
28 serial::write_str("\r\n*** PANIC ***\r\n");
29 let _ = write!(&mut serial::SerialWriter, "{}\r\n", info.message());
30 if let Some(loc) = info.location() {
31 let _ = write!(
32 &mut serial::SerialWriter,
33 " at {}:{}\r\n",
34 loc.file(),
35 loc.line()
36 );
37 }
38 loop {
39 unsafe {
40 core::arch::asm!("cli; hlt");
41 }
42 }
43}
44
45// ---------------------------------------------------------------------------
46// EFI entry point
47// ---------------------------------------------------------------------------
48#[no_mangle]
49pub extern "efiapi" fn efi_main(image_handle: Handle, system_table: *mut SystemTable) -> ! {
50 let st = unsafe { &mut *system_table };
51 let bs = unsafe { &mut *st.boot_services };
52 let con_out = unsafe { &mut *st.con_out };
53
54 // ---- Phase 1: UEFI boot services alive ----
55
56 // Print banner via UEFI console
57 unsafe {
58 let banner: [u16; 28] = [
59 'r' as u16, 'a' as u16, 'i' as u16, 's' as u16, 'e' as u16, 'r' as u16, 'n' as u16,
60 'i' as u16, 'c' as u16, 's' as u16, ' ' as u16, 'v' as u16, '0' as u16, '.' as u16,
61 '1' as u16, ' ' as u16, '-' as u16, ' ' as u16, 'b' as u16, 'o' as u16, 'o' as u16,
62 't' as u16, 'i' as u16, 'n' as u16, 'g' as u16, '.' as u16, '.' as u16, 0x0A,
63 ];
64 (con_out.output_string)(con_out, banner.as_ptr());
65 }
66
67 // Init serial early so we can debug-print before EBS
68 serial::init();
69
70 serial_println!("=== raisernics boot ===");
71
72 // Stash the memory map
73 let map_key = memory::capture_memory_map(bs);
74 let map_key = match map_key {
75 Ok(k) => k,
76 Err(e) => {
77 serial_println!("mem: capture_memory_map failed 0x{:x}", e);
78 0
79 }
80 };
81
82 // Locate GOP (Graphics Output Protocol)
83 let mut gop_interface: *mut core::ffi::c_void = core::ptr::null_mut();
84 let gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
85 let gop_result = unsafe {
86 (bs.locate_protocol)(
87 &gop_guid as *const Guid,
88 core::ptr::null_mut(),
89 &mut gop_interface,
90 )
91 };
92 if gop_result == EFI_SUCCESS {
93 let gop = unsafe { &mut *(gop_interface as *mut GraphicsOutputProtocol) };
94 serial_println!("gop: framebuffer found");
95 gop::init(gop);
96 } else {
97 serial_println!("gop: not found (0x{:x})", gop_result);
98 }
99
100 // ExitBootServices — we now own the machine
101 let ebs_result = unsafe { (bs.exit_boot_services)(image_handle, map_key) };
102 if ebs_result != EFI_SUCCESS {
103 // Memory map may have changed; try again with fresh map
104 // (This is the standard UEFI EBS retry dance.)
105 serial_println!(
106 "WARN: ExitBootServices failed (0x{:x}), retrying...",
107 ebs_result
108 );
109 let _map_key = match memory::refresh_and_exit(bs, image_handle) {
110 Ok(k) => k,
111 Err(e) => {
112 serial_println!("FATAL: cannot ExitBootServices (0x{:x})", e);
113 loop {
114 unsafe {
115 core::arch::asm!("cli; hlt");
116 }
117 }
118 }
119 };
120 }
121
122 // ---- Phase 2: Native mode ----
123
124 serial::init();
125 serial_println!("serial: COM1 115200 8N1");
126
127 // PS/2 keyboard
128 ps2::init();
129 serial_println!("ps2: keyboard initialized");
130
131 // Interrupts — IDT, PIC, PIT timer, keyboard IRQ handler
132 interrupts::init();
133 serial_println!("intr: IDT loaded, PIC remapped, timer ~100 Hz");
134
135 // Memory: the bump allocator was set up during capture_memory_map.
136 // `alloc::Vec`, `alloc::String`, `format!` etc. are now usable.
137
138 // Print memory summary
139 dump_memory_summary();
140
141 serial_println!("boot: entering shell");
142 shell::run();
143}
144
145// ---------------------------------------------------------------------------
146// Print a memory summary from the stashed memory map
147// ---------------------------------------------------------------------------
148fn dump_memory_summary() {
149 let (map, key) = memory::get_map();
150 let mut conventional_4k = 0u64;
151 let mut addr_space_4k = 0u64;
152 for desc in map.iter() {
153 let pages = desc.number_of_pages;
154 addr_space_4k += pages;
155 if desc.kind == 7 {
156 conventional_4k += pages;
157 }
158 }
159 serial_println!(
160 "mem: {} entries, key=0x{:x}, usable: {} KB ({} MB)",
161 map.len(),
162 key,
163 conventional_4k * 4,
164 (conventional_4k * 4) / 1024,
165 );
166 serial_println!(
167 "mem: address space: {} MB (incl. PCIe MMIO)",
168 (addr_space_4k * 4) / 1024,
169 );
170}
171
172// ---------------------------------------------------------------------------
173// Helper: write a panic-proof string via UEFI console (used before serial)
174// ---------------------------------------------------------------------------
175#[allow(dead_code)]
176unsafe fn uefi_puts(con_out: *mut SimpleTextOutput, s: &str) {
177 // Simple ASCII → UEFI-CHAR16 conversion (stack buffer, panic-safe)
178 let mut buf: [u16; 128] = [0; 128];
179 let len = s.len().min(127);
180 for (i, &b) in s.as_bytes()[..len].iter().enumerate() {
181 buf[i] = b as u16;
182 }
183 buf[len] = 0x0A; // LF
184 let out = unsafe { &mut *con_out };
185 (out.output_string)(out, buf.as_ptr());
186}