update-kernel.in 5.33 KB
Newer Older
1 2 3 4 5 6 7 8
#!/bin/sh -e

# update-kernel
#
# Kernel and firmware update script for Alpine installations set up
# with setup-bootable
#
# Copyright (c) 2014 Timo Teräs
9
# Copyright (c) 2014-2015 Kaarle Ritvanen
10 11 12 13 14


SCRIPT=update-kernel
VIRTUAL=.tmp-$SCRIPT

15 16 17
SUPERUSER=
[ $(id -u) -eq 0 ] && SUPERUSER=Y

18
ARCH=
19
BUILDDIR=
20
FLAVOR=
21
MNTDIR=
22 23 24 25 26
PACKAGES=
SIGNALS="HUP INT TERM"
TMPDIR=
features=

Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
27 28 29 30 31 32 33
error() {
    echo "$SCRIPT: $1" >&2
}

usage() {
    [ "$2" ] && error "$2"
    local opts="[-F <feature>]... [-p <package>]..."
34
    local dest_args="[-a <arch>] <dest_dir>"
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
35 36
    cat >&2 <<EOF

37 38 39
Syntax: $SCRIPT $opts [$dest_args]
        $SCRIPT -f <flavor> $opts $dest_args
        $SCRIPT -b <build_dir> $opts [$dest_args]
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
40

41 42
Options: -a|--arch <arch>        Install kernel for specified architecture
         -b|--build <build_dir>  Install custom-built kernel
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
43 44 45
         -f|--flavor <flavor>    Install kernel of specified flavor
         -F|--feature <feature>  Enable initfs feature
         -p|--package <package>  Additional module or firmware package
46
         -v|--verbose            Verbose output
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
47 48 49 50 51

EOF
    exit $1
}

52
QUIET_OPT="--quiet"
53 54
OPTS=$(getopt -l arch:,build-dir:,flavor:,feature:,help,package:,verbose \
	      -n $SCRIPT -o a:b:f:F:hp:v -- "$@") || usage 1
55 56 57
eval set -- "$OPTS"
while :; do
    case "$1" in
58 59 60 61
	-a|--arch)
	    shift
	    ARCH=$1
	    ;;
62
	-b|--build-dir)
63
	    shift
64
	    BUILDDIR=$1
65
	    ;;
66
	-f|--flavor)
67
	    shift
68
	    FLAVOR=$1
69 70
	    ;;
	-F|--feature)
71
	    shift
72
	    features="$features $1"
73
	    ;;
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
74
	-h|--help)
75
	    echo "$SCRIPT @VERSION@" >&2
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
76 77
	    usage 0
	    ;;
78
	-p|--package)
79
	    shift
80
	    PACKAGES="$PACKAGES $1"
81 82 83
	    ;;
	-v|--verbose)
	    QUIET_OPT=
84 85 86 87 88
	    ;;
	--)
	    break
	    ;;
    esac
89
    shift
90 91 92 93 94
done

DESTDIR=$2


95
[ "$BUILDDIR" -a "$FLAVOR" ] && \
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
96
    usage 1 "Cannot specify both build directory and flavor"
97

98
if [ -z "$DESTDIR" ]; then
99 100 101
    [ "$ARCH" ] && \
	usage 1 "Cannot specify architecture when updating the current kernel"

Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
102 103
    [ "$FLAVOR" ] && \
	usage 1 "Cannot specify flavor when updating the current kernel"
104

105 106 107
    [ "$SUPERUSER" ] || \
	usage 1 "Specify destination directory or run as superuser"

108 109 110 111
    while read MOUNT; do
	set -- $MOUNT
	[ $2 = /.modloop ] || continue
	DESTDIR=$(dirname $(losetup $1 | cut -d " " -f 3))
112
	MNTDIR=$(dirname "$DESTDIR")
113 114 115
	break
    done < /proc/mounts

Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
116 117 118 119
    if [ -z "$MNTDIR" ]; then
	error "Module loopback device not mounted"
	exit 1
    fi
120 121 122
fi

remount() {
123
    mount $1 -o remount "$MNTDIR"
124 125 126 127 128 129 130 131 132 133 134
}


ignore_sigs() {
    trap "" $SIGNALS
}

clean_up() {
    set +e
    ignore_sigs

135
    [ "$SUPERUSER" ] && apk del $QUIET_OPT $VIRTUAL
136
    rm -fr $TMPDIR
137 138 139 140 141
}

trap clean_up EXIT $SIGNALS


142
if [ "$SUPERUSER" ]; then
143
    apk add $QUIET_OPT --update-cache -t $VIRTUAL mkinitfs squashfs-tools kmod
