#!/bin/sh -e # update-kernel # # Kernel and firmware update script for Alpine installations set up # with setup-bootable # # Copyright (c) 2014 Timo Teräs # Copyright (c) 2014-2015 Kaarle Ritvanen SCRIPT=update-kernel VIRTUAL=.tmp-$SCRIPT SUPERUSER= [ $(id -u) -eq 0 ] && SUPERUSER=Y ARCH= BUILDDIR= FLAVOR= MNTDIR= PACKAGES= SIGNALS="HUP INT TERM" TMPDIR= features= error() { echo "$SCRIPT: $1" >&2 } usage() { [ "$2" ] && error "$2" local opts="[-F ]... [-p ]..." local dest_args="[-a ] " cat >&2 < $opts $dest_args $SCRIPT -b $opts [$dest_args] Options: -a|--arch Install kernel for specified architecture -b|--build Install custom-built kernel -f|--flavor Install kernel of specified flavor -F|--feature Enable initfs feature -p|--package Additional module or firmware package -v|--verbose Verbose output EOF exit $1 } QUIET_OPT="--quiet" OPTS=$(getopt -l arch:,build-dir:,flavor:,feature:,help,package:,verbose \ -n $SCRIPT -o a:b:f:F:hp:v -- "$@") || usage 1 eval set -- "$OPTS" while :; do case "$1" in -a|--arch) shift ARCH=$1 ;; -b|--build-dir) shift BUILDDIR=$1 ;; -f|--flavor) shift FLAVOR=$1 ;; -F|--feature) shift features="$features $1" ;; -h|--help) echo "$SCRIPT @VERSION@" >&2 usage 0 ;; -p|--package) shift PACKAGES="$PACKAGES $1" ;; -v|--verbose) QUIET_OPT= ;; --) break ;; esac shift done DESTDIR=$2 [ "$BUILDDIR" -a "$FLAVOR" ] && \ usage 1 "Cannot specify both build directory and flavor" if [ -z "$DESTDIR" ]; then [ "$ARCH" ] && \ usage 1 "Cannot specify architecture when updating the current kernel" [ "$FLAVOR" ] && \ usage 1 "Cannot specify flavor when updating the current kernel" [ "$SUPERUSER" ] || \ usage 1 "Specify destination directory or run as superuser" while read MOUNT; do set -- $MOUNT [ $2 = /.modloop ] || continue DESTDIR=$(dirname $(losetup $1 | cut -d " " -f 3)) MNTDIR=$(dirname "$DESTDIR") break done < /proc/mounts if [ -z "$MNTDIR" ]; then error "Module loopback device not mounted" exit 1 fi fi remount() { mount $1 -o remount "$MNTDIR" } ignore_sigs() { trap "" $SIGNALS } clean_up() { set +e ignore_sigs [ "$SUPERUSER" ] && apk del $QUIET_OPT $VIRTUAL rm -fr $TMPDIR } trap clean_up EXIT $SIGNALS if [ "$SUPERUSER" ]; then apk add $QUIET_OPT --update-cache -t $VIRTUAL mkinitfs squashfs-tools kmod fi if [ -z "$features" ]; then . /etc/mkinitfs/mkinitfs.conf fi if [ -z "$FLAVOR" ]; then FLAVOR=$(uname -r | cut -d - -f 3-) [ "$FLAVOR" ] || FLAVOR=vanilla fi [ "$ARCH" ] || ARCH=$(apk --print-arch) ARM=$(echo "$ARCH" | grep ^arm || :) TMPDIR=$(mktemp -d /tmp/$SCRIPT.XXXXXX) ROOT=$TMPDIR/root BOOT=$ROOT/boot WRAPPER= _exec() { $WRAPPER "$@" } _apk() { local cmd=$1 shift local wrapper= if [ -z "$SUPERUSER" ]; then local opt= local fake_env=$TMPDIR/fake-env if [ -f $fake_env ]; then opt="-i $fake_env" WRAPPER="fakeroot $opt --" fi wrapper="fakeroot $opt -s $fake_env --" fi $wrapper apk $cmd $QUIET_OPT -p $ROOT --arch "$ARCH" \ --keys-dir /etc/apk/keys \ --repositories-file /etc/apk/repositories $* } extra_pkgs() { local res=$(_apk search -x $1) if [ "$res" ]; then echo $* fi } # set up the root and get the APKINDEX for search _apk add --initdb --update-cache if [ "$BUILDDIR" ]; then mkdir -p $BOOT make -C "$BUILDDIR" ${ARM:+z}install firmware_install modules_install \ INSTALL_MOD_PATH=$ROOT INSTALL_PATH=$BOOT else if [ -z "$PACKAGES" ]; then PACKAGES="$(extra_pkgs "dahdi-linux-$FLAVOR" dahdi-linux) $(extra_pkgs "xtables-addons-$FLAVOR")" fi PACKAGES="$PACKAGES linux-$FLAVOR linux-firmware" fi _apk add --no-scripts alpine-base $PACKAGES KVER_FLAVOR= [ "$FLAVOR" = vanilla ] || KVER_FLAVOR=-$FLAVOR KVER=$(basename $(ls -d $ROOT/lib/modules/*"$KVER_FLAVOR")) depmod -b $ROOT "$KVER" STAGING=$TMPDIR/boot MODLOOP=$TMPDIR/modloop MODIMG=modloop-$FLAVOR DTB_STAGING=$TMPDIR/dtbs mkdir $DTB_STAGING $MODLOOP $STAGING cp -a $ROOT/lib/modules $MODLOOP mkdir -p $MODLOOP/modules/firmware find $ROOT/lib/modules -type f -name "*.ko" | xargs modinfo -F firmware | sort -u | while read FW; do if [ -e "$ROOT/lib/firmware/$FW" ]; then install -pD $ROOT/lib/firmware/$FW $MODLOOP/modules/firmware/$FW fi done _exec mksquashfs $MODLOOP "$STAGING/$MODIMG" -comp xz _exec mkinitfs -q -b $ROOT -F "$features base squashfs" \ -o "$STAGING/initramfs-$FLAVOR" "$KVER" for file in System.map config vmlinuz; do cp "$BOOT/$file$KVER_FLAVOR" $STAGING done if [ "$ARM" ]; then DTBDIR=$ROOT/usr/lib/linux-$KVER [ "$BUILDDIR" ] && DTBDIR=$BUILDDIR/source/arch/arm/boot/dts cp -a "$DTBDIR"/* $DTB_STAGING find "$DTB_STAGING" -type f \! -name "*.dtb" -delete fi if [ "$MNTDIR" ]; then ignore_sigs umount /.modloop remount -w fi mv $STAGING/* "$DESTDIR" if [ "$ARM" ]; then DTBDIR=$DESTDIR/dtbs mkdir -p "$DTBDIR" mv $DTB_STAGING/* "$DTBDIR" fi if [ "$MNTDIR" ]; then set +e sync remount -r mount -o loop "$DESTDIR/$MODIMG" /.modloop fi exit 0