1use crate::boot::fdt;
23
24#[inline(always)]
27unsafe fn early_print(s: &[u8]) {
28 let thr: u16 = 0x3F8;
29 let lsr: u16 = 0x3F8 + 5;
30 for &b in s {
31 loop {
32 let status: u8;
33 core::arch::asm!("in al, dx", out("al") status, in("dx") lsr, options(nomem, nostack, preserves_flags));
34 if status & 0x20 != 0 {
35 break;
36 }
37 }
38 core::arch::asm!("out dx, al", in("dx") thr, in("al") b, options(nomem, nostack, preserves_flags));
39 }
40}
41
42unsafe fn early_print_hex(mut val: u64) {
44 const HEX: &[u8; 16] = b"0123456789abcdef";
45 if val == 0 {
46 early_print(b"0");
47 return;
48 }
49 let mut buf = [0u8; 16];
50 let mut i = 16;
51 while val > 0 {
52 i -= 1;
53 buf[i] = HEX[(val & 0xf) as usize];
54 val >>= 4;
55 }
56 early_print(&buf[i..]);
57}
58
59pub const KERNEL_STACK_SIZE: usize = 256 * 1024;
61
62static mut KERNEL_ELF_BASE: u64 = 0;
64static mut KERNEL_ELF_SIZE: u64 = 0;
65
66pub fn kernel_elf_bytes() -> Option<&'static [u8]> {
68 let base = unsafe { KERNEL_ELF_BASE };
69 let size = unsafe { KERNEL_ELF_SIZE } as usize;
70 if base == 0 || size == 0 {
71 return None;
72 }
73 Some(unsafe { core::slice::from_raw_parts(base as *const u8, size) })
74}
75
76#[inline(always)]
78unsafe fn enable_cpu_features() {
79 let mut cr0: u64;
80 core::arch::asm!("mov {}, cr0", out(reg) cr0);
81 cr0 &= !(1 << 2); cr0 |= (1 << 1) | (1 << 5); core::arch::asm!("mov cr0, {}", in(reg) cr0, options(nomem, nostack));
84
85 let mut cr4: u64;
86 core::arch::asm!("mov {}, cr4", out(reg) cr4);
87 cr4 |= 0x600; core::arch::asm!("mov cr4, {}", in(reg) cr4, options(nomem, nostack));
89}
90
91#[no_mangle]
100#[allow(static_mut_refs)]
101pub unsafe extern "C" fn kmain(args_ptr: u64) -> ! {
102 {
105 let thr: u16 = 0x3F8;
106 let s = b"[kmain] RAW entry\r\n";
107 for &b in s {
108 let mut lsr: u8;
109 core::arch::asm!("in al, dx", in("dx") 0x3F8 + 5, out("al") lsr, options(nostack, preserves_flags));
110 loop {
111 core::arch::asm!("in al, dx", in("dx") 0x3F8 + 5, out("al") lsr, options(nostack, preserves_flags));
112 if lsr & 0x20 != 0 {
113 break;
114 }
115 }
116 core::arch::asm!("out dx, al", in("dx") thr, in("al") b, options(nostack, preserves_flags));
117 }
118 }
119
120 enable_cpu_features();
122
123 {
125 let mut early_port = uart_16550::SerialPort::new(0x3F8);
126 let _ = core::fmt::Write::write_str(
127 &mut early_port,
128 "[kmain] *** Strat9-OS kernel entry ***\r\n",
129 );
130 }
131
132 let args = if args_ptr == 0 {
139 early_print(b"[kmain] PVH boot (no args)\r\n");
140 build_minimal_args()
141 } else {
142 early_print(b"[kmain] Bootloader boot (args=0x");
143 early_print_hex(args_ptr);
144 early_print(b")\r\n");
145 let ptr = args_ptr as *const strat9_abi::boot::KernelArgs;
148 strat9_abi::boot::KernelArgs {
149 magic: core::ptr::read_unaligned(core::ptr::addr_of!((*ptr).magic)),
150 abi_version: core::ptr::read_unaligned(core::ptr::addr_of!((*ptr).abi_version)),
151 kernel_base: core::ptr::read_unaligned(core::ptr::addr_of!((*ptr).kernel_base)),
152 kernel_size: core::ptr::read_unaligned(core::ptr::addr_of!((*ptr).kernel_size)),
153 acpi_rsdp_base: core::ptr::read_unaligned(core::ptr::addr_of!((*ptr).acpi_rsdp_base)),
154 memory_map_base: core::ptr::read_unaligned(core::ptr::addr_of!((*ptr).memory_map_base)),
155 memory_map_size: core::ptr::read_unaligned(core::ptr::addr_of!((*ptr).memory_map_size)),
156 framebuffer_addr: core::ptr::read_unaligned(core::ptr::addr_of!(
157 (*ptr).framebuffer_addr
158 )),
159 hhdm_offset: core::ptr::read_unaligned(core::ptr::addr_of!((*ptr).hhdm_offset)),
160 cmdline_ptr: core::ptr::read_unaligned(core::ptr::addr_of!((*ptr).cmdline_ptr)),
161 cmdline_len: core::ptr::read_unaligned(core::ptr::addr_of!((*ptr).cmdline_len)),
162 modules_base: core::ptr::read_unaligned(core::ptr::addr_of!((*ptr).modules_base)),
163 modules_size: core::ptr::read_unaligned(core::ptr::addr_of!((*ptr).modules_size)),
164 framebuffer_width: core::ptr::read_unaligned(core::ptr::addr_of!(
165 (*ptr).framebuffer_width
166 )),
167 framebuffer_height: core::ptr::read_unaligned(core::ptr::addr_of!(
168 (*ptr).framebuffer_height
169 )),
170 framebuffer_stride: core::ptr::read_unaligned(core::ptr::addr_of!(
171 (*ptr).framebuffer_stride
172 )),
173 framebuffer_bpp: core::ptr::read_unaligned(core::ptr::addr_of!((*ptr).framebuffer_bpp)),
174 framebuffer_red_mask_size: core::ptr::read_unaligned(core::ptr::addr_of!(
175 (*ptr).framebuffer_red_mask_size
176 )),
177 framebuffer_red_mask_shift: core::ptr::read_unaligned(core::ptr::addr_of!(
178 (*ptr).framebuffer_red_mask_shift
179 )),
180 framebuffer_green_mask_size: core::ptr::read_unaligned(core::ptr::addr_of!(
181 (*ptr).framebuffer_green_mask_size
182 )),
183 framebuffer_green_mask_shift: core::ptr::read_unaligned(core::ptr::addr_of!(
184 (*ptr).framebuffer_green_mask_shift
185 )),
186 framebuffer_blue_mask_size: core::ptr::read_unaligned(core::ptr::addr_of!(
187 (*ptr).framebuffer_blue_mask_size
188 )),
189 framebuffer_blue_mask_shift: core::ptr::read_unaligned(core::ptr::addr_of!(
190 (*ptr).framebuffer_blue_mask_shift
191 )),
192 bss_virt_base: core::ptr::read_unaligned(core::ptr::addr_of!((*ptr).bss_virt_base)),
193 bss_virt_size: core::ptr::read_unaligned(core::ptr::addr_of!((*ptr).bss_virt_size)),
194 }
195 };
196
197 if args.magic != strat9_abi::boot::STRAT9_BOOT_MAGIC {
198 early_print(b"[kmain] ERROR: Bad KernelArgs magic: 0x");
199 early_print_hex(
200 unsafe { core::ptr::read_unaligned(core::ptr::addr_of!(args.magic)) } as u64,
201 );
202 early_print(b"\r\n");
203 hlt_loop();
204 }
205
206 let memory_map_base =
207 unsafe { core::ptr::read_unaligned(core::ptr::addr_of!(args.memory_map_base)) };
208 let memory_map_size =
209 unsafe { core::ptr::read_unaligned(core::ptr::addr_of!(args.memory_map_size)) };
210 let framebuffer_addr =
211 unsafe { core::ptr::read_unaligned(core::ptr::addr_of!(args.framebuffer_addr)) };
212 let acpi_rsdp_base =
213 unsafe { core::ptr::read_unaligned(core::ptr::addr_of!(args.acpi_rsdp_base)) };
214 early_print(b"[kmain] mmap=0x");
215 early_print_hex(memory_map_base);
216 early_print(b"/0x");
217 early_print_hex(memory_map_size);
218 early_print(b" fb=0x");
219 early_print_hex(framebuffer_addr);
220 early_print(b" rsdp=0x");
221 early_print_hex(acpi_rsdp_base);
222 early_print(b"\r\n");
223
224 crate::kernel_main(&args as *const _);
227}
228
229#[inline(always)]
231fn hlt_loop() -> ! {
232 loop {
233 unsafe {
234 core::arch::asm!("hlt", options(nomem, nostack, preserves_flags));
235 }
236 }
237}
238
239fn build_minimal_args() -> super::entry::KernelArgs {
241 super::entry::KernelArgs {
242 magic: strat9_abi::boot::STRAT9_BOOT_MAGIC,
243 abi_version: strat9_abi::boot::STRAT9_BOOT_ABI_VERSION,
244 kernel_base: 0,
245 kernel_size: 0,
246 acpi_rsdp_base: 0,
247 memory_map_base: 0,
248 memory_map_size: 0,
249 framebuffer_addr: 0,
250 framebuffer_width: 0,
251 framebuffer_height: 0,
252 framebuffer_stride: 0,
253 framebuffer_bpp: 0,
254 framebuffer_red_mask_size: 8,
255 framebuffer_red_mask_shift: 16,
256 framebuffer_green_mask_size: 8,
257 framebuffer_green_mask_shift: 8,
258 framebuffer_blue_mask_size: 8,
259 framebuffer_blue_mask_shift: 0,
260 hhdm_offset: 0,
261 cmdline_ptr: 0,
262 cmdline_len: 0,
263 modules_base: 0,
264 modules_size: 0,
265 bss_virt_base: 0,
266 bss_virt_size: 0,
267 }
268}