Files
bfe-core1106-sdk/README.md
T
BFE EngineeringandClaude Fable 5 13b7d063a2 qemu: display + touch scenario, ADR-0006, docs
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
2026-08-29 20:16:36 -06:00

7.0 KiB

warden-sdk

ci Lines of code Tests Coverage

The build, driver, and simulation SDK for WardenOS (the Luckfox Pico 86-Panel / RV1106 HMI). A from-scratch replacement for the twice-ported vendor stack (Rockchip SDK → Luckfox SDK → our patched fork), built to the same standard as the rest of the firmware: tested, benchmarked, reproducible, and honest about what runs on real silicon versus what we simulate.

Status: bringup. The hardware simulator and its tests, the RV1106 kernel forward-port as a reviewable patches/ series, the hermetic kernel build, two Tier-1 drivers at 100% MC/DC, and the QEMU device sim (qemu/, ADR-0006: boots the real kernel + real userspace on -M virt — check-in/OTA against the mock portal, watchdog, RS485-to-sim bridge, 720x720 display + touch, all emulation-verified) are in. What remains before this is on the production build path: qemu-system-arm on the kernel-build runner (see docs/ci-cd.md §5) and having flare-edge consume warden-sdk as a dependency — both [maintainer]-gated. Until then, flare-edge still builds firmware from the vendored SDK + sdk-patches/.

Why a new SDK

The vendored SDK is a ~2 GB opaque fork of a fork. Our real changes to it lived, until recently, as uncommitted edits in one working copy (flare-edge/sdk-patches/ is the tracked form). It bakes absolute paths, needs python (not python3), silently drops Kconfig options, and — the failure that motivated this repo — gives us no way to test hardware-dependent code off the device. Every driver change had to be validated by flashing a panel. That is slow, and it is dangerous: it is how a boot-loaded-watchdog change bricked a bench unit (the load address collided with unreserved kernel RAM — a mistake a target-config check or a memory-map model would have caught before any flash).

The SDK's job is to make the firmware buildable, testable, and hardenable without a panel in the loop, and to move us onto a modern, maintained kernel.

Goals (from future-features)

  1. Modern kernel. A self-built Linux 6.18.46, forward-ported directly from the vendor 5.10.160 tree (no plan44/OpenWrt code) on our current Buildroot LTS (2025.02.x). This is done and hardware-verified on warden-c8a3: essentially every RV1106 block the 86-Panel uses boots and works — clk, pinctrl, eMMC, GMAC, TRNG, OTP, SARADC/TSADC, RTC, USB host, PWM/backlight, VOP display, GT911 touch, AIC8800 wifi, RGA, I2S audio, HPMCU mailbox, the open NPU driver, and PVTM. Mainline was not viable (no DT/clk/display/RGA/NPU/ flash-boot upstream for RV1106); the direct 5.10→6.18 forward-port reuses the already-in-mainline rv1126 register data where it matches and carries our deltas as a reviewable patch series (patches/).
  2. Ported, hardened drivers → 100% MC/DC on the code we own. "100% MC/DC on 100% of drivers" is infeasible as literally stated: ~97% of driver LOC is vendor blobs (the AIC8800 wifi driver alone is 88.5K lines). So the target is tiered: real MC/DC on our hardware code (modbus master, relays, RGA wrapper, HPMCU supervisor, devmem/reset ladder); fault-injection + branch hardening for the vendor blobs behind a stable seam.
  3. A proper simulator. Simulate the hardware the vendor SDK cannot: RGA (2D blitter), the RISC-V HPMCU coprocessor, and the NPU — plus the register/SRAM (/dev/mem) and sysfs surfaces the drivers touch — so driver and supervisor logic runs and is tested on the host, in CI, with no panel.
  4. Its own repo, held to firmware standards. Tests, benchmarks, reproducible builds, CI. This repo.

Architecture — one seam, two backends

The organizing idea is a thin Hardware Abstraction Seam per hardware block. Firmware code talks to the seam (a trait in Rust, a function table in C); the seam has two backends:

        firmware / driver logic
                  │
          Hardware Abstraction Seam        (devmem, hpmcu, rga, npu, modbus, gpio)
             ┌────┴────┐
        real backend   sim backend
      (/dev/mem, ioctl, (software model,
       /proc, serial)    host-testable)
  • On-device, the seam binds the real backend (mmap /dev/mem, librga ioctls, the serial port, /proc/rknpu).
  • On the host, it binds the sim backend — a faithful software model of the block. The HPMCU sim, for example, runs the SCR1 watchdog firmware's exact state machine (boot-grace, heartbeat-timeout, fire) against an in-memory mailbox, so the flared supervisor's arm/beat protocol is exercised end-to-end in a unit test.

The seam is the same object the driver-hardening effort measures MC/DC against, and the same object the simulator implements — so the two goals reinforce rather than duplicate each other.

Layout

sim/        the hardware simulator (Rust): membus/devmem, HPMCU, CRU, Modbus, RGA, NPU.
qemu/       the device simulator (ADR-0006): QEMU -M virt boots the real kernel and
            real userspace; A/B disk layout, RS485 bridge into sim/, scenario tests.
drivers/    our own hardened drivers + their seams (relays, freshness; more migrate in).
patches/    the RV1106 kernel forward-port delta onto pristine linux-6.18.46 (subsystem-split).
kernel/     forward-port docs + provenance (rv1106-enablement/, PROVENANCE.md).
build/      the hermetic kernel build (fetch pristine → apply patches → zImage + dtb).
docs/       architecture + ADRs (decisions/) + ci-cd + generated workflow flowcharts.
tools/      dev tooling. config-lint: static target-config gates (MCU-load-vs-reserved-memory,
            the 0x40000 brick class); flowgen: the workflow-flowchart generator.
.github/    CI (workflows/ci.yml): patches-apply, host tests, coverage, MC/DC, benchmarks, badges.

Principles

Evaluated against the stack philosophy — openness, hardness, modernness:

  • Open over closed where we can: rkdeveloptool over the closed upgrade_tool; source-buildable librga over blobs where a source path exists; the simulator is fully open and ours.
  • Hard: every seam has a fault-injection path (a wedged SDIO link, a stalled MCU, an RGA timeout) so recovery code is tested against failure, not just success. On-device claims still need on-device evidence; the sim narrows which claims need a panel, it does not replace that rule.
  • Modern: newest kernel we can actually run; current Buildroot LTS; Rust for new host-testable code; reproducible builds.

Relationship to flare-edge

flare-edge (WardenOS: the LVGL UI + the flared daemon) is the product; warden-sdk is what builds and tests it. During bootstrap, flare-edge consumes warden-sdk piece by piece: first the simulator (as a dev/test dependency), later the image build. No flare-edge code moves here — only the SDK/build/sim/driver-seam layer.