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