Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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 at libcapos.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).
  • Makefile additions: libcapos, c-hello, run-c-hello targets; fmt and fmt-check inclusion; DEPENDENCY_POLICY_* lists.
  • .cargo/config.toml: build-libcapos alias.

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. Wraps capos_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) – raw exit syscall.
  • capos_sys_cap_enter(min_complete, timeout_ns) – raw cap_enter.
  • malloc / free / calloc / realloc – C heap shims that delegate to the Rust global allocator already initialized by capos-rt.

Build chain:

  • cargo build-libcapos builds libcapos.a for targets/x86_64-unknown-capos.json with -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 against libcapos.a. The capos-rt _start (already present in libcapos.a via the Rust dep) is the entry point; libcapos’s capos_rt_main parks the Runtime in a static and dispatches to C main(0, NULL).

Smoke (make run-c-hello):

  • system-c-hello.cue boots c-hello as the init binary with one Console cap.
  • C main() calls capos_capset_get("console", ...) -> calls capos_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.sh greps the kernel log for the marker line, the proc: process N exited with code 0 line, and sched: 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 manual Sync and 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-posix layer.

Validation Gates

Run before merging:

  • make fmt-check
  • cargo build --features qemu
  • cargo test-lib
  • cargo test-config
  • make capos-rt-check
  • make libcapos
  • make c-hello
  • make run-smoke
  • make 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.