diff options
Diffstat (limited to 'recipes-core/swupd-client/oe-swupd-helpers/kernel_updater.sh~')
-rwxr-xr-x | recipes-core/swupd-client/oe-swupd-helpers/kernel_updater.sh~ | 395 |
1 files changed, 395 insertions, 0 deletions
diff --git a/recipes-core/swupd-client/oe-swupd-helpers/kernel_updater.sh~ b/recipes-core/swupd-client/oe-swupd-helpers/kernel_updater.sh~ new file mode 100755 index 0000000..0060be0 --- /dev/null +++ b/recipes-core/swupd-client/oe-swupd-helpers/kernel_updater.sh~ @@ -0,0 +1,395 @@ +#!/bin/bash + +####################################### +# Clear Linux Kernel update script +# Author Brad Peters <brad.t.peters@intel.com> +# kernel_updater.sh: Provides a minimal-copy wrapper which finesses +# the VFAT /boot fs to minimize writes, while implementing Clear Linux +# update/install and fix policies +####################################### + +VERSION=3.60 +HASH="/usr/bin/sha256sum" + +function printUsage() +{ + echo "kernel_updater.sh [--path <path to chroot>]" + echo " -v | --version : Prints version of kernel_updater.sh" + echo " -h | --help : Prints usage" + echo " -p | --path : Optional. Used when creating new image " + echo " in a subdir. Should be absolute path" +} + +function cleanDuplicates() +{ + # Move duplicate kernels out of the way in /boot, if necessary. + # Kernels in /usr are considered 'correct' + SRCFILES=org.clearlinux.* + + for f in $SRCFILES + do + destfile="$SUBDIR/boot/$f" + if [ ! -f $destfile ] + then + continue + fi + + srcsha=$(sha1sum $f) + destsha=$(sha1sum $destfile) + + srcsha=$(echo $srcsha | awk '{print $1}') + destsha=$(echo $destsha | awk '{print $1}') + + if [ "$srcsha" != "$destsha" ] + then + newname="${destfile/clearlinux/clearTMP}" +# echo "Renaming $destfile to $newname prior to replacement" + mv $destfile $newname + fi + done +} + +function cleanDuplicatesEFI() +{ + # Move duplicate kernels out of the way in /boot, if necessary. + # Kernels in /usr are considered 'correct' + SRCFILES=*.efi + + for f in $SRCFILES + do + destfile="$SUBDIR/boot/EFI/Linux/$f" + if [ ! -f $destfile ] + then + continue + fi + + srcsha=$(sha1sum $f) + destsha=$(sha1sum $destfile) + + srcsha=$(echo $srcsha | awk '{print $1}') + destsha=$(echo $destsha | awk '{print $1}') + + if [ "$srcsha" != "$destsha" ] + then + newname="${destfile/clearlinux/clearTMP}" +# echo "Renaming $destfile to $newname prior to replacement" + mv $destfile $newname + fi + done +} + + +function cleanOldEFI() +{ + # Clean up old kernels + + # Get list of all kernels in reverse sorted order (based only on release ID) + LS_KERNELS_SORTED=$(ls org.clearlinux*.efi | sort --field-separator=- -n -k3 -r) + + i=0 + for k in $LS_KERNELS_SORTED + do + if [[ "$i" -ge 3 ]] + then + cur_kernel=$(uname -r | cut -f1,2,3 -d.) + ls_kernel=$(echo $k | cut -f4,5,6 -d.) + + #Do not clean up currently running kernel + if [[ $ls_kernel = $cur_kernel ]] + then + echo "Keeping $k. Is currently running kernel" + continue; + fi + + echo "Clean up old kernel: $k" + echo "Clean up modules $SUBDIR/lib/modules/$ls_kernel" + rm "$k" + rm -Rf "$SUBDIR/lib/modules/$ls_kernel" + fi + i=$((i + 1)) + done +} + +function cleanOld() +{ + # Clean up old kernels + + # Get list of all kernels in reverse sorted order (based only on release ID) + LS_KERNELS_SORTED=($(ls org.clearlinux.* | sort --field-separator=- -n -k3 -r)) + + i=0 + for k in $LS_KERNELS_SORTED[*] + do + if [[ "$i" -ge 3 ]] + then + cur_kernel=$(uname -r | cut -f1,2,3 -d.) + ls_kernel=$(echo $k | cut -f4,5,6 -d.) + + #Do not clean up currently running kernel + if [[ $ls_kernel = $cur_kernel ]] + then + echo "Keeping $k. Is currently running kernel" + continue; + fi + + echo "Clean up old kernel: $k" + if [[ -z "${SUBDIR}" ]]; then + ${KINSTALL} remove "${ls_kernel}" + else + ${KINSTALL} --root "${SUBDIR}" remove "${ls_kernel}" + fi + fi + i=$((i + 1)) + done +} + +#Set the "default" entry option in file /boot/loader/loader.conf +#requires /boot partition mounted +function updateDefaultEntry() +{ + LOADER_CONF_FILE="/boot/loader/loader.conf" + if [ ! -f "$SUBDIR""$LOADER_CONF_FILE" ]; then + mkdir -p "$(dirname "$SUBDIR""$LOADER_CONF_FILE" )" + touch "$SUBDIR""$LOADER_CONF_FILE" + fi + + for typename in "native" "kvm" "container" ; do + TPATH="${SUBDIR}/usr/lib/kernel/default-${typename}" + if [[ -e "${TPATH}" ]] ; then + kfile="$(basename $(readlink ${TPATH}))" + + ktype="$(echo $kfile|cut -d. -f 3)" + kversion="$(echo $kfile|cut -f4,5,6 -d.|cut -d - -f 1)" + krelease="$(echo $kfile|cut -d - -f 2)" + defaultConf="Clear-linux-${ktype}-${kversion}-${krelease}" + break + fi + done + + if [[ -z "${defaultConf}" ]]; then + echo "Default loader cannot be found" + return + fi + + configFile="$SUBDIR""$LOADER_CONF_FILE" + hashFile="${configFile}.sha256sum" + + sync + echo "default ${defaultConf}" > "${configFile}" + sync + + echo "Updated default to: ${defaultConf}" + + if [[ -e "${hashFile}" ]]; then + echo "Removing legacy file: ${hashFile}" + rm -v "${hashFile}" + sync + fi +} + +# Copies kernel from /usr to /boot. Checks each kernel to +# ensure modules are installed, and only copies if so +function copyKernelBlobs() +{ + pushd "$SUBDIR/usr/lib/kernel" > /dev/null + LS_KERNELS_SORTED=$(ls org.clearlinux.* | sort --field-separator=- -n -k3 -r) + popd > /dev/null + + for k in $LS_KERNELS_SORTED + do + kernel_version=$(echo "$k" | cut -f4,5,6 -d.) + kernel_file="${SUBDIR}/usr/lib/kernel/$(basename ${k})" + kernel_blob=$(echo "$k" | cut -f5 -d/) + echo "Kernel version = $kernel_version , blob = $kernel_blob" + kmods=$(ls $SUBDIR/lib/modules | sed -n "/$kernel_version/p") + kmods_len=${#kmods} + + # Proceed with cp if kernel modules are present and kernel is not + # already installed + if [ $kmods_len -gt 0 ] && [ ! -e "$SUBDIR/boot/$kernel_blob" ] + then + echo " Installing $k to $SUBDIR/boot/" + if [[ -z "${SUBDIR}" ]]; then + ${KINSTALL} add "${kernel_version}" "${kernel_file}" + else + ${KINSTALL} --root "${SUBDIR}" add "${kernel_version}" "${kernel_file}" + fi + + if [[ $? -eq 0 ]]; then + echo "Installed $k to /boot/" + else + echo "Failed to copy $k to /boot" + fi + + else + if [ ! $kmods_len -gt 0 ] + then + echo "Skipping kernel $kernel_version - No modules found." + fi + if [ -e "$SUBDIR/boot/$kernel_blob" ] + then + echo "Skipping kernel $kernel_version - Already installed." + fi + fi + + done +} + +##################### Main ##################### +if [[ $# > 2 ]] +then + printUsage +fi + +# Parse cmdline +if [[ $# > 0 ]] +then + case "$1" in + -h|--help) + printUsage + exit 0 + ;; + -v|--version) + echo "kernel_updater.sh version $VERSION" + exit 0 + ;; + -p|--path) + if [[ $# = 1 ]] + then + echo "Invalid arguments. --path requires a second argument." + exit 1 + fi + SUBDIR="$2" + ;; + *) + echo "Unrecognized argument ($1). Try again" + printUsage + exit 1 + ;; + esac +fi + +if [[ $EUID -ne 0 ]]; then + echo "Must be root to execute kernel_updater.sh" + exit 1 +fi + +KINSTALL="${SUBDIR}/usr/bin/kernel-install" + +# Clean up /usr/lib/kernel to the minimal 3 kernels we want to install +pushd "$SUBDIR/usr/lib/kernel/" > /dev/null + +have_blobs=0 +have_legacy=0 +for test in org.clearlinux.*; do + have_blobs=1 + if [[ "${test}" == *.efi ]] ; then + have_legacy=1 + fi + break; +done +if [[ "$have_blobs" -eq 1 ]]; then + cleanOld + if [[ "$have_legacy" -eq 1 ]]; then + cleanOldEFI + fi +else + echo "No kernel blobs found." + echo "kernel update complete." + exit 0 +fi + +# Note that if we are given a --SUBDIR or if there are no org.clearlinux blobs +# in /usr/lib/kernel, we do not attempt a mount of /boot +if [ -z "${SUBDIR}" ]; then + # Get boot partition UUID + BOOTUUIDENTRY=$(ls /sys/firmware/efi/efivars/LoaderDevicePartUUID*) + if [[ -e $BOOTUUIDENTRY ]]; then + UUID=$(cat $BOOTUUIDENTRY | tr -cd '[[:alnum:]]._-' | tr '[:upper:]' '[:lower:]') + fi + + strlen=${#UUID} + + IS_MOUNTED=$(mount | sed -n '/boot/p' | sed -n '/vfat/p') + if [[ -z "$IS_MOUNTED" ]]; + then + if [ "$strlen" -gt 0 ] + then + echo "Mounting boot partition with UUID=$UUID" + mount /dev/disk/by-partuuid/$UUID /boot -o rw -t vfat + else + echo "Failed to identify boot partition using /sys/firmware/efi/efivars." + echo " Attempting to mount by-partlabel" + mount /dev/disk/by-partlabel/ESP /boot -o rw -t vfat + fi + else + if [ "$strlen" -gt 0 ] + then + echo "Mounting boot partition with UUID=$UUID" + mount -o remount,rw /dev/disk/by-partuuid/$UUID /boot -t vfat + else + echo "Failed to identify boot partition using /sys/firmware/efi/efivars." + echo " Attempting to remount by-partlabel" + mount -o remount,rw /dev/disk/by-partlabel/ESP /boot -t vfat + fi + fi + + IS_MOUNTED=$(mount | sed -n '/boot/p' | sed -n '/vfat/p') + if [[ -z "$IS_MOUNTED" ]]; + then + echo "/boot partition was not found. Unable to continue" + exit 1 + fi +fi + +echo "Updating kernel... please wait..." +# Identify kernels in /boot/EFI/Linux which are different from those +# in /usr. Assume /usr is 'correct', and remove those in /boot +cleanDuplicates +cleanDuplicatesEFI + +# Sync after cleanup to protect against VFAT corruption +pushd "$SUBDIR/boot" > /dev/null +sync +popd > /dev/null + +# Copy new kernels from /usr/lib/kernel into /boot/ +copyKernelBlobs + +# Step 3 - Cleanup kernels which were repaired, then sync +if [[ -e "$SUBDIR/boot/EFI/Linux/" ]]; then + pushd "$SUBDIR/boot/EFI/Linux/" > /dev/null + rm -f *clearTMP* 2>/dev/null + sync + popd > /dev/null +fi + +pushd "$SUBDIR/boot/" > /dev/null +rm -f *clearTMP* 2>/dev/null +sync +popd > /dev/null + +# Clean up legacy EFI blobs which are no longer needed +if [[ -e "$SUBDIR/boot/EFI/Linux" ]]; then + pushd "$SUBDIR/boot/EFI/Linux" > /dev/null + cleanOldEFI + sync + popd > /dev/null +fi + +# Finally, clean up kernels which are no longer needed +pushd "$SUBDIR/boot" > /dev/null +cleanOld +sync +popd > /dev/null + +#Update default kernel with the latest version +updateDefaultEntry + +if [ -z "${SUBDIR}" ]; then + umount /boot +fi + +popd > /dev/null + +echo "kernel update complete." |