Files
edge/sbin/update-kernel
2018-11-06 00:13:24 +00:00

313 lines
6.5 KiB
Bash
Executable File

#!/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
if [ -z "$SUPERUSER" ] && [ -z "$FAKEROOTKEY" ]; then
exec fakeroot "$0" "$@"
fi
ARCH=
BUILDDIR=
FLAVOR=
MEDIA=
MNTDIR=
PACKAGES=
MKINITFS_ARGS=
REPOSITORIES_FILE=/etc/apk/repositories
SIGNALS="HUP INT TERM"
TMPDIR=
features=
error() {
echo "$SCRIPT: $1" >&2
}
usage() {
[ "$2" ] && error "$2"
local opts="[-F <feature>]... [-p <package>]..."
local dest_args="[-a <arch>] <dest_dir>"
cat >&2 <<-__EOF__
Syntax: $SCRIPT $opts [$dest_args]
$SCRIPT -f <flavor> $opts $dest_args
$SCRIPT -b <build_dir> $opts [$dest_args]
Options: -a|--arch <arch> Install kernel for specified architecture
-b|--build <build_dir> Install custom-built kernel
-f|--flavor <flavor> Install kernel of specified flavor
-F|--feature <feature> Enable initfs feature
-p|--package <package> Additional module or firmware package
-v|--verbose Verbose output
-k|--apk-pubkey <key> Include given key in initramfs
-K|--hostkeys Include host keys in initramfs
-C|--compression Initramfs compression (see mkinitfs for options)
-M|--media Boot media directory layout
--repositories-file <f> apk repositories file
__EOF__
exit $1
}
QUIET_OPT="--quiet"
OPTS=$(getopt -l arch:,build-dir:,flavor:,feature:,help,package:,verbose,apk-pubkey:,hostkeys,compression:,media,repositories-file: \
-n $SCRIPT -o a:b:f:F:hp:vk:KC:M -- "$@") || 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 3.8.0-r0" >&2
usage 0
;;
-p|--package)
shift
PACKAGES="$PACKAGES $1"
;;
-v|--verbose)
QUIET_OPT=
;;
-k|--apk-pubkey)
shift
APK_PUBKEY="$1"
;;
-K|--hostkeys)
MKINITFS_ARGS="$MKINITFS_ARGS -K"
;;
-C|--compression)
shift
MKINITFS_ARGS="$MKINITFS_ARGS -C $1"
;;
-M|--media)
MEDIA=yes
;;
--repositories-file)
shift
REPOSITORIES_FILE=$1
;;
--)
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 $(busybox 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
if [ "$SUPERUSER" ] && [ -z "$FAKEROOTKEY" ]; then
apk del $QUIET_OPT $VIRTUAL
fi
rm -fr $TMPDIR
}
trap clean_up EXIT $SIGNALS
if [ "$SUPERUSER" ] && [ -z "$FAKEROOTKEY" ]; 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)
TMPDIR=$(mktemp -d /tmp/$SCRIPT.XXXXXX)
ROOT=$TMPDIR/root
BOOT=$ROOT/boot
_apk() {
local cmd=$1
shift
apk $cmd $QUIET_OPT -p $ROOT --arch "$ARCH" \
--keys-dir /etc/apk/keys \
--repositories-file "$REPOSITORIES_FILE" $*
}
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
case "$ARCH" in
arm*|aarch64*) _install="zinstall dtbs_install" ;;
*) _install="install" ;;
esac
mkdir -p $BOOT
make -C "$BUILDDIR" $_install firmware_install modules_install \
INSTALL_MOD_PATH=$ROOT \
INSTALL_PATH=$BOOT \
INSTALL_DTBS_PATH='$ROOT/usr/lib/linux-$(KERNELRELEASE)'
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
if [ -n "$APK_PUBKEY" ]; then
mkdir -p "$ROOT"/etc/apk/keys
cp "$APK_PUBKEY" "$ROOT"/etc/apk/keys/
fi
KVER_FLAVOR=
[ "$FLAVOR" = vanilla ] || KVER_FLAVOR=-$FLAVOR
KVER=$(basename $(ls -d $ROOT/lib/modules/*"$KVER_FLAVOR"))
DTBDIR=$ROOT/usr/lib/linux-$KVER
depmod -b $ROOT "$KVER"
STAGING=$TMPDIR/boot
MODLOOP=$TMPDIR/modloop
MODIMG=modloop-$FLAVOR
mkdir $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
# include nvram files if firmware is needed.
if [ -e "$ROOT/lib/firmware/${FW%.*}.txt" ]; then
install -pD $ROOT/lib/firmware/${FW%.*}.txt $MODLOOP/modules/firmware/${FW%.*}.txt
fi
fi
done
# include bluetooth firmware in modloop
if [ -d "$MODLOOP/modules/firmware/brcm" ]; then
for _btfw in "$ROOT"/lib/firmware/brcm/*.hcd; do
install -pD "$_btfw" \
"$MODLOOP"/modules/firmware/brcm/"${_btfw##*/}"
done
fi
mksquashfs $MODLOOP "$STAGING/$MODIMG" -comp xz -exit-on-error
mkinitfs $MKINITFS_ARGS -q -b $ROOT -F "$features base squashfs" \
-o "$STAGING/initramfs-$FLAVOR" "$KVER"
for file in System.map config vmlinuz; do
if [ -f "$BOOT/$file-$FLAVOR" ]; then
cp "$BOOT/$file-$FLAVOR" $STAGING
else
cp "$BOOT/$file" $STAGING
fi
done
if [ "$MNTDIR" ]; then
ignore_sigs
umount /.modloop
remount -w
fi
mkdir -p "$DESTDIR"/${MEDIA:+boot/}
mv $STAGING/* "$DESTDIR"/${MEDIA:+boot/}
if [ -d "$DTBDIR" ]; then
_opwd=$PWD
case "$MEDIA,$FLAVOR" in
yes,rpi*) _dtb="$DESTDIR/" ;;
yes,*) _dtb="$DESTDIR/boot/dtbs" ;;
*,*) _dtb="$DESTDIR/dtbs" ;;
esac
mkdir -p "$_dtb"
_dtb=$(realpath "$_dtb")
cd "$DTBDIR"
find -type f \( -name "*.dtb" -o -name "*.dtbo" \) | cpio -pudm "$_dtb" 2> /dev/null
cd "$_opwd"
fi
if [ "$MNTDIR" ]; then
set +e
sync
remount -r
mount -o loop "$DESTDIR/$MODIMG" /.modloop
fi
exit 0