Implement system-update feature
The `system-update` and `install-update` scripts are the same as from Aimee OS v1, with references to Gentoo replaced, of course. We need some additional kernel features in order to mount the firmware partition and update the GRUB environment file, and of course the `grub-editenv` tool itself. We also need `wget` for now, since that's how the tool downloads the specified update file from the network. Eventually, `system-update` will be replaced by a much more robust tool, with package URL discovery, signature verification, etc. The shell script will do for now while development is still proceeding rapidly.master
parent
7e5a83ba28
commit
821ea84ea7
|
@ -65,6 +65,7 @@ pipeline {
|
|||
'firmware.img.zst',
|
||||
'rootfs.squashfs',
|
||||
'sdcard.img.zst',
|
||||
'update.tar.zst',
|
||||
].join(','))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,12 @@ define AIMEEOS_LINUX_CONFIG_FIXUPS
|
|||
$(call KCONFIG_ENABLE_OPT,CONFIG_BLK_DEV_INITRD)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_BTRFS_FS)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_EFI)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_MSDOS_FS)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_NLS_CODEPAGE_437)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_NLS_ISO8859_1)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_NLS_UTF8)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_SQUASHFS)
|
||||
$(call KCONFIG_ENABLE_OPT,CONFIG_VFAT_FS)
|
||||
endef
|
||||
LINUX_KCONFIG_FIXUP_CMDS += $(AIMEEOS_LINUX_CONFIG_FIXUPS)
|
||||
|
||||
|
@ -71,6 +76,8 @@ $(BR2_EXTERNAL_AIMEEOS_PATH)/boot/grub2/gen-grub-cfg.sh $(AIMEEOS_KERNEL_FILENAM
|
|||
endef
|
||||
LINUX_TARGET_FINALIZE_HOOKS += AIMEEOS_GEN_GRUB_CFG
|
||||
|
||||
BR2_ROOTFS_POST_IMAGE_SCRIPT += $(BR2_EXTERNAL_AIMEEOS_PATH)/update/make-package.sh
|
||||
|
||||
endif
|
||||
|
||||
include $(sort $(wildcard $(BR2_EXTERNAL_AIMEEOS_PATH)/package/*/*.mk))
|
||||
|
|
|
@ -6,3 +6,5 @@ config BR2_PACKAGE_AIMEE_OS_UTILS
|
|||
select BR2_PACKAGE_UTIL_LINUX_MOUNTPOINT
|
||||
select BR2_PACKAGE_UTIL_LINUX_PARTX
|
||||
select BR2_PACKAGE_UTIL_LINUX_SWITCH_ROOT
|
||||
select BR2_PACKAGE_WGET
|
||||
select BR2_TARGET_GRUB2_INSTALL_TOOLS
|
||||
|
|
|
@ -12,6 +12,13 @@ AIMEE_OS_UTILS_DEPENDENCIES = \
|
|||
|
||||
AIMEE_OS_UTILS_SOURCE =
|
||||
|
||||
define AIMEE_OS_UTILS_INSTALL_TARGET_CMDS
|
||||
$(INSTALL) -D -m u=rwx,go=rx \
|
||||
$(AIMEE_OS_UTILS_PKGDIR)/system-update.sh \
|
||||
$(TARGET_DIR)/usr/sbin/system-update
|
||||
mkdir -p $(TARGET_DIR)/boot/efi
|
||||
endef
|
||||
|
||||
define AIMEE_OS_UTILS_INSTALL_INIT_SYSTEMD
|
||||
$(INSTALL) -D -m u=rw,go=r \
|
||||
$(AIMEE_OS_UTILS_PKGDIR)/var.mount \
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
#!/bin/sh
|
||||
# vim: set sw=4 ts=4 sts=4 et :
|
||||
|
||||
cleanup() {
|
||||
cd /
|
||||
if [ -n "${workdir}" ] && [ "${workdir}" != / ]; then
|
||||
rm -rf "${workdir}"
|
||||
fi
|
||||
unset workdir
|
||||
}
|
||||
|
||||
die() {
|
||||
rc=$?
|
||||
if [ $rc -eq 0 ]; then
|
||||
rc=1
|
||||
fi
|
||||
error "$@"
|
||||
exit $rc
|
||||
}
|
||||
|
||||
error() {
|
||||
if [ $# -eq 1 ]; then
|
||||
echo "$1" >&2
|
||||
elif [ $# -gt 1 ]; then
|
||||
printf "$@" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
extract_update() {
|
||||
zstd -dc update.tar.zstd | tar -x \
|
||||
|| die 'Could not extract update source'
|
||||
sha256sum -c digests \
|
||||
|| die 'Invalid update source: checksum mismatch'
|
||||
}
|
||||
|
||||
fetch_update() {
|
||||
wget -O update.tar.zstd "$1"
|
||||
}
|
||||
|
||||
get_root() {
|
||||
set -- $(cat /proc/cmdline)
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
root=*)
|
||||
_root=${1#root=}
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
echo $(findfs "${_root}")
|
||||
}
|
||||
|
||||
get_partlabel() {
|
||||
blkid -o value -s PARTLABEL "$1"
|
||||
}
|
||||
|
||||
help() {
|
||||
usage
|
||||
}
|
||||
|
||||
info() {
|
||||
if [ $# -eq 1 ]; then
|
||||
echo "$1" >&2
|
||||
elif [ $# -gt 1 ]; then
|
||||
printf "$@" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
usage() {
|
||||
printf 'usage: %s source_url\n' "${0##*/}"
|
||||
}
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--help)
|
||||
help
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
if [ -z "${source_url}" ]; then
|
||||
source_url="$1"
|
||||
else
|
||||
usage >&2
|
||||
exit 2
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ -z "${source_url}" ]; then
|
||||
usage >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
root=$(get_root)
|
||||
partlabel=$(get_partlabel "${root}")
|
||||
|
||||
case "${partlabel}" in
|
||||
rootfs-a)
|
||||
newpartlabel=rootfs-b
|
||||
;;
|
||||
rootfs-b)
|
||||
newpartlabel=rootfs-a
|
||||
;;
|
||||
*)
|
||||
die \
|
||||
'Unsupported system configuration: invalid rootfs partition label: %s\n' \
|
||||
"${partlabel}" >&2
|
||||
esac
|
||||
newroot=$(findfs PARTLABEL="${newpartlabel}")
|
||||
if [ -z "${newroot}" ]; then
|
||||
die 'Could not find partition with label %s\n' "${partlabel}"
|
||||
fi
|
||||
info 'Current rootfs: %s (%s)\n' "${partlabel}" "${root}"
|
||||
info 'New rootfs: %s (%s)\n' "${newpartlabel}" "${newroot}"
|
||||
|
||||
trap cleanup INT TERM QUIT EXIT
|
||||
workdir=$(mktemp -d)
|
||||
cd "${workdir}"
|
||||
|
||||
fetch_update "${source_url}" || die 'Failed to fetch update source'
|
||||
extract_update || die 'Failed to extact update source'
|
||||
./install "${newroot}" || die 'Error installing system update'
|
||||
|
||||
printf 'Do you want to reboot now? [y/N] '
|
||||
read confirm
|
||||
case "${confirm}" in
|
||||
[yY]|[yY][eE][sS])
|
||||
systemctl reboot
|
||||
;;
|
||||
*)
|
||||
info 'A reboot is required to complete the update'
|
||||
;;
|
||||
esac
|
|
@ -0,0 +1,101 @@
|
|||
#!/bin/sh
|
||||
# vim: set sw=4 ts=4 sts=4 et :
|
||||
|
||||
EFIMOUNT=/boot/efi
|
||||
GRUBENV=${EFIMOUNT}/EFI/BOOT/grubenv
|
||||
|
||||
die() {
|
||||
rc=$?
|
||||
if [ $rc -eq 0 ]; then
|
||||
rc=1
|
||||
fi
|
||||
error "$@"
|
||||
exit $rc
|
||||
}
|
||||
|
||||
error() {
|
||||
printf 'ERROR: '
|
||||
info "$@"
|
||||
}
|
||||
|
||||
get_partuuid() {
|
||||
blkid -o value -s PARTUUID "$1"
|
||||
}
|
||||
|
||||
info() {
|
||||
if [ $# -eq 1 ]; then
|
||||
echo "$1" >&2
|
||||
elif [ $# -gt 1 ]; then
|
||||
printf "$@" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
set_default_boot() {
|
||||
_rc=0
|
||||
mkdir -p newroot || return
|
||||
mount -oro "$1" newroot || return
|
||||
_partuuid=$(get_partuuid "$1")
|
||||
_id=id-${_partuuid}
|
||||
printf 'Setting default boot entry to %s\n' "${_id}"
|
||||
grub-editenv "${GRUBENV}" set "default=${_id}" || rc=$?
|
||||
umount newroot
|
||||
return $rc
|
||||
}
|
||||
|
||||
warn() {
|
||||
printf 'WARNING: '
|
||||
info "$@"
|
||||
}
|
||||
|
||||
write_firmware() {
|
||||
_rc=0
|
||||
_esp=$(findfs PARTLABEL='EFI System Partition')
|
||||
if [ -z "${_esp}" ]; then
|
||||
error 'Could not identify EFI System Partition'
|
||||
return 1
|
||||
fi
|
||||
if ! mountpoint -q "${EFIMOUNT}"; then
|
||||
mount -o ro "${_esp}" "${EFIMOUNT}" \
|
||||
|| warn 'Failed to mount EFI System Partition'
|
||||
fi
|
||||
if [ -f "${GRUBENV}" ]; then
|
||||
info 'Saving current GRUB environment ...'
|
||||
cp "${GRUBENV}" grubenv \
|
||||
|| warn 'Failed to save GRUB environment'
|
||||
fi
|
||||
if mountpoint -q "${EFIMOUNT}"; then
|
||||
umount "${EFIMOUNT}" || return
|
||||
fi
|
||||
info 'Writing firmware image to EFI System Partition (%s) ...\n' "${_esp}"
|
||||
dd if=firmware.img of="${_esp}" bs=1M || _rc=$?
|
||||
if [ $_rc -eq 0 ]; then
|
||||
mount -orw "${_esp}" "${EFIMOUNT}" || rc=$?
|
||||
fi
|
||||
if [ $_rc -eq 0 ]; then
|
||||
if [ -f grubenv ]; then
|
||||
printf 'Restoring GRUB environment ...\n'
|
||||
cp grubenv "${GRUBENV}" || _rc=$?
|
||||
fi
|
||||
fi
|
||||
return $_rc
|
||||
}
|
||||
|
||||
write_rootfs() {
|
||||
printf 'Writing rootfs image to %s ...\n' "$1"
|
||||
dd if=rootfs.squashfs of="$1" bs=1M
|
||||
}
|
||||
|
||||
rc=0
|
||||
newroot="$1"
|
||||
|
||||
write_rootfs "${newroot}" || die 'Failed to write new rootfs image to disk'
|
||||
write_firmware || die 'Failed to write new firmware image to disk'
|
||||
if ! set_default_boot "${newroot}"; then
|
||||
rc=$?
|
||||
error 'Failed to set default boot option'
|
||||
fi
|
||||
|
||||
if [ $rc -eq 0 ]; then
|
||||
info 'Successfully installed update'
|
||||
fi
|
||||
exit $rc
|
|
@ -0,0 +1,17 @@
|
|||
#!/bin/sh
|
||||
# vim: set sw=4 ts=4 sts=4 et :
|
||||
|
||||
UPDATE_PACKAGE=update.tar.zstd
|
||||
SRCDIR=$(realpath "${0%/*}")
|
||||
|
||||
cd "${BINARIES_DIR}"
|
||||
printf 'Creating %s/%s\n' "${BINARIES_DIR}" "${UPDATE_PACKAGE}" >&2
|
||||
sha256sum firmware.img > digests || exit
|
||||
sha256sum rootfs.squashfs >> digests || exit
|
||||
cp -u "${SRCDIR}"/install-update.sh install || exit
|
||||
tar -c --zstd -f "${UPDATE_PACKAGE}" \
|
||||
digests \
|
||||
firmware.img \
|
||||
rootfs.squashfs \
|
||||
install \
|
||||
|| exit
|
Loading…
Reference in New Issue