Plan: libcapos C-Substrate v0
Overview
Phase 0 of the C-language substrate from
docs/proposals/userspace-binaries-proposal.md (section “C via libcapos”).
Goal: ship a thin Rust staticlib (libcapos.a) that exposes the capos-rt
syscall + ring + CapSet + heap surface to C consumers via extern "C",
plus a C “hello world” smoke that exercises the surface end to end. No
POSIX shape – no errno, no fd table, no open/read/write, no
signals, no fork/exec, no sockets. Those belong to a future
libcapos-posix layer above libcapos.
Conflict Surface
Owned by this plan:
libcapos/(new crate,crate-type = ["staticlib"],name = "capos"so the archive lands atlibcapos.a).libcapos/include/capos/capos.h(public C header).demos/c-hello/(new C smoke binary).system-c-hello.cue(focused boot manifest).tools/qemu-c-hello-smoke.sh(boot assertion harness).Makefileadditions:libcapos,c-hello,run-c-hellotargets; fmt and fmt-check inclusion;DEPENDENCY_POLICY_*lists..cargo/config.toml:build-libcaposalias.
Disjoint from active tracks: no schema changes, no kernel edits, no
capos-rt/init/demos Rust changes. Parallel-safe with Lua piccolo
(L.1), LaunchParameters (L.3), Remote Session DTO additions, and Device
Driver Foundation work.
Doc updates owned by this plan:
docs/programming-languages.md– C row status moved from “Future design” to “Phase 0 in tree (libcapos C-substrate v0)”.docs/proposals/userspace-binaries-proposal.md– “Future Phase: libcapos for C” closes out as shipped; “Future: C via libcapos” gains an implementation status note.WORKPLAN.md– C-track ad-hoc bullet pointing at this plan + the proposal.
Scope (v0)
C-callable surface (all extern "C", header at
include/capos/capos.h):
capos_capset_get(name, name_len, out_cap_id, out_iface_id)– bootstrap CapSet lookup by name.capos_cap_call(cap_id, method_id, params, params_len, result, result_len)– synchronous capability invocation. Wrapscapos_rt::RingClient::submit_call_borrowed_wait_forever. Returns the kernel CQE result int directly.capos_console_write_line(console_cap, text, text_len)– typed wrapper for the v0 smoke; handles capnp encoding internally so the C side does not need a capnp implementation.capos_sys_exit(code)– rawexitsyscall.capos_sys_cap_enter(min_complete, timeout_ns)– rawcap_enter.malloc/free/calloc/realloc– C heap shims that delegate to the Rust global allocator already initialized bycapos-rt.
Build chain:
cargo build-libcaposbuildslibcapos.afortargets/x86_64-unknown-capos.jsonwith-Zbuild-std=core,alloc.- C link:
clang --target=x86_64-unknown-none-elf -ffreestanding -nostdlib -static -fuse-ld=lld -Wl,-T,demos/linker.ld. Links againstlibcapos.a. The capos-rt_start(already present inlibcapos.avia the Rust dep) is the entry point; libcapos’scapos_rt_mainparks the Runtime in a static and dispatches to Cmain(0, NULL).
Smoke (make run-c-hello):
system-c-hello.cueboots c-hello as the init binary with one Console cap.- C
main()callscapos_capset_get("console", ...)-> callscapos_console_write_line(console_cap, "[c-hello] hello from c-hello", ...)-> returns 0 ->capos_sys_exit(0)via the trampoline return. tools/qemu-c-hello-smoke.shgreps the kernel log for the marker line, theproc: process N exited with code 0line, andsched: last process exited, halting.
Out Of Scope (v0)
Deferred to later libcapos phases:
- Generated typed wrappers per capability interface (currently only Console is wrapped because the smoke needs it).
- Transferred result-cap propagation across the C ABI (the v0 smoke does not pass caps).
- Multi-thread routing of the Runtime ring (the v0 substrate is
single-threaded; the Runtime stash is a
RefCell<Option<Runtime>>with manualSyncand a documented invariant). - Argv/envp delivery (the trampoline always passes
argc=0, argv=NULL; real argv waits on the LaunchParameters cap from the language-support planning Task L.3). - Any POSIX surface (errno, fd table, file I/O, sockets, signals,
fork/exec) – belongs to the planned
libcapos-posixlayer.
Validation Gates
Run before merging:
make fmt-checkcargo build --features qemucargo test-libcargo test-configmake capos-rt-checkmake libcaposmake c-hellomake run-smokemake run-c-hello
Closeout
When v0 is reviewed and merged, mark the WORKPLAN bullet [x] with the
closeout commit SHA and a minute-precision UTC timestamp. Successor work
(libcapos-posix scaffold, generated wrappers, multi-thread Runtime
routing) gets new plan files referenced from new WORKPLAN bullets; do
not append to this plan.