Microkernel based hobby OS

Linting pass

+3 -1
.claude/settings.local.json
··· 81 81 "Bash(cmd /c \"cd /d F:\\OS\\aethelos-source && cargo build 2>&1 | findstr /C:\"Compiling\" /C:\"Finished\" /C:\"error\"\")", 82 82 "Bash(cargo doc:*)", 83 83 "Bash(cmd /c \"cd /d F:\\OS\\aethelos-source && taskkill /F /IM qemu-system-x86_64.exe 2>nul & cd /d F:\\OS\\aethelos-source & del serial.log 2>nul & start /B \"\" \"C:Program Filesqemuqemu-system-x86_64.exe\" -cdrom aethelos.iso -serial file:serial.log -m 256M -display gtk -no-reboot -no-shutdown\")", 84 - "Bash(cmd /c \"cd /d F:\\OS\\aethelos-source && taskkill /F /IM qemu-system-x86_64.exe 2>nul & del serial.log 2>nul & start /B \"\" \"C:Program Filesqemuqemu-system-x86_64.exe\" -cdrom aethelos.iso -serial file:serial.log -m 256M -display gtk -no-reboot -no-shutdown\")" 84 + "Bash(cmd /c \"cd /d F:\\OS\\aethelos-source && taskkill /F /IM qemu-system-x86_64.exe 2>nul & del serial.log 2>nul & start /B \"\" \"C:Program Filesqemuqemu-system-x86_64.exe\" -cdrom aethelos.iso -serial file:serial.log -m 256M -display gtk -no-reboot -no-shutdown\")", 85 + "Bash(cargo fix:*)", 86 + "Bash(tee:*)" 85 87 ], 86 88 "deny": [], 87 89 "ask": []
-6
aethelos-source/heartwood/Cargo.toml
··· 21 21 [[bin]] 22 22 name = "heartwood" 23 23 path = "src/main.rs" 24 - 25 - [profile.dev] 26 - panic = "abort" 27 - 28 - [profile.release] 29 - panic = "abort"
+2 -2
aethelos-source/heartwood/src/attunement/keyboard.rs
··· 35 35 unsafe { 36 36 let keyboard = Keyboard::new(); 37 37 let lock = InterruptSafeLock::new(keyboard); 38 - core::ptr::write(KEYBOARD.as_mut_ptr(), lock); 38 + core::ptr::write(core::ptr::addr_of_mut!(KEYBOARD).cast(), lock); 39 39 KEYBOARD_INITIALIZED = true; 40 40 } 41 41 } ··· 47 47 return; 48 48 } 49 49 50 - let mut keyboard = (*KEYBOARD.as_ptr()).lock(); 50 + let mut keyboard = (*core::ptr::addr_of!(KEYBOARD).cast::<InterruptSafeLock<Keyboard>>()).lock(); 51 51 let scancode = keyboard.read_scancode(); 52 52 53 53 // Ignore key release events (scancode >= 0x80)
-1
aethelos-source/heartwood/src/boot/boot32.rs
··· 7 7 8 8 global_asm!( 9 9 r#" 10 - .intel_syntax noprefix 11 10 .section .boot.text, "awx" 12 11 .code32 13 12 .globl boot32_start
-2
aethelos-source/heartwood/src/boot/multiboot2.rs
··· 8 8 //! This is the handshake between bootloader and kernel - the first 9 9 //! moment of trust between two systems working together. 10 10 11 - use core::arch::global_asm; 12 - 13 11 /// Multiboot2 magic number 14 12 /// Bootloaders look for this to identify our kernel 15 13 pub const MULTIBOOT2_MAGIC: u32 = 0xE85250D6;
+60 -21
aethelos-source/heartwood/src/eldarin.rs
··· 9 9 //! The shell does not merely execute - it interprets, validates, and responds 10 10 //! with both action and wisdom. 11 11 12 - use core::fmt::Write; 13 12 use crate::mana_pool::InterruptSafeLock; 14 13 use core::mem::MaybeUninit; 15 14 ··· 191 190 unsafe { 192 191 let buffer = CommandBuffer::new(); 193 192 let lock = InterruptSafeLock::new(buffer); 194 - core::ptr::write(COMMAND_BUFFER.as_mut_ptr(), lock); 193 + core::ptr::write(core::ptr::addr_of_mut!(COMMAND_BUFFER).cast(), lock); 195 194 BUFFER_INITIALIZED = true; 196 195 197 196 let history = CommandHistory::new(); 198 197 let history_lock = InterruptSafeLock::new(history); 199 - core::ptr::write(COMMAND_HISTORY.as_mut_ptr(), history_lock); 198 + core::ptr::write(core::ptr::addr_of_mut!(COMMAND_HISTORY).cast(), history_lock); 200 199 HISTORY_INITIALIZED = true; 201 200 } 202 201 } 203 202 204 203 /// Get reference to command buffer 205 204 unsafe fn get_buffer() -> &'static InterruptSafeLock<CommandBuffer> { 206 - COMMAND_BUFFER.assume_init_ref() 205 + &*core::ptr::addr_of!(COMMAND_BUFFER).cast::<InterruptSafeLock<CommandBuffer>>() 207 206 } 208 207 209 208 /// Get reference to command history 210 209 unsafe fn get_history() -> &'static InterruptSafeLock<CommandHistory> { 211 - COMMAND_HISTORY.assume_init_ref() 210 + &*core::ptr::addr_of!(COMMAND_HISTORY).cast::<InterruptSafeLock<CommandHistory>>() 212 211 } 213 212 214 213 /// Handle a character from keyboard input ··· 328 327 let has_newline = buffer.as_str().contains('\n'); 329 328 if has_newline { 330 329 // Debug: we found a newline! 331 - let mut port = 0x3f8u16; 330 + let port = 0x3f8u16; 332 331 core::arch::asm!( 333 332 "out dx, al", 334 333 in("dx") port, ··· 382 381 pub fn display_prompt() { 383 382 // Debug: signal that we're about to print prompt 384 383 unsafe { 385 - let mut port = 0x3f8u16; 384 + let port = 0x3f8u16; 386 385 core::arch::asm!( 387 386 "out dx, al", 388 387 in("dx") port, ··· 592 591 0 593 592 }; 594 593 595 - // Draw a beautiful progress bar 596 - crate::println!(" Total Essence: {} KB", total_kb); 597 - crate::println!(); 598 - crate::print!(" ["); 594 + // Sanctuary Pool (Persistent Memory) 595 + crate::println!(" Sanctuary Pool (Persistent):"); 596 + crate::println!(" Total: {} KB", sanctuary_total_kb); 597 + crate::println!(" Used: {} KB", sanctuary_used_kb); 598 + crate::println!(" Free: {} KB", sanctuary_free_kb); 599 599 600 - let bar_width = 50; 601 - let filled = (used_percent as usize * bar_width) / 100; 600 + // Draw sanctuary progress bar 601 + let sanctuary_percent = if stats.sanctuary_total > 0 { 602 + (stats.sanctuary_used * 100) / stats.sanctuary_total 603 + } else { 604 + 0 605 + }; 606 + crate::print!(" ["); 607 + let bar_width = 40; 608 + let filled = (sanctuary_percent as usize * bar_width) / 100; 602 609 for i in 0..bar_width { 603 610 if i < filled { 604 611 crate::print!("█"); ··· 606 613 crate::print!("░"); 607 614 } 608 615 } 609 - crate::println!("] {}%", used_percent); 616 + crate::println!("] {}%", sanctuary_percent); 610 617 crate::println!(); 611 618 612 - crate::println!(" Sustenance (Used): {} KB", used_kb); 613 - crate::println!(" Free Flow (Available): {} KB", free_kb); 619 + // Ephemeral Pool (Temporary Memory) 620 + crate::println!(" Ephemeral Mist (Temporary):"); 621 + crate::println!(" Total: {} KB", ephemeral_total_kb); 622 + crate::println!(" Used: {} KB", ephemeral_used_kb); 623 + crate::println!(" Free: {} KB", ephemeral_free_kb); 624 + 625 + // Draw ephemeral progress bar 626 + let ephemeral_percent = if stats.ephemeral_total > 0 { 627 + (stats.ephemeral_used * 100) / stats.ephemeral_total 628 + } else { 629 + 0 630 + }; 631 + crate::print!(" ["); 632 + let filled = (ephemeral_percent as usize * bar_width) / 100; 633 + for i in 0..bar_width { 634 + if i < filled { 635 + crate::print!("█"); 636 + } else { 637 + crate::print!("░"); 638 + } 639 + } 640 + crate::println!("] {}%", ephemeral_percent); 614 641 crate::println!(); 615 642 616 - crate::println!(" Sanctuary (Long-lived):"); 617 - crate::println!(" Used: {} KB / {} KB", sanctuary_used_kb, sanctuary_total_kb); 618 - crate::println!(); 643 + // Overall Summary 644 + crate::println!(" Overall Summary:"); 645 + crate::println!(" Total: {} KB", total_kb); 646 + crate::println!(" Used: {} KB", used_kb); 647 + crate::println!(" Free: {} KB", free_kb); 619 648 620 - crate::println!(" Ephemeral Mist (Short-lived):"); 621 - crate::println!(" Used: {} KB / {} KB", ephemeral_used_kb, ephemeral_total_kb); 649 + // Draw total progress bar 650 + crate::print!(" ["); 651 + let bar_width = 40; 652 + let filled = (used_percent as usize * bar_width) / 100; 653 + for i in 0..bar_width { 654 + if i < filled { 655 + crate::print!("█"); 656 + } else { 657 + crate::print!("░"); 658 + } 659 + } 660 + crate::println!("] {}%", used_percent); 622 661 crate::println!(); 623 662 624 663 crate::println!(" Total Objects: {}", stats.total_objects);
+1 -1
aethelos-source/heartwood/src/irq_safe_mutex.rs
··· 18 18 } 19 19 } 20 20 21 - pub fn lock(&self) -> IrqSafeMutexGuard<T> { 21 + pub fn lock(&self) -> IrqSafeMutexGuard<'_, T> { 22 22 // Check if interrupts are currently enabled 23 23 let were_enabled: bool; 24 24 unsafe {
+1 -1
aethelos-source/heartwood/src/loom_of_fate/context.rs
··· 436 436 /// 437 437 /// This function is called when a new thread is first scheduled. 438 438 /// It handles any setup needed before calling the actual entry point. 439 - pub extern "C" fn thread_entry_wrapper(entry_point: fn() -> !) -> ! { 439 + pub extern "C" fn thread_entry_wrapper(entry_point: extern "C" fn() -> !) -> ! { 440 440 // Enable interrupts for this new thread 441 441 unsafe { 442 442 asm!("sti", options(nomem, nostack));
+2 -2
aethelos-source/heartwood/src/loom_of_fate/mod.rs
··· 69 69 serial_out(b'D'); // InterruptSafeLock created 70 70 71 71 // Write the small InterruptSafeLock<Box<Scheduler>> to static 72 - core::ptr::write(LOOM.as_mut_ptr(), lock); 72 + core::ptr::write(core::ptr::addr_of_mut!(LOOM).cast(), lock); 73 73 serial_out(b'y'); // Written to MaybeUninit 74 74 75 75 LOOM_INITIALIZED = true; ··· 110 110 /// # Safety 111 111 /// LOOM must be initialized before calling this function 112 112 pub unsafe fn get_loom() -> &'static InterruptSafeLock<Box<Scheduler>> { 113 - LOOM.assume_init_ref() 113 + &*core::ptr::addr_of!(LOOM).cast::<InterruptSafeLock<Box<Scheduler>>>() 114 114 } 115 115 116 116 /// Spawn a new thread
+12 -2
aethelos-source/heartwood/src/loom_of_fate/scheduler.rs
··· 54 54 55 55 // Pre-allocate capacity to prevent reallocation during push 56 56 // This avoids memory overlap between Vec storage and stack allocations 57 - let mut threads = Vec::with_capacity(16); 57 + let threads = Vec::with_capacity(16); 58 58 unsafe { serial_out(b'b'); } // threads Vec created 59 - let mut stacks = Vec::with_capacity(16); 59 + let stacks = Vec::with_capacity(16); 60 60 unsafe { serial_out(b'c'); } // stacks Vec created 61 61 let ready_queue = VecDeque::new(); 62 62 unsafe { serial_out(b'd'); } // ready_queue created ··· 250 250 /// 251 251 /// # Safety 252 252 /// Assumes both thread IDs are valid and the threads exist 253 + /// 254 + /// Note: This is an old implementation from preemptive scheduling experiments. 255 + /// The system now uses a different approach (cooperative + interrupt-based). 256 + /// Kept as reference for alternative scheduling strategies. 257 + #[allow(dead_code)] 253 258 fn perform_context_switch(&mut self, from_id: ThreadId, to_id: ThreadId) { 254 259 // Get raw pointers to the contexts before borrowing 255 260 let from_idx = self.threads.iter().position(|t| t.id() == from_id).unwrap(); ··· 276 281 /// 277 282 /// # Safety 278 283 /// This function never returns normally - it restores the thread's context 284 + /// 285 + /// Note: Old implementation from preemptive scheduling experiments. 286 + /// Current system uses context::context_switch_first() instead. 287 + /// Kept as reference for alternative boot strategies. 288 + #[allow(dead_code)] 279 289 fn restore_first_thread(&mut self, to_id: ThreadId) -> ! { 280 290 // Find the thread's context 281 291 let to_idx = self.threads.iter().position(|t| t.id() == to_id).unwrap();
+4 -4
aethelos-source/heartwood/src/loom_of_fate/system_threads.rs
··· 10 10 //! The keyboard thread listens attentively to user intentions. 11 11 //! The shell thread translates human wishes into system actions. 12 12 13 - use super::{ThreadPriority, yield_now}; 13 + use super::yield_now; 14 14 15 15 /// The Idle Thread - The First Awakening 16 16 /// ··· 32 32 33 33 // DEBUG: Silent marker that we've awakened 34 34 unsafe { 35 - let mut port = 0x3f8u16; 35 + let port = 0x3f8u16; 36 36 core::arch::asm!( 37 37 "out dx, al", 38 38 in("dx") port, ··· 65 65 66 66 // DEBUG: Interrupts enabled 67 67 unsafe { 68 - let mut port = 0x3f8u16; 68 + let port = 0x3f8u16; 69 69 core::arch::asm!( 70 70 "out dx, al", 71 71 in("dx") port, ··· 191 191 ); 192 192 let interrupts_enabled = (flags & 0x200) != 0; 193 193 194 - let mut port = 0x3f8u16; 194 + let port = 0x3f8u16; 195 195 core::arch::asm!( 196 196 "out dx, al", 197 197 in("dx") port,
+7
aethelos-source/heartwood/src/loom_of_fate/thread.rs
··· 37 37 pub(crate) id: ThreadId, 38 38 pub(crate) state: ThreadState, 39 39 pub(crate) priority: ThreadPriority, 40 + 41 + /// Entry point function - kept for debugging/inspection 42 + #[allow(dead_code)] 40 43 pub(crate) entry_point: fn() -> !, 41 44 42 45 // CPU state (for context switching) 43 46 pub(crate) context: ThreadContext, 47 + 48 + /// Stack boundaries - kept for future stack overflow detection 49 + #[allow(dead_code)] 44 50 pub(crate) stack_bottom: u64, 51 + #[allow(dead_code)] 45 52 pub(crate) stack_top: u64, 46 53 47 54 // Harmony tracking
+6 -2
aethelos-source/heartwood/src/main.rs
··· 15 15 extern crate alloc; 16 16 17 17 // Reference the modules from lib.rs 18 - use heartwood::{nexus, loom_of_fate, mana_pool, attunement, vga_buffer}; 18 + use heartwood::{nexus, loom_of_fate, mana_pool, attunement}; 19 19 20 20 // Need to use macros with #[macro_use] 21 21 #[macro_use] ··· 101 101 } 102 102 103 103 // UNREACHABLE - the bootstrap ghost is gone 104 - unreachable!("The Great Hand-Off should never return") 104 + // This is intentional defensive programming to document the expected behavior 105 + #[allow(unreachable_code)] 106 + { 107 + unreachable!("The Great Hand-Off should never return") 108 + } 105 109 } 106 110 107 111 /// Initialize the Heartwood's core systems
+1 -1
aethelos-source/heartwood/src/mana_pool/buddy.rs
··· 210 210 /// unused parts to the appropriate free lists 211 211 fn split_block(&mut self, block: NonNull<Block>, current_order: usize, target_order: usize) { 212 212 let mut order = current_order; 213 - let mut addr = block.as_ptr() as usize; 213 + let addr = block.as_ptr() as usize; 214 214 215 215 while order > target_order { 216 216 order -= 1;
+1 -1
aethelos-source/heartwood/src/mana_pool/interrupt_lock.rs
··· 33 33 } 34 34 35 35 /// Acquire the lock, returning a guard that restores interrupt state on drop 36 - pub fn lock(&self) -> InterruptSafeLockGuard<T> { 36 + pub fn lock(&self) -> InterruptSafeLockGuard<'_, T> { 37 37 // Save current interrupt state 38 38 let interrupts_enabled = are_interrupts_enabled(); 39 39
+2 -2
aethelos-source/heartwood/src/mana_pool/mod.rs
··· 174 174 let lock = InterruptSafeLock::new(mana_pool_on_heap); 175 175 serial_out(b'Q'); // After InterruptSafeLock::new 176 176 177 - core::ptr::write(MANA_POOL.as_mut_ptr(), lock); 177 + core::ptr::write(core::ptr::addr_of_mut!(MANA_POOL).cast(), lock); 178 178 serial_out(b'R'); // Written to static 179 179 180 180 MANA_POOL_INITIALIZED = true; ··· 184 184 185 185 /// Get reference to MANA_POOL (assumes initialized) 186 186 unsafe fn get_mana_pool() -> &'static InterruptSafeLock<Box<ManaPool>> { 187 - MANA_POOL.assume_init_ref() 187 + &*core::ptr::addr_of!(MANA_POOL).cast::<InterruptSafeLock<Box<ManaPool>>>() 188 188 } 189 189 190 190 /// Allocate memory with a specific purpose
+2
aethelos-source/heartwood/src/mana_pool/object_manager.rs
··· 20 20 21 21 /// An object in the Mana Pool 22 22 struct Object { 23 + /// Object handle - kept for future reverse lookups and debugging 24 + #[allow(dead_code)] 23 25 pub(super) handle: ObjectHandle, 24 26 pub(super) object_type: ObjectType, 25 27 pub(super) address: usize,
+2 -2
aethelos-source/heartwood/src/nexus/mod.rs
··· 52 52 let lock = InterruptSafeLock::new(nexus_core); 53 53 serial_out(b'u'); // After InterruptSafeLock::new 54 54 55 - core::ptr::write(NEXUS.as_mut_ptr(), lock); 55 + core::ptr::write(core::ptr::addr_of_mut!(NEXUS).cast(), lock); 56 56 serial_out(b'!'); // Written to static 57 57 58 58 NEXUS_INITIALIZED = true; ··· 61 61 62 62 /// Get reference to NEXUS (assumes initialized) 63 63 unsafe fn get_nexus() -> &'static InterruptSafeLock<NexusCore> { 64 - NEXUS.assume_init_ref() 64 + &*core::ptr::addr_of!(NEXUS).cast::<InterruptSafeLock<NexusCore>>() 65 65 } 66 66 67 67 /// Send a message through the Nexus
+5 -61
aethelos-source/heartwood/src/vga_buffer.rs
··· 242 242 243 243 // Wrap in IRQ-safe mutex and write to static 244 244 let mutex = IrqSafeMutex::new(writer); 245 - core::ptr::write(WRITER.as_mut_ptr(), mutex); 245 + core::ptr::write(core::ptr::addr_of_mut!(WRITER).cast(), mutex); 246 246 WRITER_INITIALIZED = true; 247 247 248 248 // Clear the screen 249 - let mut writer = WRITER.assume_init_mut().lock(); 249 + let mut writer = (*core::ptr::addr_of_mut!(WRITER).cast::<IrqSafeMutex<Writer>>()).lock(); 250 250 for row in 0..BUFFER_HEIGHT { 251 251 writer.clear_row(row); 252 252 } ··· 258 258 259 259 /// Get reference to WRITER (assumes initialized) 260 260 unsafe fn get_writer() -> &'static IrqSafeMutex<Writer> { 261 - WRITER.assume_init_ref() 261 + &*core::ptr::addr_of!(WRITER).cast::<IrqSafeMutex<Writer>>() 262 262 } 263 263 264 264 /// Force unlock the VGA writer (for use before context switches) ··· 268 268 /// no other code will try to use the lock. 269 269 pub unsafe fn force_unlock() { 270 270 if WRITER_INITIALIZED { 271 - let writer = WRITER.assume_init_mut(); 271 + let writer = &mut *core::ptr::addr_of_mut!(WRITER).cast::<IrqSafeMutex<Writer>>(); 272 272 writer.force_unlock(); 273 273 } 274 274 } ··· 282 282 } 283 283 284 284 // Get raw pointer to the writer inside the IRQ-safe mutex 285 - let writer_ptr = WRITER.as_ptr() as *mut IrqSafeMutex<Writer>; 285 + let writer_ptr = core::ptr::addr_of_mut!(WRITER).cast::<IrqSafeMutex<Writer>>(); 286 286 // Access the inner Mutex to get the data (unsafe pointer dereference) 287 287 let inner_mutex = &mut (*writer_ptr).inner; 288 288 let writer = inner_mutex.get_mut(); ··· 392 392 } 393 393 } 394 394 } 395 - 396 - /// Execute a closure with interrupts disabled 397 - /// This prevents deadlocks when acquiring locks that might be used in interrupt handlers 398 - fn without_interrupts<F, R>(f: F) -> R 399 - where 400 - F: FnOnce() -> R, 401 - { 402 - // Check if interrupts are currently enabled 403 - let were_enabled: bool; 404 - unsafe { 405 - let flags: u64; 406 - core::arch::asm!( 407 - "pushfq", 408 - "pop {0}", 409 - out(reg) flags, 410 - options(nomem, preserves_flags) 411 - ); 412 - were_enabled = (flags & 0x200) != 0; 413 - } 414 - 415 - // Disable interrupts 416 - unsafe { 417 - core::arch::asm!("cli", options(nomem, nostack, preserves_flags)); 418 - } 419 - 420 - // Execute the closure 421 - let result = f(); 422 - 423 - // Only re-enable if they were enabled before 424 - // This prevents re-enabling interrupts during early boot 425 - if were_enabled { 426 - unsafe { 427 - core::arch::asm!("sti", options(nomem, nostack, preserves_flags)); 428 - 429 - // Debug: output to serial that we re-enabled interrupts 430 - core::arch::asm!( 431 - "mov dx, 0x3f8", 432 - "mov al, 0x2B", // '+' = re-enabled 433 - "out dx, al", 434 - options(nomem, nostack, preserves_flags) 435 - ); 436 - } 437 - } else { 438 - unsafe { 439 - // Debug: output that we DIDN'T re-enable 440 - core::arch::asm!( 441 - "mov dx, 0x3f8", 442 - "mov al, 0x2D", // '-' = stayed disabled 443 - "out dx, al", 444 - options(nomem, nostack, preserves_flags) 445 - ); 446 - } 447 - } 448 - 449 - result 450 - }