From e895c3f86c56b6ea65859b2f1bdd630c9fe86b05 Mon Sep 17 00:00:00 2001 From: Tomaz Zaman Date: Wed, 19 Aug 2026 00:10:20 +0200 Subject: [PATCH 76/77] mono-update: let native packages survive OTA (feeds + reinstall) apk-add'd packages are wiped by a sysupgrade (the rootfs is replaced). Make them installable and bring them back: - Seed: enable the official OpenWrt luci + packages apk feeds (repo lines only, no bulk build) - the ~9000 arch-independent AND arch-dependent packages the stock 25.12.5 repo serves become installable. kmods can't come from there (kernel vermagic), so scripts/mono-update.sh publishes a per-release kmod feed (bin/targets/.../packages -> releases//kmods) and 92-mono-feeds points apk at //kmods (404s harmlessly until published). - 93-mono-baseline snapshots the factory package set on first boot; the mono-update client writes world-minus-baseline (the user's adds) right before flashing; 95-mono-reinstall (hotplug on ifup) re-adds them from the feeds after boot. Both files are kept across sysupgrade. Validated on the DUT: apk add luci-theme-openwrt-2020 installs from the official feed; the snapshot delta is exactly the user's added package; a deleted package run through the reinstall hook comes back. Co-Authored-By: Claude Opus 4.8 --- configs/mono_gateway-dk.seed | 8 +++-- package/mono/updater/Makefile | 7 +++++ package/mono/updater/files/92-mono-feeds | 12 ++++++++ package/mono/updater/files/93-mono-baseline | 10 ++++++ package/mono/updater/files/95-mono-reinstall | 32 ++++++++++++++++++++ package/mono/updater/files/mono-update | 10 ++++++ package/mono/updater/files/mono-update.keep | 4 +++ scripts/mono-update.sh | 7 +++++ 8 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 package/mono/updater/files/92-mono-feeds create mode 100644 package/mono/updater/files/93-mono-baseline create mode 100644 package/mono/updater/files/95-mono-reinstall diff --git a/configs/mono_gateway-dk.seed b/configs/mono_gateway-dk.seed index 260fdc8e9e..22e855dc9d 100644 --- a/configs/mono_gateway-dk.seed +++ b/configs/mono_gateway-dk.seed @@ -15,8 +15,12 @@ CONFIG_TARGET_layerscape=y CONFIG_TARGET_layerscape_armv8_64b=y CONFIG_TARGET_layerscape_armv8_64b_DEVICE_mono_gateway-dk=y CONFIG_DEVEL=y -# CONFIG_FEED_luci is not set -# CONFIG_FEED_packages is not set +# Enable the official OpenWrt luci + packages apk feeds on the device (repo +# lines only - does NOT bulk-build the feeds). Lets users `apk add` the ~9000 +# arch-independent + arch-dependent packages the stock 25.12.5 repo serves; +# kmods still come from the mono per-release feed (vermagic-locked). +CONFIG_FEED_luci=y +CONFIG_FEED_packages=y CONFIG_KERNEL_GIT_CLONE_URI="https://github.com/nxp-qoriq/linux" CONFIG_KERNEL_GIT_LOCAL_REPOSITORY="" CONFIG_KERNEL_GIT_MIRROR_HASH="" diff --git a/package/mono/updater/Makefile b/package/mono/updater/Makefile index e1acea199f..cf642a7099 100644 --- a/package/mono/updater/Makefile +++ b/package/mono/updater/Makefile @@ -67,6 +67,13 @@ define Package/mono-update/install $(INSTALL_BIN) ./files/mono-update $(1)/usr/sbin/ $(INSTALL_DIR) $(1)/etc/uci-defaults $(INSTALL_BIN) ./files/90-mono-update-cron $(1)/etc/uci-defaults/ + # 92: point apk at the per-release mono kmod feed. 93: snapshot the factory + # package set as the reinstall baseline (both first-boot uci-defaults). + $(INSTALL_BIN) ./files/92-mono-feeds $(1)/etc/uci-defaults/ + $(INSTALL_BIN) ./files/93-mono-baseline $(1)/etc/uci-defaults/ + # 95: reinstall the user's added packages after a sysupgrade, on network-up. + $(INSTALL_DIR) $(1)/etc/hotplug.d/iface + $(INSTALL_BIN) ./files/95-mono-reinstall $(1)/etc/hotplug.d/iface/ # Trusted release signing keys (public halves): the primary key used # nightly, plus an offline rotation key so a lost primary never strands # the fleet. Private halves never leave the release host / offline media. diff --git a/package/mono/updater/files/92-mono-feeds b/package/mono/updater/files/92-mono-feeds new file mode 100644 index 0000000000..7224a58e9b --- /dev/null +++ b/package/mono/updater/files/92-mono-feeds @@ -0,0 +1,12 @@ +#!/bin/sh +# Add the Mono per-release kmod feed to apk's repositories. Kernel modules are +# vermagic-locked to this build, so the official OpenWrt feed cannot serve them; +# this per-release feed on the update server carries the ones built for THIS +# image. The official luci + packages feeds already come from distfeeds.list +# (CONFIG_FEED_luci/packages). Regenerated each boot so tracks the release. +base=$(uci -q get mono-update.check.url) +tag=$(cat /etc/mono_release 2>/dev/null) +case "$tag" in mono-v*) ;; *) exit 0 ;; esac # dev build: no published feed +[ -n "$base" ] || exit 0 +echo "$base/$tag/kmods/packages.adb" > /etc/apk/repositories.d/mono-kmods.list +exit 0 diff --git a/package/mono/updater/files/93-mono-baseline b/package/mono/updater/files/93-mono-baseline new file mode 100644 index 0000000000..3d0408dcf9 --- /dev/null +++ b/package/mono/updater/files/93-mono-baseline @@ -0,0 +1,10 @@ +#!/bin/sh +# Capture the factory apk 'world' (the package set the image ships) once, so the +# updater can compute the user's added packages as (world - baseline) before a +# flash. Preserved across sysupgrade via keep.d and captured on the first factory +# boot, before the user installs anything. +[ -f /etc/mono-update.baseline ] && exit 0 +[ -f /etc/apk/world ] || exit 1 +cp /etc/apk/world /etc/mono-update.baseline +sync +exit 0 diff --git a/package/mono/updater/files/95-mono-reinstall b/package/mono/updater/files/95-mono-reinstall new file mode 100644 index 0000000000..8a6f56328c --- /dev/null +++ b/package/mono/updater/files/95-mono-reinstall @@ -0,0 +1,32 @@ +#!/bin/sh +# After a sysupgrade wipes the rootfs, reinstall the packages the user had added. +# mono-update snapshots the list pre-flash into /etc/mono-update.reinstall (kept +# across the flash). This fires on interface-up, so the feeds are reachable, and +# removes the list once done - later events are then no-ops. +[ "$ACTION" = ifup ] || exit 0 +[ -s /etc/mono-update.reinstall ] || exit 0 +mkdir /tmp/mono-reinstall.lock 2>/dev/null || exit 0 # a run is already in flight + +# Refresh the indexes. Best-effort: a per-release feed can briefly 404 (or be +# unpublished on a dev build), which makes apk exit non-zero even though the +# official feeds refreshed - so never gate the reinstall on apk update's status. +apk update >/dev/null 2>&1 + +succ=0; fail=0 +for p in $(cat /etc/mono-update.reinstall); do + if apk add "$p" >/dev/null 2>&1; then + succ=$((succ + 1)); logger -t mono-reinstall "reinstalled $p" + else + fail=$((fail + 1)); logger -t mono-reinstall "could not reinstall $p" + fi +done + +# Drop the list once the network was clearly reachable (something installed, or +# nothing failed); keep it only when EVERYTHING failed (WAN not up yet) so a +# later ifup retries. +if [ "$fail" = 0 ] || [ "$succ" -gt 0 ]; then + rm -f /etc/mono-update.reinstall + sync +fi +rmdir /tmp/mono-reinstall.lock 2>/dev/null +exit 0 diff --git a/package/mono/updater/files/mono-update b/package/mono/updater/files/mono-update index 72086c5b68..a810f5ebae 100755 --- a/package/mono/updater/files/mono-update +++ b/package/mono/updater/files/mono-update @@ -204,6 +204,16 @@ do_install() { printf 'floor=%s\n' "$TAG" > "$FLOORFILE" sync + # Snapshot the packages the user added on top of the factory set (world - + # baseline, by bare name), so 95-mono-reinstall can put them back from the + # feeds after the flash wipes the rootfs. Best-effort - never block the flash. + if [ -f /etc/mono-update.baseline ]; then + sed 's/[=<>].*//' /etc/mono-update.baseline 2>/dev/null | sort -u > "$TMP/base_names" + sed 's/[=<>].*//' /etc/apk/world 2>/dev/null | sort -u > "$TMP/cur_names" + grep -vxF -f "$TMP/base_names" "$TMP/cur_names" 2>/dev/null > /etc/mono-update.reinstall + sync + fi + say "verified $TAG - applying via sysupgrade, the device will reboot now" exec sysupgrade "$TMP/image.bin" } diff --git a/package/mono/updater/files/mono-update.keep b/package/mono/updater/files/mono-update.keep index 7dc8db109f..f54bdcb87c 100644 --- a/package/mono/updater/files/mono-update.keep +++ b/package/mono/updater/files/mono-update.keep @@ -1,2 +1,6 @@ # Preserve the update anti-rollback floor across sysupgrade. /etc/mono-update.state +# Preserve the factory package baseline and the pre-flash reinstall list, so the +# user's added packages can be put back after a sysupgrade (95-mono-reinstall). +/etc/mono-update.baseline +/etc/mono-update.reinstall diff --git a/scripts/mono-update.sh b/scripts/mono-update.sh index cf6e23867f..8a7ffc6dc1 100755 --- a/scripts/mono-update.sh +++ b/scripts/mono-update.sh @@ -146,6 +146,13 @@ mkdir -p "$OUT" cp "$BINDIR"/openwrt-layerscape-armv8_64b-mono_*-ext4-emmc.img.gz \ "$BINDIR"/openwrt-layerscape-armv8_64b-mono_*-ext4-sysupgrade*.bin \ "$BINDIR"/openwrt-layerscape-armv8_64b-mono_*.manifest "$OUT/" + +# Per-release kmod feed: kernel modules are vermagic-locked to this build, so +# devices cannot get them from the official OpenWrt repo. The device's +# 92-mono-feeds points apk at //kmods/. luci + packages come from the +# official feed; we ship only what it cannot - the signed target/kmod packages. +mkdir -p "$OUT/kmods" +cp "$BINDIR"/packages/packages.adb "$BINDIR"/packages/*.apk "$OUT/kmods/" git format-patch --quiet -o "$OUT/patches" "$LATEST..$BRANCH" (cd "$OUT" && sha256sum *.img.gz *.bin > sha256sums) -- 2.47.3