1#![no_std]
12#![no_main]
13#![feature(abi_x86_interrupt)]
14#![feature(alloc_error_handler)]
15#![feature(negative_impls)]
16#![feature(offset_of)]
17
18extern crate alloc;
19
20pub mod ostd;
22
23pub mod acpi;
24pub mod arch;
25pub mod audit;
26pub mod boot;
27pub mod capability;
28pub mod components;
29pub mod debug;
30pub mod debug_cfg;
31
32pub mod async_io;
33pub mod dma;
34pub mod entropy;
35pub mod framebuffer;
36pub mod hardware;
37pub mod ipc;
38pub mod memory;
39pub mod namespace;
40pub mod process;
41pub mod shell;
42pub mod silo;
43pub mod sync;
44pub mod syscall;
45pub mod trace;
46pub mod vfs;
47
48pub use boot::limine::kmain;
50
51pub fn init_serial() {
56 arch::x86_64::serial::init();
57}
58
59pub fn init_logger() {
61 boot::logger::init();
62}
63
64pub fn init_components(stage: component::InitStage) -> Result<(), component::ComponentInitError> {
69 component::init_all(stage)
70}
71
72use core::panic::PanicInfo;
73
74const PAGE_SIZE: u64 = 4096;
75const MAX_BOOT_MMAP_REGIONS_WORK: usize = 1024;
76
77const fn null_region() -> boot::entry::MemoryRegion {
79 boot::entry::MemoryRegion {
80 base: 0,
81 size: 0,
82 kind: boot::entry::MemoryKind::Reserved,
83 }
84}
85
86#[inline]
88const fn align_down(value: u64, align: u64) -> u64 {
89 value & !(align - 1)
90}
91
92#[inline]
94const fn align_up(value: u64, align: u64) -> u64 {
95 (value + align - 1) & !(align - 1)
96}
97
98#[inline]
100const fn virt_or_phys_to_phys(addr: u64, hhdm: u64) -> u64 {
101 if hhdm != 0 && addr >= hhdm {
102 addr - hhdm
103 } else {
104 addr
105 }
106}
107
108fn reserve_range_in_map(
110 map: &mut [boot::entry::MemoryRegion],
111 len: &mut usize,
112 reserve_start: u64,
113 reserve_end: u64,
114) {
115 if reserve_start >= reserve_end {
116 return;
117 }
118
119 let mut i = 0usize;
120 while i < *len {
121 let region = map[i];
122 if !matches!(
123 region.kind,
124 boot::entry::MemoryKind::Free | boot::entry::MemoryKind::Reclaim
125 ) {
126 i += 1;
127 continue;
128 }
129
130 let region_start = region.base;
131 let region_end = region.base.saturating_add(region.size);
132 if reserve_end <= region_start || reserve_start >= region_end {
133 i += 1;
134 continue;
135 }
136
137 let overlap_start = core::cmp::max(region_start, reserve_start);
138 let overlap_end = core::cmp::min(region_end, reserve_end);
139
140 if overlap_start <= region_start && overlap_end >= region_end {
141 map[i].kind = boot::entry::MemoryKind::Reserved;
142 i += 1;
143 continue;
144 }
145
146 if overlap_start <= region_start {
147 map[i].base = overlap_end;
148 map[i].size = region_end.saturating_sub(overlap_end);
149 i += 1;
150 continue;
151 }
152
153 if overlap_end >= region_end {
154 map[i].size = overlap_start.saturating_sub(region_start);
155 i += 1;
156 continue;
157 }
158
159 let left = boot::entry::MemoryRegion {
160 base: region_start,
161 size: overlap_start.saturating_sub(region_start),
162 kind: region.kind,
163 };
164 let right = boot::entry::MemoryRegion {
165 base: overlap_end,
166 size: region_end.saturating_sub(overlap_end),
167 kind: region.kind,
168 };
169
170 if *len + 1 > map.len() {
171 map[i] = left;
172 i += 1;
173 continue;
174 }
175
176 for j in (i + 1..*len).rev() {
177 map[j + 1] = map[j];
178 }
179 map[i] = left;
180 map[i + 1] = right;
181 *len += 1;
182 i += 2;
183 }
184}
185
186#[inline]
187fn count_free_like_regions(map: &[boot::entry::MemoryRegion], len: usize) -> usize {
188 map[..len]
189 .iter()
190 .filter(|region| {
191 matches!(
192 region.kind,
193 boot::entry::MemoryKind::Free | boot::entry::MemoryKind::Reclaim
194 )
195 })
196 .count()
197}
198
199#[cfg(feature = "selftest")]
201fn region_kind_for_addr(
202 map: &[boot::entry::MemoryRegion],
203 len: usize,
204 addr: u64,
205) -> Option<boot::entry::MemoryKind> {
206 map.iter().take(len).find_map(|r| {
207 let start = r.base;
208 let end = r.base.saturating_add(r.size);
209 if addr >= start && addr < end {
210 Some(r.kind)
211 } else {
212 None
213 }
214 })
215}
216
217#[panic_handler]
219fn panic_handler(info: &PanicInfo) -> ! {
220 boot::panic::panic_handler(info)
221}
222
223fn register_initfs_module(path: &str, module: Option<(u64, u64)>) {
225 let Some((base, size)) = module else {
226 return;
227 };
228 if base == 0 || size == 0 {
229 return;
230 }
231
232 let base_virt = memory::phys_to_virt(base) as *const u8;
233 let len = size as usize;
234 #[cfg(feature = "selftest")]
235 {
236 let data = unsafe { core::slice::from_raw_parts(base_virt, len.min(4)) };
238 if data.len() == 4 {
239 serial_println!(
240 "[init] /initfs/{} source magic={:02x}{:02x}{:02x}{:02x} size={}",
241 path,
242 data[0],
243 data[1],
244 data[2],
245 data[3],
246 size
247 );
248 }
249 }
250
251 if let Err(e) = vfs::register_initfs_file(path, base_virt, len) {
253 serial_println!("[init] Failed to register /initfs/{}: {:?}", path, e);
254 } else {
255 serial_println!("[init] Registered /initfs/{} ({} bytes)", path, size);
256 }
257}
258
259fn register_boot_initfs_modules(initfs_base: u64, initfs_size: u64) {
261 let boot_test_pid = if initfs_base != 0 && initfs_size != 0 {
262 Some((initfs_base, initfs_size))
263 } else {
264 None
265 };
266 let initfs_modules = [
267 ("test_pid", boot_test_pid),
268 ("test_syscalls", crate::boot::limine::test_syscalls_module()),
269 ("test_mem", crate::boot::limine::test_mem_module()),
270 (
271 "test_mem_stressed",
272 crate::boot::limine::test_mem_stressed_module(),
273 ),
274 (
275 "test_mem_region",
276 crate::boot::limine::test_mem_region_module(),
277 ),
278 (
279 "test_mem_region_proc",
280 crate::boot::limine::test_mem_region_proc_module(),
281 ),
282 ("test_exec", crate::boot::limine::test_exec_module()),
283 (
284 "test_exec_helper",
285 crate::boot::limine::test_exec_helper_module(),
286 ),
287 ("fs-ext4", crate::boot::limine::fs_ext4_module()),
288 (
289 "strate-fs-ramfs",
290 crate::boot::limine::strate_fs_ramfs_module(),
291 ),
292 ("init", crate::boot::limine::init_module()),
293 ("console-admin", crate::boot::limine::console_admin_module()),
294 ("strate-net", crate::boot::limine::strate_net_module()),
295 ("strate-bus", crate::boot::limine::strate_bus_module()),
296 ("bin/dhcp-client", crate::boot::limine::dhcp_client_module()),
297 ("bin/ping", crate::boot::limine::ping_module()),
298 ("bin/telnetd", crate::boot::limine::telnetd_module()),
299 ("bin/udp-tool", crate::boot::limine::udp_tool_module()),
300 ("bin/web-admin", crate::boot::limine::web_admin_module()),
301 ("strate-wasm", crate::boot::limine::strate_wasm_module()),
302 ("strate-webrtc", crate::boot::limine::strate_webrtc_module()),
303 ("bin/hello.wasm", crate::boot::limine::hello_wasm_module()),
304 (
305 "wasm-test.toml",
306 crate::boot::limine::wasm_test_toml_module(),
307 ),
308 ];
309 for (path, module) in initfs_modules {
310 register_initfs_module(path, module);
311 }
312}
313
314#[inline]
316fn boot_module_slice(base: u64, size: u64) -> &'static [u8] {
317 let base_virt = memory::phys_to_virt(base);
318 unsafe { core::slice::from_raw_parts(base_virt as *const u8, size as usize) }
319}
320
321#[cfg(feature = "selftest")]
323fn log_boot_module_magics(stage: &str) {
324 let modules = [
325 ("init", crate::boot::limine::init_module()),
326 ("console-admin", crate::boot::limine::console_admin_module()),
327 ("strate-net", crate::boot::limine::strate_net_module()),
328 ("strate-bus", crate::boot::limine::strate_bus_module()),
329 ("bin/dhcp-client", crate::boot::limine::dhcp_client_module()),
330 ("bin/ping", crate::boot::limine::ping_module()),
331 ("bin/telnetd", crate::boot::limine::telnetd_module()),
332 ("bin/udp-tool", crate::boot::limine::udp_tool_module()),
333 ("bin/web-admin", crate::boot::limine::web_admin_module()),
334 ("strate-wasm", crate::boot::limine::strate_wasm_module()),
335 ("strate-webrtc", crate::boot::limine::strate_webrtc_module()),
336 ("bin/hello.wasm", crate::boot::limine::hello_wasm_module()),
337 (
338 "wasm-test.toml",
339 crate::boot::limine::wasm_test_toml_module(),
340 ),
341 ];
342 for (name, module) in modules {
343 let Some((base, size)) = module else {
344 continue;
345 };
346 if size < 4 {
347 continue;
348 }
349 let ptr = memory::phys_to_virt(base) as *const u8;
350 let m0 = unsafe { core::ptr::read_volatile(ptr) };
351 let m1 = unsafe { core::ptr::read_volatile(ptr.add(1)) };
352 let m2 = unsafe { core::ptr::read_volatile(ptr.add(2)) };
353 let m3 = unsafe { core::ptr::read_volatile(ptr.add(3)) };
354 serial_println!(
355 "[init] Module magic [{}]: {} phys=0x{:x} magic={:02x}{:02x}{:02x}{:02x} size={}",
356 stage,
357 name,
358 base,
359 m0,
360 m1,
361 m2,
362 m3,
363 size
364 );
365 }
366}
367
368#[cfg(not(feature = "selftest"))]
370fn log_boot_module_magics(_stage: &str) {}
371
372pub unsafe fn kernel_main(args: *const boot::entry::KernelArgs) -> ! {
374 debug_assert!(
378 !arch::x86_64::interrupts_enabled(),
379 "interrupts must be disabled at boot entry"
380 );
381
382 arch::x86_64::boot_timestamp::init();
386 crate::e9_println!("B0 kernel_main");
387 init_serial();
388
389 arch::x86_64::serial::set_boot_log_prefix_enabled(true);
391
392 init_logger();
393 boot_milestone!("Kernel entry");
394 arch::x86_64::speaker::beep_phase(1);
395
396 crate::e9_println!("B1 pre-IDT");
402 serial_println!("[init] IDT (early)...");
403 arch::x86_64::idt::init();
404 serial_println!("[init] IDT initialized.");
405 crate::e9_println!("B2 post-IDT");
406 boot_milestone!("IDT initialized");
407
408 debug_assert!(
409 !arch::x86_64::interrupts_enabled(),
410 "interrupts must be disabled after IDT init"
411 );
412
413 crate::arch::x86_64::cpuid::init();
415
416 crate::e9_println!("B2a pre-cpu-extensions");
418 crate::arch::x86_64::init_cpu_extensions();
419 crate::e9_println!("B2b post-cpu-extensions");
420
421 crate::e9_println!("B2c pre-entropy");
423 crate::entropy::seed_from_rdrand();
424 crate::e9_println!("B2d post-entropy");
425
426 crate::e9_println!("B2e pre-panic-hooks");
429 boot::panic::install_default_panic_hooks();
430 crate::e9_println!("B2f post-panic-hooks");
431
432 serial_println!();
434 serial_println!();
435 serial_println!(r" __ __ ________ ");
436 serial_println!(r" _______/ |_____________ _/ |_/ __ \ ____ ______ ");
437 serial_println!(r" / ___/\ __\_ __ \__ \\ __\____ / ______ / _ \/ ___/ ");
438 serial_println!(r" \___ \ | | | | \// __ \| | / / /_____/ ( <_> )___ \ ");
439 serial_println!(r"/____ > |__| |__| (____ /__| /____/ \____/____ > ");
440 serial_println!(r" \/ \/ \/ ");
441 serial_println!();
442
443 serial_println!("");
444 serial_println!("=======================================================================================================");
445 serial_println!(" strat9-OS kernel v0.1.0 (Bedrock)");
446 serial_println!(" Copyright (c) 2024-26 Guillaume Gielly - GPLv3 License");
447 serial_println!("");
448 serial_println!(" This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY, without");
449 serial_println!(
450 " even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
451 );
452 serial_println!(" See the GNU General Public License for more details.");
453 serial_println!("=======================================================================================================");
454 serial_println!();
455
456 if args.is_null() {
458 serial_println!("[CRIT] No KernelArgs provided. System will hang.");
459 loop {
460 arch::x86_64::hlt();
461 }
462 }
463
464 let args = &*args;
465 serial_println!("[init] KernelArgs at {:p}", args);
466
467 if args.magic != strat9_abi::boot::STRAT9_BOOT_MAGIC {
468 serial_println!(
469 "[CRIT] Bad KernelArgs magic: 0x{:08x} (expected 0x{:08x})",
470 args.magic,
471 strat9_abi::boot::STRAT9_BOOT_MAGIC
472 );
473 loop {
474 arch::x86_64::hlt();
475 }
476 }
477 if args.abi_version != strat9_abi::boot::STRAT9_BOOT_ABI_VERSION {
478 serial_println!(
479 "[CRIT] Unsupported boot ABI version: {} (kernel expects {})",
480 args.abi_version,
481 strat9_abi::boot::STRAT9_BOOT_ABI_VERSION
482 );
483 loop {
484 arch::x86_64::hlt();
485 }
486 }
487
488 if args.cmdline_ptr != 0 && args.cmdline_len != 0 {
490 unsafe { arch::x86_64::serial::parse_cmdline(args.cmdline_ptr, args.cmdline_len) };
492 } else {
493 serial_println!("[init] No kernel cmdline provided");
494 }
495
496 let hhdm = args.hhdm_offset;
502 memory::set_hhdm_offset(hhdm);
503 serial_println!("[init] HHDM offset: 0x{:x}", hhdm);
504
505 serial_println!(
506 "[init] Memory map: 0x{:x} ({} bytes)",
507 args.memory_map_base,
508 args.memory_map_size
509 );
510
511 log_boot_module_magics("pre-mm");
512
513 serial_println!("[init] Memory manager...");
517 let mmap_ptr = args.memory_map_base as *const boot::entry::MemoryRegion;
518 let mmap_len =
519 args.memory_map_size as usize / core::mem::size_of::<boot::entry::MemoryRegion>();
520 let mmap = core::slice::from_raw_parts(mmap_ptr, mmap_len);
521 let mut mmap_work = [null_region(); MAX_BOOT_MMAP_REGIONS_WORK];
522 let mut mmap_work_len = core::cmp::min(mmap.len(), mmap_work.len());
523 for (dst, src) in mmap_work.iter_mut().zip(mmap.iter()).take(mmap_work_len) {
524 *dst = *src;
525 }
526
527 let reserve_modules = [
528 (
529 "test_pid",
530 if args.initfs_base != 0 && args.initfs_size != 0 {
531 Some((args.initfs_base, args.initfs_size))
532 } else {
533 None
534 },
535 ),
536 ("test_syscalls", crate::boot::limine::test_syscalls_module()),
537 ("test_mem", crate::boot::limine::test_mem_module()),
538 (
539 "test_mem_stressed",
540 crate::boot::limine::test_mem_stressed_module(),
541 ),
542 ("fs-ext4", crate::boot::limine::fs_ext4_module()),
543 (
544 "strate-fs-ramfs",
545 crate::boot::limine::strate_fs_ramfs_module(),
546 ),
547 ("init", crate::boot::limine::init_module()),
548 ("console-admin", crate::boot::limine::console_admin_module()),
549 ("strate-net", crate::boot::limine::strate_net_module()),
550 ("strate-bus", crate::boot::limine::strate_bus_module()),
551 ("bin/dhcp-client", crate::boot::limine::dhcp_client_module()),
552 ("bin/ping", crate::boot::limine::ping_module()),
553 ("bin/telnetd", crate::boot::limine::telnetd_module()),
554 ("bin/udp-tool", crate::boot::limine::udp_tool_module()),
555 ("strate-wasm", crate::boot::limine::strate_wasm_module()),
556 ("bin/hello.wasm", crate::boot::limine::hello_wasm_module()),
557 (
558 "wasm-test.toml",
559 crate::boot::limine::wasm_test_toml_module(),
560 ),
561 ];
562
563 let mut protected_ranges = [None; memory::boot_alloc::MAX_PROTECTED_RANGES];
564 for (idx, (_name, module)) in reserve_modules.iter().enumerate() {
565 if idx >= protected_ranges.len() {
566 break;
567 }
568 protected_ranges[idx] = *module;
569 }
570 memory::boot_alloc::set_protected_ranges(&protected_ranges);
571
572 memory::boot_alloc::init_boot_allocator(&mmap_work[..mmap_work_len]);
577 serial_println!("[init] Boot allocator ready.");
578
579 let total_ram = mmap_work[..mmap_work_len]
580 .iter()
581 .filter(|region| {
582 matches!(
583 region.kind,
584 boot::entry::MemoryKind::Free | boot::entry::MemoryKind::Reclaim
585 )
586 })
587 .map(|region| region.base.saturating_add(region.size))
588 .max()
589 .unwrap_or(0);
590 let free_like_regions = count_free_like_regions(&mmap_work, mmap_work_len);
591 let metadata_bytes = memory::frame::metadata_size_for(total_ram) as usize;
592 let boot_stats = memory::boot_alloc::boot_allocator_stats();
593 serial_println!(
594 "[init] Frame metadata plan: total_ram={:#x} free_regions={} bytes={} boot_free={} largest_boot_region={}",
595 total_ram,
596 free_like_regions,
597 metadata_bytes,
598 boot_stats.total_free_bytes as usize,
599 boot_stats.largest_region_bytes as usize,
600 );
601
602 {
603 let mut boot_alloc = memory::boot_alloc::get_boot_allocator().lock();
604 memory::frame::init_metadata_array(total_ram, &mut *boot_alloc);
605 }
606 serial_println!("[init] Frame metadata ready.");
607
608 for (_name, module) in reserve_modules {
609 let Some((base, size)) = module else {
610 continue;
611 };
612 if size == 0 {
613 continue;
614 }
615 let phys = virt_or_phys_to_phys(base, hhdm);
616 let reserve_start = align_down(phys, PAGE_SIZE);
617 let reserve_end = align_up(phys.saturating_add(size), PAGE_SIZE);
618 let before_regions = count_free_like_regions(&mmap_work, mmap_work_len);
619 reserve_range_in_map(
620 &mut mmap_work,
621 &mut mmap_work_len,
622 reserve_start,
623 reserve_end,
624 );
625 let after_regions = count_free_like_regions(&mmap_work, mmap_work_len);
626 serial_println!(
627 "[init] reserve_range_in_map: {} phys=0x{:x}..0x{:x} free_regions {} -> {}",
628 _name,
629 reserve_start,
630 reserve_end,
631 before_regions,
632 after_regions
633 );
634 #[cfg(feature = "selftest")]
635 {
636 serial_println!(
637 "[init] Reserved module pages: {} phys=0x{:x}..0x{:x}",
638 _name,
639 reserve_start,
640 reserve_end
641 );
642 let kind = region_kind_for_addr(&mmap_work, mmap_work_len, reserve_start);
643 serial_println!(
644 "[init] Module map kind: {} @0x{:x} => {:?}",
645 _name,
646 reserve_start,
647 kind
648 );
649 }
650 }
651
652 memory::buddy::init_buddy_allocator(&mmap_work[..mmap_work_len]);
653
654 serial_println!("[init] Buddy allocator ready.");
655
656 memory::vmalloc::init();
658 serial_println!("[init] Vmalloc arena ready.");
659
660 debug_assert!(
661 !arch::x86_64::interrupts_enabled(),
662 "interrupts must be disabled after buddy allocator init"
663 );
664
665 boot_milestone!("Memory manager ready");
666 arch::x86_64::speaker::beep_phase(2);
667 log_boot_module_magics("post-buddy");
668
669 crate::e9_println!("B5 pre-paging");
673 serial_println!("[init] Paging...");
674 memory::paging::init(hhdm);
675 crate::e9_println!("B6 post-paging");
676
677 memory::paging::map_all_ram(&mmap_work[..mmap_work_len]);
680
681 if args.framebuffer_addr != 0 && args.framebuffer_stride != 0 && args.framebuffer_height != 0 {
685 let fb_phys = if args.framebuffer_addr >= hhdm {
686 args.framebuffer_addr - hhdm
687 } else {
688 args.framebuffer_addr
689 };
690 let fb_size =
691 (args.framebuffer_stride as u64).saturating_mul(args.framebuffer_height as u64);
692 memory::paging::ensure_identity_map_range(fb_phys, fb_size);
693 serial_println!(
694 "[init] Framebuffer mapped: phys=0x{:x} size={} bytes",
695 fb_phys,
696 fb_size
697 );
698 }
699 serial_println!("[init] Paging initialized.");
700 boot_milestone!("Paging initialized");
701 arch::x86_64::speaker::beep_phase(3);
702
703 serial_println!("[init] Console...");
707 arch::x86_64::vga::init(
708 args.framebuffer_addr,
709 args.framebuffer_width,
710 args.framebuffer_height,
711 args.framebuffer_stride,
712 args.framebuffer_bpp,
713 args.framebuffer_red_mask_size,
714 args.framebuffer_red_mask_shift,
715 args.framebuffer_green_mask_size,
716 args.framebuffer_green_mask_shift,
717 args.framebuffer_blue_mask_size,
718 args.framebuffer_blue_mask_shift,
719 );
720 arch::x86_64::vgabuf::vgabuf_flush_to_framebuffer();
722 vga_println!("[OK] Paging initialized");
723 vga_println!("[OK] Serial port initialized");
724 vga_println!("[OK] Memory manager active");
725
726 serial_println!("[init] TSS...");
730 vga_println!("[..] Initializing TSS...");
731 arch::x86_64::tss::init();
732 serial_println!("[init] TSS initialized.");
733 vga_println!("[OK] TSS initialized");
734
735 serial_println!("[init] GDT...");
739 vga_println!("[..] Initializing GDT...");
740 arch::x86_64::gdt::init();
741 serial_println!("[init] GDT initialized.");
742 vga_println!("[OK] GDT loaded (with TSS)");
743
744 serial_println!("[init] SYSCALL/SYSRET...");
748 vga_println!("[..] Initializing SYSCALL/SYSRET...");
749 arch::x86_64::syscall::init();
750 serial_println!("[init] SYSCALL/SYSRET initialized.");
751 vga_println!("[OK] SYSCALL/SYSRET configured");
752
753 serial_println!("[init] Components (bootstrap)...");
757 vga_println!("[..] Initializing bootstrap components...");
758 if let Err(e) = component::init_all(component::InitStage::Bootstrap) {
759 serial_println!("[WARN] Some bootstrap components failed: {:?}", e);
760 }
761 serial_println!("[init] Bootstrap components initialized.");
762 vga_println!("[OK] Bootstrap components ready");
763
764 log_boot_module_magics("post-paging");
773
774 serial_println!("[init] Kernel address space...");
778 vga_println!("[..] Initializing kernel address space...");
779 memory::address_space::init_kernel_address_space();
780 serial_println!("[init] Kernel address space initialized.");
781 debug_assert!(
782 !arch::x86_64::interrupts_enabled(),
783 "interrupts must be disabled after kernel address space init"
784 );
785 vga_println!("[OK] Kernel address space initialized");
786 log_boot_module_magics("post-kas");
787
788 serial_println!("[init] VFS...");
792 vga_println!("[..] Initializing virtual file system...");
793
794 vfs::init();
795
796 serial_println!("[init] VFS initialized.");
797 vga_println!("[OK] VFS initialized");
798 register_boot_initfs_modules(args.initfs_base, args.initfs_size);
799
800 log_boot_module_magics("post-cow");
801
802 serial_println!("[init] Interrupt controller...");
806 vga_println!("[..] Initializing interrupt controller...");
807
808 memory::paging::ensure_identity_map(args.acpi_rsdp_base);
810
811 let rsdp_virt = memory::phys_to_virt(args.acpi_rsdp_base);
812 let apic_active = init_apic_subsystem(rsdp_virt);
813
814 if !apic_active {
815 serial_println!("[init] APIC unavailable, falling back to legacy PIC");
817 vga_println!("[..] Falling back to legacy PIC...");
818 arch::x86_64::pic::init(
819 arch::x86_64::pic::PIC1_OFFSET,
820 arch::x86_64::pic::PIC2_OFFSET,
821 );
822 arch::x86_64::pic::disable();
823 arch::x86_64::pic::enable_irq(0); arch::x86_64::pic::enable_irq(1); serial_println!("[init] Legacy PIC initialized.");
826 vga_println!("[OK] Legacy PIC initialized (IRQ0: timer, IRQ1: keyboard)");
827 } else {
828 serial_println!("[init] APIC subsystem initialized.");
829 vga_println!("[OK] APIC + I/O APIC + APIC timer active");
830 }
831
832 if apic_active {
834 arch::x86_64::tlb::init();
835 serial_println!("[init] TLB shootdown system initialized.");
836 debug_assert!(
837 !arch::x86_64::interrupts_enabled(),
838 "interrupts must be disabled after TLB init"
839 );
840 }
841
842 if apic_active {
846 let bsp_apic_id = arch::x86_64::apic::lapic_id();
847 arch::x86_64::percpu::init_boot_cpu(bsp_apic_id);
848 arch::x86_64::percpu::init_gs_base(0);
849 serial_println!("[init] SMP: booting secondary cores...");
850 vga_println!("[..] SMP: starting APs...");
851
852 match arch::x86_64::smp::init() {
853 Ok(count) => {
854 serial_println!("[init] SMP: {} core(s) online", count);
855 vga_println!("[OK] SMP: {} core(s) online", count);
856 }
857 Err(e) => {
858 serial_println!("[init] SMP init failed: {}", e);
859 vga_println!("[WARN] SMP init failed: {}", e);
860 }
861 }
862 } else {
863 arch::x86_64::percpu::init_boot_cpu(0);
864 }
865 boot_milestone!("APIC + SMP ready");
866 arch::x86_64::speaker::beep_phase(4);
867
868 arch::x86_64::keyboard::init();
869 serial_println!("[init] PS/2 keyboard controller initialized.");
870
871 if apic_active {
875 let mouse_ok = arch::x86_64::mouse::init();
876
877 if mouse_ok {
878 serial_println!("[init] PS/2 mouse initialized.");
879 vga_println!("[OK] PS/2 mouse ready");
880 } else {
881 serial_println!("[init] PS/2 mouse not found (optional).");
882 }
883 }
884
885 crate::e9_println!("B7 pre-sched");
889 serial_println!("[init] Initializing scheduler...");
890 vga_println!("[..] Setting up multitasking...");
891 crate::process::task::Task::debug_print_layout();
893 process::init_scheduler();
894 crate::e9_println!("B8 post-sched");
895
896 debug_assert!(
897 !arch::x86_64::interrupts_enabled(),
898 "interrupts must be disabled after scheduler init"
899 );
900
901 if apic_active {
907 debug_assert!(
908 !arch::x86_64::interrupts_enabled(),
909 "interrupts must be disabled before APIC timer start"
910 );
911 serial_println!("[init] Starting APIC timer on BSP...");
912 arch::x86_64::timer::start_apic_timer_cached();
913 }
914
915 serial_println!("[init] Scheduler initialized.");
916 serial_println!("[trace][bsp] after init_scheduler");
917 boot_milestone!("Scheduler + timer ready");
918 arch::x86_64::speaker::beep_phase(5);
919 vga_println!("[OK] Multitasking enabled");
920
921 crate::e9_println!("B9 pre-kthread");
925 serial_println!("[trace][bsp] before kthread init_all");
926 serial_println!("[init] Components (kthread)...");
927 vga_println!("[..] Initializing kthread components...");
928
929 if let Err(e) = component::init_all(component::InitStage::Kthread) {
930 serial_println!("[WARN] Some kthread components failed: {:?}", e);
931 }
932
933 serial_println!("[trace][bsp] after kthread init_all");
934 serial_println!("[init] Kthread components initialized.");
935 vga_println!("[OK] Kthread components ready");
936
937 #[cfg(feature = "selftest")]
938 {
939 serial_println!("[init] Creating self-test tasks...");
943 vga_println!("[..] Adding self-test tasks...");
944 process::selftest::create_selftest_tasks();
945 serial_println!("[init] Self-test tasks created.");
946 vga_println!("[OK] Self-test tasks added");
947 }
948
949 #[cfg(not(feature = "selftest"))]
953 {
954 let mut init_task_id: Option<crate::process::TaskId> = None;
958
959 crate::e9_println!("BB pre-process");
960 serial_println!("[init] Components (process)...");
961 vga_println!("[..] Initializing process components...");
962 if let Err(e) = component::init_all(component::InitStage::Process) {
963 serial_println!("[WARN] Some process components failed: {:?}", e);
964 }
965 serial_println!("[init] Process components initialized.");
966 vga_println!("[OK] Process components ready");
967
968 crate::e9_println!("BG pre-hardware");
976 serial_println!("[init] Loading hardware drivers...");
977 vga_println!("[..] Initializing hardware drivers...");
978 hardware::init();
979 crate::e9_println!("BH post-hardware");
980 boot_milestone!("Hardware drivers ready");
981 arch::x86_64::speaker::beep_phase(15);
982 arch::x86_64::speaker::beep_phase(6);
983
984 serial_println!("[init] Initializing timers...");
985 vga_println!("[..] Initializing HPET and RTC...");
986 hardware::timer::init();
987 serial_println!("[init] Timers initialized.");
988 vga_println!("[OK] HPET/RTC initialized");
989 arch::x86_64::speaker::beep_phase(16); serial_println!("[init] Initializing USB...");
992 vga_println!("[..] Looking for USB controllers...");
993 hardware::usb::init();
994 serial_println!("[init] USB initialized.");
995 vga_println!("[OK] USB xHCI/EHCI/UHCI initialized");
996 arch::x86_64::speaker::beep_phase(17); serial_println!("[init] Initializing VirtIO block...");
999 vga_println!("[..] Looking for VirtIO block device...");
1000 hardware::storage::virtio_block::init();
1001 serial_println!("[init] VirtIO block initialized.");
1002 vga_println!("[OK] VirtIO block driver initialized");
1003 arch::x86_64::speaker::beep_phase(18); serial_println!("[init] Initializing AHCI...");
1006 vga_println!("[..] Looking for AHCI SATA controller...");
1007 {
1009 let dummy = 0u64;
1010 let rsp = &dummy as *const u64 as u64;
1011 serial_println!("[DEBUG] BSP stack before AHCI: rsp={:#x}", rsp);
1012 if rsp < 0xC0000 {
1016 serial_println!("[WARN] BSP stack usage high! rsp={:#x}", rsp);
1017 }
1018 }
1019 hardware::storage::ahci::init();
1020 serial_println!("[init] AHCI probe done.");
1021 vga_println!("[OK] AHCI probe done");
1022 arch::x86_64::speaker::beep_phase(19); serial_println!("[init] Initializing ATA/IDE...");
1025 vga_println!("[..] Looking for ATA/IDE devices...");
1026 hardware::storage::ata_legacy::init();
1027 serial_println!("[init] ATA/IDE probe done.");
1028 vga_println!("[OK] ATA/IDE probe done");
1029 arch::x86_64::speaker::beep_phase(20); serial_println!("[init] Initializing NVMe...");
1032 vga_println!("[..] Looking for NVMe controllers...");
1033 hardware::storage::nvme::init();
1034 serial_println!("[init] NVMe probe done.");
1035 vga_println!("[OK] NVMe probe done");
1036 arch::x86_64::speaker::beep_phase(21); serial_println!("[init] Initializing VirtIO net...");
1039 vga_println!("[..] Looking for VirtIO net device...");
1040 hardware::nic::virtio_net::init();
1041 serial_println!("[init] VirtIO net initialized.");
1042 vga_println!("[OK] VirtIO net driver initialized");
1043 arch::x86_64::speaker::beep_phase(22); serial_println!("[init] Initializing VirtIO RNG...");
1046 vga_println!("[..] Looking for VirtIO RNG device...");
1047 crate::hardware::virtio::rng::init();
1048 serial_println!("[init] VirtIO RNG initialized.");
1049 vga_println!("[OK] VirtIO RNG driver initialized");
1050 arch::x86_64::speaker::beep_phase(23); serial_println!("[init] Initializing VirtIO Console...");
1053 vga_println!("[..] Looking for VirtIO Console device...");
1054 crate::hardware::virtio::console::init();
1055 serial_println!("[init] VirtIO Console initialized.");
1056 vga_println!("[OK] VirtIO Console driver initialized");
1057 arch::x86_64::speaker::beep_phase(24); serial_println!("[init] Checking for devices...");
1062 vga_println!("[..] Checking for devices...");
1063
1064 if let Some(blk) = hardware::storage::virtio_block::get_device() {
1065 use hardware::storage::virtio_block::BlockDevice;
1066 serial_println!(
1067 "[INFO] VirtIO block device found. Capacity: {} sectors",
1068 blk.sector_count()
1069 );
1070 vga_println!("[OK] VirtIO block driver loaded");
1071 } else {
1072 serial_println!("[WARN] No VirtIO block device found");
1073 vga_println!("[WARN] No VirtIO block device found");
1074 }
1075
1076 if let Some(ahci) = hardware::storage::ahci::get_device() {
1077 serial_println!(
1078 "[INFO] AHCI SATA device found. Capacity: {} sectors ({} MiB)",
1079 ahci.sector_count(),
1080 (ahci.sector_count() * 512) / 1048576, );
1082 vga_println!("[OK] AHCI SATA driver loaded");
1083 } else {
1084 serial_println!("[INFO] No AHCI SATA device found");
1085 }
1086
1087 if let Some(nvme) = hardware::storage::nvme::get_first_controller() {
1088 let nvme = nvme.lock();
1089 if let Some(ns) = nvme.get_namespace(0) {
1090 serial_println!(
1091 "[INFO] NVMe device found. Namespace {} - {} blocks @ {} bytes ({} MiB)",
1092 ns.nsid,
1093 ns.size,
1094 ns.block_size,
1095 (ns.size * ns.block_size as u64) / 1048576, );
1097 vga_println!("[OK] NVMe driver loaded");
1098 }
1099 } else {
1100 serial_println!("[INFO] No NVMe device found");
1101 }
1102
1103 {
1105 let ifaces = hardware::nic::list_interfaces();
1106 if ifaces.is_empty() {
1107 serial_println!("[WARN] No network devices found");
1108 vga_println!("[WARN] No network devices found");
1109 } else {
1110 for name in &ifaces {
1111 if let Some(dev) = hardware::nic::get_device(name) {
1112 let mac = dev.mac_address();
1113 serial_println!(
1114 "[INFO] Network {} ({}) MAC {:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x} link={}",
1115 name, dev.name(),
1116 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
1117 if dev.link_up() { "up" } else { "down" },
1118 );
1119 vga_println!("[OK] Network {} ({}) loaded", name, dev.name());
1120 }
1121 }
1122 }
1123 }
1124
1125 serial_println!("[init] Storage verification skipped (boot path)");
1126 vga_println!("[..] Storage verification skipped at boot");
1127
1128 let mut init_loaded = false;
1132
1133 if let Some((base, size)) = crate::boot::limine::init_module() {
1134 let elf_data = boot_module_slice(base, size);
1135 let init_caps = [crate::silo::create_silo_admin_capability()];
1136 match process::elf::load_and_run_elf_with_caps(elf_data, "init", &init_caps) {
1137 Ok(task_id) => {
1138 init_task_id = Some(task_id);
1139 init_loaded = true;
1140 serial_println!("[init] ELF '/initfs/init' loaded as task 'init'.");
1141 }
1142 Err(e) => {
1143 serial_println!("[init] Failed to load init ELF: {}; trying fallback.", e);
1144 }
1145 }
1146 }
1147
1148 if !init_loaded && args.initfs_base != 0 && args.initfs_size != 0 {
1149 let elf_data = boot_module_slice(args.initfs_base, args.initfs_size);
1150 let init_caps = [crate::silo::create_silo_admin_capability()];
1151 match process::elf::load_and_run_elf_with_caps(elf_data, "init", &init_caps) {
1152 Ok(task_id) => {
1153 init_task_id = Some(task_id);
1154 serial_println!(
1155 "[init] ELF '/initfs/test_pid' loaded as task 'init' (fallback)."
1156 );
1157 }
1158 Err(e) => {
1159 serial_println!("[init] Failed to load test_pid ELF: {}", e);
1160 }
1161 }
1162 }
1163 if let Some((base, size)) = crate::boot::limine::strate_fs_ramfs_module() {
1164 let ram_data = boot_module_slice(base, size);
1165 match process::elf::load_elf_task_with_caps(ram_data, "strate-fs-ramfs", &[]) {
1166 Ok(task) => {
1167 let task_id = task.id;
1168 crate::serial_force_println!(
1169 "[trace][boot] before register_boot_strate_task tid={} label=ramfs-default",
1170 task_id.as_u64()
1171 );
1172 let reg_res = crate::silo::register_boot_strate_task(task_id, "ramfs-default");
1173 crate::serial_force_println!(
1174 "[trace][boot] marker: returned from register_boot_strate_task"
1175 );
1176 if let Err(e) = reg_res {
1177 crate::serial_force_println!(
1178 "[trace][boot] register_boot_strate_task failed tid={} err={:?}",
1179 task_id.as_u64(),
1180 e
1181 );
1182 } else {
1183 crate::serial_force_println!(
1184 "[trace][boot] register_boot_strate_task ok tid={}",
1185 task_id.as_u64()
1186 );
1187 }
1188 crate::serial_force_println!(
1189 "[trace][boot] before add_task tid={} name=strate-fs-ramfs",
1190 task_id.as_u64()
1191 );
1192 process::add_task(task);
1193 crate::serial_force_println!(
1194 "[trace][boot] after add_task tid={} name=strate-fs-ramfs",
1195 task_id.as_u64()
1196 );
1197 serial_println!("[init] Component 'strate-fs-ramfs' loaded.");
1198 }
1199 Err(e) => serial_println!("[init] Failed to load strate-fs-ramfs component: {}", e),
1200 }
1201 }
1202 if let Some((base, size)) = crate::boot::limine::fs_ext4_module() {
1203 let ext4_data = boot_module_slice(base, size);
1204 match process::elf::load_elf_task_with_caps(ext4_data, "strate-fs-ext4", &[]) {
1205 Ok(task) => {
1206 let task_id = task.id;
1207 crate::serial_force_println!(
1208 "[trace][boot] before register_boot_strate_task tid={} label=ext4-default",
1209 task_id.as_u64()
1210 );
1211 if let Err(e) = crate::silo::register_boot_strate_task(task_id, "ext4-default")
1212 {
1213 crate::serial_force_println!(
1214 "[trace][boot] register_boot_strate_task failed tid={} err={:?}",
1215 task_id.as_u64(),
1216 e
1217 );
1218 } else {
1219 crate::serial_force_println!(
1220 "[trace][boot] register_boot_strate_task ok tid={}",
1221 task_id.as_u64()
1222 );
1223 }
1224 crate::serial_force_println!(
1225 "[trace][boot] before add_task tid={} name=strate-fs-ext4",
1226 task_id.as_u64()
1227 );
1228 process::add_task(task);
1229 crate::serial_force_println!(
1230 "[trace][boot] after add_task tid={} name=strate-fs-ext4",
1231 task_id.as_u64()
1232 );
1233 serial_println!("[init] Component 'strate-fs-ext4' loaded.");
1234 }
1235 Err(e) => serial_println!("[init] Failed to load strate-fs-ext4 component: {}", e),
1236 }
1237 }
1238 if let (Some(task_id), Some(device)) =
1239 (init_task_id, hardware::storage::virtio_block::get_device())
1240 {
1241 if let Some(task) = crate::process::get_task_by_id(task_id) {
1242 let cap = crate::capability::get_capability_manager().create_capability(
1243 crate::capability::ResourceType::Volume,
1244 device as *const _ as usize,
1245 crate::capability::CapPermissions {
1246 read: true,
1247 write: true,
1248 execute: false,
1249 grant: true,
1250 revoke: true,
1251 },
1252 );
1253 unsafe { (&mut *task.process.capabilities.get()).insert(cap) };
1254 serial_println!("[init] Granted volume capability to init");
1255 }
1256 }
1257
1258 match process::Task::new_kernel_task_with_stack(
1259 shell::shell_main,
1260 "chevron-shell",
1261 process::TaskPriority::Normal,
1262 64 * 1024,
1263 ) {
1264 Ok(shell_task) => {
1265 process::add_task(shell_task);
1266 serial_println!("[init] Chevron shell ready.");
1267 }
1268 Err(e) => {
1269 serial_println!("[WARN] Failed to create shell task: {}", e);
1270 }
1271 }
1272 if let Ok(status_task) = process::Task::new_kernel_task_with_stack(
1273 arch::x86_64::vga::status_line_task_main,
1274 "status-line",
1275 process::TaskPriority::Low,
1276 64 * 1024,
1277 ) {
1278 process::add_task(status_task);
1279 crate::debug_cfg::set_vga_debug_live(false);
1282 }
1283 }
1284 #[cfg(feature = "selftest")]
1285 {
1286 serial_println!("[init] Selftest mode: skipping process services and virtio drivers");
1287 }
1288
1289 crate::arch::x86_64::keyboard_layout::set_french_layout();
1291
1292 if apic_active {
1296 arch::x86_64::smp::open_ap_scheduler_gate();
1297 }
1298 crate::e9_println!("BC pre-schedule");
1299 boot_milestone!("Boot complete ! Now entering in scheduler");
1300 arch::x86_64::speaker::beep_startup();
1301 serial_println!("[init] Boot complete. Starting preemptive scheduler...");
1302 vga_println!("[OK] Starting multitasking (preemptive)");
1303 arch::x86_64::serial::set_boot_log_prefix_enabled(false);
1304
1305 serial_force_println!("[trace][bsp] schedule start (never returns)");
1311 process::schedule();
1312}
1313
1314fn init_apic_subsystem(rsdp_vaddr: u64) -> bool {
1319 use arch::x86_64::{apic, ioapic, pic, timer};
1320 use timer::TIMER_HZ;
1321
1322 if !apic::is_present() {
1324 log::warn!("APIC: not present (CPUID)");
1325 return false;
1326 }
1327 serial_println!("[init] 6a. APIC present (CPUID)");
1328
1329 match acpi::init(rsdp_vaddr) {
1331 Ok(true) => {}
1332 Ok(false) => {
1333 log::warn!("APIC: no RSDP from bootloader");
1334 return false;
1335 }
1336 Err(e) => {
1337 log::warn!("APIC: ACPI init failed: {}", e);
1338 return false;
1339 }
1340 }
1341 serial_println!("[init] 6b. ACPI RSDP validated");
1342
1343 let madt_info = match acpi::madt::parse_madt() {
1345 Some(info) => info,
1346 None => {
1347 log::warn!("APIC: MADT not found");
1348 return false;
1349 }
1350 };
1351 serial_println!("[init] 6c. MADT parsed");
1352
1353 if let Some(mcfg) = acpi::mcfg::parse_mcfg() {
1354 serial_println!(
1355 "[init] 6c+. MCFG parsed ({} segment(s))",
1356 mcfg.entries.len()
1357 );
1358 for entry in mcfg.entries.iter() {
1359 log::info!(
1360 "ACPI: MCFG seg={} ecam={:#x} buses={}..{} ({} bus(es))",
1361 entry.segment_group,
1362 entry.base_address,
1363 entry.start_bus,
1364 entry.end_bus,
1365 entry.bus_count()
1366 );
1367 }
1368 } else {
1369 serial_println!("[init] 6c+. MCFG not found");
1370 }
1371
1372 memory::paging::ensure_identity_map(madt_info.local_apic_address as u64);
1375 apic::init(madt_info.local_apic_address);
1376 serial_println!("[init] 6d. Local APIC initialized");
1377
1378 if madt_info.io_apic_count == 0 {
1380 log::warn!("APIC: no I/O APIC in MADT");
1381 return false;
1382 }
1383 let Some(io_apic_entry) = madt_info.io_apics[0] else {
1384 log::warn!("APIC: MADT I/O APIC entry[0] missing");
1385 return false;
1386 };
1387 memory::paging::ensure_identity_map(io_apic_entry.address as u64);
1389 ioapic::init(io_apic_entry.address, io_apic_entry.gsi_base);
1390 serial_println!("[init] 6e. I/O APIC initialized");
1391
1392 pic::init(pic::PIC1_OFFSET, pic::PIC2_OFFSET);
1398 pic::disable_permanently();
1399 pic::enable_irq(1);
1400 pic::enable_irq(2);
1401 pic::enable_irq(12);
1402 serial_println!("[init] 6f. Legacy PIC remapped; PS/2 IRQ1/IRQ12 left enabled");
1403
1404 let lapic_id = apic::lapic_id();
1407 ioapic::route_legacy_irq(0, lapic_id, 0x20, &madt_info.overrides);
1408 ioapic::mask_legacy_irq(1, &madt_info.overrides);
1409 ioapic::mask_legacy_irq(12, &madt_info.overrides);
1410
1411 ioapic::store_madt_overrides(&madt_info.overrides);
1413
1414 serial_println!("[init] 6g. IRQ0->vec 0x20 via IOAPIC; IRQ1/IRQ12 via PIC");
1415
1416 serial_println!("[init] 6h. Calibrating APIC timer using PIT channel 2...");
1418 serial_println!(
1419 "[timer] ================================ TIMER INIT ================================"
1420 );
1421
1422 let ticks_per_10ms = timer::calibrate_apic_timer();
1423
1424 if ticks_per_10ms == 0 {
1425 log::error!("APIC: timer calibration FAILED");
1426 log::warn!("Falling back to legacy PIT timer at 100Hz");
1427
1428 serial_println!("[timer] APIC calibration failed, initializing PIT fallback...");
1431 timer::init_pit(TIMER_HZ as u32);
1432 serial_println!(
1433 "[timer] PIT initialized at {}Hz ({} ms/tick)",
1434 TIMER_HZ,
1435 1_000 / TIMER_HZ
1436 );
1437 serial_println!("[init] 6h. PIT timer initialized (fallback)");
1438
1439 serial_println!("[timer] ============================= TIMER INIT COMPLETE ============================");
1440 serial_println!("[timer] Mode: PIT (legacy fallback)");
1441 serial_println!("[timer] Frequency: {}Hz", TIMER_HZ);
1442 serial_println!("[timer] Interval: {} ms per tick", 1_000 / TIMER_HZ);
1443 serial_println!(
1444 "[timer] =========================================================================="
1445 );
1446
1447 } else {
1450 serial_println!("[init] 6h. APIC timer calibrated successfully");
1451
1452 timer::stop_pit();
1458 ioapic::mask_legacy_irq(0, &madt_info.overrides);
1459 serial_println!("[init] 6i+. Legacy PIT stopped and masked in IOAPIC");
1460
1461 serial_println!("[timer] ============================= TIMER INIT COMPLETE ============================");
1462 serial_println!("[timer] Mode: APIC (native)");
1463 serial_println!("[timer] Frequency: {}Hz", TIMER_HZ);
1464 serial_println!("[timer] Interval: {} ms per tick", 1_000 / TIMER_HZ);
1465 serial_println!("[timer] Ticks per 10ms: {}", ticks_per_10ms);
1466 serial_println!(
1467 "[timer] =========================================================================="
1468 );
1469 }
1470
1471 true
1472}