<feed xmlns='http://www.w3.org/2005/Atom'>
<title>rs-dos/bins/hello/src/main.rs, branch qemu</title>
<subtitle>Simple, kernel-only, 64bit OS, early stage.
</subtitle>
<id>https://git.2137697.xyz/rs-dos/atom?h=qemu</id>
<link rel='self' href='https://git.2137697.xyz/rs-dos/atom?h=qemu'/>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/'/>
<updated>2026-08-27T14:58:31Z</updated>
<entry>
<title>streams: per-invocation channel, pumping mode, filter pipeline wiring</title>
<updated>2026-08-27T14:58:31Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-27T14:58:31Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=300c0acbd7ab3fae8596ff839c39d9a17c70c68d'/>
<id>urn:sha1:300c0acbd7ab3fae8596ff839c39d9a17c70c68d</id>
<content type='text'>
exec: LineChannel bounded ring (cap=16) with abort/eof/marker fields.
Shell 'pumping mode' assembles canonical lines from its queue into the
channel while the command runs; ^C marks the channel aborted.

Shell-side grammar: USE/TIL pre-drain into the channel before spawn;
&lt;cmd&gt; &lt;path&gt; TIL &lt;marker&gt; sugar drains paths until the marker line.
Interactive TIL: pump_key checks each submitted line against the marker
and closes the channel when it matches.

Exports callbacks run in the command task but touch shell-owned state:
this is safe by construction — the shell blocks in exec_external until
the command completes.  put_line feeds Pipeline::line directly;
get_line pops from the channel (yield-poll when empty).

load: drop NX from image mapping (single-privilege kernel, NX bit 63
reserved when EFER.NXE is set by OVMF); compute image span from section
RVAs not file size.

bins/count: gate binary — reads lines via get_line, reports count via
put_line.  Verified: count USE file → 6; count &lt;path&gt; TIL END → 2;
interactive count TIL DONE → 3; -h filter across task boundary;
^C abort.

v1 stream exports: put_line → Pipeline, get_line ← channel, log_line
→ klog append, exit → abort_current.

Accounting: print_one_line → pipe.line() returns false (head kill /
pager ^C) → the binary should wrap up promptly; accepted: binary does
not check the return value in v1 (phase 3 simplification).
</content>
</entry>
<entry>
<title>exec: PE32+ loader, versioned ABI, first external binaries (v0.6.0)</title>
<updated>2026-08-21T19:17:44Z</updated>
<author>
<name>salmonik</name>
<email>salmonik@tuta.io</email>
</author>
<published>2026-08-21T19:17:44Z</published>
<link rel='alternate' type='text/html' href='https://git.2137697.xyz/rs-dos/commit/?id=71b6445b048456bf198d8b622570db95f4665cb9'/>
<id>urn:sha1:71b6445b048456bf198d8b622570db95f4665cb9</id>
<content type='text'>
rsapi: the kernel&lt;-&gt;binary ABI crate (no_std, no deps).  Versioned
Exports table (magic + version header), EntryPoint = extern "C" on
x86_64-unknown-uefi (Win64: RCX/RDX/R8), Line/Arg/StreamResult types.
Binaries link only this crate.

rsnix::load: PE32+ parser — DOS/COFF/optional headers, section copy,
BSS zero-fill, .reloc base relocations (DIR64) via rva_to_file mapping
(the reloc directory is an RVA, not a file offset).  Images are
allocated at LOAD_BASE=192MiB inside the page allocator's conventional
span and identity-mapped user+writable+nx.

rsnix::exec: resolution name -&gt; /disk/&lt;UID&gt;/bin/&lt;kind&gt;/&lt;name&gt;.efi per
mounted volume; spawn reserves a sched slot, stores a per-task ExecCtx
(exports + argv block + image) before launch_at installs the frame —
no adopt race.  Trampoline calls entry(&amp;Exports, argc, argv), posts
TaskMsg::User(exit_code) to the shell.  abort_current notifies the
shell with u64::MAX when an exec'd binary dies, so a faulting command
cannot leave the shell blocked forever.

sched: reserve_slot/launch_at split out of spawn; task_exit made pub.

shell: exec_external runs before non-frozen built-ins (ADR 0006
resolution rule); frozen core (help/clear/echo/halt/poweroff/exit/
rescan) is exempt.  Exports v1 wires put_line to the terminal and
get_line to EOF; stream injection lands in Phase 3.  ^C while waiting
kills the command task.

bins/{hello,boom}: gate binaries.  hello prints through the exports
table; boom faults on 0x400000000000 to prove containment.  The image
entry point IS the ABI entry (efi_main carries the Exports signature).

Version 0.6.0: exec exists end-to-end.

Gates verified in QEMU: 'hello' loads from \\bin\\cli\\hello.efi, calls
put_line across the ABI, exits 0, shell unblocks; 'boom' faults, task
dies gracefully with full report, shell survives, jobs shows the corpse;
built-in fallback works when the file is absent; test-disk PASS.
</content>
</entry>
</feed>
