diff --git a/ci/firmware/Dockerfile b/ci/firmware/Dockerfile
index ea7791e..6e4456b 100644
--- a/ci/firmware/Dockerfile
+++ b/ci/firmware/Dockerfile
@@ -17,7 +17,7 @@ RUN apt-get update \
libnl-3-dev libssl-dev llvm-dev lz4 openssl parted patch \
pkg-config python-is-python3 python3 python3-dev python3-pip python3-pyelftools \
rsync sudo texinfo \
- u-boot-tools udev unzip uuid-dev wget xz-utils zstd \
+ u-boot-tools udev unzip uuid-dev wget xxd xz-utils zstd \
&& rm -rf /var/lib/apt/lists/*
# Google's `repo` launcher (v2.69), pinned by content hash.
diff --git a/docs/firmware-release.md b/docs/firmware-release.md
index 5ac166a..57523ed 100644
--- a/docs/firmware-release.md
+++ b/docs/firmware-release.md
@@ -80,6 +80,7 @@ What a freshly flashed unit looks like, and what "factory reset" must restore:
| Item | Factory state |
| --- | --- |
+| `/userdata` | empty partition; first boot copies the factory binary from `/usr/lib/rustkvm/` |
| `/userdata/rustkvm/config.toml` | absent → setup wizard on first login (device password or no-password mode) |
| TLS certificate | self-signed, generated at start |
| SSH (dropbear) | off; enabled only by `/userdata/rustkvm/devmode.enable` |
diff --git a/os/rk3588/README.md b/os/rk3588/README.md
index 7c4f728..6a4c055 100644
--- a/os/rk3588/README.md
+++ b/os/rk3588/README.md
@@ -10,9 +10,11 @@ checks it out at the commits pinned here and applies the rest.
| `patches//NNNN-*.patch` | Changes to SDK projects, applied in order with `git apply` |
| `rootfs-overlay/` | Files copied into the root filesystem (init script, network config) |
-The build also adds two things that are not in the tree: the `rustkvm_app` binary
-(installed to `/userdata/rustkvm/bin/`) and `/etc/rustkvm-release` with the firmware
-version.
+The build also adds two things that are not in the tree: the `rustkvm_app` binary and
+`/etc/rustkvm-release` with the firmware version. The binary ships in the rootfs as
+`/usr/lib/rustkvm/rustkvm_app`, because `/userdata` is a separate partition that starts
+empty and is mounted over the rootfs directory; `S99rustkvm` copies it to
+`/userdata/rustkvm/bin/` on first boot and whenever userdata has been wiped.
## What the patches do
@@ -20,6 +22,7 @@ version.
| --- | --- |
| `buildroot` | dhcpcd privsep seccomp allows `dup3` (SIGSYS at boot); chrony drift file ownership |
| `buildroot` | RustKVM defconfig (GStreamer Opus, RGA, uvc-gadget, dropbear client, update engine); uvc-gadget builds with `-Dwerror=false` and accepts CONTINUOUS frame intervals |
+| `buildroot` | rkupdate's license points at its real `LICENSE` file, so `make legal-info` completes |
| `kernel` | `nanopi6_linux_defconfig`: NBD built in (virtual media), USB UAC2 gadget |
| `scripts/sd-fuse` | builds the `v4l2loopback` module (operator-camera passthrough) |
| `external` | rockit links `librkAlgoDis.so` |
diff --git a/os/rk3588/manifest.xml b/os/rk3588/manifest.xml
index 1c8bf3c..a771c3b 100644
--- a/os/rk3588/manifest.xml
+++ b/os/rk3588/manifest.xml
@@ -11,7 +11,8 @@
-
+
+
diff --git a/os/rk3588/patches/buildroot/0003-rkupdate-point-license-at-the-existing-LICENSE-file.patch b/os/rk3588/patches/buildroot/0003-rkupdate-point-license-at-the-existing-LICENSE-file.patch
new file mode 100644
index 0000000..15cf07d
--- /dev/null
+++ b/os/rk3588/patches/buildroot/0003-rkupdate-point-license-at-the-existing-LICENSE-file.patch
@@ -0,0 +1,13 @@
+diff --git a/package/rockchip/rkupdate/rkupdate.mk b/package/rockchip/rkupdate/rkupdate.mk
+index 2ac99eb6..dfb1d658 100644
+--- a/package/rockchip/rkupdate/rkupdate.mk
++++ b/package/rockchip/rkupdate/rkupdate.mk
+@@ -9,7 +9,7 @@ RKUPDATE_SITE = $(TOPDIR)/../external/rkupdate
+ RKUPDATE_SITE_METHOD = local
+
+ RKUPDATE_LICENSE = Apache V2.0
+-RKUPDATE_LICENSE_FILES = NOTICE
++RKUPDATE_LICENSE_FILES = LICENSE
+
+ RKUPDATE_DEPENDENCIES = \
+ libpthread-stubs util-linux
diff --git a/os/rk3588/rootfs-overlay/etc/init.d/S99rustkvm b/os/rk3588/rootfs-overlay/etc/init.d/S99rustkvm
index 207dfba..7f90409 100755
--- a/os/rk3588/rootfs-overlay/etc/init.d/S99rustkvm
+++ b/os/rk3588/rootfs-overlay/etc/init.d/S99rustkvm
@@ -4,6 +4,7 @@
# exit, so it is always stopped with SIGTERM. SIGKILL reboots the device.
APP=/userdata/rustkvm/bin/rustkvm_app
+FACTORY_APP=/usr/lib/rustkvm/rustkvm_app
LOG_DIR=/userdata/rustkvm/log
stop_app() {
@@ -43,6 +44,12 @@ start)
mkdir -p $LOG_DIR
+ # First boot or wiped userdata: install the binary shipped in the image.
+ if [ ! -f "$APP" ] && [ -f "$FACTORY_APP" ]; then
+ mkdir -p "$(dirname "$APP")"
+ cp "$FACTORY_APP" "$APP.tmp" && mv "$APP.tmp" "$APP"
+ fi
+
if [ ! -f "$APP" ]; then
echo "rustkvm_app not found!" >>$LOG_DIR/rustkvm_app.log
exit 1
diff --git a/scripts/build-firmware.sh b/scripts/build-firmware.sh
index 32aea16..7edacef 100755
--- a/scripts/build-firmware.sh
+++ b/scripts/build-firmware.sh
@@ -119,17 +119,32 @@ BOARD=${BOARD_MK%.mk}
EOF
[ -f "$APP" ] || die "application binary not found: $APP (run scripts/build-app.sh first)"
+ # /userdata is its own (initially empty) partition mounted over the rootfs
+ # directory, so the factory binary lives in the rootfs and S99rustkvm copies
+ # it to /userdata/rustkvm/bin on first boot (and after a userdata wipe).
log "install application $(basename "$APP")"
- local bin=$SDK/device/rockchip/common/images/userdata/normal/rustkvm/bin
- mkdir -p "$bin"
- install -m 0755 "$APP" "$bin/rustkvm_app"
+ rm -rf "$SDK/device/rockchip/common/images/userdata/normal/rustkvm"
+ install -D -m 0755 "$APP" "$files/usr/lib/rustkvm/rustkvm_app"
}
step_build() {
cd "$SDK"
- log "build kernel, u-boot, Buildroot and SD image ($BOARD_MK)"
- ./build.sh "$BOARD_MK"
- log "build eMMC flasher image"
+ # `./build.sh .mk` builds everything twice, the second time as root,
+ # which leaves root-owned objects that break the next unprivileged build.
+ # Select the board ourselves and build each part as the current user; only
+ # image packing needs root (build.sh sudoes for those targets itself).
+ if [ -n "$(find u-boot kernel buildroot/output -maxdepth 3 -user root -print -quit 2>/dev/null)" ]; then
+ log "reclaim root-owned build files"
+ sudo chown -R "$(id -u):$(id -g)" u-boot kernel buildroot/output scripts/sd-fuse/out
+ fi
+ ln -sfn "$(readlink -f .current)/$BOARD_MK" .current_config.mk
+ for part in uboot kernel buildroot; do
+ log "build $part ($BOARD_MK)"
+ ./build.sh "$part"
+ done
+ log "pack SD image"
+ ./build.sh sd-img
+ log "pack eMMC flasher image"
./build.sh emmc-img
}
@@ -140,10 +155,14 @@ step_collect() {
sd=$(ls -t "$SDK"/out/*_sd.img 2>/dev/null | head -n1) || true
eflasher=$(ls -t "$SDK"/out/*_eflasher.img 2>/dev/null | head -n1) || true
[ -n "$sd" ] || die "no SD image under $SDK/out"
- local name=rustkvm-rk3588-$FW_VERSION
+ # Name the files after the version baked into the image, not the current HEAD.
+ local release=$SDK/device/friendlyelec/rustkvm-files/etc/rustkvm-release
+ local built
+ built=$(sed -n 's/^FIRMWARE_VERSION=//p' "$release")
+ local name=rustkvm-rk3588-$built
gzip -c "$sd" >"$OUT/$name-sd.img.gz"
[ -n "$eflasher" ] && gzip -c "$eflasher" >"$OUT/$name-eflasher.img.gz"
- cp "$SDK/device/friendlyelec/rustkvm-files/etc/rustkvm-release" "$OUT/$name.release"
+ cp "$release" "$OUT/$name.release"
(cd "$OUT" && sha256sum "$name"-* "$name.release" >"$name.SHA256SUMS")
ls -lh "$OUT"/"$name"*
}
diff --git a/scripts/devkit.sh b/scripts/devkit.sh
index 62248b4..c77a599 100755
--- a/scripts/devkit.sh
+++ b/scripts/devkit.sh
@@ -97,8 +97,9 @@ cmd_firmware_image() {
cmd_firmware() {
have_image "$FIRMWARE_IMAGE" || cmd_firmware_image
mkdir -p "$SDK" "$CACHE/dl" "$CACHE/ccache"
- # --privileged: the SDK packs SD/eMMC images through loop devices.
- docker run --rm "${TTY[@]}" --privileged \
+ # --privileged and the host /dev: the SDK packs SD/eMMC images through loop
+ # devices, and only the host creates the loopNpM partition nodes.
+ docker run --rm "${TTY[@]}" --privileged -v /dev:/dev \
-e RUSTKVM_SDK_DIR=/sdk -e BR2_DL_DIR=/cache/dl \
-e RUSTKVM_ROOT_PASSWORD -e FW_VERSION -e BOARD_MK -e REPO_DEPTH \
-v "$ROOT:/work" -v "$SDK:/sdk" -v "$CACHE:/cache" \
diff --git a/scripts/gpl-source-bundle.sh b/scripts/gpl-source-bundle.sh
index a35c51f..f0df4bb 100755
--- a/scripts/gpl-source-bundle.sh
+++ b/scripts/gpl-source-bundle.sh
@@ -50,6 +50,8 @@ if [ "${LEGAL_INFO:-0}" = 1 ]; then
out_dir=$SDK/buildroot/output/rockchip_rk3588
[ -f "$out_dir/.config" ] || { echo "error: no built Buildroot tree in $out_dir" >&2; exit 1; }
make -C "$SDK/buildroot" O="$out_dir" legal-info
- tar -C "$out_dir" -czf "$OUT/rustkvm-$version-legal-info.tar.gz" legal-info
+ # Host tools are not distributed, so their sources stay out of the bundle.
+ tar -C "$out_dir" --exclude=legal-info/host-sources \
+ -czf "$OUT/rustkvm-$version-legal-info.tar.gz" legal-info
echo "==> $OUT/rustkvm-$version-legal-info.tar.gz"
fi