summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
* rustfmt: reflow fat.rs/fs.rs formattingsalmonik2026-08-012-12/+18
|
* CONTEXT.md: record pending decisions (klog ring, disk-recognition scope)salmonik2026-08-011-0/+16
|
* fat: mount every FAT32 volume under /disk/<UID>/, fix multi-entry LFNsalmonik2026-08-016-121/+241
| | | | | | | | | | | | | | | | | | | | | | | | | - 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)
* scripts: automate the data-disk workflow (mkdisk / sendkeys / test-disk)salmonik2026-08-019-8/+377
| | | | | | | | | | | | | | | | | | | | | - scripts/mkdisk.sh: create the FAT32 disk with mkfs.fat -C (the flag that actually creates the file — plain mkfs.fat fails on a missing path), accept M/G/K sizes, seed seed/ files via mtools; --fresh re-formats, --no-seed skips seeding - scripts/sendkeys.py: type lines into the guest via the QEMU monitor (US layout). Punctuation must use QEMU's named keys (minus, slash, dot, ...) — bare '-', '.', '/' are not valid sendkey names, and '-' is the modifier separator, so they were silently dropped before - scripts/test-disk.sh: full automated round trip — build, deploy, ensure image, boot headless QEMU, drive the shell (ls /disk, mkdir, echo >, cat, poweroff), then verify with fsck.fat (must be clean) and mtype (file content must have survived poweroff) - Makefile: make disk / disk-fresh / inspect / test-disk; run, run-gui and debug now auto-create a missing DISK_IMG; fix the stale comment (mkfs.fat without -C) - scripts/boot.sh: auto-create a missing DISK_IMG via mkdisk.sh - seed/: motd.txt + lines.txt seeded onto fresh images - Verified end to end: ./scripts/test-disk.sh --fresh passes
* ahci: skip ATAPI ports and fast-fail on device abortsalmonik2026-08-011-5/+22
| | | | | | | | | | | | A CD-ROM (or any ATAPI device) on a scanned port previously made the driver spin the full 100M-iteration timeout on IDENTIFY, then log a scary 'timed out' (QEMU leaves ATAPI aborts pending in PxCI instead of completing the slot; tfd=0x441 = ABRT). - skip a port up-front when firmware set PxCMD.ATAPI (bit 24) - bail out of the completion poll as soon as PxTFD.ERR is set, clear the error bits and any wedged slot, and report the abort instead of timing out — the port scan stays fast with a CD attached
* ahci: scan all ports; fat: mount first valid FAT32 disksalmonik2026-07-315-68/+160
| | | | | | | | | | | | | | | | | The kernel previously started only AHCI port 0, so any launch where the firmware/QEMU put something else on port 0 (e.g. the ESP from an implicit -drive file=fat:rw:esp) left the real disk unnoticed: 'unsupported sector size 0' and no mount. - ahci.rs: enumerate CAP.NP/PI ports, start every port that links up (empty ports settle at DET=0 and are skipped quickly), keep up to 8 disks, and expose disk_count()/select() for the filesystem - fat.rs: try each disk in port order and mount the first valid FAT32 volume; non-FAT disks are logged and skipped - scripts/boot.sh: attach the data disk on ide.0 and the ESP on ide.1 (DISK_IMG env var, default /tmp/disk.img), matching the Makefile - Verified with the disk on port 0 (Makefile style), port 5 (old-style command line), and with the ESP on port 0; fsck.fat stays clean
* ahci: SATA driver + FAT32 persistent disk mounted at /disksalmonik2026-07-3111-16/+1556
| | | | | | | | | | | | | | | | | | - 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-315-27/+108
| | | | | | | | | | | | | | | | | | | | | | | | 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.
* gop: RAM backbuffer — scrolling never reads the framebuffersalmonik2026-07-312-12/+73
| | | | | | | | | | | | | | | | | | | | | | Real-hardware GOP framebuffers are typically uncacheable or write-combining (firmware MTRR/PAT), so the scroll shift's full-screen memcpy *read* ~4-8 MB through uncached memory — a bus round-trip per cache line. That made scroll printing crawl on real hardware while plain printing (a few glyph writes) stayed instant. - gop keeps a RAM shadow copy of the whole framebuffer (same pitch layout), allocated at init. - Every raster write (glyph blits, clear) goes to both the display and the shadow. - shift_up becomes: cached shadow memcpy up one row + clear exposed bottom row in the shadow + one write-only push shadow→display via copy_nonoverlapping (64-byte bursts that coalesce on WC memory) — the display is never read. - Fallback to the old direct shift if the shadow allocation is null. Verified in QEMU: mmap output scrolls ~100 lines with coherent rows and a clean bottom row, clear wipes the screen, cursor tracks the prompt, editor paths untouched. Release + dev builds pass.
* vt: don't strand stale inverse cursor cells on scroll/clearsalmonik2026-07-314-10/+36
| | | | | | | | | | | | | | | | | | | | | | | | | | 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-316-34/+261
| | | | | | | | | | | | | | | | | 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-3114-258/+2209
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* shell: ^C cancels the line / aborts streams, ^D = EOF → poweroffsalmonik2026-07-314-67/+152
| | | | | | | | | | | | - ps2: Ctrl+C and Ctrl+D are now KeyEvents (ctrl modifier + c/d map); other Ctrl+key combos are swallowed - shell read_line: ^C clears the line and echoes '^C' (bash-style), ^D on an empty line echoes '^D' and shuts down (EOF), ^D with text on the line is ignored - cat/hexdump stream incrementally (was: build whole string then print) and check for ^C between chunks, so a running dump can be aborted - verified in QEMU: line cancel, standalone interrupt, ^C aborts an infinite 'cat /dev/zero' stream, ^D powers off
* vfs: everything is a file — dirs, ramfs, character devicessalmonik2026-07-315-2/+736
| | | | | | | | | | | | | | | | - 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 + pci: CMOS clock with date command, PCI bus enumerationsalmonik2026-07-316-1/+282
| | | | | | | | | | - 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
* style: rustfmt field alignment in RuntimeServicessalmonik2026-07-311-15/+14
|
* docs: CONTEXT.md — poweroff milestone, power.rs layout entrysalmonik2026-07-311-1/+4
|
* power: proper shutdown via UEFI ResetSystem (ACPI S5)salmonik2026-07-315-11/+97
| | | | | | | | | | | - 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
* docs: CONTEXT.md — paging adoption, heap growth, shell additionssalmonik2026-07-311-7/+30
| | | | | | | | - paging strategy: adopt_tables() rebuilds the firmware map into the kernel's own tables (UEFI maps its tables read-only) and switches CR3 - physical memory: heap grows into the page allocator on demand - milestones: paging helpers, heap growth, mmap/stress commands - project layout: paging.rs entry
* shell: fix mem memory-type labels, add mmap and stress commandssalmonik2026-07-311-6/+156
| | | | | | | | | | | - cmd_mem: correct type grouping — 1|2 loader, 5|6 runtime (new line), 9|10 ACPI, 7 conventional, 11|12 MMIO (previously 6 was mislabeled LoaderData and 5|10 were called ACPI) - cmd_mmap: per-region dump using uefi::memory_type_name with index/type/start/pages/size columns - cmd_stress <chunks(1-64)> <kb>: allocate chunk Vecs via try_reserve_exact, report heap+page stats while held and after free; exercises heap growth past the base region
* rsnix: memory management — free-list heap, bitmap pages, paging adoptionsalmonik2026-07-315-42/+1050
| | | | | | | | | | | | | | - 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
* rsboot: loader file buffers use LoaderData (2) instead of RuntimeData (6)salmonik2026-07-311-0/+0
| | | | | Submodule rsboot ee1c85b — reclaimable loader scratch instead of permanent runtime-services memory.
* fix(rsdos): organizational changessalmonik2026-07-3115-97/+362
|
* restructure: rsnix kernel + shell crate + rsdos entry pointsalmonik2026-07-3118-230/+229
| | | | | | | | | | | | 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").
* auto-version all strings from Cargo.toml via env!("CARGO_PKG_VERSION")salmonik2026-07-311-3/+4
|
* bump: 0.1.0 → 0.2.0 — working interrupt handlingsalmonik2026-07-313-5/+5
| | | | | | Interrupts are functional: PIT timer (~100 Hz), PS/2 keyboard IRQ with lock-free SPSC ring buffer, PIC remapped, IDT with 64-bit interrupt gates. Kernel runs cleanly with no exceptions.
* fix: ISR dispatch calling convention + PS/2 interrupt enablesalmonik2026-07-312-48/+112
| | | | | | | | | | | | Root cause: x86_64-unknown-uefi uses the Microsoft x64 calling convention where the first argument is passed in rcx, not rdi. The ISR stub was setting rdi = rsp, but isr_dispatch() read the frame pointer from rcx, getting garbage → triple fault. Also: - Enable PS/2 keyboard IRQ via controller config byte (bit 0). - Expose read_scancode() and TICKS from interrupt module. - ps2::poll_key() uses 'sti; hlt' race-free sleep pattern.
* interrupts: IDT, PIC remap, PIT timer, PS/2 keyboard IRQsalmonik2026-07-315-37/+414
| | | | | | | | | | | | | - IDT with 256 entries, loaded via lidt (CS read from current context) - PIC 8259A remapped to vectors 32-47, timer+keyboard IRQs unmasked - PIT channel 0 at ~100 Hz (mode 2, rate generator) - PS/2 keyboard IRQ (IRQ1 → vector 33): reads port 0x60, pushes byte to lock-free SPSC ring buffer - Timer IRQ (IRQ0 → vector 32): sends EOI, increments tick counter - ps2::poll_key() now reads from ring buffer with cli/sti+hlt for race-free sleep (instead of busy-polling the data port) - build.rs: use idiomatic Result<_, Box<dyn Error>> return type - tools/qemu.sh: fix SC2207 shellcheck warning
* Initial commit: raisernics toy kernelsalmonik2026-07-3119-0/+2218
- Bare-metal x86_64 UEFI kernel (PE32+, no libc) - GOP framebuffer + 8x16 bitmap font - PS/2 keyboard (polling, scancode set 1) - UART 16550 serial driver (COM1, 115200 8N1) - Bump allocator as #[global_allocator] (alloc::String, Vec, format!) - UEFI memory map capture (static buffer, ADR 0001) - Shell with 7 commands (help, echo, clear, hello, info, mem, halt) - Dual output: GOP framebuffer + serial console - Makefile: run, run-gui, debug, release, image targets - tools/: qemu.sh, boot-image.sh, debug-kernel.py