From 63d01e9d8eb6f3ccb6a96b7c577834276cf51add Mon Sep 17 00:00:00 2001 From: salmonik Date: Sat, 1 Aug 2026 03:44:57 +0200 Subject: Clean up warnings, fix FAT32 multi-cluster dirs, prep for edition 2024 Warning cleanup (cargo check + clippy now 0 across the workspace): - Migrate all 21 static_mut_refs sites to &raw mut accessors (fat, gop, ps2, vt, ahci, interrupts, memory) so edition 2024 won't deny them - panic = "abort" profiles: bare cargo check/build now works without nightly/-Zbuild-std - Wire TICKS in the timer ISR (it was never incremented, so the vt scroll batching trigger was dead code) - Clippy: efi_main becomes unsafe extern "efiapi" with a # Safety doc, KeyBuf::new uses inline-const array repeat (no interior-mutable const), editor main loop is a while-let, PIT control byte regrouped - [workspace.lints.clippy] allows result_unit_err + needless_range_loop (deliberate kernel style); large_enum_variant allowed on LineInput - Drop now-stale static_mut_refs allow from the rsdos bin FAT32 correctness fixes (both pre-existing, exposed by the SFN fix): - Unique 8.3 short names: to_8_3() never disambiguated collisions, so files sharing a long-name prefix got identical SFNs and fsck reported duplicate directory entries. Add dir_short_names() + unique_short_name() (~N tails, Windows-style) and force LFN when the SFN changes. - Multi-cluster directories: scan_dir/dir_short_names stopped at the first 0x00 slot, hiding every entry written into a chained cluster (writes failed with 'cannot write', duplicate SFNs accumulated); add_dir_entry now packs the cluster (0xE5 deleted-markers) before extending so other FAT readers (mtools, Windows) see the continuation too. Other: delete dead fields (Disk.fis, Volume.fat_count), drop timer_irq/ keyboard_irq/rendered, refresh_and_exit is a documented unsafe fn, CONTEXT .md corrected (stable toolchain, IRQ input, 4-crate layout), .gitignore excludes .pi-subagents artifacts. Validated: cargo check/clippy/fmt clean, make test-disk PASS on fresh and reused images (incl. two directory-chain extensions and ~10 SFN tails), editor round-trip smoke test PASS. --- rsnix/src/interrupts.rs | 70 +++++++------------------------------------------ 1 file changed, 10 insertions(+), 60 deletions(-) (limited to 'rsnix/src/interrupts.rs') diff --git a/rsnix/src/interrupts.rs b/rsnix/src/interrupts.rs index 66dc59f..cbd234e 100644 --- a/rsnix/src/interrupts.rs +++ b/rsnix/src/interrupts.rs @@ -98,7 +98,7 @@ fn pit_set_rate(hz: u64) { let divisor = (PIT_FREQ / hz) as u16; unsafe { // Mode 2, channel 0, lobyte/hibyte, binary - asm!("out dx, al", in("dx") PIT_CMD, in("al") 0b00_11_010_0u8, + asm!("out dx, al", in("dx") PIT_CMD, in("al") 0b0011_0100u8, options(nostack, preserves_flags)); asm!("out dx, al", in("dx") PIT_CH0, in("al") (divisor & 0xFF) as u8, options(nostack, preserves_flags)); @@ -122,47 +122,10 @@ unsafe impl Sync for KeyBuf {} impl KeyBuf { const fn new() -> Self { - // UnsafeCell requires const initialisation in a const ctx. - // Build an array the long way — one cell at a time. - const NEW_CELL: core::cell::UnsafeCell = core::cell::UnsafeCell::new(0); - // `[NEW_CELL; 256]` needs Clone, which UnsafeCell doesn't have. - // Use a union trick or just mark the whole buffer init with zeroes. - // SAFETY: we initialise via the const-fn path in init(). + // Inline-const array repeat (stable since 1.79): each element is a + // fresh `UnsafeCell::new(0)` value, so no interior-mutable const. Self { - buf: [ - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, NEW_CELL, - ], + buf: [const { core::cell::UnsafeCell::new(0) }; 256], head: AtomicU16::new(0), tail: AtomicU16::new(0), } @@ -297,7 +260,10 @@ struct IntFrame { unsafe extern "C" fn isr_dispatch(frame: &IntFrame) { unsafe { match frame.vector { - 32 => eoi(0), + 32 => { + TICKS.fetch_add(1, Ordering::Relaxed); + eoi(0); + } 33 => { let byte: u8; core::arch::asm!("in al, dx", out("al") byte, in("dx") 0x60u16, @@ -311,22 +277,6 @@ unsafe extern "C" fn isr_dispatch(frame: &IntFrame) { } } -/// Timer IRQ (PIT channel 0 ~ 100 Hz). -fn timer_irq() { - eoi(0); -} - -/// Keyboard IRQ — read scancode from port 0x60 and push to ring buffer. -fn keyboard_irq() { - let byte: u8; - unsafe { - asm!("in al, dx", out("al") byte, in("dx") 0x60, - options(nostack, preserves_flags)); - } - KEYBUF.push(byte); - eoi(1); -} - // --------------------------------------------------------------------------- // Public API // --------------------------------------------------------------------------- @@ -348,7 +298,7 @@ pub fn init() { let cs = cs as u16; // Build the IDT. - let idt_ptr = IDT.as_mut_ptr(); + let idt_ptr = core::ptr::addr_of_mut!(IDT[0]); let spurious = isr_stub_spurious as *const () as u64; // Fill all 256 entries with the spurious handler. @@ -370,7 +320,7 @@ pub fn init() { ]; // Load IDT. - asm!("lidt [{}]", in(reg) &IDTR, options(nostack, preserves_flags)); + asm!("lidt [{}]", in(reg) core::ptr::addr_of!(IDTR), options(nostack, preserves_flags)); // Remap PIC and mask everything. remap_pic(); -- cgit v1.2.3