| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Real hardware has no serial console: a pre-shell panic was a silent
blank screen (the panic handler only wrote to serial, then cli;hlt).
v0.5.4's shadow change made this window reachable — if the fb-aware
page allocation or the heap fallback failed on hardware, the kernel
halted before the shell banner with zero screen output.
- gop::boot_marker(): every boot stage now draws straight to the
framebuffer (row 0, white-on-black). The last marker visible before
a hang identifies where the kernel died.
- Panic handler: pre-shell panics now draw a white-on-red
'*** PANIC *** <msg> at file:line' band via gop::dump_lines.
- init_shadow(): heap fallback is panic-proof (try_reserve_exact +
resize instead of vec![0; words] which aborts on OOM); page-alloc
result defensively re-checked against the fb region; any failure
degrades to no-shadow mode with a visible warning band.
- Verified: full chain (rsboot -> kernel) boots with markers, shell
banner renders, all 5 test suites pass.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Real-hardware scroll freeze (no exception, QEMU-clean) — the per-word
push (0.5.3) did not fix it, so the wedge is upstream of the push.
A QEMU slow-display simulation (new DISPLAY_STALL knob + shell 'stall'
command busy-waits per display store, mimicking an uncached real-GPU
framebuffer) proved the per-word push and shadow memmove are slow but
finite — the shell keeps ticking, scrolls eventually complete. The
freeze mechanism QEMU cannot exhibit is the shadow *landing on the
framebuffer*: the heap free list spans the fb hole, so the 1.9 MB heap
shadow can alias the display on machines where firmware reports the fb
as ConventionalMemory — every scroll then becomes an MMIO->MMIO memcpy
on an uncached framebuffer, which wedges real hardware (a stall, no
fault, hence no dump).
Fix:
- gop::init_shadow(): allocate the shadow from the fb-aware page
allocator (init_page_allocator marks fb pages used per-page), so it
can never overlap the display; heap allocation kept only as a
fallback with an explicit overlap rejection. Boot log now prints
'gop: shadow @ <addr> ... origin=page-alloc|heap|none'.
- Scroll shadow memmove converted to per-word stores (belt and
suspenders — immune to any future fb-aliased shadow).
- Verified on QEMU: shadow @ 0x100000 vs fb 0x80000000..0x801d5000,
overlap=false; all 5 test suites pass; scroll completes even under
the stalled-display simulation.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The real-hardware scroll crash (white bands + instant freeze, QEMU-clean)
was invisible because the only trace was a single serial line on machines
with no serial console. This makes every crash self-identifying and
hardens the real-hardware failure surfaces:
- Every CPU exception vector 0-31 now has an IDT entry (macro-generated
stubs; 8/14 keep their IST stacks). A fault in the shell prints a
white-on-red band to the framebuffer via gop::dump_lines (raw fb
writes bypassing the vt, fully clamped) plus a parseable serial line:
'!!! <kind> vec=N err=… rip=… cr2=… rsp=… rflags=… task=N "name"',
then halts — instead of converging to a cryptic double fault.
Background-task faults abort the task as before.
- Boot log now reports the authoritative post-SetMode geometry:
'gop: fb base=… size=… pitch=… WxH bpp=… bgr=…', so the next real
machine's report identifies whether pitch*height exceeds the mapping.
- Framebuffer writes (clear, push_rect, shift_up_n bulk push, cursor
overlay) are clamped to the firmware's framebuffer_size: a pitch-
padded mode degrades to a truncated view instead of faulting past
the mapping.
- The GOP framebuffer region is excluded from the page allocator (and
subtracted from the heap's conventional-region pick) even when the
firmware lists it as ConventionalMemory — kernel allocations can
never overwrite the display again. The GOP protocol is located and
peeked before the memory map is captured so the exclusion is known
at heap-init time.
- Shell gains a hidden 'fault' command (deliberate unmapped write) and
'make test-fault' verifies the dump: vec=14, cr2=0x400000000000,
task=0, halt — no triple fault. All other suites re-pass.
- CONTEXT.md: fault-dump format documented for real-hardware reports.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The first visible GUI surface: real rect primitives, a single
shadow→display push path, and an on-screen mouse cursor that can
never race the text surface.
gop:
- fill_rect + push_rect(x,y,w,h): every raster op rasterises into the
RAM shadow, then push_rect copies the rect to the display (write-only,
still never read) and composites the cursor on top. blit_glyph and
scroll shifts now route through it.
- cursor overlay: 12x16 pointer (const-fn built from column lists) drawn
white with a black offset outline; position in one AtomicU64 (x:high
32, y:low 32) — unpack masks the low word (a bare 'as usize' cast is
a no-op on 64-bit). The cursor never enters the shadow, so erasing is
just a shadow push of the old rect.
- cursor_redraw after scroll shifts and once at spawn (the vt diff never
re-blits idle cells).
cursor task (task 2, spawned at boot when a mouse is present):
- owns the PS/2 ring; polls every 10 ms, moves the cursor (clamped),
tracks buttons, and forwards every event to a task's queue when
'mouse <id>' armed it (the window-manager input path).
- /dev/mouse is now a position device (x/y/buttons snapshot); 'mouse'
watches the cursor live (prints on change); 'cursor' prints one-shot
state; 'gfx' draws a status-bar demo; 'gfx check' is an in-kernel
pixel self-test (shadow readback, display readback, cursor overlay
purity) — PASS/FAIL per stage.
Tests (headless QEMU + monitor injection):
- make test-gfx (new): all four compositor checks PASS.
- make test-mouse (rewritten): cursor tracks mouse_move deltas, buttons
ride along, /dev/mouse snapshot, live watch, real-event queue routing.
- make test-msg: task numbering shifted (cursor is task 2; msgrecv is
task 3) — updated, still PASS.
- make test-disk regression re-passes. 0 build warnings.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
Mouse (IRQ12, stream mode): ByteRing generalized for both PS/2 devices,
ISR routes data-port bytes by the controller's aux bit; mouse_init with
bounded-ACK handshake (boots without a mouse); packet decoder with
bit-3 resync, screen-relative deltas, buttons. Exposed as /dev/mouse,
the `mouse` stream command, and `make test-mouse`.
Message queues (ADR 0003's GUI-era primitive): every task gets a static
16-slot TaskMsg ring; send/recv/recv_blocking with direct wake + tick
scan safety net for the lost-wakeup race; `msgrecv`/`send` commands,
`mouse <id>` routes real IRQ12 events into a task's queue, jobs shows
q=. `make test-msg` + `make test-disk` regression pass.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
(fmtbuf/scripts/hexdump/cat/ahci/pci)
- memory.rs: self-test Layout::from_size_align no longer panics — the
test fails cleanly on an invalid layout
- fat.rs: v() no longer unwraps the active-volume slot — invariant
violation logs + halts instead of panicking mid-disk-io
- strbuf: shared FmtBuf replaces the duplicated PanicBuf/FmtBuf
(main.rs + sched.rs)
- test-disk.sh: SC2046 — conditional --fresh arg no longer relies on
word splitting
- scripts: boot.sh/boot-image.sh share lib-boot-args.sh (dup args loop)
- shell: cat/hexdump stdin pairs unified with Option<&str> marker;
hexdump format_row folded into format_partial
- ahci: read/write_sectors unified behind dma_sectors
- pci: config_read/write share config_addr
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
176-byte frames
- sched: 16-slot static table, shell=task 0, idle=task 1, spawn with
guard page + 8 KiB stack, RR on the 100 Hz tick, int 0x60 yield,
sleep_ms, lazy reap, jobs/bg/sleep/kill shell commands
- gdt: own GDT mirroring UEFI selectors + TSS with IST1/IST2
(guard-page overflows die gracefully instead of triple-faulting)
- interrupts: isr_dispatch returns next frame in rax; IntFrame grows
rsp/ss fields — QEMU's 64-bit iretq always pops all five slots from
a 176-byte frame, so synthetic task frames must carry rsp=top+ss
(a 160-byte frame made the first iretq pop rsp/ss from the unmapped
page beyond the frame)
- panic handler: task panics abort the task, shell keeps running
- main: sched::init moved after page allocator + adopted tables
(the idle's stack+guard need both; it was silently not spawning)
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
- 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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- fat.rs: VOL: Option<Volume> → VOLS: Vec<Volume>; try_mount() returns
a Volume per disk and init() mounts every valid FAT32 volume found.
Volume UID = sanitized uppercase label + 8-hex volume serial
(e.g. RSDOS-5BD1E55F): unique per format, stable across reboots,
human-recognizable, machine-parseable (^[A-Z0-9_]+-[0-9A-F]{8}$);
cloned volumes get a -N suffix. Public ops take a vol index and
select it (select_vol also picks the backing AHCI disk), matching
the ahci::select pattern
- fs.rs: /disk is now a plain directory whose children are one Disk
node per mounted volume, named by UID; DiskInfo carries vol
- LFN fix: entries are stored last-first on disk — both the writer
(head-entry first) and reader (append in disk order) were reversed
and cancelled out for ≤13-char names; multi-entry names (>13 chars)
read back mangled (e.g. 'from-kernel.txt' as 'xt'). Writer now
places seq=1 closest to the SFN and seq=N|0x40 first; reader places
chunks by sequence number and trims at the first NUL. Verified with
a 25-char filename round trip: kernel ls/cat correct, mtools shows
the full LFN, fsck clean on both volumes
- test-disk.sh: test file renamed to disk-test-.txt (>13 chars,
exercises multi-entry LFN); UID discovered from the boot log; QEMU
stdio redirected to a log file + EXIT trap so an orphaned QEMU can
never hang a piped caller (it previously did, 400s)
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- 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
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- fs.rs: node-table VFS (root /dev /tmp /etc). Regular files are
in-memory ramfs; char devices regenerate content on every read so
'cat /dev/rtc' shows the live time. Nodes are stable handles with
tombstone removal; . and .. path resolution.
- /dev devices: mem (raw physical RAM, offset = address), rtc, pci,
version, meminfo, null, zero, console (write prints to screen+serial),
serial. /etc/motd static file.
- shell: ls, cat, hexdump (hexdump -C style), mkdir, touch, rm; echo
gains '>' overwrite and '>>' append redirection (append bug fixed:
first '>' in '>>' was parsed as overwrite)
- boot: fs init + self-test (create/read/write/remove) before the shell
- QEMU verified: file lifecycle, redirection, console/null writes,
mkdir/touch/rm, hexdump /dev/mem and /tmp/x byte-exact
|
| |
|
|
|
|
|
|
|
|
| |
- rtc.rs: read the PC RTC via CMOS ports 0x70/0x71 (UIP wait, BCD/12h
normalization, century sanity-check with 2000+ fallback); boot prints
the wall clock, shell gains 'date'
- pci.rs: legacy config-space access (0xCF8/0xCFC) with full enumeration
of buses 0-255; boot reports device count, shell gains 'pci' (lspci
style listing with class names)
- QEMU q35 verified: Q35 host bridge, stdvga, e1000, ICH9 LPC
|
| |
|
|
|
|
|
|
|
|
|
| |
- uefi.rs: full EFI_RUNTIME_SERVICES layout with reset_system at index 10
(spec order); EfiResetSystem type + RESET_* constants
- power.rs: stash the runtime-services table pre-EBS; poweroff() calls
ResetSystem(EfiResetShutdown) — still callable after ExitBootServices
because we never call SetVirtualAddressMap, so the pointers keep
working with physical addresses; falls back to the hlt loop
- shell: 'poweroff' and 'exit' shut the machine down (QEMU exits),
'halt' keeps the plain hlt loop
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
- uefi.rs: full EfiMemoryType constants (0-14) + memory_type_name(); fix
MEMORY_TYPE_LOADER_DATA from 6 to 2 per the UEFI spec
- memory.rs: replace the bump allocator with a first-fit free-list heap
(splitting, coalescing, 8-byte back-pointer for alignment-safe free);
add a bitmap physical page allocator (heap region reserved, page-0
guard, aligned runs); grow the heap from the page allocator on demand
- paging.rs: identity page-table helpers — adopt_tables() rebuilds the
firmware map into our own tables (OVMF maps its tables read-only, so
the firmware tree can't be modified in place) and switches CR3;
map_page/unmap_page/is_mapped with 2 MB/1 GB large-page splitting
- main.rs: boot self-tests for heap, pages, and paging
|
|
|
Architecture:
rs-dos/ (workspace root, was raisernics/)
├── rsnix/ — kernel lib crate (uefi, serial, gop, ps2, interrupts, memory)
├── shell/ — shell lib crate (prompt, commands, line input)
├── rsdos/ — binary crate (efi_main, init, panic handler)
└── rsboot/ — future git submodule
No functional changes — boots to shell prompt identically.
Version auto-pulled from Cargo.toml via env!("CARGO_PKG_VERSION").
|