ubuntu-latest ships shellcheck 0.9.0, which warns that ash scripts are
checked as dash; 0.10 (local) does not. shell=dash is the accurate dialect
for busybox ash. Verified clean under BOTH versions; boot smoke re-run.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018HUayid7W5w7jBdb9Rrj1K
- ci-cd.md phrasing made time-invariant (true before and after the
visibility flip; the prior wording asserted a state not yet real).
- ui-shot: liveness check before the tap QMP call too — the commit-message
claim of "before every QMP call" is now actually true.
- busybox fetcher checks its pin before downloading, mirroring the
kernel-tarball fetcher's ordering.
- Fragment disable-arm: absence of a deps-gated symbol is a valid disable
outcome; only "still set" is fatal (the iteration-2 symmetrization
overcorrected). Negative-tested both directions under set -e.
Iteration 3 produced four findings, none blocking, all applied — the
recursive review is converged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018HUayid7W5w7jBdb9Rrj1K
- build-kernel.sh fragment assertion: survives a missing trailing newline
(the read footgun, reproduced) and treats an absent symbol on a disable
line as FATAL, symmetric with the enable arm.
- fetch-kernel-tarball.sh checks the pin before downloading; both fetchers
add --retry-connrefused.
- mkimage rejects '.'/'..' state keys.
- ui-shot: VM liveness checked before every QMP call, console.log preserved
as evidence on every failure path, repaint deadline widened to 90s with
the contended-runner rationale documented.
- rs485-bridge: overflow discards back off one gap and rate-limit their log
line, mirroring the accept-loop fix; clippy nit fixed.
- .gitignore ignores *.elf/*.map so the untracked artifacts cannot silently
return; CI shellcheck glob now covers build/ and the rootfs boot scripts
(directives added for the deliberate in-guest source paths).
- Docs: NPU parity row matches its sibling verification docs; line-pinned
audit cross-references unpinned; CROSS_COMPILE documented in the build
header; payload README lists warden-ui; ci-cd tense settled.
Verified: guards negative-tested (bad state keys, no-newline fragment);
boot smoke, portal scenario, ui-shot all PASS; 53 tests green; shellcheck
clean across the widened glob; clippy zero.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018HUayid7W5w7jBdb9Rrj1K
CI/pipeline:
- KERNEL_TARBALL passed as a YAML env literal '~' was never tilde-expanded
and would have failed every hosted kernel-build dispatch; the path is now
exported from the shell. Verified reproducible before the fix.
- Every job gets timeout-minutes; boot smoke uses timeout -k so a wedged
qemu is SIGKILLed instead of holding the job.
- Tarball fetch + fail-closed sha256 verification deduplicated into
build/fetch-kernel-tarball.sh (with curl retries), used by build-kernel.sh
and both CI jobs. busybox fetch gains retries too.
- ccache layer for kernel-build (cache keyed on defconfig+patches) recovers
the incremental-compile speed the ephemeral-runner move cost.
- build-kernel.sh now asserts every fragment option survived olddefconfig —
merge_config -m pastes text and Kconfig silently drops unmet symbols.
rs485-bridge:
- pending-buffer cap (2x max RTU ADU) instead of unbounded growth;
explicit accept-loop error handling with backoff instead of .flatten();
per-arm inline bounds instead of the string-keyed lookup whose default
would have mis-bounded a future get-input; control-socket cleanup errors
surfaced; flag-shaped values rejected in arg parsing; doc example uses a
private mktemp dir. Test timing margins widened for contended runners
(gap 25->120ms, 60x margin on the split-frame test).
VM harness:
- stage-1/stage-2 boot scripts share one validated slot parser and one
by-name populator (qemu/rootfs/etc/warden-lib.sh) — the duplicated
parser had already diverged on validation; userdata/oem mount failures
now fail fast with a greppable sentinel; udhcpc fallback keys off the
interface actually having an address; switch_root applet guarded.
- boot-smoke delegates the qemu invocation to run.sh (machine shape lives
in ONE place); run.sh port 0 disables a hostfwd.
- mkimage: unknown partition names fail at build time; DISK_END is a max,
not last-entry; --state keys validated as filenames.
- portal-scenario: mock readiness is asserted (no silent fall-through),
hostfwd port collisions retried, mount-failure sentinel fails fast.
- ui-shot: fixed sleeps replaced with bounded screendump polling; the
repaint assertion is real and documented as such. qmp.py loses its
module-global and gains argv validation.
Docs/scrub: bench-host paths and the site AP name removed from six more
port docs and two evidence tables; path-bearing build artifacts (.elf,
.map) untracked (the 154-byte firmware .bin is path-free and stays);
ADR-0003 marked visibility-superseded by ADR-0007; stale section
cross-reference fixed; flare-edge noted as private for outside readers;
stale root-level review report removed per the new workspace rule.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018HUayid7W5w7jBdb9Rrj1K
Replaces the dual MIT/Apache-2.0 licensing (and its GPL carve-out) with a
single GPL-2.0-only license for the whole repository: coherent with the
kernel patch series it exists to carry, the embedded-Linux norm, and the
stack's openness principle — anyone shipping products on this SDK publishes
their changes. GPL-2.0 (not 3) deliberately: the Installation-Information
clause of GPLv3 sits badly with WardenOS's signed A/B firmware chain.
LICENSE is now the canonical GPLv2 text; crate manifests updated;
inbound = outbound noted in the README.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018HUayid7W5w7jBdb9Rrj1K
Decision/directive lines keep their dates and content, drop the name;
hands-on confirmations become "confirmed by hand at the panel"; a dangling
CLAUDE.md reference becomes "repo policy". Upstream vendor author
attributions in the GPL kernel sources (MODULE_AUTHOR, copyright headers,
LKML citations) are third-party legal attributions and stay.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018HUayid7W5w7jBdb9Rrj1K
Preparing the repo to go public (ADR-0007):
- CI: kernel-build moves from the self-hosted runner to ubuntu-latest
(installs its own cross toolchain + qemu, caches the pristine tarball).
On a public repo a registered self-hosted runner is reachable from
approved fork-PR workflows — i.e. arbitrary code on private
infrastructure — and the build never actually needed the SDK host.
ADR-0004 marked superseded-in-part; docs/ci-cd.md rewritten (site
specifics now live only in the private deployment log).
- Licensing: LICENSE gains the GPL-2.0 carve-out for patches/ and the
kernel source excerpts (Linux derivatives; per-driver provenance was
already tracked in PROVENANCE.md); patches/README.md states it too.
- Scrubbed from the tip: bench-unit dev credentials and its gadget IP
(m2-boot notes), the site AP SSID+BSSID and a neighboring AP's BSSID
and the device WLAN MAC (wifi bring-up evidence — BSSIDs are
geolocatable), the runner mesh IP. NOTE: these remain in git history;
decision on a pre-publication history rewrite is separate.
- Emoji cleanup across 21 tracked files (kernel port docs, review report,
enforce-mcdc.sh) per repo text conventions: status marks became
[x]/[wip]/[ ]/OK plain text.
- "[maintainer]-gated" process phrasing normalized to "maintainer-gated"
(attributions in dated evidence docs kept).
Verified: zero emojis tracked; scrub grep clean; patches carry no internal
references; ci.yml parses; shellcheck unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018HUayid7W5w7jBdb9Rrj1K
Installed 2026-08-30 on bfe-mpc-0640 (QEMU 10.0.11; cpio/curl already
present); recorded in flare-deployment deploy-log. End-to-end CI check of
the smoke step waits on the account-wide Actions billing stall.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018HUayid7W5w7jBdb9Rrj1K
Phase 4+5 of the device sim:
- Display + touch verified end-to-end: virtio-gpu at 720x720 (fbdev
emulation) renders the real WardenOS dashboard from the static LVGL
fbdev+evdev UI build (flare-edge qemu-vm-support tools/build-ui-vm.sh);
QMP input-send-event taps the Metrics tab and qemu/tests/ui-shot.sh
asserts the repaint from screendumps. Two load-bearing QEMU flags found
and documented: -global virtio-mmio.force-legacy=false (gpu/input are
VERSION_1-only) and the 200ms press hold (an instantaneous press+release
lands inside one LVGL indev poll and never clicks).
- qemu/tests/qmp.py: minimal QMP client (screendump, tap, quit).
- stage-2 init starts warden-ui when present and fb0 exists.
- docs/decisions/0006-qemu-device-sim.md: virt-not-custom-board, the
enters-at-kernel boundary, fragment policy, naming, consequences.
- docs/architecture.md: new section 7 (device emulation), order-of-work
item 7; modbus cross-reference to the bridge.
- qemu/README.md: emulated-vs-not table, scenarios, gotchas, host/runner
requirements. docs/ci-cd.md: runner needs one-time qemu-system-arm
install (fail-closed smoke until then, [maintainer]-gated). Repo README updated.
Final sweep on this commit: shellcheck clean, bridge 7/7 tests, boot smoke
PASS, portal scenario PASS (check-in + fw pull + signed .wfw download),
ui-shot PASS (touch navigates to Metrics) — all under the final flags.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018HUayid7W5w7jBdb9Rrj1K
Phase 3 of the device sim, all verified on QEMU 10.0.11:
- qemu/rs485-bridge/: std-only crate bridging a QEMU serial chardev (unix
socket) to warden_sim::ModbusSlave — gap-based RTU framing (CRC failures
degrade to real-slave silence), line-protocol control socket for register
seeding and fault injection (drop/exception/clear), bounds-checked so a
scenario typo answers err instead of panicking the bus. 7 unit tests,
bench in the sim_bench pattern. Verified end-to-end: guest master frame
on /dev/ttyS4 (pci-serial) answered from the sim slave, CRC-correct.
- virt machine gains highmem=off: the 32-bit non-LPAE kernel cannot reach
virt's default 40-bit PCIe ECAM (pci-host-generic EOVERFLOW); with it the
full PCI set probes (16550A ttyS0, i6300esb).
- Watchdog scenario verified: guest arms /dev/watchdog, no petting, i6300esb
resets the VM ~30s later (first environment where this arm is testable).
- qemu/tests/portal-scenario.sh: the real static-musl warden-flared inside
the VM against flare-edge's mock portal on the host — authenticated
check-in, firmware desired-state pull, and download of a real signed
tier-1 .wfw offer, asserted from the portal log. Found and filed
flare-edge#106 (fatal SIGBUS in the HPMCU boot-loaded probe on
non-RV1106 memory maps); runs against a flared built from the
qemu-vm-support fix branch.
- stage-2 init: WARDEN_FLARE_INSECURE=1 + WARDEN_HPMCU=0 (documented VM
deviations), firmware-version stamp, newline-terminated state seeds.
- CI: rs485-bridge joins the test loop and bench job; new qemu-tools job
(shellcheck + initramfs + disk image on hosted runners); kernel-build
gains a fail-closed qemu boot-smoke step. All qemu scripts shellcheck-clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018HUayid7W5w7jBdb9Rrj1K
The third simulator (deliberately not named "sim"): a QEMU -M virt VM that
boots the real 6.18.46 kernel and enters at -kernel zImage — everything below
(BootROM/idblock/U-Boot/real BCB A/B selection) is closed blobs + mask ROM
and is explicitly out of scope.
- qemu/mkinitramfs.sh: pinned static busybox (sha256 fail-closed) + rootfs/
- qemu/mkimage.sh: unprivileged sparse disk image with the device's canonical
12-partition blkdevparts A/B layout (vda == mmcblk0 mapping)
- qemu/rootfs/: stage-1 init (by-name symlinks from PARTNAME uevents,
whole-token warden.slot= parse, switch_root) + stage-2 init (userdata/oem
mounts, slirp networking, payload daemon start)
- qemu/run.sh: runner with --slot/--rtc/--watchdog/--rs485/--qmp/--display
- qemu/configs/virt.fragment + WARDEN_KCONFIG_FRAGMENT hook in
build/build-kernel.sh (canonical RV1106 build untouched when unset):
adds PCI, pci-serial, i6300esb watchdog, WireGuard, virtio-gpu/input
- qemu/tests/boot-smoke.sh: sentinel-asserting boot test
Verified on QEMU 10.0.11: canonical zImage boots -M virt unmodified (the
feared DEBUG_UNCOMPRESS decompressor hang does not exist in 6.18); full
stack boots both slots; 12 by-name symlinks; userdata persists across
reboot; -rtc base=2021-01-01 reproduces the no-RTC wrong-clock class.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018HUayid7W5w7jBdb9Rrj1K
Mirror flare-edge's artifact GC so the shared Actions storage quota can't fill
from either repo. A new prune-artifacts job (ubuntu, gh + built-in token,
actions:write) runs before the kernel-build upload and deletes older
kernel-rv1106 artifacts beyond the newest 3; kernel-build needs it. retention-days
14 -> 5 as the backstop. Best-effort so it never blocks a build. Completes the
account-wide auto-clear (an over-quota once blocked ALL runs, not just uploads).
The .c/.dts/.frag files here are a point-in-time port-provenance snapshot (with
standalone test programs + instructional fragments the narrative docs reference),
not a maintained second copy of the kernel delta. Add a prominent canonical-source
note so the snapshots (which can lag the final series, e.g. the clk CLK_IGNORE_UNUSED
fix) are never mistaken for current code. patches/ + build/build-kernel.sh remain the
single source of truth.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
The kernel build itself is the gate; uploading the zImage/dtb can fail on an
account-wide GitHub artifact-storage-quota hit unrelated to the build. Mark the
upload continue-on-error so a good build isn't red-X'd by it. Outputs also remain
on the self-hosted runner host.
Verified: kernel-build compiled the RV1106 6.18.46 kernel end-to-end on
bfe-mpc-0640 (zImage 8.25 MB + rv1106-warden.dtb 37 KB); the patch series applied
(issue #1 fix confirmed).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
The kernel-build job set WORK inside the repo checkout, so build-kernel.sh's
`git apply` ran from a subdirectory of the warden-sdk git repo — where git apply
silently ignores out-of-subdir paths and exits 0 without applying anything. The
build then failed at the (never-created) rv1106-warden.dtb target, and the
unconditional `echo "applied"` had masked it.
- ci.yml: WORK -> ${{ runner.temp }}/kbuild-out (outside the checkout); artifact
paths follow.
- build-kernel.sh: the patch loop now fails loudly instead of echoing on silent
failure, and a post-apply sentinel assert (rv1106-warden.dts must exist) makes a
silent no-op impossible to ship — the regression guard for this class.
Refs #1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
Make the self-hosted kernel-build runnable with zero manual toolchain/python setup
on the runner host (docs/ci-cd.md steps 3-4 move into the workflow):
- build/build-kernel.sh: honor a caller-provided CROSS_COMPILE (default stays the
Luckfox uclibc prefix). The kernel is freestanding, so a generic arm cross
compiler links it.
- kernel-build job: set CROSS_COMPILE=arm-linux-gnueabihf- (Debian
gcc-arm-linux-gnueabihf, already on 0640) instead of depending on the ephemeral
SDK checkout path; symlink python->python3 into $RUNNER_TEMP/bin on $GITHUB_PATH
for the bare-`python` SDK quirk.
- docs/ci-cd.md: only steps 1-2 (systemd service + cgroup cap) still need 0640 sudo.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
Point the badges job's branch guard at refs/heads/main and update the README /
ci-cd docs to name main as the canonical branch, ahead of establishing main from
bringup as the SDK's first main commit.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
Second recursive pass: two adversarial re-reviewers verified the iteration-1 fixes.
Fuzz/empirical checks cleared the freshness min-budget rewrite (200k random trials),
the config-lint reg-token scanner, its UTF-8 boundary safety, and the build-kernel.sh
trap (5 exit scenarios) — no defects. Three items corrected here:
- config-lint is_known_safe_loader: match the WHOLE normalized loader name, not an
unanchored substring. The iteration-1 allowlist swap kept `contains()`, so a future
coprocessor whose name merely contained a boot word ("AudioLoader" ⊃ "loader",
"SplRtos" ⊃ "spl", "Bl32" ≠ "bl31") would have been waved through — reopening the
0x40000-brick false-negative the fail-closed change exists to prevent. Regression
test added with those exact adversarial names.
- docs/architecture.md §3: the `cru` bullet no longer claims flared's devmem `Bus`
seam is shipped — it lands when flare-edge consumes warden-sdk ([maintainer]-gated), which
is what §7 item 3 already said. Resolves an in-document contradiction.
- drivers/README.md: modbus "11 pty scenarios" -> "8 pty scenarios + 3 wire/daemon
checks (11 total)", matching flare-edge tools/modbus-sim's actual SCENARIOS list.
- docs/decisions/0002-mcdc-tiering.md: Consequences now describe the shared
drivers/enforce-mcdc.sh + drivers/<name>/test/ layout actually built (not the
per-driver dirs the ADR first anticipated); Rust MC/DC tooling reality noted.
config-lint: 9 tests pass; clippy clean under -D warnings; gitleaks clean. C drivers
untouched (still relays 40/40, freshness 66/66 MC/DC).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
First recursive code-review-harness pass over the authored SDK code (sim/,
config-lint, flowgen, drivers/{relays,freshness}, build/, ci.yml). Four parallel
dimension reviewers; all findings at every severity corrected per workspace rule.
Correctness / reliability:
- freshness.c min_budget_ms: use a `seen` flag, not `best==0`, as the empty
sentinel — a zero-tolerance (max_stale_ms==0) binding was silently widened to a
looser neighbour's budget. Regression test added; still 66/66 MC/DC.
- config-lint parse_reserved_ranges: match `reg` as a whole property token (ident
boundary before, `=` after) so `reg-names` / a `region-*` label no longer
mis-parses into a bogus reserved range.
- config-lint loader check: fail closed — flag any loader with a LOAD_ADDR that is
not a known-safe boot component, instead of only known MCU names, so a future
coprocessor ("Rtos"/"Bl32") can't slip past the 0x40000-brick gate.
- build-kernel.sh: sha256 verification is now mandatory (refuse to build if the pin
is missing) and the mktemp scratch tree is removed on exit (trap), while a
caller-provided WORK is left intact for CI artifact upload.
Test quality:
- freshness: added the age==max_stale boundary case and a clock-wraparound
(now < last_ok) fail-safe-to-UNKNOWN test.
- relays: unsetenv(WARDEN_GPIO_ROOT) at main() so the NULL-env arm is hermetic.
Security / CI:
- ci.yml: top-level `permissions: contents: read` (badges overrides to write);
pin taiki-e/install-action to commit SHA (v2.86.7).
Maintainability / docs:
- drivers/enforce-mcdc.sh: one shared, name-derived gate replaces the two
copy-pasted per-driver scripts; Makefiles call ../../enforce-mcdc.sh.
- docs/architecture.md: §3/§4/§6/§7 rewritten to match reality — NPU/RGA models,
config-lint, and the relays+freshness MC/DC harnesses are done; kernel §6 now
reflects the 5.10->6.18.46 forward-port (ADR-0001), not the superseded plan44/6.6.
- README: status blurb + layout table corrected (kernel/, .github/; stale ci/ and
patches/ descriptions fixed). hpmcu "8 tests" -> 7 in docs.
- freshness.{c,h}: ADR reference points at flare-edge ADR-0004 (warden-sdk's
ADR-0004 is the CI runner — number collision).
- normalize rustfmt drift across sim/ + config-lint.
All green: sim 37 tests, config-lint 8 tests, both drivers 100% MC/DC (relays
40/40, freshness 66/66), clippy clean under -D warnings, gitleaks clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
- tools/flowgen.py: generates docs/workflows/<name>.md — one outcome-first mermaid
flowchart per workflow the SDK tests (hpmcu watchdog, modbus read, cru ladder,
rga offload, relay drive, freshness contract), each stamped with its benchmark
ns/op or 100% MC/DC result. Deterministic; reads the cargo-bench trend json.
- drivers/README.md: honest Tier-1 (relays + freshness, 100% MC/DC here now) vs
Tier-2 (modbus/rga — serious testing + fault-injection + benchmarks via sim
models; driver sources migrate in with the flare-edge unification) per ADR-0002/0005.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
freshness.c (ADR-0004 freshness-contract engine) is pure logic via produce/render
callbacks — no hardware seam needed, the callbacks are the seam. Host harness reaches
100% MC/DC (66/66 conditions, 100% lines, 27 checks) by driving warden_fresh_decide
directly + the bind/tick/invalidate/min-budget state machine through fakes, with
-DFRESH_MAX=2 so the table-full and unused/hidden-slot arms are reachable. Directly
serves future-features-2's "never a stale number in the UI" requirement. The CI mcdc
job now enforces relays + freshness.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
Registered a 3rd repo-scoped runner on bfe-mpc-0640 (label warden-sdk,
bfe-mpc-0640-warden-sdk) per ADR-0004. It is offline pending the sudo-gated steps
(service install + CPUQuota/MemoryMax cgroup cap + toolchain/python provisioning),
documented in docs/ci-cd.md as a [maintainer] handoff. kernel-build stays dispatch-gated
and passes JOBS=4 as a belt-and-braces resource bound.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
- patches/: the pristine-6.18.46 -> WardenOS delta as a 13-patch, subsystem-split
series (223 files, ~136K lines: clk, pinctrl, DTs/mach, usb-phy, VOP/panel/rgb,
mailbox, pvtm, rknpu, rga, aic8800 wifi, audio codec, thermal/rtc/adc/gmac/touch).
Verified: every patch applies cleanly onto pristine (git apply --check), the full
series reproduces the hardware-verified tree, and the applied source configures +
builds the warden dtb + rockchip DRM drivers (rc=0).
- build/build-kernel.sh: fetch+verify pristine (sha256-pinned) -> apply series ->
warden_defconfig -> zImage + rv1106-warden.dtb. build/warden_defconfig captured.
- CI: `patches-apply` (GitHub-hosted, cached tarball) enforces the series applies;
`kernel-build` (self-hosted warden-sdk runner, dispatch-gated until registered)
runs the full build and uploads the image.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
benches/sim_bench.rs (harness=false, zero deps): fixed-iteration ns/op timing for
hpmcu_tick, cru_poll, modbus_read_holding, rga_improcess, membus_poke_peek. Human
timings to stdout, one JSON trend line per bench to stderr for CI capture. New CI
`bench` job smoke-runs them. Regression-vs-history gating is future work.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
Bring relays.c into warden-sdk/drivers/ behind a relay_io seam (ADR-0005): the
sysfs plumbing is an injectable backend, the gpio root is $WARDEN_GPIO_ROOT-
overridable. Host harness (drivers/relays/test/) reaches 100% MC/DC (40/40
conditions, 100% lines) by combining fake-io unit tests (logic branches incl.
export->node-appears) with real-sysfs integration tests over a scratch tree
(backend fopen/stat branches). CI `mcdc` job enforces 100% across drivers/*/test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
test job runs cargo test across sim + config-lint and cargo-llvm-cov line coverage
on the sim crate; badges job renders loc/tests/coverage shields on push to bringup
([skip ci] + paths-ignore loop guard). mcdc/bench/kernel-build jobs land with
P2/P4/P1. README carries the CI + badge row.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
mailbox + NPU + pvtm all now show VERIFIED with accurate notes (the prior
reason cells still said 'unexercised'/'no userspace'/'deferred'). Only
crypto-accel (CPU crypto covers) and open-NPU-compute (person-year RE) remain,
both documented.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
MAILBOX (fully open A7<->RISC-V SCR1 round-trip, 5/5 exact echoes on c8a3):
- rockchip-mailbox.c: rv1106 has 1 shared IRQ, not 4/channel -> added
rv1106_drv_data{num_chans=1} + compatible (rk3368 fallback assumed 4 -> probe
failed 'IRQ index 1 not found').
- clk-rv1106.c: CLK_CORE_MCU (SCR1 core clock) marked CLK_IGNORE_UNUSED -
6.18's clk_disable_unused() was switching off the coprocessor clock so a
loaded firmware never ran (5.10 left it on).
- Open SCR1 echo firmware (scr1-echo/, 154B RV32IMC) + load/test scripts;
A2B_INTEN on the MCU side + CMD-then-DAT (DAT=doorbell) order. Loaded via the
proven hpmcu.rs SRAM path; do NOT kill warden-flared (dw-wdt). mailbox/VERIFIED.md.
NPU (open GPL rknpu 0.9.2 kernel driver on 6.18):
- DT fix: base npu node lacks interrupt-names, driver requests IRQ byname
'npu_irq' -> probe bailed -ENXIO. Added interrupt-names='npu_irq'.
- Verified: [drm] Initialized rknpu 0.9.2 on minor 1; /dev/dri/card1;
rknpu_version_test PASS (0.9.2 + hw version, full power/clock/reset path).
- Honest ceiling: open compute (regcmd compiler) is a from-scratch ~person-year
RE project, no RV1106 prior art; ship the driver, no blob. npu/VERIFIED.md.
DRIVER-PARITY + CAPABILITIES-AUDIT updated; dts snapshot refreshed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
Six drivers verified on hardware this run (wifi, TRNG, OTP, GMAC, SARADC,
audio). Final honest ledger: mailbox (fallback-binds, no client), crypto-v3
(CPU crypto covers), NPU (no open userspace), pvtm (DVFS-only) all deferred
with reasons — no unexplored capability gap. Morning bench tasks documented
(display connector, audible audio, wifi boot-time auto-load).
OVERNIGHT-RESULTS.md added.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
Ported rv1106_codec.c (acodec) + rk_dsm.c (built, dsm disabled — panel uses
acodec) into 6.18 (6 ASoC API-delta fixes: gpiod, volsw unify, DAIFMT CBC/CBP
rename, remove->void, header swaps). simple-audio-card 'rv1106-acodec'.
Fixed the subagent's gap: cpu DAI SND_SOC_ROCKCHIP_I2S_TDM was left =m (module,
never loaded on bare _b boot) so the card stuck in 'asoc-simple-card: parse
error' deferred probe. Set it + SND_SOC_ROCKCHIP =y.
✅ VERIFIED on c8a3: /proc/asound/cards shows rv1106-acodec; aplay -l shows
card 0 device 0 ffae0000.i2s-rv1106-hifi; /dev/snd has pcmC0D0p + pcmC0D0c.
Audible speaker test deferred to the bench (with display).
Six drivers verified this run: wifi, TRNG, OTP, GMAC, SARADC, audio.
audio/PORT-PROGRESS.md; DRIVER-PARITY updated; dts snapshot refreshed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
The saradc -22 was regulator_get_voltage on a dummy vref (no vref-supply in
DT), not the clk divider. Added vcc_1v8 fixed 1.8V regulator + vref-supply
(matching the vendor 86-panel). iio:device0 now reads both channels
(in_voltage0_raw=1023, in_voltage1_raw=246) — the adc-keys path works.
Five drivers verified this run: wifi, TRNG, OTP, GMAC, SARADC.
adc/SARADC-FIX.md; DRIVER-PARITY updated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
GMAC ✅ eth0 Link Up 100Mbps/Full on c8a3: ported rv1106_ops into mainline
dwmac-rk.c (VOGRF RMII mode/speed + integrated FEPHY powerup via CON0;
mainline set_speed/powerup split; bandgap trim omitted — analog opt the PHY
runs without). &gmac enabled; uses the internal ethernet-phy@2. gmac/PORT-DONE.md.
OTP ✅ now reads real data (px30_otp_read): 5211 02fe 084d 5231 ('MR1' chip id),
no timeout. rng-otp/PORT-DONE.md updated.
Batch A + GMAC complete — TRNG, OTP, GMAC all verified on hardware.
DRIVER-PARITY updated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
On-hardware proof (self-built 6.18.46, _b slot): aic8800 modules load,
download firmware, wlan0 up ([device-mac]), iw scan finds real APs
incl. SSID BlueFlare @ -43dBm. RF path fully functional. See
wifi/VERIFIED-on-c8a3.md.
Two changes from the initial built-in attempt:
- Built-in =y DEADLOCKS: aicbsp_init's eager SDIO bring-up (device_initcall,
sequential) blocks the dw_mmc controller probe that would enumerate the
card it waits for (aicsdio.c:597 2s down_timeout -> unregister). Converted
to modules (=m): AIC_WLAN_SUPPORT bool->tristate; loaded late, after the
mmc-pwrseq enumerates the card — the vendor-proven flow.
- Restored fdrv's own md5.o (each .ko needs its own MD5; bsp doesn't export
it). Refreshed kbuild snapshot accordingly.
Kernel-size fix (CONFIG_KERNEL_GZIP -> XZ): the wifi kernel's 12.12MB gzip
zImage overran U-Boot's DTB-at-0xc00000 load boundary (Sysmem Error, FLARE-AB
fell back to _a). XZ -> 8.15MB, ~4MB headroom; also correct for a firmware
kernel. Uncompressed Image ~30MB but the ARM decompressor relocates the FDT
at runtime, so only the U-Boot load-time overlap mattered.
DRIVER-PARITY: wifi ✅ M5; BT 🔨 (module built, HCI not yet exercised).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
Capabilities audit — classify every RV1106 SoC block against a 6.18 driver:
GMAC (wired eth, enabled on-board), crypto-v3, trngv1 (hw RNG), OTP, mailbox,
NPU, audio codec/DSM, pvtm still to port; camera/ISP + SPI are N/A (no HW).
Provenance ledger — per [maintainer]'s openness directive extended to already-ported
drivers: every ported driver is GPL-2.0 kernel source (vendor-src or
mainline-sibling); the only binary in the whole path is on-device wifi-chip
firmware, which by construction cannot be host source. No vendor binary is
loaded into our kernel.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
RTC: ported the vendor rockchip,rv1106-rtc driver (rtc-rockchip.c) to 6.18 — one
API delta (rtc_register_device -> devm_rtc_register_device). Verified on
warden-c8a3: /dev/rtc0 registers and reads.
tsadc thermal: ported the rv1106 data + rk_tsadcv9_initialize + the TSADCV9/VOGRF
macros + code table from the vendor; adapted .chn_id[SENSOR_CPU] -> .chn_offset
for 6.18. Verified: thermal_zone0 "soc-thermal" reads 39.8 C.
i2s-tdm: rv1126 fallback compatible added (DAI builds; sound card needs the acodec
port next). saradc still -22 (clk-rv1106 SARADC divider — deferred).
Includes the NPU + RGA open-source port plans (research): rknpu kernel driver is a
small port (RV1106 config already in the vendor driver; 4 dead-code headers need
compat stubs) but no open userspace exists for this NPU gen; RGA = port the vendor
char-dev rga3 driver (WardenOS's librga uses /dev/rga, not V4L2), + a cma pool +
hrtimer_setup. All ports are open source (vendor C source / mainline siblings).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
The brief: port/enable every remaining RV1106 hardware capability on 6.18,
open-source-first (source we own + can harden, never blobs), new drivers if
needed, zero capabilities left on the table. Priority: AIC8800 wifi/BT, RGA,
rknpu, RTC, tsadc, i2s, saradc-fix, eth0-gadget, then a full capabilities audit.
Display deferred to tomorrow (needs eyes on the panel). Pipelined: research
subagents ∥ port/build/verify on c8a3; krecover-hardened for resilience.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
usb2phy: ported the RV1106 inno-usb2 phy config to 6.18 (rv1106_usb2phy_cfg;
fields map 1:1 except utmi_iddig->utmi_id and chg_mode->opmode; 5.10-only
iddig_output/en/bvalid_grf_sel dropped; phy_tuning left off, guarded so safe).
With PHY_ROCKCHIP_INNO_USB2=y + the u2phy/usbdrd/dwc3 DT enabled, verified on
warden-c8a3: the DWC3 comes up as xhci-hcd @ 0xffb00000 — USB host works. eth0
gadget just needs dr_mode=peripheral.
saradc: added rv1106_saradc_data (2-ch v2, matches the vendor) + the native
compatible. Driver now matches; probe still returns -22 (a clk-rate/setup detail,
not the data) — TODO.
Also captured: the growing board dts (USB nodes), the port fragments under usb/
and adc/. DRIVER-PARITY.md updated: ~14 drivers now at parity on 6.18.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
The RV1106 VOP is the RV-series "lite" VOP (rockchip,rv1106-vop, VOP_VERSION 2.0xc),
mainline's VOP1 driver. Its sibling rv1126 is already in 6.18, so rv1106_vop reuses
rv1126's register sub-structs + VOP_FEATURE_INTERNAL_RGB + the smaller raster.
Verified on warden-c8a3: with the driver delta + DT (vop enabled with named
"ahb"/"dclk" resets, vop_out repointed to a panel-dpi 720x720 node, pwm-backlight
on pwm1), the VOP BINDS and DRM initialises (/dev/dri/card0), and the PWM backlight
comes up. The register data / version / feature / resets are validated.
Open: /sys/class/drm/card0 has no connector yet — rockchip_rgb_init isn't producing
one ("Cannot find any crtc"). Last mile of M4; needs a debug print in rgb_init + the
panel bus_format, and the pixels must be verified on the physical panel (can't be
checked over serial/ssh). Full recipe + next steps in display/README.md.
Also batch-2 config: GPIO_SYSFS, PWM_ROCKCHIP, crypto (aes/ccm/ctr/arc4), CFG80211,
DRM_ROCKCHIP/ROCKCHIP_VOP all =y; PSCI-style SMC removed via the psci-node deletion.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
Move from the hand-built minimal DT to the vendor rv1106.dtsi (full SoC:
pinctrl, gpio×5, dmac, cru+grf_cru, all peripherals), with our lean board DTS
(rv1106-warden.dts) enabling only the wall-HMI's needs — no camera/ISP/CSI.
Two deltas made it boot on 6.18: overwrite boot-mode.h with the vendor's (extra
BOOT_* constants) and DELETE the psci node (no secure monitor → SMC fault →
"Attempted to kill the idle task"). Recipe in dts/README.md.
Verified on warden-c8a3 (uname 6.18.46, full WardenOS userspace): pinctrl,
gpio0-4, pl330 DMA, uart1/2/4 (ttyS1/2/4), i2c3, dw-wdt (watchdog0) all probe.
DRIVER-PARITY.md tracks the remaining ports (VOP display, AIC8800 wifi, rknpu,
usb2phy, saradc-compat, RGA) toward full parity with the 5.10 kernel.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
Adding the eMMC dw_mmc node (mmc@ffa90000, clocks from cru + grf_cru) was all M3
needed. On warden-c8a3 the 6.18 kernel enumerates the eMMC at HS200
(mmcblk0 8GTF4R 7.28 GiB), mounts the ext4 rootfs, runs /sbin/init, and starts
every WardenOS daemon. Serial root login confirms:
Linux warden-c8a3 6.18.46 armv7l
ps: warden-flared warden-modbus warden-mikrotik warden-asic warden-ui warden-flight
Expected M4/M5 gaps are clean failures: the 5.10 aic8800 wifi/BT .ko won't load on
6.18 (vermagic), and no backlight/framebuffer yet (no VOP node). Next: M4 display,
M5 AIC8800 SDIO port, M6 the rest; plus a lean defconfig + Buildroot-on-6.18.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
The Linux 6.18.46 forward-port boots on the panel through our ported drivers,
verified on the serial console: earlycon, arch timer (BogoMIPS calibrated), our
clk-rv1106 CRU, pinctrl, and the mainline 8250 bound to uart2 clocked by our CRU
(ttyS2 16550A), then rootfs mount.
Two DT fixes got it past "Starting kernel":
- fdt placed high (load=0x08000000) so the bloated multi_v7 zImage (~20 MiB
decompressed) stops overrunning the DTB at 0xc00000 (was: r2=0, "invalid dtb").
- added the rockchip,rv1106-grf-cru node (grf-clock-controller child of grf) so
clk-rv1106's grf_ctx isn't NULL (was: panic in rockchip_clk_register_branches).
Console pinned to 115200 (readable on the CP2102 bench adapter; prod uses 1.5M).
The boot-image format and the A/B _b-slot safe-test method (which auto-reverted to
_a on every failed attempt) are in docs/m2-boot-on-c8a3.md. M3 next: lean defconfig
+ dw_mmc DT + our Buildroot userspace rebuilt on 6.18.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
Investigated whether the RV1106 NPU (RKNPU) could do 3D rendering or other
graphical work as we port its driver to 6.18. Verdict: no. Read the vendored
rknpu driver directly — it executes a pre-compiled regcmd list from Rockchip's
closed RKNN compiler; no register ISA, no arbitrary-kernel submit path. Only the
vertex-transform stage (GEMM) maps at all, and rasterization/depth/texture/
shading/framebuffer have no mapping to a conv/pool op set — absent, not slow. For
every CNN-shaped graphical candidate the SoC already has a better fit (RGA 2D,
idle RKIVE classic-CV), and there's no camera. Recommend porting rknpu.ko only
for future non-visual inference, never for graphics.
Caveat flagged in the doc: the no-rasterizer claim is from the RKNN op taxonomy +
architecture, not register-level ground truth (TRM Part 2 is unpublished).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
M1 is complete (clk + pinctrl + mach compile clean); this reaches M2's build
milestone. multi_v7_defconfig + configs/m2-earlycon.fragment builds an 11.8 MB
zImage with clk-rv1106.o and pinctrl-rockchip.o (our rv1106 data) compiled into
the full tree — no rv1106 warnings. dts/rv1106-warden-m2.dts (CPU, GIC-400, arch
timer, 256 MiB RAM, GRF, the CRU, uart2 as snps,dw-apb-uart) compiles clean at
W=1 with earlycon=uart8250,mmio32,0xff4c0000. Reproducible via build-m2.sh.
Boot is the next step and is on-hardware/attended: package zImage + dtb, load on
a bench unit with a recovery net, watch for the earlycon "it's alive". PORT-VERIFY
before trusting a boot: DDR size/base, the CPU clock mux, console baud.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
The device counterpart to warden-modbus's master/scanner: request-frame in,
response-frame out, in host memory. CRC16 is byte-identical to the master
(poly 0xA001, low-first; known vector 01 03 00 00 00 01 -> 84 0A verified).
Implements the data plane — read/write holding & input registers, coils,
discrete inputs (FC 0x01-0x06, 0x0F, 0x10) + Report Slave ID (0x11) — with
exception replies (illegal function/address/value) and the two real-world
faults the master must survive: a device that silently ignores a request
(drop_next) and one that NAKs everything (force_exception). This is what the
modbus-master MC/DC harness drives against; MEI (0x2B/0x0E) is a follow-up.
11 tests, sim crate 25/25 green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
The c8a3 brick was a memory-map fault no behavioural sim can catch: a
boot-loaded coprocessor firmware dropped at 0x40000, which is a reserved-memory
carve-out on Thunder-Boot boards but plain kernel RAM on ours. config-lint is
the static gate for it — parse the rkbin loader .ini for every LOADERn=Hpmcu
LOAD_ADDR, parse the target devicetree for reserved-memory ranges, fail if any
MCU load lands outside a reservation.
Tests encode the brick as a regression against the REAL Thunder-Boot .ini
(Hpmcu@0x40000): fails with no rtos@40000 node, passes once reserved; our
board's non-TB loader (no boot-loaded MCU) always passes. 6/6 green; CLI
verified against the on-disk rkbin .ini files.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
Models the RV1106 reset ladder + boot-mode register on the MemBus seam, so
flared's devmem::hard_reset ladder and the boot-mode -> MaskRom recovery
maneuver are testable entirely on the host. Bakes in the two hardware facts
that cost real bench time as regression tests:
- the CRU global-reset register is 0xff3b0c08/0xfdb9; the magic at the wrong
offset 0xff3a0614 (from other Rockchip SoCs) is a SILENT NO-OP here;
- the boot-mode register 0xff020200 survives a warm reset (the mechanism that
makes "set MaskRom, then reset" drop the SoC into BootROM download), and a
power-on reset clears it.
6 tests (both rungs, pet, the wrong-offset no-op, MaskRom-survives-warm-reset,
POR-clears-request); the sim crate is 14/14 green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
2-line DT-compat add to rockchip_board_dt_compat[] (rv1103 + rv1106), per the
breadth survey. Did NOT recreate the dropped CPU_RV1106 symbol (mainline IDs the
SoC purely via DT compat at runtime). clk + pinctrl + mach = the 3 core compile
components; DT + defconfig + full build remain for M2 (console boot).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
M1 pinctrl ported from vendor 5.10 (effort S, no API drift): enum, DRV/PULL/SMT
macros + 3 calc fns, case RV1106 in the 3 pull fns + RK3568 drive group, pin_banks
+ pin_ctrl, of_device_id (dropped CPU_RV1106 guard). pinctrl-rockchip.o 173KB, no
errors. iomux DRV/PULL/SMT offsets cross-validated against the upstream Simon Glass
v3 patch (match with the 0x10000 per-bank IOC base) -> the boot-critical iomux
PORT-VERIFY is retired via a 3rd independent source, no hardware. Upstream tracked
as a correctness oracle (doesn't apply to 6.18 cleanly; unmerged).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
Per [maintainer]: forward-port the RV1106 SoC enablement from the vendor 5.10 tree to
6.18 LTS ourselves (no plan44), on our Buildroot. Verified mainline has ZERO
RV1106 support, so this is a whole-BSP port. docs/bringup.md = the console-first
milestone plan + method (sibling-delta from rv1126/rv1108, which exist in both
trees). M1 (clk driver) underway: gcc-8.3 builds 6.18; wired CLK_RV1106; ported
55 CRU macros + the panic_notifier header split + the armclk signature change
(flagged PORT-VERIFY for the CPU-mux, TRM-check needed). Captured in
rv1106-enablement/. Honest: first of ~120 files; multi-month effort.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
Grounded in a full survey of the flare-edge firmware: catalogs every hardware
seam (register/MemBus, resource-path env-override, RGA compile-time), the tiered
MC/DC target (our code real MC/DC via the uboot-ab pattern; blobs fault-injection),
the target-config-lint class that the sim CANNOT cover (the 0x40000 brick), and
the ordered plan. Notes the flared<-warden-sim Cargo dep needs a repo remote
([maintainer] go-ahead).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
New from-scratch SDK for WardenOS (RV1106). First substance: the hardware
simulator's core — a MemBus register/SRAM seam (one trait, real /dev/mem backend
on device + in-memory SimBus on host) and a faithful port of the HPMCU watchdog
firmware (hpmcu/watchdog/main.c) as HpmcuSim, with 8 tests validating boot-grace
fire, heartbeat-timeout, disarm stand-down, and the flared arm-within-grace safety
property (no boot-loop) — all off-device, in a virtual clock, in <1ms.
This closes the gap the Explore map flagged: flared's devmem.rs/hpmcu.rs are the
only register-touching modules with zero tests. README lays out the SDK vision
(modern kernel, tiered driver MC/DC, proper RGA/HPMCU/NPU simulator, own repo).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf