mirror of
https://github.com/archr-linux/Arch-R.git
synced 2026-07-12 18:19:42 -07:00
update: let kernel and DTB fixes flow through pacman via flash-sync
Until now anything living on the FAT boot partition (kernel Image and the device trees) was reflash-only, breaking the promise that every update can arrive either by rewriting the image or through pacman and the ES update menu. Close the gap with three pieces: - The linux package now ships the kernel image in the rootfs under /usr/share/bootloader/Image next to the device_trees it already installs, so a pacman upgrade of linux delivers both. - archr-flash-sync copies Image to /flash/KERNEL (refreshing the KERNEL.md5 sidecar) and device_trees/*.dtb to /flash/dtbs, but only the files whose sha256 actually changed, each written as a verified .new temp in the same FAT directory and renamed over the original so the torn-write window is the rename alone. /flash/overlays (the user's panel overlay), extlinux, boot scripts and u-boot are never touched; u-boot/TPL live in raw sectors where a torn write bricks the card, so the bootloader intentionally stays image-flash only. - An alpm PostTransaction hook (HookDir /etc/pacman.d/hooks) fires the sync whenever a transaction touches the bootloader payload. gen-pacman-repo now prunes the .image build-plumbing directory from packages, which would otherwise dump a duplicate raw kernel at /.image on every update. Hardware test pending: run archr-flash-sync by hand over SSH and check the device still boots with the synced KERNEL and dtbs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -146,6 +146,12 @@ EOF
|
||||
cp ${PKG_DIR}/sources/scripts/* ${INSTALL}/usr/bin
|
||||
chmod 0755 ${INSTALL}/usr/bin/* 2>/dev/null ||:
|
||||
|
||||
# alpm hooks (pacman.conf points HookDir at /etc/pacman.d/hooks): the
|
||||
# flash-sync hook keeps the FAT boot partition in step with kernel or
|
||||
# DTB updates delivered through pacman.
|
||||
mkdir -p ${INSTALL}/etc/pacman.d/hooks
|
||||
cp ${PKG_DIR}/sources/pacman-hooks/*.hook ${INSTALL}/etc/pacman.d/hooks
|
||||
|
||||
### Install man pages
|
||||
if [ -d "${PKG_DIR}/sources/man" ]; then
|
||||
for page in ${PKG_DIR}/sources/man/*.[1-9]; do
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# Sync the kernel and device trees delivered by pacman into the FAT
|
||||
# boot partition (/flash), so kernel-side fixes reach users through the
|
||||
# normal update flow. See /usr/bin/archr-flash-sync for the safety
|
||||
# model; u-boot/TPL stays image-flash only.
|
||||
[Trigger]
|
||||
Operation = Install
|
||||
Operation = Upgrade
|
||||
Type = Path
|
||||
Target = usr/share/bootloader/Image
|
||||
Target = usr/share/bootloader/device_trees/*
|
||||
|
||||
[Action]
|
||||
Description = Syncing kernel and device trees to the boot partition...
|
||||
When = PostTransaction
|
||||
Exec = /usr/bin/archr-flash-sync
|
||||
@@ -0,0 +1,111 @@
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (C) 2026-present ArchR (https://github.com/archr-linux/Arch-R)
|
||||
#
|
||||
# archr-flash-sync: bring the boot partition (FAT, /flash) in line with
|
||||
# the kernel and device trees shipped in the rootfs. This is what lets
|
||||
# kernel and DTB fixes flow through `pacman -Syu` / the ES update menu
|
||||
# instead of demanding a reflash: the linux package delivers the new
|
||||
# files under /usr/share/bootloader and an alpm PostTransaction hook
|
||||
# runs this script to copy the changed ones over.
|
||||
#
|
||||
# Safety model: each target is written as <name>.new in the same FAT
|
||||
# directory, synced, read back and hash-verified, then renamed over the
|
||||
# old file. The window where a power cut leaves a torn file is the
|
||||
# rename itself, the smallest FAT allows. Anything user-owned on the
|
||||
# FAT is never touched: /flash/overlays (the user's mipi-panel.dtbo),
|
||||
# extlinux/, boot.scr, boot.ini.
|
||||
#
|
||||
# u-boot/TPL (idbloader) stays OUT of scope on purpose: it lives in raw
|
||||
# sectors before the first partition and a torn write there bricks the
|
||||
# card with no recovery besides a reflash. Bootloader updates remain
|
||||
# image-flash only.
|
||||
|
||||
SRC="/usr/share/bootloader"
|
||||
BOOT="/flash"
|
||||
|
||||
log() { echo "flash-sync: $*"; }
|
||||
|
||||
if [ ! -d "${BOOT}" ] || ! grep -q " ${BOOT} " /proc/mounts; then
|
||||
log "no boot partition mounted at ${BOOT}, nothing to do"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! mount -o remount,rw "${BOOT}" 2>/dev/null; then
|
||||
log "WARN: could not remount ${BOOT} read-write, skipping"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
finish() {
|
||||
sync
|
||||
mount -o remount,ro "${BOOT}" 2>/dev/null
|
||||
}
|
||||
trap finish EXIT
|
||||
|
||||
CHANGED=0
|
||||
FAILED=0
|
||||
|
||||
# sync_file <src> <dst>: copy only when the content differs, via a
|
||||
# verified temp file in the destination directory.
|
||||
sync_file() {
|
||||
s="$1"
|
||||
d="$2"
|
||||
[ -f "${s}" ] || return 0
|
||||
|
||||
src_sum=$(sha256sum "${s}" | cut -d' ' -f1)
|
||||
if [ -f "${d}" ]; then
|
||||
dst_sum=$(sha256sum "${d}" | cut -d' ' -f1)
|
||||
[ "${src_sum}" = "${dst_sum}" ] && return 0
|
||||
fi
|
||||
|
||||
tmp="${d}.new"
|
||||
if ! cp "${s}" "${tmp}" 2>/dev/null; then
|
||||
log "ERROR: writing ${tmp} failed (FAT full?)"
|
||||
rm -f "${tmp}" 2>/dev/null
|
||||
FAILED=1
|
||||
return 1
|
||||
fi
|
||||
sync
|
||||
new_sum=$(sha256sum "${tmp}" | cut -d' ' -f1)
|
||||
if [ "${new_sum}" != "${src_sum}" ]; then
|
||||
log "ERROR: verify of ${tmp} failed, keeping the old file"
|
||||
rm -f "${tmp}" 2>/dev/null
|
||||
FAILED=1
|
||||
return 1
|
||||
fi
|
||||
mv -f "${tmp}" "${d}"
|
||||
sync
|
||||
log "updated ${d}"
|
||||
CHANGED=1
|
||||
return 0
|
||||
}
|
||||
|
||||
# Kernel: /usr/share/bootloader/Image -> /flash/KERNEL. Refresh the
|
||||
# sidecar md5 too (legacy .update flow reads it with the target/KERNEL
|
||||
# name baked in).
|
||||
if [ -f "${SRC}/Image" ]; then
|
||||
if sync_file "${SRC}/Image" "${BOOT}/KERNEL" && [ "${CHANGED}" = "1" ]; then
|
||||
md5=$(md5sum "${BOOT}/KERNEL" | cut -d' ' -f1)
|
||||
printf '%s target/KERNEL\n' "${md5}" > "${BOOT}/KERNEL.md5" 2>/dev/null
|
||||
fi
|
||||
else
|
||||
log "no ${SRC}/Image in this rootfs (older build), kernel left alone"
|
||||
fi
|
||||
|
||||
# Device trees: only into the dtbs/ dir the image layout uses. The
|
||||
# user's panel overlay lives in /flash/overlays and is never touched.
|
||||
if [ -d "${SRC}/device_trees" ] && [ -d "${BOOT}/dtbs" ]; then
|
||||
for dtb in "${SRC}/device_trees/"*.dtb; do
|
||||
[ -f "${dtb}" ] || continue
|
||||
sync_file "${dtb}" "${BOOT}/dtbs/$(basename "${dtb}")"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "${FAILED}" = "1" ]; then
|
||||
log "finished WITH ERRORS, the untouched files remain bootable"
|
||||
elif [ "${CHANGED}" = "1" ]; then
|
||||
log "boot partition updated, changes take effect on the next boot"
|
||||
else
|
||||
log "boot partition already up to date"
|
||||
fi
|
||||
exit 0
|
||||
@@ -378,6 +378,11 @@ makeinstall_target() {
|
||||
|
||||
if [ "${BOOTLOADER}" = "u-boot" ]; then
|
||||
mkdir -p ${INSTALL}/usr/share/bootloader
|
||||
# Ship the kernel image in the rootfs as well: pacman carries it to
|
||||
# updated systems and archr-flash-sync copies it over /flash/KERNEL
|
||||
# (the FAT copy u-boot actually boots). Fresh images stay in sync by
|
||||
# construction; this closes the update-without-reflash path.
|
||||
cp -p arch/${TARGET_KERNEL_ARCH}/boot/${KERNEL_TARGET} ${INSTALL}/usr/share/bootloader/
|
||||
for dtb in arch/${TARGET_KERNEL_ARCH}/boot/dts/**/*.dtb; do
|
||||
if [ -f ${dtb} ]; then
|
||||
if [ "${DEVICE}" = "H700" -o "${DEVICE}" = "RK3326" -o "${DEVICE}" = "RK3399" -o "${DEVICE}" = "RK3566" -o "${DEVICE}" = "RK3588" ]; then
|
||||
|
||||
@@ -139,7 +139,10 @@ EOF
|
||||
filelist="$(mktemp)"
|
||||
{
|
||||
echo ".PKGINFO"
|
||||
find . -mindepth 1 -maxdepth 1 -not -name '.PKGINFO' -printf '%P\n'
|
||||
# .image is build-system plumbing (raw kernel + symbols the
|
||||
# image script consumes); shipping it would dump ~25MB at
|
||||
# /.image on every kernel update for nothing.
|
||||
find . -mindepth 1 -maxdepth 1 -not -name '.PKGINFO' -not -name '.image' -printf '%P\n'
|
||||
} > "${filelist}"
|
||||
tar --zstd -cf "${outfile}" --owner=0 --group=0 -T "${filelist}"
|
||||
rm -f "${filelist}"
|
||||
|
||||
Reference in New Issue
Block a user