summaryrefslogtreecommitdiffstats
path: root/rsdos/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rsdos/src/main.rs')
-rw-r--r--rsdos/src/main.rs138
1 files changed, 138 insertions, 0 deletions
diff --git a/rsdos/src/main.rs b/rsdos/src/main.rs
new file mode 100644
index 0000000..543556b
--- /dev/null
+++ b/rsdos/src/main.rs
@@ -0,0 +1,138 @@
1#![no_std]
2#![no_main]
3#![allow(static_mut_refs, unsafe_code)]
4
5use core::panic::PanicInfo;
6use rsnix::uefi::*;
7
8// ---------------------------------------------------------------------------
9// Panic handler
10// ---------------------------------------------------------------------------
11#[panic_handler]
12fn panic(info: &PanicInfo) -> ! {
13 use core::fmt::Write;
14 rsnix::serial::write_str("\r\n*** PANIC ***\r\n");
15 let _ = write!(&mut rsnix::serial::SerialWriter, "{}\r\n", info.message());
16 if let Some(loc) = info.location() {
17 let _ = write!(
18 &mut rsnix::serial::SerialWriter,
19 " at {}:{}\r\n",
20 loc.file(),
21 loc.line()
22 );
23 }
24 loop {
25 unsafe {
26 core::arch::asm!("cli; hlt");
27 }
28 }
29}
30
31// ---------------------------------------------------------------------------
32// EFI entry point
33// ---------------------------------------------------------------------------
34#[no_mangle]
35pub extern "efiapi" fn efi_main(image_handle: Handle, system_table: *mut SystemTable) -> ! {
36 let st = unsafe { &mut *system_table };
37 let bs = unsafe { &mut *st.boot_services };
38 let con_out = unsafe { &mut *st.con_out };
39
40 // ---- Phase 1: UEFI boot services alive ----
41
42 // Print banner via UEFI console
43 unsafe {
44 let s = concat!("rsnix v", env!("CARGO_PKG_VERSION"), " booting..\n");
45 let bytes = s.as_bytes();
46 let mut buf: [u16; 48] = [0; 48];
47 for (i, &b) in bytes.iter().enumerate().take(47) {
48 buf[i] = b as u16;
49 }
50 (con_out.output_string)(con_out, buf.as_ptr());
51 }
52
53 rsnix::serial::init();
54 rsnix::serial_println!("=== rsnix boot ===");
55
56 // Stash the memory map
57 let map_key = match rsnix::memory::capture_memory_map(bs) {
58 Ok(k) => k,
59 Err(e) => {
60 rsnix::serial_println!("mem: capture_memory_map failed 0x{:x}", e);
61 0
62 }
63 };
64
65 // Locate GOP (Graphics Output Protocol)
66 let mut gop_interface: *mut core::ffi::c_void = core::ptr::null_mut();
67 let gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
68 let gop_result = unsafe {
69 (bs.locate_protocol)(
70 &gop_guid as *const Guid,
71 core::ptr::null_mut(),
72 &mut gop_interface,
73 )
74 };
75 if gop_result == EFI_SUCCESS {
76 let gop = unsafe { &mut *(gop_interface as *mut GraphicsOutputProtocol) };
77 rsnix::serial_println!("gop: framebuffer found");
78 rsnix::gop::init(gop);
79 } else {
80 rsnix::serial_println!("gop: not found (0x{:x})", gop_result);
81 }
82
83 // ExitBootServices — we now own the machine
84 if unsafe { (bs.exit_boot_services)(image_handle, map_key) } != EFI_SUCCESS {
85 rsnix::serial_println!("WARN: ExitBootServices failed, retrying...");
86 match rsnix::memory::refresh_and_exit(bs, image_handle) {
87 Ok(_) => {}
88 Err(e) => {
89 rsnix::serial_println!("FATAL: cannot ExitBootServices (0x{:x})", e);
90 loop {
91 unsafe {
92 core::arch::asm!("cli; hlt");
93 }
94 }
95 }
96 }
97 }
98
99 // ---- Phase 2: Native mode ----
100 rsnix::serial::init();
101 rsnix::serial_println!("serial: COM1 115200 8N1");
102 rsnix::ps2::init();
103 rsnix::serial_println!("ps2: keyboard initialized");
104 rsnix::interrupts::init();
105 rsnix::serial_println!("intr: IDT loaded, PIC remapped, timer ~100 Hz");
106
107 dump_memory_summary();
108
109 rsnix::serial_println!("boot: entering shell");
110 shell::run();
111}
112
113// ---------------------------------------------------------------------------
114// Print a memory summary from the stashed memory map
115// ---------------------------------------------------------------------------
116fn dump_memory_summary() {
117 let (map, key) = rsnix::memory::get_map();
118 let mut conventional_4k = 0u64;
119 let mut addr_space_4k = 0u64;
120 for desc in map.iter() {
121 let pages = desc.number_of_pages;
122 addr_space_4k += pages;
123 if desc.kind == 7 {
124 conventional_4k += pages;
125 }
126 }
127 rsnix::serial_println!(
128 "mem: {} entries, key=0x{:x}, usable: {} KB ({} MB)",
129 map.len(),
130 key,
131 conventional_4k * 4,
132 (conventional_4k * 4) / 1024,
133 );
134 rsnix::serial_println!(
135 "mem: address space: {} MB (incl. PCIe MMIO)",
136 (addr_space_4k * 4) / 1024,
137 );
138}