NoahandClaude Opus 5 caa12d17ff Correct the FIT alignment to 512, and stop gating on 2048
054790d claimed the vendor aligns FIT sub-images to 0x800 and made that a build
gate. Both were wrong, and the reasoning was thin: two payloads from one build,
generalised into an invariant.

What U-Boot actually requires. IMAGE_ALIGN_SIZE is 512 (include/image.h:955-958)
and the read is blk_off = (FIT_ALIGN(fdt_totalsize) + offset) / blksz
(arch/arm/mach-rockchip/fit.c:331), a truncating divide by the 512-byte eMMC
block. So the metadata size must be a multiple of 512 -- otherwise FIT_ALIGN
rounds it up and EVERY payload is read late, including ones whose own position
is perfectly aligned -- and each data-position must be a multiple of 512.
Nothing in the FIT or RESC path references 2048.

Why the 2048 gate was actively harmful: of the eight boot.img files on this
machine, four are 512-aligned but sit at data-position % 2048 = 1536, including
vendor RELEASE_TEST builds that boot. The gate would have rejected images the
vendor shipped. 0x800 is the vendor's -p value -- the file position of the FIRST
payload -- not an alignment; 054790d moved it into the -B slot.

And it broke the build inside the SDK. mk-bootimg.sh resolves mkimage with a
bare `command -v`, project/build.sh:64 prepends the SDK tool directory to PATH,
and the SDK vendors mkimage 2017.09, which has no -B and exits 255 with
"invalid option -- 'B'" under set -euo pipefail. The 6.18 image built only
because it was made from a normal shell that found host mkimage 2025.01. The
flag is now feature-detected; the vendor packer 512-aligns natively, so omitting
it there is correct rather than a fallback.

9387cff's -B 0x200 was right, and better derived than 054790d credited: the
proven image's resource sits at 8748544, a multiple of 512 but not of 1024 or
2048, which pins the alignment at exactly 512 rather than bounding it.

The gate now asserts what U-Boot enforces -- metadata % 512 and every
data-position % 512 -- and the embedded-data guard drops from 65536 to >= 4096
to match FIT_FDT_MAX_SIZE (SZ_4K, fit.c:24). At 65536 a 5000-byte header passed
the build and returned "No fit blob" on a panel.

The already-flashed 6.18 boot.img is unaffected: 2048 is a multiple of 512, so
it satisfies the real requirement, which is why it booted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T2D2KtdgwbhbF6Mo64eUrn
2026-09-04 16:39:44 -06:00
2026-08-31 22:32:07 +00:00
2026-09-03 18:16:37 -06:00
2026-08-30 07:44:32 -06:00

bfe-core1106-sdk

ci Lines of code Tests Coverage Code quality

A modern, open development environment for the Luckfox Pico 86 Panel (Rockchip RV1106), replacing the vendor SDK, and honest about what runs on real silicon versus what is simulated.

Vendor SDK This repo
Kernel 5.10.160, twice-forked, frozen 6.18.46: a reviewable, subsystem-split patch series onto pristine upstream; full peripheral set (display, touch, wifi, audio, NPU, ...) hardware-verified on a bench panel
Build ~2 GB tree, absolute paths baked in, Kconfig options silently dropped one hermetic script: sha256-pinned source fetch, fail-closed patch apply and config fragments
Off-device testing none; every change means flashing a panel register-level hardware models (sim/) plus a QEMU device VM booting the real kernel, real daemons, and the real UI with display + touch
Config safety memory-map mistakes reach hardware (one bricked a bench unit) static gates (tools/config-lint) catch them before any flash
CI none hosted pipeline: tests, coverage, benchmarks, patch-apply gate, kernel build with an in-CI QEMU boot smoke
Flashing tools closed (upgrade_tool) open (rkdeveloptool)
License mixed GPL-2.0-only, with a per-driver provenance ledger

Quick Start

Requirements: gcc-arm-linux-gnueabihf, qemu-system-arm, curl, cpio, mkfs.ext4, a bare python on PATH (Debian/Ubuntu: python-is-python3), gcc >= 14 (driver harnesses), and Rust (for the simulators' tests).

# 1. Build the kernel: fetch pinned pristine 6.18.46, apply patches/, emit
#    zImage + rv1106-warden.dtb. WORK must sit outside any git checkout.
WORK=$HOME/kbuild-out CROSS_COMPILE=arm-linux-gnueabihf- bash build/build-kernel.sh

# 2. Boot it in the QEMU device simulator (no hardware needed):
bash qemu/mkinitramfs.sh
bash qemu/mkimage.sh
bash qemu/run.sh --kernel $HOME/kbuild-out/linux-6.18.46/arch/arm/boot/zImage --shell

# 3. Run the test suites:
for d in sim tools/config-lint qemu/rs485-bridge; do
  (cd "$d" && cargo test)
done
for d in drivers/*/test; do make -C "$d" check; done  # driver harnesses (gcc >= 14)

Add WARDEN_KCONFIG_FRAGMENT=qemu/configs/virt.fragment to step 1 for the kernel variant with the simulator's extra devices; qemu/README.md has the scenario tests (portal, OTA apply, display + touch, watchdog).

Layout

Directory Contents
patches/ the RV1106 forward-port onto pristine linux-6.18.46, subsystem-split
build/ hermetic kernel build: pinned fetch -> apply patches -> zImage + dtb
qemu/ device simulator: QEMU -M virt boots the real kernel and real userspace
sim/ register-level hardware models (Rust): membus, HPMCU, CRU, Modbus, RGA, NPU
drivers/ hardened hardware-facing drivers: HAL seams, test harnesses
kernel/ forward-port provenance and bring-up records (patches/ is canonical)
tools/ config-lint (static memory-map gates) and dev tooling
build/vendor.manifest the third-party trees this platform builds against (LVGL, the vendor RV1106 SDK), pinned to exact commits; build/fetch-vendor.sh obtains and verifies them
docs/ architecture, ADRs (decisions/), CI/CD

Architecture

One thin hardware abstraction seam per block (a trait in Rust, a function table in C): firmware logic talks to the seam; the seam binds a real backend on the device or a simulated backend on the host. The driver test harnesses measure against the same seam the simulator implements, so the two reinforce each other. Full detail: docs/architecture.md.

Simulator Runs Proves
sim/ register-level Rust models driver and supervisor logic, with fault injection
qemu/ the real kernel + userspace on -M virt boot, init, daemons, networking, OTA, watchdog, display + touch
lvglsim (downstream) the LVGL UI on SDL rendering and UI flows

With the production UI binary in qemu/payload/, run.sh --display on opens the panel's 720x720 screen in a window, mouse clicks landing as touch: device and UI in one VM. Emulation results are never on-silicon evidence; the simulators narrow which claims need a panel.

Principles

  • Open: open tools over closed ones; GPL-2.0-only.
  • Hard: every seam has a fault-injection path; recovery code is tested against failure, not just success.
  • Modern: the newest kernel the hardware can run, current toolchains, Rust for new host-testable code, reproducible builds.

License

GPL-2.0-only, repo-wide (LICENSE; a per-file SPDX identifier governs where present). patches/ and kernel/ are derivative of the Linux kernel and GPL-2.0 vendor code; per-driver origin is tracked in kernel/rv1106-enablement/PROVENANCE.md. Contributions are accepted under the same license (inbound = outbound).

S
Description
No description provided
Readme GPL-2.0
2.1 MiB
Languages
C 52%
Rust 22.9%
Shell 15.9%
Python 4.2%
Makefile 2.4%
Other 2.6%