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.
This commit is contained in:
1
ci/Jenkinsfile
vendored
1
ci/Jenkinsfile
vendored
@@ -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 \
|
||||
|
||||
135
package/aimee-os-utils/system-update.sh
Executable file
135
package/aimee-os-utils/system-update.sh
Executable file
@@ -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
|
||||
101
update/install-update.sh
Executable file
101
update/install-update.sh
Executable file
@@ -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
|
||||
17
update/make-package.sh
Executable file
17
update/make-package.sh
Executable file
@@ -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
|
||||
Reference in New Issue
Block a user