The vendor 5.10 kernel is built without CONFIG_BRIDGE, and that absence has
shaped the firmware: the panel's access point has to be its own subnet with its
own DHCP pool instead of joining the LAN, and warden_router_set_zone() treats a
second LAN port as impossible. Both carry a code comment saying "this kernel has
no bridge".
Turning it on is what lets a Client-mode panel run an access point the way an
ordinary ceiling AP does -- wlan0 and the wired uplink in one broadcast domain,
addresses handed out by whatever router is already upstream.
Verified on the bench panel: before, `ip link add type bridge` returned
"Operation not supported"; on this kernel the bridge is created and eth0
enslaves into it (/sys/class/net/br0/brif/eth0). WireGuard, iptables and VLAN
still work.
Also fixes a warden-modbus path in architecture.md left stale by the apps/ move.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T2D2KtdgwbhbF6Mo64eUrn
Two gaps between "this SDK builds a kernel" and "this SDK can replace the
vendor SDK for the device".
BOOT IMAGE. build-kernel.sh emitted a zImage and a dtb and stopped, so
producing something the board's U-Boot would actually boot still meant going
through the vendor tree. mk-bootimg.sh packages the pair the way M2 bring-up
established (kernel/docs/m2-boot-on-c8a3.md): an EXTERNAL-DATA FIT
(mkimage -E -p 0x800), a mandatory `resource` multi sub-image carrying
rk-kernel.dtb plus any logos, and the sysmem sentinel load addresses. Each of
those was learned from a specific failure -- an embedded-data FIT is "No fit
blob", a missing resource image is "Failed to load DTB, ret=-19", real load
addresses collide -- so the script also ASSERTS the metadata stayed small,
because an embedded-data FIT looks perfectly fine until a panel will not come
back.
NETWORKING. Diffing this defconfig's expansion against the kernel actually
shipping on the panel found three whole subsystems missing, none of which fail
at build time and none of which are visible until the unit is in the field:
- WIREGUARD + NET_UDP_TUNNEL: flared's mesh to FLARE. Without it wg0 never
comes up.
- VLAN_8021Q: the MikroTik app configures tagged ports the panel terminates.
- NETFILTER and legacy iptables: every rule in S35iptables, and NAT for
router mode.
The netfilter half carried a trap worth naming. 6.18 split the legacy tables
out behind NETFILTER_XTABLES_LEGACY and IP_NF_IPTABLES_LEGACY, symbols that do
not exist in 5.10 -- so copying the vendor kernel's symbol list verbatim gives
a kernel where IP_NF_FILTER and IP_NF_NAT silently stay off and `iptables` has
no filter or nat table at all. Our userspace drives legacy iptables, not nft.
The result now shows ZERO regressions against the shipping 5.10 kernel across
mesh, gadget, firewall, VLAN, storage, net core, display/input, RGA/NPU,
wifi/BT and watchdog.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T2D2KtdgwbhbF6Mo64eUrn
- 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