| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Architecture:
- vt: ACTIVE terminal redirect — when set, all gop_print!/put_char/write_str
go there instead of HOME. Terminal::from_buffer() renders into a
WM-owned pixel buffer.
- tty: read_line_from_queue() — canonical-mode line input from the task's
own message queue (TaskMsg::Key). Returns None on Close.
- shell: run_windowed() — same shell as the console but reads from the
message queue. Returns on ^D or window close.
- wm: F1 calls SPAWN_TERMINAL_CB (set by rsdos). No shell logic in the WM.
- rsdos: terminal_task callback + terminal_entry task — creates a 640x400
chrome window, wires up Terminal::from_buffer, sets ACTIVE, runs
shell::run_windowed(), cleans up on exit.
- shell: 'term' debug command that invokes the callback directly and
logs each step to serial.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- wm rewrite: chrome flag per window, create_home_window for the
console (window 0, chrome-less, bottom-pinned, never closed),
composite_rect fills desktop background then blits windows bottom-to-top,
draw_window_intersect handles chrome-less windows, hit_test returns
Content for chrome-less, destroy/move_window no-op for id 0.
- vt: add window_params() so main.rs can wire the Terminal to wm window 0.
- main.rs: create home terminal window 0 and attach Terminal after wm::init().
- Focus fix: focus(0) now stores CONSOLE sentinel (not raw 0) so
focused() returns None when the home terminal has focus. Without this,
closing a GUI window left FOCUSED=0, which tty::poll_key() interpreted
as 'a GUI app has focus', spinning forever and swallowing all keyboard
input.
|
| |
|
|
|
|
|
|
|
|
|
| |
- Refactor vt.rs into a per-instance Terminal struct (owned cell/rendered
grids, cursor, ANSI parser, scroll state), rendering glyphs into a
caller-owned pixel buffer with dirty-region blitting
- Add gop buffer primitives (buffer_glyph_px, buffer_shift_up) and keep
the legacy vt:: API as thin wrappers around the home terminal
- Remove the now-obsolete scroll hook and shadow scroll path
- Home terminal renders into its own buffer; window_id stays None until
the WM integration lands
|
| |
|
|
|
|
|
| |
The console's batched scroll (gop::shift_up_n) shifts the whole shared
shadow, which dragged any composited window pixels up with it. Add a
scroll hook so the window manager re-composites every visible window
after a console scroll, restoring them at their fixed positions.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
- Add the wm window-manager facility per ADR 0004: overlapping
pixel-surface windows, damage-rectangle compositing, WM-drawn title
bar, focus/minimize/close, and F1-F4 keybindings
- Add gop shadow compositing primitives and vt::repaint_region so the
console stays layer 0 beneath windows
- Route mouse (absolute coords, press/release edges) and keyboard
(focus-aware input pump) to the focused window
- Add the rspaint drawing-program crate (pen, 8 colors, clear) and shell
draw/windows/restore commands
- Extend TaskMsg with AppMouse/Focus/Close and document the design in
CONTEXT.md + ADR 0004
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
- 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
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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)
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- 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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
- 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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.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
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
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.
|