summaryrefslogtreecommitdiffstats
path: root/rsnix/src/vt.rs (follow)
Commit message (Collapse)AuthorAgeFilesLines
* USB2/1.1 (EHCI/UHCI) drivers + real-hardware bring-up hardeningsalmonik2026-08-171-2/+49
| | | | | | | | | | | | | - Add polled EHCI (USB2) and UHCI (USB1.1) host-controller drivers with HID boot mouse support, wired into cursor polling and the 'usb' shell cmd - Add USB Legacy ownership handoff (claim_usb_legacy) plus config_write_byte - Harden boot: verify the PIT/timer ticks before shell entry, EOI stray interrupts in the LAPIC to stop interrupt storms, bound PS/2 controller waits, and INTx-disable AHCI (polled driver) - Add boot stage markers, klog screen echo, and QR lock; scheduler mark_shell_running; NO_USB stopgap to keep BIOS USB-Legacy input alive - alloc_pages_above for DMA buffers that must avoid low conventional memory - Expand DEBUG_NOTES with EHCI/QEMU bring-up findings
* v0.5.9: fix OptiPlex heap crash — EBS retry must not rebuild the free listsalmonik2026-08-041-25/+44
| | | | | | | | | | | | | | | | | | | | | | | Root cause: on real hardware SetMode can invalidate the pre-captured ExitBootServices map key, so EBS fails and the retry refreshed the map via capture_memory_map -> init_heap, which REBUILT the free list from the raw map and wiped the allocation state of every pre-EBS live object (the display shadow and the vt grids). Their spans became free while still live, later allocations carved inside the shadow, and the display writes clobbered them — zeroed back-pointers (family A ptr=0x404443e0 block=0x0) and gray glyph pixels (family B 0xaaaaaa00aaaaaa = 0x00AAAAAA = PALETTE[7] fg-7 text colour, not a firmware scrub). Fix: refresh_and_exit now re-captures the map and returns a fresh EBS key without rebuilding the free list (refresh_map_key); the free list is the authoritative live-allocation state. Verified in QEMU under a forced EBS failure (SIMULATE_EBS_FAILURE test hook): verify ok, probe NOT free, flhead outside the shadow — identical to a clean boot, and the full shell sequence is crash-free. Also: removed the crash-family debug markers from the screen (boot-time heapdbg lines, vt verify marker, shadow marker) — the vt grid self-check stays serial-only. Version 0.5.8 -> 0.5.9.
* v0.5.8: heap-free QR encoder + crash-dump QR on framebuffersalmonik2026-08-031-1/+5
| | | | | | | | | | | | | | | | | | | | | | | Real hardware has no serial console, so a kernel crash only leaves a frozen screen. Every dump_lines() report now also renders the crash text as a scannable QR below the white-on-red band (photograph the screen instead of relaying text). - rsnix/src/qr.rs: from-scratch no_std/no_alloc byte-mode QR encoder (EC-L, v1..v40, .bss statics only — safe on the fault path): RS over GF(256), codeword interleave, zigzag placement, 8 masks with N1-N4 penalty auto-selection, format/version info. - gop.rs: dump_qr() joins dump lines into a static buffer, truncates with '...' at the v40-L capacity, encodes, and renders centered black-on-white with a 4-module quiet zone. - tools/qrcheck: host harness (embedds qr.rs) + qrcheck.py cross-check against segno's placement primitives. Verified bit-exact: 12 versions x 8 masks forced, plus auto-mask choice matches segno's penalty evaluation. Caught 3 encoder bugs (multi-block interleave offsets, transposed version info, mask eval ordering). - QEMU e2e: page-fault dump screendump decodes via zbarimg, content matches the serial log line-for-line. - test-msg.sh and test-fault.sh both PASS; debug+release 0 warnings.
* v0.5.7: fix vt verify content check — expect BLANK (0x70020), not zerosalmonik2026-08-031-28/+104
| | | | | | | | | | | | | | | | | | | | | | | The pre-verify 0x70020 'mystery' was a debug artifact, not corruption: BLANK = {ch:32, fg:7, bg:0} = raw 0x70020, and vec![BLANK; n] fills both grids with it at init. The old check compared cells against 0 and its probe loop break-ed on the first non-zero cell, so probes 1-3 stayed at their zero-initialized slots — c=[0x70020,0,0,0] was bogus on every healthy boot. A full-grid dump proves QEMU grids are 100% BLANK at shell entry (nz=3700 blank=3700). Fix: probes compare against blank_raw (0x70020), record all four values (no early break), probe both cells and rendered, and add a full-grid nz/blank summary line. The OptiPlex firmware 0x00AAAAAA scrub remains cleanly distinguishable (scrub != blank). Markers: the shell banner occupies grid rows 0-1 and the prompt row 2 (proven by screendump), and a stale crash.log replays at rows 2+, so the shadow and vt markers moved to the bottom of the screen via the new gop::text_rows()/bottom_row(off) helpers instead of rows 1-2. QEMU verified: verify: ok every boot; test-msg + test-fault PASS; debug and release builds 0 warnings.
* v0.5.7: guard dumps block-header math + 16-word window; vt content verify; ↵salmonik2026-08-031-3/+30
| | | | | | | | | | | | | | | | | | | shadow marker The klog -t 2 crash drops a 126-byte String (the vt verify klog line) whose data ptr 0x40444970 points into the first-heap-block region whose content is the firmware 0x00AAAAAA scrub — a stale pointer, not a real allocation (back-pointer slot never written). Upgrades so the next real-hardware crash shows the full picture: - guard: explicit candidate block bases (b=ptr-24 / b16=ptr-32) with their size/free fields, plus a 16-word window (mem..mem4) from ptr-0x30 instead of the old 8 words - vt::debug_verify: content probe of the cells grid (must be all-BLANK at shell entry) — catches a stale in-heap cells pointer that passes the range checks - gop: on-screen marker for shadow carved vs NO-SHADOW fallback (the scrub content at the crash ptr suggests the shadow was rejected and its block stayed free + firmware-scrubbed)
* v0.5.7: vt verify also as a boot marker (real hardware has no serial)salmonik2026-08-021-0/+12
|
* v0.5.7: drop test-poison hooks; vt heap-struct verify at shell entrysalmonik2026-08-021-0/+42
| | | | | | | | | | | The OptiPlex's first banner write #GPs when the vt cells VecData holds firmware 0xAA fill instead of a real buffer pointer. The poison/fill test hooks (stack + free-heap + free-page 0x00AAAAAA) were removed from the release image — they changed boot behavior and may walk a corrupt free list over live blocks. Added vt::debug_verify() (cells/rendered ptr/cap/len + in-heap check) at shell entry: the next real-hardware boot shows whether the corruption is present at shell entry or lands during the banner write.
* v0.5.5: self-diagnosing boot — vt refuses 0x0 geometry, panic band shows ↵salmonik2026-08-021-0/+20
| | | | | | | | | | | | | | | | | | | | | last stage The user's real-hardware boot showed 'PANIC: index out of bounds (len 0, index 0) at vt.rs:146' — the vt grid was created empty because the framebuffer geometry was 0x0 at vt::init (GOP missing or the active mode reporting zero resolution). The v0.5.4 blank screen was the same panic, previously invisible (no screen dump in the panic handler). - vt::init: rows/cols == 0 now halts with a visible white-on-red 'FATAL: no framebuffer geometry — GOP missing or active mode is 0x0' band instead of building an empty grid that panics at the first cell write. - boot_marker records the last boot stage; the panic band appends it as a 4th line so a crash shows exactly how far boot got. - The gop+vt marker now carries the measured geometry ('rsnix: gop 800x600 vt 100x37 ok') so a good boot is self-confirming on the screen. - All 5 test suites pass; build/clippy clean.
* klog: [ssss.mmm] millisecond timestamps from the PITsalmonik2026-08-011-3/+9
| | | | | | | | | | | | | | | | | | | | - interrupts::uptime_ms(): monotonic ms since boot — the 100 Hz PIT tick (10 ms) plus interpolation from the PIT's live 1.19 MHz down-counter (read twice around the tick load; a count jump means a tick fired between reads) for true sub-ms resolution. TICKS widened AtomicU16 -> AtomicU64 (u16 wrapped after ~11 min). - PIT_READY gates interpolation until interrupts::init configures the timer, so early-boot lines are deterministically [0000.000] instead of uninitialised-PIT noise; klog clamps timestamps monotonic. - The CMOS RTC cannot provide milliseconds (1 Hz BCD device, seconds only) — millis come from the PIT. - klog stores ms per line at append time; dump format is now '[0000.123] 000000 === rsnix boot ===' (user-specified format). Verified in QEMU: first line [0000.000], Phase-2 lines show real monotonic ms (fs: vfs ready at [0000.519], self-test [0000.524]), per-dump monotonicity, boot.log persists timestamps, test-disk round trip fsck-clean.
* Bump workspace to edition 2024salmonik2026-08-011-7/+1
| | | | | | | | | | | | | | - edition = "2024" in the workspace manifest and rsdosedit - extern blocks must be unsafe: interrupts.rs ISR stubs -> unsafe extern "C" - #[no_mangle] -> #[unsafe(no_mangle)] (efi_main, isr_dispatch) - One missed static-mut read in free_list_insert wrapped in an explicit unsafe block (edition 2024 removed the implicit unsafe context inside unsafe fns) - rustfmt reflows for 2024: nested if-lets become let-chains, imports re-sorted, rsdosedit help-screen box rows wrapped No codegen-affecting changes. Validated: cargo check/clippy/fmt clean (host + uefi target), make test-disk PASS, editor round-trip PASS.
* Clean up warnings, fix FAT32 multi-cluster dirs, prep for edition 2024salmonik2026-08-011-4/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* ahci: SATA driver + FAT32 persistent disk mounted at /disksalmonik2026-07-311-3/+1
| | | | | | | | | | | | | | | | | | - ahci.rs: polling AHCI on PCI class 1/6/1, bus mastering + ABAR map, port 0 up, IDENTIFY + READ/WRITE DMA EXT through one 4KiB DMA buffer - fat.rs: BPB parse, whole-FAT RAM cache with write-back to both copies, LFN read/write, dirs, multi-cluster files, FSInfo free-count sync, space-padded dot entries ('..' = cluster 0 under root), fsck-clean - fs.rs: /disk mount node + 24-slot ephemeral node pool; ls/cat/hexdump/ echo/mkdir/touch/rm/edit all work on disk paths unchanged - QEMU: explicit bus assignment (disk=ide.0, ESP=ide.1); the implicit fat:rw:esp drive was stealing AHCI port 0 - Debugged against QEMU source: header DW0 is CFL in bits 4:0 / PRDTL in bits 31:16 (Linux libahci layout), FIS count at bytes 12-13, device at byte 7; QEMU rejects H2D FIS flags bits 6:4, so direction is the header W bit only - Verified: full shell round-trip on /disk, reboot persistence (poweroff then mdir/mtype and a fresh boot), fsck.fat clean
* vt: defer scrolls and batch framebuffer pushessalmonik2026-07-311-5/+66
| | | | | | | | | | | | | | | | | | | | | | | | Streaming output scrolled one framebuffer push per line (each a ~3-8 MB write-only copy). The vt now scrolls the logical grid instantly in RAM and defers the display shift: N pending scrolls are pushed together as one shift_up_n — one push regardless of batch size. - vt: PENDING_SCROLLS counter; scroll_up shifts CELLS only; flush renders nothing while pending (the diff would otherwise re-rasterise the whole screen per line); sync_scroll() does one gop::shift_up_n + RENDERED mirror + normal diff flush (which re-blits just the newly exposed rows and the cursor). - Sync triggers: batch of 16 rows, ~40 ms of stream pause (100 Hz TICKS), any CSI sequence (full-screen apps like the editor render immediately), clear_all/set_cursor_visible, interactive input (tty read_line/read_byte), and the shell before each prompt. - gop: shift_up → shift_up_n(n) (one shadow memcpy + one push). Verified in QEMU: mmap/hexdump streaming renders in coherent batches with the prompt syncing at the end; clear wipes clean; the editor scrolls and redraws immediately (45-line file, gutter + status bar intact, cursor correct); save/exit/cat round-trip unchanged. Release and dev builds pass.
* vt: don't strand stale inverse cursor cells on scroll/clearsalmonik2026-07-311-7/+26
| | | | | | | | | | | | | | | | | | | | | | | | | | The cursor was blitted as an inverse-video cell directly onto the framebuffer, but that inversion was never recorded. RENDERED (the diff grid) only stored the logical cell, so when scrolling shifted the raw pixels up (gop::shift_up), the stale inverse block rode along while the grids said 'blank' — and blank-vs-blank never re-blits. Result: a cursor-shaped block at the end of every scrolled line, surviving even 'clear'. - flush() now mirrors the inverse colours into RENDERED when drawing the cursor (and restores RENDERED when erasing it), and the diff loop skips the visible cursor cell (owned by the cursor pass). Any scroll/clear then sees CELLS != RENDERED at a stale-inverse position and repaints it. - memory.rs heap self-test: snapshot heap state before its own allocations and assert the heap returns to that state, instead of asserting it coalesces to a single empty block. The vt cell grids (allocated earlier in boot) made the old 'free_blocks == 1' check fail; the new check is correct regardless of prior live allocations. Verified in QEMU: hexdump /dev/mem streams hundreds of lines, ^C, screendump shows exactly one inverse cell (the live cursor); 'clear' leaves exactly one (the fresh prompt cursor). heap self-test OK again.
* vt: decode UTF-8, render box-drawing/arrow glyphs procedurallysalmonik2026-07-311-17/+70
| | | | | | | | | | | | | | | | | The editor's gutter '│' (U+2502) appeared as '???' — write_bytes fed each UTF-8 byte to the state machine, which mapped every byte >= 0x80 to '?', and the Latin-1 font has no box-drawing glyphs anyway. - vt.write_bytes now decodes UTF-8 sequences; printable non-ASCII dispatches to the glyph path instead of the byte parser. - gop: unicode_glyph_bits() procedurally rasterises box-drawing (U+2500-257F light/heavy/double), arrows (U+2190-2193) and the em dash (U+2014) — pure geometry, no font data needed; blit_glyph falls back to it for ch >= 256. Verified via framebuffer dumps: editor gutter │ renders as a vertical line, help screen ═ separators and ←→↑↓ all render as lines (no '?'). Shell banner em dash renders too.
* tty + vt terminal split, rsdosedit editor (1:1 UNIX console)salmonik2026-07-311-0/+476
Kernel now has the classic UNIX console split, so full-screen ANSI apps can run in ring 0: - vt.rs: terminal emulator owning the text screen — cell grid (char + fg/bg), logical cursor (inverse-video), scrolling, and a small ANSI CSI parser (cursor position H/f, erase J/K, moves A-D, SGR 16-colour with correct ANSI→VGA mapping, cursor show/hide ?25). Blits only changed cells; scroll shifts cell grids + pixels and re-rasterises only the exposed bottom row. gop_println!/clear_screen now render through the vt; gop.rs is the raw rasteriser (colored glyph blits, pixel shift). - tty.rs: line discipline — canonical read_line (echo, line buffer, ^C cancel, ^D EOF) moved out of the shell, and raw read_byte that translates KeyEvents to the terminal byte protocol (arrows → ESC[A-D, Backspace → 0x7f, ^X → 0x18, Ctrl+arrows → ESC[1;5A-D, Home/End/PgUp/ PgDn/Delete). interrupt_pressed() stays for streaming commands. - ps2: generic Ctrl(char) + CtrlArrow events (was: only CtrlC/CtrlD). - rsdosedit: no_std port of the RNG rsedit editor as the first real app — undo, syntax highlighting (verified green/gray/yellow on the framebuffer), search, word nav, smart indent, ^S save / ^X exit / ^X again to discard. termios → tty raw, stdout → vt, std::fs → VFS (ramfs), SIGWINCH → fixed geometry, force-exit window → key counter. - shell: 'edit <path>' command; read_line/strbuf moved to rsnix. - CONTEXT.md: layout + milestones + known-issue perf notes. Verified in QEMU: full edit → type → arrow-move → insert → save → exit round trip with byte-exact file content; ANSI colors via screendump.