-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy patharchkernel-load.sh
executable file
·178 lines (150 loc) · 5.56 KB
/
archkernel-load.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#!/bin/bash
#
# Rewrite Scaleway initrd and kexec into ARCH kernel
#
# Author: stuffo (https://github.com/stuffo/)
# Location: https://github.com/stuffo/scaleway-archkernel
#
# kernel modules to add to the Scaleway initrd to enable Arch kernel network
# and to mount nbd devices. If module is missing, we skip it as it may be a
# kernel that does not require it. Path prefix is /lib/modules/<kernel version>
REQUIRED_MODULES="net/phy/phylink net/ethernet/marvell/mvneta_bm net/ethernet/marvell/mvneta block/nbd"
# where to account current Arch kernel version
ARCH_KERNEL_STAMP="/boot/.archkernel-version"
# default value initialization
INITRD_KERNEL_VERSION="none"
ARCH_KERNEL_VERSION="wedontknowyet"
set -eu
set -o pipefail
shopt -s nullglob
shopt -s dotglob
umask 022
export LC_ALL=C
export LANG=C
unset LANGUAGE
log() {
echo "$@" >&2
}
fatal() {
log "$@"
log "Exiting."
exit 1
}
rebuild_initrd() {
local workdir=$(mktemp -d)
local tftp_server=$(grep bootserver /proc/net/pnp | cut -f2 -d" ")
if [ -z "$tftp_server" ] ; then
tftp_server=10.1.31.34
fi
log "Scaleway TFTP server: $tftp_server"
tftp -m binary $tftp_server -c get uboot.bootscript $workdir/uboot.bootscript
# XXX: maybe one day we can use scw-metadata to do this
dd if=$workdir/uboot.bootscript of=$workdir/uboot.bootscript.raw ibs=72 skip=1 2> /dev/null
local orig_initrd=$(grep 'tftp .* initrd/uInitrd-Linux-armv7l' $workdir/uboot.bootscript.raw |cut -f3 -d" ")
rm -f $workdir/uboot.bootscript $workdir/uboot.bootscript.raw
if [ -z "$orig_initrd" ] ; then
fatal "failed to get Scaleway initrd"
fi
log "Scaleway initrd: $orig_initrd"
log "+ get scaleway initrd"
tftp -m binary $tftp_server -c get $orig_initrd $workdir/uInitrd.orig
dd if=$workdir/uInitrd.orig of=$workdir/uInitrd.orig.gz ibs=64 skip=1 2> /dev/null
rm -f $workdir/uInitrd.orig
log "+ extract scaleway initrd"
local initrd_dir=$(mktemp -d initrd.XXXXXX)
( cd $initrd_dir && gunzip < $workdir/uInitrd.orig.gz | cpio -i --quiet > /dev/null )
rm -f $workdir/uInitrd.orig.gz
# copy kernel modules
local insmod_command=
local modname mod
local initrd_mod_dir="$initrd_dir/lib/modules/$ARCH_KERNEL_VERSION"
mkdir -p $initrd_mod_dir
for mod in $REQUIRED_MODULES ; do
if [ -e /lib/modules/$ARCH_KERNEL_VERSION/kernel/drivers/$mod.ko.gz ] ; then
log "+ add module $mod to initrd"
modname=$(basename $mod).ko
gunzip < /lib/modules/$ARCH_KERNEL_VERSION/kernel/drivers/$mod.ko.gz > $initrd_mod_dir/$modname
insmod_command=$insmod_command"insmod /lib/modules/$ARCH_KERNEL_VERSION/$modname\n"
else
log "+ skipping module $mod for initrd. not found."
fi
done
log "+ prepend loading modules before entering scaleway initrd"
mv $initrd_dir/init $initrd_dir/init.scw
cat > $initrd_dir/init <<-EOF
#!/bin/sh
# this was added by archkernel-load.sh to load Arch kernel modules
# before executing the Scaleway init script. Please do not remove.
/bin/busybox mkdir -p /bin /sbin /etc /proc /sys /newroot /usr/bin /usr/sbin
/bin/busybox --install -s
EOF
echo -e $insmod_command >> $initrd_dir/init
echo '. init.scw' >> $initrd_dir/init
chmod 755 $initrd_dir/init
log "+ rebuild initrd archive"
( cd $initrd_dir && find . -print0 | cpio --quiet --null -o --format=newc | gzip -9 > /boot/uInitrd.gz )
# record kernel version we just integrated into intird for later
echo $ARCH_KERNEL_VERSION > $ARCH_KERNEL_STAMP
rm -fr $initrd_dir $workdir
}
shutdown_initrd_kexec_check() {
# compat for old initrds which don't know how to kexec
if ! grep -q 'kexec -e' /run/initramfs/shutdown ; then
log "current initrd won't kexec automatically. patching it."
fixup_shutdown_initrd
fi
}
fixup_shutdown_initrd() {
mv /run/initramfs/shutdown /tmp/oldshutdown
{
head -n -1 /tmp/oldshutdown
echo "kexec -e"
} > /run/initramfs/shutdown && chmod 755 /run/initramfs/shutdown
rm -f /tmp/oldshutdown
}
get_kernel_version() {
local installed_kernel=$(pacman -Q -o /boot/zImage|cut -f5 -d" ")
ARCH_KERNEL_VERSION=$(pacman -Q -l $installed_kernel |grep '/usr/lib/modules/.*/kernel/$'|cut -f5 -d /)
if [ -r $ARCH_KERNEL_STAMP ] ; then
INITRD_KERNEL_VERSION=$(cat $ARCH_KERNEL_STAMP)
fi
log "Arch kernel version: $ARCH_KERNEL_VERSION"
log "Initrd kernel version: $INITRD_KERNEL_VERSION"
}
sanity_checks() {
[ ${EUID} -eq 0 ] || fatal "Script must be run as root."
[ ${UID} -eq 0 ] || fatal "Script must be run as root."
if [ ! -r /proc/sys/kernel/kexec_load_disabled ] ; then
fatal "kernel has no kexec support. please change bootscript."
fi
if [ ! -x /run/initramfs/sbin/kexec ] ; then
fatal "current initrd has no kexec binary. kexec will fail."
fi
exit_if_disabled
}
# kill switch
exit_if_disabled() {
if scw-metadata |grep -q "TAGS_[[:digit:]]=archkernel_disabled" ; then
fatal "archkernel load disabled via server tag."
fi
}
#
# main
#
sanity_checks
shutdown_initrd_kexec_check
get_kernel_version
if [ "$ARCH_KERNEL_VERSION" != "$INITRD_KERNEL_VERSION" ] ; then
rebuild_initrd
fi
# we disable some features of the Scaleway initrd as they are superfluous
# for a kexeced environment
log "Kexec engaged. Make it So!"
kexec -l /boot/zImage \
--initrd=/boot/uInitrd.gz \
--command-line="$(cat /proc/cmdline) \
is_in_kexec=yes \
NO_SIGNAL_STATE=1 \
DONT_FETCH_KERNEL_MODULES=1 \
NO_NTPDATE=1 \
archkernel" && systemctl kexec