1#[cfg(target_arch = "x86_64")]
7use crate::virt;
8use crate::{
9 arch, audio, cap, desktop, error::KernelResult, fs, graphics, ipc, irq, mm, net, perf, pkg,
10 process, sched, security, services, timer, video,
11};
12
13#[cfg(feature = "alloc")]
14extern crate alloc;
15
16#[macro_export]
33macro_rules! define_bootstrap_stages {
34 ($print_fn:ident) => {
35 pub fn stage1_start() {
36 $print_fn!("[BOOTSTRAP] Starting multi-stage kernel initialization...");
37 $print_fn!("[BOOTSTRAP] Stage 1: Hardware initialization");
38 }
39
40 pub fn stage1_complete() {
41 $print_fn!("[BOOTSTRAP] Architecture initialized");
42 }
43
44 pub fn stage2_start() {
45 $print_fn!("[BOOTSTRAP] Stage 2: Memory management");
46 }
47
48 pub fn stage2_complete() {
49 $print_fn!("[BOOTSTRAP] Memory management initialized");
50 }
51
52 pub fn stage3_start() {
53 $print_fn!("[BOOTSTRAP] Stage 3: Process management");
54 }
55
56 pub fn stage3_complete() {
57 $print_fn!("[BOOTSTRAP] Process management initialized");
58 }
59
60 pub fn stage4_start() {
61 $print_fn!("[BOOTSTRAP] Stage 4: Kernel services");
62 }
63
64 pub fn stage4_complete() {
65 $print_fn!("[BOOTSTRAP] Core services initialized");
66 }
67
68 pub fn stage5_start() {
69 $print_fn!("[BOOTSTRAP] Stage 5: Scheduler activation");
70 }
71
72 pub fn stage5_complete() {
73 $print_fn!("[BOOTSTRAP] Scheduler activated - entering main scheduling loop");
74 }
75
76 pub fn stage6_start() {
77 $print_fn!("[BOOTSTRAP] Stage 6: User space transition");
78 }
79
80 pub fn stage6_complete() {
81 $print_fn!("[BOOTSTRAP] User space transition prepared");
82 $print_fn!("[KERNEL] Boot sequence complete!");
83 $print_fn!("BOOTOK");
84 }
85 };
86}
87
88pub const BOOTSTRAP_PID: u64 = 0;
90pub const BOOTSTRAP_TID: u64 = 0;
91
92#[cfg(target_arch = "x86_64")]
107fn switch_to_heap_stack(size: usize) {
108 use alloc::vec;
109
110 let stack_mem = vec![0u8; size];
112 let stack_top = stack_mem.as_ptr() as usize + size;
113
114 core::mem::forget(stack_mem);
116
117 let stack_top_aligned = stack_top & !0xF;
119
120 kprintln!(
121 "[BOOTSTRAP] Switching to heap stack ({} KB at {:#x})",
122 size / 1024,
123 stack_top_aligned
124 );
125
126 unsafe {
131 core::arch::asm!(
132 "mov rsp, {0}",
133 "call {1}",
134 in(reg) stack_top_aligned,
135 sym kernel_init_stage3_onwards,
136 options(noreturn)
137 );
138 }
139}
140
141#[cfg(target_arch = "x86_64")]
147extern "C" fn kernel_init_stage3_onwards() -> ! {
148 if let Err(e) = kernel_init_stage3_impl() {
149 crate::println!("[BOOTSTRAP] FATAL: Stage 3+ init failed: {:?}", e);
150 loop {
151 unsafe {
154 core::arch::asm!("hlt", options(nomem, nostack));
155 }
156 }
157 }
158
159 kprintln!("[BOOTSTRAP] Stage 6: User space transition");
161 kprintln!("[BOOTSTRAP] About to create init process...");
162 create_init_process();
163 kprintln!("[BOOTSTRAP] Init process created");
164 kprintln!("[BOOTSTRAP] User space transition prepared");
165 kprintln!("[KERNEL] Boot sequence complete!");
166 kprintln!("BOOTOK");
167
168 kprintln!("[BOOTSTRAP] User-mode entry available (Ring 3 via iretq)");
174 kprintln!("[BOOTSTRAP] Skipping Ring 3 transition for interactive shell");
175
176 #[cfg(target_arch = "x86_64")]
180 {
181 arch::x86_64::enable_keyboard_irq();
182 arch::x86_64::enable_timer_irq();
183 arch::x86_64::enable_interrupts();
184 kprintln!("[BOOTSTRAP] Keyboard IRQ + interrupts enabled");
185 }
186
187 graphics::fbcon::enable_output();
191
192 #[cfg(all(feature = "alloc", target_arch = "x86_64"))]
196 {
197 let vfs = crate::fs::get_vfs().read();
198 let has_sh = vfs.resolve_path("/bin/sh").is_ok();
199 drop(vfs);
200 if has_sh {
201 kprintln!("[BOOTSTRAP] BusyBox ash available at /bin/sh (run 'ash' from vsh)");
202 }
203 }
204
205 #[cfg(feature = "alloc")]
208 {
209 kprintln!("[BOOTSTRAP] Starting interactive shell...");
210 crate::services::shell::run_shell();
211 }
212
213 #[cfg(not(feature = "alloc"))]
215 sched::start();
216}
217
218pub fn kernel_init() -> KernelResult<()> {
224 #[cfg(target_arch = "riscv64")]
226 unsafe {
231 let uart_base = 0x1000_0000 as *mut u8;
232 uart_base.write_volatile(b'K');
233 uart_base.write_volatile(b'I');
234 uart_base.write_volatile(b'N');
235 uart_base.write_volatile(b'I');
236 uart_base.write_volatile(b'T');
237 uart_base.write_volatile(b'\n');
238 }
239
240 kprintln!("[BOOTSTRAP] Starting multi-stage kernel initialization...");
242 kprintln!("[BOOTSTRAP] Stage 1: Hardware initialization");
243
244 arch::init();
245
246 #[cfg(target_arch = "x86_64")]
249 {
250 crate::arch::x86_64::pat::init();
251 kprintln!("[BOOTSTRAP] PAT configured (WC available)");
252 crate::arch::x86_64::rtc::init();
253 }
254
255 kprintln!("[BOOTSTRAP] Architecture initialized");
256
257 kprintln!("[BOOTSTRAP] Stage 2: Memory management");
259
260 mm::init_default();
261
262 #[cfg(target_arch = "x86_64")]
265 mm::reserve_boot_page_table_frames();
266
267 kprintln!("[BOOTSTRAP] Memory management initialized");
268
269 #[cfg(target_arch = "aarch64")]
271 {
272 let test_box = alloc::boxed::Box::new(42u64);
273 assert!(*test_box == 42);
274 drop(test_box);
275 kprintln!("[BOOTSTRAP] Heap allocation verified OK");
276 }
277
278 #[cfg(target_arch = "x86_64")]
282 {
283 if let Some(fb_info) = crate::arch::x86_64::boot::get_framebuffer_info() {
284 let format = if fb_info.is_bgr {
285 crate::graphics::fbcon::FbPixelFormat::Bgr
286 } else {
287 crate::graphics::fbcon::FbPixelFormat::Rgb
288 };
289 unsafe {
292 crate::graphics::fbcon::init(
293 fb_info.buffer,
294 fb_info.width,
295 fb_info.height,
296 fb_info.stride,
297 fb_info.bpp,
298 format,
299 );
300 }
301 kprintln!("[BOOTSTRAP] Framebuffer console initialized");
302
303 let phys_offset =
307 crate::mm::PHYS_MEM_OFFSET.load(core::sync::atomic::Ordering::Acquire);
308 if phys_offset > 0 {
309 let fb_phys = (fb_info.buffer as u64).wrapping_sub(phys_offset);
310 crate::graphics::framebuffer::set_phys_addr(fb_phys);
311 kprintln!("[BOOTSTRAP] Framebuffer phys addr: 0x{:x}", fb_phys);
312 }
313
314 let fb_size = fb_info.stride * fb_info.height;
317 let fb_size_aligned = (fb_size + 4095) & !4095;
318 unsafe {
322 crate::arch::x86_64::pat::apply_write_combining(
323 fb_info.buffer as usize,
324 fb_size_aligned,
325 );
326 }
327 kprintln!(
328 "[BOOTSTRAP] Framebuffer WC enabled ({} pages)",
329 fb_size_aligned / 4096
330 );
331 }
332 }
333
334 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
338 {
339 match crate::drivers::ramfb::init(1024, 768) {
340 Ok(fb_ptr) => {
341 unsafe {
344 crate::graphics::fbcon::init(
345 fb_ptr,
346 1024,
347 768,
348 1024 * 4, 4, crate::graphics::fbcon::FbPixelFormat::Rgb,
351 );
352 }
353 kprintln!("[BOOTSTRAP] ramfb + fbcon initialized (1024x768)");
354 }
355 Err(_) => {
356 kprintln!("[BOOTSTRAP] ramfb not available, serial-only output");
357 }
358 }
359 }
360
361 #[cfg(target_arch = "x86_64")]
365 {
366 kprintln!("[BOOTSTRAP] Pre-initializing CSPRNG...");
367 let _ = crate::crypto::random::init();
368 let rng = crate::crypto::random::get_random();
370 let v = rng.next_u64();
371 crate::println!("[BOOTSTRAP] CSPRNG initialized (test: {})", v);
372 }
373
374 #[cfg(target_arch = "x86_64")]
384 {
385 const BOOT_STACK_SIZE: usize = 1024 * 1024; switch_to_heap_stack(BOOT_STACK_SIZE);
387 }
389
390 #[cfg(not(target_arch = "x86_64"))]
392 {
393 kernel_init_stage3_impl()?;
394 }
395
396 Ok(())
397}
398
399fn kernel_init_stage3_impl() -> KernelResult<()> {
406 kprintln!("[BOOTSTRAP] Stage 3: Process management");
408
409 process::init_without_init_process().expect("Failed to initialize process management");
410
411 kprintln!("[BOOTSTRAP] Process management initialized");
412
413 kprintln!("[BOOTSTRAP] Stage 4: Kernel services");
415
416 kprintln!("[BOOTSTRAP] Initializing capabilities...");
417 cap::init();
418 kprintln!("[BOOTSTRAP] Capabilities initialized");
419
420 kprintln!("[BOOTSTRAP] Initializing security subsystem...");
425 security::memory_protection::init().expect("Failed to initialize memory protection");
426 security::auth::init().expect("Failed to initialize auth");
427 security::tpm::init().expect("Failed to initialize TPM");
428 security::mac::init().expect("Failed to initialize MAC");
429 security::audit::init().expect("Failed to initialize audit");
430 let _ = security::boot::verify();
431 kprintln!("[BOOTSTRAP] Security subsystem initialized");
432
433 kprintln!("[BOOTSTRAP] Initializing performance monitoring...");
434 perf::init().expect("Failed to initialize performance monitoring");
435 crate::perf::pmu::init();
437 kprintln!(
438 "[BOOTSTRAP] Performance monitoring initialized (PMU: {} counters)",
439 crate::perf::pmu::num_counters()
440 );
441
442 kprintln!("[BOOTSTRAP] Initializing IPC...");
443 ipc::init();
444 kprintln!("[BOOTSTRAP] IPC initialized");
445
446 #[cfg(feature = "alloc")]
448 {
449 kprintln!("[BOOTSTRAP] Initializing VFS...");
450 fs::init();
451 kprintln!("[BOOTSTRAP] VFS initialized");
452 }
453
454 #[cfg(feature = "alloc")]
458 {
459 kprintln!("[BOOTSTRAP] Populating initramfs with embedded binaries...");
460 if crate::userspace::embedded::populate_initramfs().is_err() {
461 kprintln!("[BOOTSTRAP] Warning: Failed to populate initramfs");
462 } else {
463 kprintln!("[BOOTSTRAP] Initramfs populated successfully");
464 }
465 }
466
467 #[cfg(feature = "alloc")]
472 {
473 kprintln!("[BOOTSTRAP] Initializing drivers + virtio-blk...");
474 services::driver_framework::init();
475
476 #[cfg(target_arch = "x86_64")]
481 {
482 crate::drivers::pci::init();
483 {
485 let pci_bus = crate::drivers::pci::get_pci_bus().lock();
486 let _ = pci_bus.enumerate_devices();
487 }
488 crate::drivers::pci::probe_known_drivers();
490 }
491
492 crate::drivers::virtio::blk::init();
495
496 crate::drivers::mouse::init();
498
499 kprintln!("[BOOTSTRAP] Drivers + virtio-blk initialized");
500
501 load_rootfs_from_disk();
505 }
506
507 #[cfg(feature = "alloc")]
509 {
510 kprintln!("[BOOTSTRAP] Initializing services...");
511 services::init();
512 kprintln!("[BOOTSTRAP] Services initialized");
513
514 if let Some(init) = crate::services::init_system::try_get_init_system() {
516 if let Err(_e) = init.initialize() {
517 kprintln!("[BOOTSTRAP] Init system activation deferred: {:?}", _e);
518 }
519 }
520 }
521
522 kprintln!("[BOOTSTRAP] Core services initialized");
523
524 #[cfg(target_arch = "x86_64")]
528 {
529 crate::drivers::keyboard::init();
530 kprintln!("[BOOTSTRAP] Keyboard driver initialized");
531 }
532
533 kernel_init_main();
535
536 kprintln!("[BOOTSTRAP] Stage 5: Scheduler activation");
538
539 sched::init();
540
541 #[cfg(feature = "alloc")]
543 {
544 kprintln!("[BOOTSTRAP] Initializing package manager...");
545 pkg::init();
546 kprintln!("[BOOTSTRAP] Package manager initialized");
547 kprintln!("[PKGMGR] Package manager v0.4.0 ready");
548 }
549
550 #[cfg(feature = "alloc")]
552 {
553 kprintln!("[BOOTSTRAP] Initializing network stack...");
554 net::init().expect("Failed to initialize network stack");
555 kprintln!("[BOOTSTRAP] Network stack initialized");
556 }
557
558 kprintln!("[BOOTSTRAP] Initializing graphics subsystem...");
560 graphics::init().expect("Failed to initialize graphics");
561 kprintln!("[BOOTSTRAP] Graphics subsystem initialized");
562
563 #[cfg(feature = "alloc")]
565 {
566 if let Err(_e) = irq::init() {
567 kprintln!("[BOOTSTRAP] IRQ manager init skipped (already initialized)");
568 }
569 if let Err(_e) = timer::init() {
570 kprintln!("[BOOTSTRAP] Timer wheel init skipped (already initialized)");
571 }
572 }
573
574 #[cfg(feature = "alloc")]
576 {
577 kprintln!("[BOOTSTRAP] Initializing USB subsystem...");
578 crate::drivers::usb::init();
579 kprintln!("[BOOTSTRAP] USB subsystem initialized");
580 }
581
582 #[cfg(feature = "alloc")]
584 {
585 crate::syscall::userland_ext::users::init_user_db();
586 kprintln!("[BOOTSTRAP] User database initialized");
587 }
588
589 #[cfg(feature = "alloc")]
591 {
592 if let Err(_e) = crate::fs::pty::init() {
593 kprintln!("[BOOTSTRAP] PTY init failed (non-fatal)");
594 }
595 }
596
597 #[cfg(feature = "alloc")]
599 {
600 kprintln!("[BOOTSTRAP] Initializing desktop subsystem...");
601 if let Err(_e) = desktop::init() {
602 kprintln!("[BOOTSTRAP] Desktop init deferred (non-fatal)");
603 }
604 if let Some(hw) = graphics::fbcon::get_hw_info() {
606 crate::desktop::notification::init(hw.width, hw.height);
607 }
608 kprintln!("[BOOTSTRAP] Desktop subsystem initialized");
609 }
610
611 #[cfg(feature = "alloc")]
613 {
614 kprintln!("[BOOTSTRAP] Initializing audio subsystem...");
615 if let Err(_e) = audio::init() {
616 kprintln!("[BOOTSTRAP] Audio init deferred (non-fatal)");
617 }
618 kprintln!("[BOOTSTRAP] Audio subsystem initialized");
619 }
620
621 #[cfg(feature = "alloc")]
623 {
624 kprintln!("[BOOTSTRAP] Initializing video subsystem...");
625 if let Err(_e) = video::init() {
626 kprintln!("[BOOTSTRAP] Video init deferred (non-fatal)");
627 }
628 kprintln!("[BOOTSTRAP] Video subsystem initialized");
629 }
630
631 #[cfg(target_arch = "x86_64")]
633 {
634 kprintln!("[BOOTSTRAP] Initializing virtualization subsystem...");
635 virt::init();
636 kprintln!("[BOOTSTRAP] Virtualization subsystem initialized");
637 }
638
639 #[cfg(target_arch = "x86_64")]
641 {
642 kprintln!("[BOOTSTRAP] Initializing KPTI shadow page tables...");
643 crate::arch::x86_64::kpti::init();
644 kprintln!("[BOOTSTRAP] KPTI initialized");
645 }
646
647 kprintln!("[BOOTSTRAP] Scheduler activated - entering main scheduling loop");
648
649 #[cfg(all(feature = "alloc", target_arch = "x86_64"))]
653 {
654 test_user_binary_load();
655 }
656
657 Ok(())
658}
659
660pub fn run() -> ! {
662 #[cfg(target_arch = "riscv64")]
664 unsafe {
669 let uart_base = 0x1000_0000 as *mut u8;
670 uart_base.write_volatile(b'R');
671 uart_base.write_volatile(b'U');
672 uart_base.write_volatile(b'N');
673 uart_base.write_volatile(b'\n');
674 }
675
676 if let Err(e) = kernel_init() {
677 panic!("Bootstrap failed: {:?}", e);
680 }
681
682 kprintln!("[BOOTSTRAP] Stage 6: User space transition");
684
685 kprintln!("[BOOTSTRAP] About to create init process...");
686 create_init_process();
687 kprintln!("[BOOTSTRAP] Init process created");
688
689 kprintln!("[BOOTSTRAP] User space transition prepared");
691 kprintln!("[KERNEL] Boot sequence complete!");
692 kprintln!("BOOTOK");
693
694 #[cfg(target_arch = "aarch64")]
697 {
698 kprintln!("[BOOTSTRAP] Attempting user-mode entry...");
699 if crate::arch::aarch64::usermode::try_enter_usermode().is_err() {
700 kprintln!("[BOOTSTRAP] User-mode entry deferred (prerequisites not met)");
701 }
702 }
703 #[cfg(target_arch = "riscv64")]
704 {
705 kprintln!("[BOOTSTRAP] Attempting user-mode entry...");
706 if crate::arch::riscv64::usermode::try_enter_usermode().is_err() {
707 kprintln!("[BOOTSTRAP] User-mode entry deferred (prerequisites not met)");
708 }
709 }
710
711 graphics::fbcon::enable_output();
713
714 #[cfg(feature = "alloc")]
717 {
718 kprintln!("[BOOTSTRAP] Starting interactive shell...");
719 crate::services::shell::run_shell();
720 }
721
722 #[cfg(not(feature = "alloc"))]
724 sched::start();
725}
726
727#[cfg(feature = "alloc")]
737fn load_rootfs_from_disk() {
738 use crate::drivers::virtio::blk;
739
740 if !blk::is_initialized() {
741 kprintln!("[ROOTFS] No virtio-blk device, skipping disk load");
742 return;
743 }
744
745 let device = match blk::get_device() {
746 Some(dev) => dev,
747 None => {
748 kprintln!("[ROOTFS] virtio-blk device not available");
749 return;
750 }
751 };
752
753 let mut probe_buf = [0u8; 512];
755 {
756 let mut dev = device.lock();
757 if let Err(_e) = dev.read_block(0, &mut probe_buf) {
758 kprintln!("[ROOTFS] Failed to read sector 0 for probe");
759 return;
760 }
761 }
762
763 let magic = u32::from_le_bytes([probe_buf[0], probe_buf[1], probe_buf[2], probe_buf[3]]);
764 if magic == crate::fs::blockfs::BLOCKFS_MAGIC {
765 kprintln!("[ROOTFS] BlockFS magic detected -- mounting persistent root");
766 mount_blockfs_root();
767 return;
768 }
769
770 load_tar_rootfs();
772}
773
774#[cfg(feature = "alloc")]
780fn mount_blockfs_root() {
781 use alloc::sync::Arc;
782
783 use spin::Mutex;
784
785 use crate::fs::{
786 blockfs::{BlockFs, VirtioBlockBackend},
787 devfs::DevFs,
788 get_vfs,
789 procfs::ProcFs,
790 Permissions,
791 };
792
793 let backend = Arc::new(Mutex::new(VirtioBlockBackend));
794
795 let blockfs = match BlockFs::open_existing(backend) {
796 Ok(fs) => {
797 kprintln!("[ROOTFS] BlockFS loaded successfully");
798 fs
799 }
800 Err(_e) => {
801 kprintln!(
802 "[ROOTFS] Failed to open BlockFS: {:?}, falling back to TAR rootfs",
803 _e
804 );
805 load_tar_rootfs();
806 return;
807 }
808 };
809
810 let blockfs_arc: Arc<dyn crate::fs::Filesystem> = Arc::new(blockfs);
811
812 {
814 let vfs = get_vfs();
815 let mut vfs_guard = vfs.write();
816
817 let _ = vfs_guard.unmount("/dev");
819 let _ = vfs_guard.unmount("/proc");
820
821 vfs_guard.swap_root(blockfs_arc);
822 }
823
824 kprintln!("[ROOTFS] BlockFS mounted as persistent root");
825
826 {
828 let vfs = get_vfs();
829 let vfs_guard = vfs.read();
830 if let Ok(root) = vfs_guard.resolve_path("/") {
831 root.mkdir("dev", Permissions::default()).ok();
833 root.mkdir("proc", Permissions::default()).ok();
834 root.mkdir("tmp", Permissions::from_mode(0o777)).ok();
835 }
836 }
837
838 {
840 let vfs = get_vfs();
841 let mut vfs_guard = vfs.write();
842 vfs_guard.mount("/dev".into(), Arc::new(DevFs::new())).ok();
843 vfs_guard
844 .mount("/proc".into(), Arc::new(ProcFs::new()))
845 .ok();
846 }
847
848 kprintln!("[ROOTFS] DevFS and ProcFS re-mounted on BlockFS root");
849}
850
851#[cfg(feature = "alloc")]
854fn load_tar_rootfs() {
855 use crate::drivers::virtio::blk;
856
857 let device = match blk::get_device() {
858 Some(dev) => dev,
859 None => {
860 kprintln!("[ROOTFS] virtio-blk device not available");
861 return;
862 }
863 };
864
865 let mut dev = device.lock();
866 let total_sectors = dev.capacity_sectors();
867 let total_bytes = total_sectors as usize * blk::BLOCK_SIZE;
868
869 if total_sectors == 0 {
870 kprintln!("[ROOTFS] Disk is empty (0 sectors)");
871 return;
872 }
873
874 kprintln!(
875 "[ROOTFS] Reading {} sectors ({} KB) from virtio-blk...",
876 total_sectors,
877 total_bytes / 1024
878 );
879
880 let mut disk_data = alloc::vec![0u8; total_bytes];
882
883 for sector in 0..total_sectors {
885 let offset = sector as usize * blk::BLOCK_SIZE;
886 if let Err(_e) = dev.read_block(sector, &mut disk_data[offset..offset + blk::BLOCK_SIZE]) {
887 kprintln!("[ROOTFS] Read error at sector {}/{}", sector, total_sectors);
888 return;
889 }
890 }
891
892 drop(dev);
894
895 kprintln!("[ROOTFS] Disk read complete, parsing TAR archive...");
896
897 match crate::fs::tar::load_tar_to_vfs(&disk_data) {
898 Ok(_count) => {
899 kprintln!("[ROOTFS] Loaded entries from disk into VFS");
900 }
901 Err(_e) => {
902 kprintln!("[ROOTFS] TAR parse error");
903 }
904 }
905}
906
907#[cfg(all(feature = "alloc", target_arch = "x86_64"))]
915fn test_user_binary_load() {
916 use crate::fs::get_vfs;
917
918 let vfs = get_vfs().read();
920 match vfs.resolve_path("/bin/minimal") {
921 Ok(_node) => {
922 drop(vfs);
923 match crate::userspace::load_user_program("/bin/minimal", &["minimal"], &["PATH=/bin"])
924 {
925 Ok(pid) => {
926 run_user_process_scheduled(pid);
927 }
928 Err(e) => {
929 kprintln!("[BOOT] /bin/minimal FAILED: {:?}", e);
930 }
931 }
932 }
933 Err(_) => {
934 drop(vfs);
935 }
936 }
937
938 let vfs = get_vfs().read();
940 match vfs.resolve_path("/bin/fork_test") {
941 Ok(_node) => {
942 drop(vfs);
943 match crate::userspace::load_user_program(
944 "/bin/fork_test",
945 &["fork_test"],
946 &["PATH=/bin"],
947 ) {
948 Ok(pid) => {
949 run_user_process_scheduled(pid);
950 }
951 Err(e) => {
952 kprintln!("[BOOT] /bin/fork_test FAILED: {:?}", e);
953 }
954 }
955 }
956 Err(_) => {
957 drop(vfs);
958 }
959 }
960
961 let env = &["PATH=/bin:/usr/bin"];
971
972 boot_run_program("/bin/echo", &["echo", "ECHO_PASS"], env);
974
975 boot_run_program("/bin/cat", &["cat", "/usr/src/cat_test.txt"], env);
977
978 boot_run_program("/bin/wc", &["wc", "/usr/src/wc_test.txt"], env);
980
981 boot_run_program("/bin/ls", &["ls", "/usr/src/"], env);
983
984 boot_run_program("/bin/sort", &["sort", "/usr/src/sort_test.txt"], env);
986
987 boot_run_program("/bin/pipeline_test", &["pipeline_test"], env);
990
991 {
995 let vfs = get_vfs().read();
996 let has_busybox = vfs.resolve_path("/bin/busybox").is_ok();
997 drop(vfs);
998 if has_busybox {
999 kprintln!("[BOOT] BusyBox detected -- running applet smoke tests");
1000 boot_run_program("/bin/busybox", &["busybox"], env);
1002 boot_run_program("/bin/echo", &["echo", "BUSYBOX_ECHO_PASS"], env);
1004 boot_run_program("/bin/pwd", &["pwd"], env);
1005 boot_run_program("/bin/uname", &["uname", "-a"], env);
1006 boot_run_program("/bin/ls", &["ls", "/bin/"], env);
1007 boot_run_program("/bin/cat", &["cat", "/usr/src/cat_test.txt"], env);
1008 boot_run_program("/usr/bin/wc", &["wc", "/usr/src/wc_test.txt"], env);
1009 boot_run_program("/usr/bin/sort", &["sort", "/usr/src/sort_test.txt"], env);
1010 boot_run_program("/bin/true", &["true"], env);
1011 boot_run_program("/bin/false", &["false"], env);
1012
1013 kprintln!("[BOOT] ash shell scripted tests");
1015 boot_run_program("/bin/ash", &["ash", "-c", "echo ASH_BASIC_PASS"], env);
1017 boot_run_program(
1019 "/bin/ash",
1020 &["ash", "-c", "X=veridian; echo ASH_VAR_${X}_PASS"],
1021 env,
1022 );
1023 boot_run_program(
1025 "/bin/ash",
1026 &["ash", "-c", "false; echo ASH_EXIT_$?_PASS"],
1027 env,
1028 );
1029 boot_run_program(
1031 "/bin/ash",
1032 &["ash", "-c", "test -f /bin/busybox && echo ASH_COND_PASS"],
1033 env,
1034 );
1035 boot_run_program("/bin/ash", &["ash", "-c", "echo ASH_PIPE_PASS | cat"], env);
1037 boot_run_program(
1039 "/bin/ash",
1040 &[
1041 "ash",
1042 "-c",
1043 "echo ASH_REDIR_PASS > /tmp/redir.txt; cat /tmp/redir.txt",
1044 ],
1045 env,
1046 );
1047 boot_run_program(
1049 "/bin/ash",
1050 &["ash", "-c", "for i in A B C; do echo LOOP_$i; done"],
1051 env,
1052 );
1053 boot_run_program(
1055 "/bin/ash",
1056 &["ash", "-c", "D=$(pwd); echo ASH_SUBST_${D}_PASS"],
1057 env,
1058 );
1059 boot_run_program("/usr/bin/seq", &["seq", "1", "3"], env);
1061 boot_run_program(
1063 "/bin/ash",
1064 &["ash", "-c", "echo PIPE_HEAD_PASS | head -n 1"],
1065 env,
1066 );
1067 boot_run_program("/bin/ash", &["ash", "/usr/src/busybox_test.sh"], env);
1069
1070 {
1072 let vfs = get_vfs().read();
1073 let has_gcc = vfs.resolve_path("/usr/bin/gcc").is_ok();
1074 let has_bb_src = vfs
1075 .resolve_path("/usr/src/busybox-1.36.1/include/autoconf.h")
1076 .is_ok();
1077 drop(vfs);
1078 if has_gcc && has_bb_src {
1079 kprintln!("[BOOT] Phase C: Native compilation tests");
1080
1081 boot_run_program(
1084 "/usr/bin/gcc",
1085 &[
1086 "gcc",
1087 "-c",
1088 "-std=c11",
1089 "-nostdinc",
1090 "-isystem",
1091 "/usr/include",
1092 "-isystem",
1093 "/usr/lib/gcc/x86_64-veridian/14.2.0/include",
1094 "-static",
1095 "-fno-stack-protector",
1096 "-ffreestanding",
1097 "-mno-red-zone",
1098 "-mcmodel=small",
1099 "-O2",
1100 "-o",
1101 "/tmp/echo.o",
1102 "/usr/src/coreutils/echo.c",
1103 ],
1104 env,
1105 );
1106 {
1108 let vfs = get_vfs().read();
1109 if vfs.resolve_path("/tmp/echo.o").is_ok() {
1110 kprintln!("NATIVE_COMPILE_SINGLE_PASS");
1111 } else {
1112 kprintln!("NATIVE_COMPILE_SINGLE_FAIL");
1113 }
1114 drop(vfs);
1115 }
1116
1117 boot_run_program(
1119 "/usr/bin/gcc",
1120 &[
1121 "gcc",
1122 "-static",
1123 "-nostdlib",
1124 "-ffreestanding",
1125 "-o",
1126 "/tmp/echo-native",
1127 "/usr/lib/crt0.o",
1128 "/tmp/echo.o",
1129 "-L",
1130 "/usr/lib",
1131 "-L",
1132 "/usr/lib/gcc/x86_64-veridian/14.2.0",
1133 "-lc",
1134 "-lgcc",
1135 ],
1136 env,
1137 );
1138 {
1140 let vfs = get_vfs().read();
1141 if vfs.resolve_path("/tmp/echo-native").is_ok() {
1142 drop(vfs);
1143 kprintln!("[BOOT] Phase C-2: Executing natively-compiled echo");
1144 boot_run_program(
1145 "/tmp/echo-native",
1146 &["echo", "NATIVE_ECHO_PASS"],
1147 env,
1148 );
1149 } else {
1150 drop(vfs);
1151 kprintln!(
1152 "[BOOT] Phase C-2: Link FAILED -- /tmp/echo-native not found"
1153 );
1154 }
1155 }
1156
1157 {
1162 let vfs = get_vfs().read();
1163 let has_script =
1164 vfs.resolve_path("/usr/src/build-busybox-native.sh").is_ok();
1165 drop(vfs);
1166 if has_script {
1167 kprintln!("[BOOT] Phase C-3: Skipped (208-file native build)");
1168 kprintln!("[BOOT] Run manually: ash /usr/src/build-busybox-native.sh");
1169 }
1170 }
1171
1172 {
1175 let vfs = get_vfs().read();
1176 let has_script = vfs
1177 .resolve_path("/usr/src/build-native-programs.sh")
1178 .is_ok();
1179 drop(vfs);
1180 if has_script {
1181 kprintln!("[BOOT] Phase C-4: Skipped (native sysinfo+edit build)");
1182 kprintln!("[BOOT] Run manually: ash /usr/src/build-native-programs.sh");
1183 }
1184 }
1185
1186 {
1189 let vfs = get_vfs().read();
1190 let has_sysinfo = vfs.resolve_path("/tmp/sysinfo-native").is_ok();
1191 drop(vfs);
1192 if has_sysinfo {
1193 kprintln!("[BOOT] Phase C-5: Executing natively-compiled sysinfo");
1194 boot_run_program("/tmp/sysinfo-native", &["sysinfo"], env);
1195 kprintln!("NATIVE_RUN_SYSINFO_PASS");
1196 } else {
1197 kprintln!("[BOOT] Phase C-5: Skipped (/tmp/sysinfo-native not found)");
1198 kprintln!("[BOOT] Build first: ash /usr/src/build-native-programs.sh");
1199 }
1200 }
1201
1202 {
1205 let vfs = get_vfs().read();
1206 let has_script = vfs
1207 .resolve_path("/usr/src/build-native-coreutils.sh")
1208 .is_ok();
1209 drop(vfs);
1210 if has_script {
1211 kprintln!("[BOOT] Phase C-6: Skipped (native coreutils build)");
1212 kprintln!(
1213 "[BOOT] Run manually: ash /usr/src/build-native-coreutils.sh"
1214 );
1215 }
1216 }
1217 } else {
1218 if !has_gcc {
1219 kprintln!("[BOOT] Phase C skipped: /usr/bin/gcc not in rootfs");
1220 }
1221 if !has_bb_src {
1222 kprintln!("[BOOT] Phase C skipped: BusyBox source not in rootfs");
1223 }
1224 }
1225 }
1226
1227 kprintln!("[BOOT] Boot tests complete, returning to Stage 6");
1230 }
1231 }
1232}
1233
1234#[cfg(all(feature = "alloc", target_arch = "x86_64"))]
1236fn boot_run_program(path: &str, argv: &[&str], envp: &[&str]) {
1237 use crate::fs::get_vfs;
1238
1239 let vfs = get_vfs().read();
1240 match vfs.resolve_path(path) {
1241 Ok(_node) => {
1242 drop(vfs);
1243 match crate::userspace::load_user_program(path, argv, envp) {
1244 Ok(pid) => {
1245 kprintln!("[BOOT] Running {}", path);
1246 run_user_process_scheduled(pid);
1247 }
1248 Err(e) => {
1249 kprintln!("[BOOT] {} load FAILED: {:?}", path, e);
1250 }
1251 }
1252 }
1253 Err(_) => {
1254 drop(vfs);
1255 kprintln!("[BOOT] {} not found in VFS, skipping", path);
1256 }
1257 }
1258
1259 boot_reap_orphan_zombies();
1265}
1266
1267#[cfg(all(feature = "alloc", target_arch = "x86_64"))]
1278fn boot_reap_orphan_zombies() {
1279 use crate::process::{
1280 pcb::ProcessState,
1281 table::{self, PROCESS_TABLE},
1282 ProcessId,
1283 };
1284
1285 let mut zombies_to_reap = alloc::vec::Vec::new();
1287 PROCESS_TABLE.for_each(|proc| {
1288 if proc.get_state() == ProcessState::Zombie {
1289 let dominated_by_init_or_orphaned = match proc.parent {
1292 Some(parent_pid) => parent_pid.0 <= 1 || table::get_process(parent_pid).is_none(),
1293 None => true,
1294 };
1295 if dominated_by_init_or_orphaned {
1296 zombies_to_reap.push(proc.pid);
1297 }
1298 }
1299 });
1300
1301 for pid in &zombies_to_reap {
1302 if let Some(proc) = table::get_process(*pid) {
1304 if proc.get_state() == ProcessState::Zombie {
1307 if let Some(init) = table::get_process(ProcessId(1)) {
1309 init.children.lock().retain(|&p| p != *pid);
1310 }
1311 }
1312 let pt_root = proc.memory_space.lock().get_page_table();
1317 if pt_root != 0 {
1318 crate::mm::vas::free_user_page_table_frames(pt_root);
1319 proc.memory_space.lock().set_page_table(0);
1320 }
1321 }
1322 table::remove_process(*pid);
1323 }
1324
1325 if !zombies_to_reap.is_empty() {
1326 kprintln!(
1327 "[BOOT] Reaped {} orphan zombie(s) from process table",
1328 zombies_to_reap.len()
1329 );
1330 }
1331}
1332
1333#[inline(never)]
1343#[cfg(all(feature = "alloc", target_arch = "x86_64"))]
1344pub(crate) fn run_user_process(pid: crate::process::ProcessId) {
1345 use crate::process::get_process;
1346
1347 let process = match get_process(pid) {
1348 Some(p) => p,
1349 None => return,
1350 };
1351
1352 let vas = process.memory_space.lock();
1354 let pt_root = vas.get_page_table();
1355 if pt_root == 0 {
1356 return;
1357 }
1358
1359 let threads = process.threads.lock();
1361 let thread = match threads.values().next() {
1362 Some(t) => t,
1363 None => return,
1364 };
1365
1366 let (entry_point, user_stack_ptr) = {
1367 use crate::arch::context::ThreadContext;
1368 let ctx = thread.context.lock();
1369 (
1370 ctx.get_instruction_pointer() as u64,
1371 ctx.get_stack_pointer() as u64,
1372 )
1373 };
1374
1375 drop(threads);
1377 drop(vas);
1378
1379 let user_cs: u64 = 0x33; let user_ss: u64 = 0x2B; unsafe {
1386 use crate::mm::{vas::create_mapper_from_root_pub, VirtualAddress};
1387 let mapper = create_mapper_from_root_pub(pt_root);
1388
1389 let entry_page = VirtualAddress(entry_point & !0xFFF);
1390 if mapper.translate_page(entry_page).is_err() {
1391 kprintln!("[BOOT] FATAL: entry {:#x} not mapped", entry_point);
1392 return;
1393 }
1394
1395 let stack_page = VirtualAddress((user_stack_ptr - 16) & !0xFFF);
1396 if mapper.translate_page(stack_page).is_err() {
1397 kprintln!("[BOOT] FATAL: stack {:#x} not mapped", user_stack_ptr);
1398 return;
1399 }
1400 }
1401
1402 {
1404 let fs_base = process
1405 .tls_fs_base
1406 .load(core::sync::atomic::Ordering::Acquire);
1407 if fs_base != 0 {
1408 unsafe {
1411 crate::arch::x86_64::idt::raw_serial_str(b"[BOOT] FS_BASE=0x");
1412 crate::arch::x86_64::idt::raw_serial_hex(fs_base);
1413 crate::arch::x86_64::idt::raw_serial_str(b"\n");
1414 let lo = fs_base as u32;
1415 let hi = (fs_base >> 32) as u32;
1416 core::arch::asm!(
1417 "wrmsr",
1418 in("ecx") 0xC000_0100u32, in("eax") lo,
1420 in("edx") hi,
1421 );
1422 }
1423 }
1424 }
1425
1426 let kernel_rsp_ptr = crate::arch::x86_64::syscall::per_cpu_data_ptr() as u64;
1439 unsafe {
1440 crate::arch::x86_64::usermode::enter_usermode_returnable(
1441 entry_point,
1442 user_stack_ptr,
1443 user_cs,
1444 user_ss,
1445 pt_root,
1446 kernel_rsp_ptr,
1447 );
1448 }
1449}
1450
1451#[inline(never)]
1471#[cfg(all(feature = "alloc", target_arch = "x86_64"))]
1472fn run_user_process_scheduled(pid: crate::process::ProcessId) {
1473 use crate::process::get_process;
1474
1475 let saved_pt_root = if let Some(proc) = get_process(pid) {
1481 proc.memory_space.lock().get_page_table()
1482 } else {
1483 0
1484 };
1485
1486 let tid = if let Some(proc) = get_process(pid) {
1488 let threads = proc.threads.lock();
1489 threads.values().next().map(|t| t.tid)
1490 } else {
1491 None
1492 };
1493
1494 if let Some(tid) = tid {
1495 crate::process::set_boot_current(pid, tid);
1497
1498 run_user_process(pid);
1499
1500 crate::process::clear_boot_current();
1502 } else {
1503 run_user_process(pid);
1505 }
1506
1507 let current_pt_root = if let Some(proc) = get_process(pid) {
1519 proc.memory_space.lock().get_page_table()
1520 } else {
1521 0
1522 };
1523
1524 if current_pt_root != 0 && current_pt_root != saved_pt_root {
1526 let freed = crate::mm::vas::free_user_page_table_frames(current_pt_root);
1527 if freed > 0 {
1528 kprintln!(
1529 "[BOOT] Freed {} post-exec page table frames for pid {}",
1530 freed,
1531 pid.0
1532 );
1533 }
1534 }
1535
1536 if saved_pt_root != 0 {
1538 let freed = crate::mm::vas::free_user_page_table_frames(saved_pt_root);
1539 if freed > 0 {
1540 kprintln!("[BOOT] Freed {} page table frames for pid {}", freed, pid.0);
1541 }
1542 }
1543
1544 if let Some(proc) = get_process(pid) {
1547 proc.memory_space.lock().set_page_table(0);
1548 }
1549
1550 if let Some(proc) = get_process(pid) {
1557 let state = proc.get_state();
1558 if state == crate::process::ProcessState::Zombie
1559 || state == crate::process::ProcessState::Dead
1560 {
1561 crate::process::table::remove_process(pid);
1562 }
1563 }
1564}
1565
1566#[cfg(all(feature = "alloc", target_arch = "x86_64"))]
1578pub fn boot_run_forked_child(
1579 child_pid: crate::process::ProcessId,
1580 parent_pid: crate::process::ProcessId,
1581 parent_tid: crate::process::thread::ThreadId,
1582) -> bool {
1583 use core::sync::atomic::Ordering;
1584
1585 use crate::{
1586 arch::x86_64::usermode::{
1587 ForkChildRegs, BOOT_RETURN_CR3, BOOT_RETURN_RSP, BOOT_STACK_CANARY,
1588 },
1589 process::get_process,
1590 };
1591
1592 if !crate::arch::x86_64::usermode::has_boot_return_context() {
1593 return false;
1594 }
1595
1596 let child = match get_process(child_pid) {
1597 Some(p) => p,
1598 None => return false,
1599 };
1600
1601 let (regs, child_tid) = {
1605 let threads = child.threads.lock();
1606 match threads.values().next() {
1607 Some(t) => {
1608 let ctx = t.context.lock();
1609 let r = ForkChildRegs {
1610 rip: ctx.rip,
1611 rsp: ctx.rsp,
1612 rflags: ctx.rflags,
1613 rax: ctx.rax,
1614 rbx: ctx.rbx,
1615 rcx: ctx.rcx,
1616 rdx: ctx.rdx,
1617 rsi: ctx.rsi,
1618 rdi: ctx.rdi,
1619 rbp: ctx.rbp,
1620 r8: ctx.r8,
1621 r9: ctx.r9,
1622 r10: ctx.r10,
1623 r11: ctx.r11,
1624 r12: ctx.r12,
1625 r13: ctx.r13,
1626 r14: ctx.r14,
1627 r15: ctx.r15,
1628 };
1629 (r, t.tid)
1630 }
1631 None => return false,
1632 }
1633 };
1634
1635 let cr3 = {
1636 let vas = child.memory_space.lock();
1637 vas.get_page_table()
1638 };
1639
1640 if cr3 == 0 {
1641 return false;
1642 }
1643
1644 let saved_rsp = BOOT_RETURN_RSP.load(Ordering::SeqCst);
1646 let saved_cr3 = BOOT_RETURN_CR3.load(Ordering::SeqCst);
1647 let saved_canary = BOOT_STACK_CANARY.load(Ordering::SeqCst);
1648
1649 let per_cpu = crate::arch::x86_64::syscall::per_cpu_data_ptr();
1656 let saved_kernel_rsp = unsafe { (*per_cpu).kernel_rsp };
1660 let saved_user_rsp = unsafe { (*per_cpu).user_rsp };
1661
1662 crate::process::set_boot_current(child_pid, child_tid);
1664
1665 unsafe { core::arch::asm!("swapgs", options(nomem, nostack)) };
1672
1673 let kernel_rsp_ptr = per_cpu as u64;
1674
1675 unsafe {
1679 crate::arch::x86_64::idt::raw_serial_str(b"[CHILD_DISPATCH] rip=0x");
1680 crate::arch::x86_64::idt::raw_serial_hex(regs.rip);
1681 crate::arch::x86_64::idt::raw_serial_str(b" rsp=0x");
1682 crate::arch::x86_64::idt::raw_serial_hex(regs.rsp);
1683 crate::arch::x86_64::idt::raw_serial_str(b" rbx=0x");
1684 crate::arch::x86_64::idt::raw_serial_hex(regs.rbx);
1685 crate::arch::x86_64::idt::raw_serial_str(b" rbp=0x");
1686 crate::arch::x86_64::idt::raw_serial_hex(regs.rbp);
1687 crate::arch::x86_64::idt::raw_serial_str(b"\n");
1688 }
1689
1690 unsafe {
1694 crate::arch::x86_64::usermode::enter_forked_child_returnable(®s, cr3, kernel_rsp_ptr);
1695 }
1696
1697 unsafe { core::arch::asm!("swapgs", options(nomem, nostack)) };
1704
1705 let current_child_pt = if let Some(child_proc) = get_process(child_pid) {
1714 child_proc.memory_space.lock().get_page_table()
1715 } else {
1716 0
1717 };
1718
1719 if current_child_pt != 0 && current_child_pt != cr3 {
1721 crate::mm::vas::free_user_page_table_frames(current_child_pt);
1722 }
1723
1724 if cr3 != 0 {
1726 crate::mm::vas::free_user_page_table_frames(cr3);
1727 }
1728
1729 if let Some(child_proc) = get_process(child_pid) {
1732 child_proc.memory_space.lock().set_page_table(0);
1733 }
1734
1735 unsafe {
1741 (*per_cpu).kernel_rsp = saved_kernel_rsp;
1742 (*per_cpu).user_rsp = saved_user_rsp;
1743 }
1744
1745 crate::process::set_boot_current(parent_pid, parent_tid);
1747
1748 BOOT_RETURN_RSP.store(saved_rsp, Ordering::SeqCst);
1750 BOOT_RETURN_CR3.store(saved_cr3, Ordering::SeqCst);
1751 BOOT_STACK_CANARY.store(saved_canary, Ordering::SeqCst);
1752
1753 true
1754}
1755
1756#[cfg(feature = "alloc")]
1762pub fn kernel_init_main() {
1763 kprintln!("");
1764 kprintln!("========================================");
1765 kprintln!("[INIT] VeridianOS kernel-mode init");
1766 kprintln!("========================================");
1767
1768 let mut passed = 0u32;
1769 let mut failed = 0u32;
1770
1771 run_vfs_tests(&mut passed, &mut failed);
1772
1773 if !run_shell_tests(&mut passed, &mut failed) {
1775 return;
1776 }
1777
1778 run_elf_tests(&mut passed, &mut failed);
1779 run_capability_tests(&mut passed, &mut failed);
1780 run_security_tests(&mut passed, &mut failed);
1781 run_phase4_tests(&mut passed, &mut failed);
1782 run_display_tests(&mut passed, &mut failed);
1783
1784 print_summary(passed, failed);
1786}
1787
1788#[cfg(feature = "alloc")]
1790fn run_vfs_tests(passed: &mut u32, failed: &mut u32) {
1791 kprintln!("[INIT] VFS tests:");
1792
1793 {
1795 let ok = fs::get_vfs()
1796 .read()
1797 .mkdir("/tmp/test_init", fs::Permissions::default())
1798 .is_ok();
1799 report_test("vfs_mkdir", ok, passed, failed);
1800 }
1801
1802 {
1804 let ok = (|| -> Result<(), crate::error::KernelError> {
1805 let vfs = fs::get_vfs().read();
1806 let parent = vfs.resolve_path("/tmp/test_init")?;
1807 let file = parent.create("hello.txt", fs::Permissions::default())?;
1808 file.write(0, b"Hello VeridianOS")?;
1809 Ok(())
1810 })()
1811 .is_ok();
1812 report_test("vfs_write_file", ok, passed, failed);
1813 }
1814
1815 {
1817 let ok = (|| -> Result<bool, crate::error::KernelError> {
1818 let vfs = fs::get_vfs().read();
1819 let dir = vfs.resolve_path("/tmp/test_init")?;
1820 let file = dir.lookup("hello.txt")?;
1821 let mut buf = [0u8; 32];
1822 let n = file.read(0, &mut buf)?;
1823 Ok(&buf[..n] == b"Hello VeridianOS")
1824 })()
1825 .unwrap_or(false);
1826 report_test("vfs_read_verify", ok, passed, failed);
1827 }
1828
1829 {
1831 let ok = (|| -> Result<bool, crate::error::KernelError> {
1832 let vfs = fs::get_vfs().read();
1833 let node = vfs.resolve_path("/tmp/test_init")?;
1834 let entries = node.readdir()?;
1835 Ok(entries.iter().any(|e| e.name == "hello.txt"))
1836 })()
1837 .unwrap_or(false);
1838 report_test("vfs_readdir", ok, passed, failed);
1839 }
1840
1841 {
1843 let ok = fs::get_vfs().read().resolve_path("/proc").is_ok();
1844 report_test("vfs_procfs", ok, passed, failed);
1845 }
1846
1847 {
1849 let ok = fs::get_vfs().read().resolve_path("/dev").is_ok();
1850 report_test("vfs_devfs", ok, passed, failed);
1851 }
1852}
1853
1854#[cfg(feature = "alloc")]
1859fn run_shell_tests(passed: &mut u32, failed: &mut u32) -> bool {
1860 kprintln!("[INIT] Shell tests:");
1861
1862 let shell = match services::shell::try_get_shell() {
1863 Some(s) => s,
1864 None => {
1865 kprintln!(" shell unavailable [failed]");
1866 *failed += 6;
1867 print_summary(*passed, *failed);
1868 return false;
1869 }
1870 };
1871
1872 {
1874 let ok = matches!(
1875 shell.execute_command("help"),
1876 services::shell::CommandResult::Success(_)
1877 );
1878 report_test("shell_help", ok, passed, failed);
1879 }
1880
1881 {
1883 let ok = matches!(
1884 shell.execute_command("pwd"),
1885 services::shell::CommandResult::Success(_)
1886 );
1887 report_test("shell_pwd", ok, passed, failed);
1888 }
1889
1890 {
1892 let ok = matches!(
1893 shell.execute_command("ls /"),
1894 services::shell::CommandResult::Success(_)
1895 );
1896 report_test("shell_ls", ok, passed, failed);
1897 }
1898
1899 {
1901 let ok = matches!(
1902 shell.execute_command("env"),
1903 services::shell::CommandResult::Success(_)
1904 );
1905 report_test("shell_env", ok, passed, failed);
1906 }
1907
1908 {
1910 let ok = matches!(
1911 shell.execute_command("echo hello"),
1912 services::shell::CommandResult::Success(_)
1913 );
1914 report_test("shell_echo", ok, passed, failed);
1915 }
1916
1917 {
1919 let ok = matches!(
1920 shell.execute_command("mkdir /tmp/shell_test"),
1921 services::shell::CommandResult::Success(_)
1922 ) && fs::file_exists("/tmp/shell_test");
1923 report_test("shell_mkdir_verify", ok, passed, failed);
1924 }
1925
1926 true
1927}
1928
1929#[cfg(feature = "alloc")]
1931fn run_elf_tests(passed: &mut u32, failed: &mut u32) {
1932 kprintln!("[INIT] ELF tests:");
1933
1934 {
1936 use crate::elf::ElfLoader;
1937
1938 let ok = (|| -> Result<bool, crate::error::KernelError> {
1939 let loader = ElfLoader::new();
1940 let header_size = core::mem::size_of::<crate::elf::Elf64Header>();
1942 let ph_size = core::mem::size_of::<crate::elf::Elf64ProgramHeader>();
1943 let total = header_size + ph_size;
1944 let mut buf = alloc::vec![0u8; total];
1945 buf[0] = 0x7f;
1947 buf[1] = b'E';
1948 buf[2] = b'L';
1949 buf[3] = b'F';
1950 buf[4] = 2; buf[5] = 1; buf[6] = 1;
1953 buf[16] = 2; #[cfg(target_arch = "x86_64")]
1955 {
1956 buf[18] = 62;
1957 }
1958 #[cfg(target_arch = "aarch64")]
1959 {
1960 buf[18] = 183;
1961 }
1962 #[cfg(target_arch = "riscv64")]
1963 {
1964 buf[18] = 243;
1965 }
1966 buf[20] = 1;
1968 buf[24..32].copy_from_slice(&0x401000u64.to_le_bytes());
1970 buf[32..40].copy_from_slice(&(header_size as u64).to_le_bytes());
1972 buf[52] = (header_size & 0xFF) as u8;
1974 buf[53] = ((header_size >> 8) & 0xFF) as u8;
1975 buf[54] = (ph_size & 0xFF) as u8;
1977 buf[55] = ((ph_size >> 8) & 0xFF) as u8;
1978 buf[56] = 1;
1980 let po = header_size;
1982 buf[po] = 1; buf[po + 4] = 7; buf[po + 16..po + 24].copy_from_slice(&0x400000u64.to_le_bytes()); buf[po + 24..po + 32].copy_from_slice(&0x400000u64.to_le_bytes()); buf[po + 40..po + 48].copy_from_slice(&0x1000u64.to_le_bytes()); buf[po + 48..po + 56].copy_from_slice(&0x1000u64.to_le_bytes()); let binary =
1989 loader
1990 .parse(&buf)
1991 .map_err(|_| crate::error::KernelError::InvalidArgument {
1992 name: "elf_data",
1993 value: "parse failed",
1994 })?;
1995 Ok(binary.entry_point == 0x401000 && !binary.segments.is_empty())
1996 })()
1997 .unwrap_or(false);
1998 report_test("elf_parse_valid", ok, passed, failed);
1999 }
2000
2001 {
2003 use crate::elf::ElfLoader;
2004
2005 let ok = {
2006 let loader = ElfLoader::new();
2007 let bad_data = alloc::vec![0u8; 128]; loader.parse(&bad_data).is_err()
2009 };
2010 report_test("elf_reject_bad_magic", ok, passed, failed);
2011 }
2012}
2013
2014#[cfg(feature = "alloc")]
2016fn run_capability_tests(passed: &mut u32, failed: &mut u32) {
2017 kprintln!("[INIT] Capability tests:");
2018
2019 {
2021 use crate::cap::{
2022 object::MemoryAttributes, CapabilitySpace, CapabilityToken, ObjectRef, Rights,
2023 };
2024
2025 let ok = (|| -> Result<bool, crate::error::KernelError> {
2026 let space = CapabilitySpace::new();
2027 let token = CapabilityToken::new(1, 0, 0, 0);
2028 let object = ObjectRef::Memory {
2029 base: 0x1000,
2030 size: 0x1000,
2031 attributes: MemoryAttributes::normal(),
2032 };
2033 let rights = Rights::READ | Rights::WRITE;
2034 space.insert(token, object, rights)?;
2035 if let Some(found_rights) = space.lookup(token) {
2036 Ok(found_rights.contains(Rights::READ))
2037 } else {
2038 Ok(false)
2039 }
2040 })()
2041 .unwrap_or(false);
2042 report_test("cap_insert_lookup", ok, passed, failed);
2043 }
2044
2045 {
2047 let ok = (|| -> Result<bool, crate::ipc::IpcError> {
2048 let owner = crate::ipc::ProcessId(1);
2049 let (endpoint_id, capability) = ipc::create_endpoint(owner)?;
2050 ipc::validate_capability(owner, &capability)?;
2051 Ok(endpoint_id > 0)
2052 })()
2053 .unwrap_or(false);
2054 report_test("ipc_endpoint_create", ok, passed, failed);
2055 }
2056
2057 {
2059 let ok = cap::root_capability().is_some();
2060 report_test("cap_root_exists", ok, passed, failed);
2061 }
2062
2063 {
2065 use crate::cap::{
2066 object::MemoryAttributes, CapabilitySpace, CapabilityToken, ObjectRef, Rights,
2067 };
2068
2069 let ok = (|| -> Result<bool, crate::error::KernelError> {
2070 let space = CapabilitySpace::with_quota(2);
2072 let obj = ObjectRef::Memory {
2073 base: 0x2000,
2074 size: 0x1000,
2075 attributes: MemoryAttributes::normal(),
2076 };
2077
2078 let t1 = CapabilityToken::new(10, 0, 0, 0);
2080 space.insert(t1, obj.clone(), Rights::READ)?;
2081
2082 let t2 = CapabilityToken::new(11, 0, 0, 0);
2083 space.insert(t2, obj.clone(), Rights::READ)?;
2084
2085 let t3 = CapabilityToken::new(12, 0, 0, 0);
2087 let third_result = space.insert(t3, obj, Rights::READ);
2088 Ok(third_result.is_err())
2089 })()
2090 .unwrap_or(false);
2091 report_test("cap_quota_enforced", ok, passed, failed);
2092 }
2093}
2094
2095#[cfg(feature = "alloc")]
2097fn run_security_tests(passed: &mut u32, failed: &mut u32) {
2098 {
2100 let ok = security::mac::check_file_access("/test", security::AccessType::Read, 100).is_ok();
2101 report_test("mac_user_file_read", ok, passed, failed);
2102 }
2103
2104 {
2106 security::audit::log_process_create(0, 0, 0);
2109 let (count, _max) = security::audit::get_stats();
2110 let ok = count > 0;
2111 report_test("audit_has_events", ok, passed, failed);
2112 }
2113
2114 {
2120 let canary_val: u64 = 0xDEAD_BEEF_CAFE_BABE;
2121 let mut stack_slot: u64 = canary_val;
2122 let intact = stack_slot == canary_val;
2124 stack_slot ^= 1;
2126 let corrupted = stack_slot != canary_val;
2127 let ok = intact && corrupted;
2128 report_test("stack_canary_verify", ok, passed, failed);
2129 }
2130
2131 {
2133 let ok = crate::crypto::validate();
2134 report_test("crypto_sha256_vector", ok, passed, failed);
2135 }
2136}
2137
2138#[cfg(feature = "alloc")]
2140fn run_phase4_tests(passed: &mut u32, failed: &mut u32) {
2141 kprintln!("[INIT] Phase 4 package ecosystem tests:");
2142
2143 {
2145 let ok = crate::test_framework::test_pkg_delta_compute_apply().is_ok();
2146 report_test("pkg_delta_roundtrip", ok, passed, failed);
2147 }
2148
2149 {
2151 let ok = crate::test_framework::test_pkg_reproducible_manifest().is_ok();
2152 report_test("pkg_reproducible_manifest", ok, passed, failed);
2153 }
2154
2155 {
2157 let ok = crate::test_framework::test_pkg_license_detection().is_ok();
2158 report_test("pkg_license_detection", ok, passed, failed);
2159 }
2160
2161 {
2163 let ok = crate::test_framework::test_pkg_security_scan().is_ok();
2164 report_test("pkg_security_scan", ok, passed, failed);
2165 }
2166
2167 {
2169 let ok = crate::test_framework::test_pkg_ecosystem_definitions().is_ok();
2170 report_test("pkg_ecosystem_defs", ok, passed, failed);
2171 }
2172}
2173
2174#[cfg(feature = "alloc")]
2176fn run_display_tests(passed: &mut u32, failed: &mut u32) {
2177 kprintln!("[INIT] Display/input tests:");
2178
2179 {
2181 #[cfg(target_arch = "x86_64")]
2182 let ok = crate::graphics::fbcon::is_initialized();
2183 #[cfg(not(target_arch = "x86_64"))]
2184 let ok = true; report_test("fbcon_initialized", ok, passed, failed);
2186 }
2187
2188 {
2190 #[cfg(target_arch = "x86_64")]
2191 let ok = crate::drivers::keyboard::is_initialized();
2192 #[cfg(not(target_arch = "x86_64"))]
2193 let ok = true; report_test("keyboard_driver_ready", ok, passed, failed);
2195 }
2196}
2197
2198#[cfg(not(feature = "alloc"))]
2199pub fn kernel_init_main() {
2200 kprintln!("BOOTOK");
2201}
2202
2203fn print_summary(passed: u32, failed: u32) {
2205 kprintln!("========================================");
2206 kprint_rt!("[INIT] Results: ");
2207 kprint_u64!(passed);
2208 kprint_rt!("/");
2209 kprint_u64!(passed + failed);
2210 kprintln!(" passed");
2211 if failed == 0 {
2212 kprintln!("BOOTOK");
2213 } else {
2214 kprintln!("BOOTFAIL");
2215 }
2216 kprintln!("========================================");
2217}
2218
2219fn report_test(name: &str, ok: bool, passed: &mut u32, failed: &mut u32) {
2221 kprint_rt!(" ");
2222 kprint_rt!(name);
2223 if ok {
2224 kprintln!("...[ok]");
2225 } else {
2226 kprintln!("...[failed]");
2227 }
2228
2229 if ok {
2230 *passed += 1;
2231 } else {
2232 *failed += 1;
2233 }
2234}
2235
2236fn create_init_process() {
2238 #[cfg(feature = "alloc")]
2239 {
2240 #[cfg(target_arch = "x86_64")]
2247 {
2248 kprintln!("[BOOTSTRAP] Skipping PCB creation (direct usermode path)");
2249 }
2250
2251 #[cfg(not(target_arch = "x86_64"))]
2254 {
2255 match crate::userspace::load_init_process() {
2256 Ok(_init_pid) => {
2257 kprintln!("[BOOTSTRAP] Init process ready");
2258
2259 #[cfg(not(target_arch = "riscv64"))]
2264 {
2265 let _ = crate::userspace::loader::load_shell();
2266 }
2267 }
2268 Err(_e) => {
2269 kprintln!("[BOOTSTRAP] Init process deferred (kernel shell active)");
2272 }
2273 }
2274 }
2275 }
2276}
2277
2278#[cfg(test)]
2279mod tests {
2280 use super::*;
2281
2282 #[test]
2283 fn test_bootstrap_pid_is_zero() {
2284 assert_eq!(BOOTSTRAP_PID, 0);
2285 }
2286
2287 #[test]
2288 fn test_bootstrap_tid_is_zero() {
2289 assert_eq!(BOOTSTRAP_TID, 0);
2290 }
2291
2292 #[test]
2293 fn test_bootstrap_pid_and_tid_match() {
2294 assert_eq!(BOOTSTRAP_PID, BOOTSTRAP_TID);
2296 }
2297
2298 #[test]
2299 fn test_bootstrap_pid_type() {
2300 let pid: u64 = BOOTSTRAP_PID;
2302 assert!(pid < u64::MAX);
2303 }
2304
2305 #[test]
2306 fn test_bootstrap_constants_are_not_one() {
2307 assert_ne!(BOOTSTRAP_PID, 1);
2309 assert_ne!(BOOTSTRAP_TID, 1);
2310 }
2311
2312 #[test]
2313 fn test_kernel_init_returns_kernel_result() {
2314 fn _assert_return_type() -> KernelResult<()> {
2318 Ok(())
2319 }
2320 assert!(_assert_return_type().is_ok());
2321 }
2322
2323 #[test]
2324 fn test_kernel_result_error_propagation() {
2325 fn inner() -> KernelResult<u32> {
2327 let _: () = Ok::<(), crate::error::KernelError>(())?;
2328 Ok(42)
2329 }
2330 assert_eq!(inner().unwrap(), 42);
2331 }
2332
2333 #[test]
2334 fn test_kernel_result_error_variant() {
2335 fn failing() -> KernelResult<()> {
2336 Err(crate::error::KernelError::NotInitialized { subsystem: "test" })
2337 }
2338 let result = failing();
2339 assert!(result.is_err());
2340 assert_eq!(
2341 result.unwrap_err(),
2342 crate::error::KernelError::NotInitialized { subsystem: "test" }
2343 );
2344 }
2345}