144
fi
145

146 147 148
if [ -z "$features" ]; then
    . /etc/mkinitfs/mkinitfs.conf
fi
149

150
if [ -z "$FLAVOR" ]; then
151 152
    FLAVOR=$(uname -r | cut -d - -f 3-)
    [ "$FLAVOR" ] || FLAVOR=vanilla
153 154
fi

155 156 157
[ "$ARCH" ] || ARCH=$(apk --print-arch)
ARM=$(echo "$ARCH" | grep ^arm || :)

158
TMPDIR=$(mktemp -d /tmp/$SCRIPT.XXXXXX)
159
ROOT=$TMPDIR/root
160
BOOT=$ROOT/boot
161
WRAPPER=
162 163

_exec() {
164
    $WRAPPER "$@"
165
}
166

167
_apk() {
168 169
    local cmd=$1
    shift
170 171 172 173 174 175 176 177 178 179 180 181

    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

182
    $wrapper apk $cmd $QUIET_OPT -p $ROOT --arch "$ARCH" \
183
	--keys-dir /etc/apk/keys \
184 185 186
	--repositories-file /etc/apk/repositories $*
}

187 188 189
extra_pkgs() {
    local res=$(_apk search -x $1)
    if [ "$res" ]; then
190
	echo $*
191 192 193
    fi
}

194
# set up the root and get the APKINDEX for search
195
_apk add --initdb --update-cache
196

197
if [ "$BUILDDIR" ]; then
198
    mkdir -p $BOOT
199
    make -C "$BUILDDIR" ${ARM:+z}install firmware_install modules_install \
200
	INSTALL_MOD_PATH=$ROOT INSTALL_PATH=$BOOT
201 202
else
    if [ -z "$PACKAGES" ]; then
203 204
	PACKAGES="$(extra_pkgs "dahdi-linux-$FLAVOR" dahdi-linux)
		$(extra_pkgs "xtables-addons-$FLAVOR")"
205
    fi
206
    PACKAGES="$PACKAGES linux-$FLAVOR linux-firmware"
207
fi
208
_apk add --no-scripts alpine-base $PACKAGES
209

210

211 212
KVER_FLAVOR=
[ "$FLAVOR" = vanilla ] || KVER_FLAVOR=-$FLAVOR
213 214
KVER=$(basename $(ls -d $ROOT/lib/modules/*"$KVER_FLAVOR"))
depmod -b $ROOT "$KVER"
215 216 217 218


STAGING=$TMPDIR/boot
MODLOOP=$TMPDIR/modloop
219
MODIMG=modloop-$FLAVOR
220
DTB_STAGING=$TMPDIR/dtbs
221

222
mkdir $DTB_STAGING $MODLOOP $STAGING
223
cp -a $ROOT/lib/modules $MODLOOP
224 225 226 227
mkdir -p $MODLOOP/modules/firmware
find $ROOT/lib/modules -type f -name "*.ko" | xargs modinfo -F firmware | sort -u | while read FW; do
	[ -e "$ROOT/lib/firmware/$FW" ] && install -pD $ROOT/lib/firmware/$FW $MODLOOP/modules/firmware/$FW
done
228
_exec mksquashfs $MODLOOP "$STAGING/$MODIMG" -comp xz
229

230
_exec mkinitfs -q -b $ROOT -F "$features base squashfs" \
231
    -o "$STAGING/initramfs-$FLAVOR" "$KVER"
232 233 234 235

for file in System.map config vmlinuz; do
    cp "$BOOT/$file$KVER_FLAVOR" $STAGING
done
236

237 238 239
if [ "$ARM" ]; then
    DTBDIR=$ROOT/usr/lib/linux-$KVER
    [ "$BUILDDIR" ] && DTBDIR=$BUILDDIR/source/arch/arm/boot/dts
240 241
    cp -a "$DTBDIR"/* $DTB_STAGING
    find "$DTB_STAGING" -type f \! -name "*.dtb" -delete
242 243
fi

244

245 246
if [ "$MNTDIR" ]; then
    ignore_sigs
247
    umount /.modloop
248 249
    remount -w
fi
250

251
mv $STAGING/* "$DESTDIR"
252

253 254 255 256 257 258
if [ "$ARM" ]; then
    DTBDIR=$DESTDIR/dtbs
    mkdir -p "$DTBDIR"
    mv $DTB_STAGING/* "$DTBDIR"
fi

259 260 261 262
if [ "$MNTDIR" ]; then
    set +e
    sync
    remount -r
263
    mount -o loop "$DESTDIR/$MODIMG" /.modloop
264
fi
265 266

exit 0