summaryrefslogtreecommitdiffstats
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/main.rs186
1 files changed, 0 insertions, 186 deletions
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}