-
Notifications
You must be signed in to change notification settings - Fork 7
/
mkinitrd
executable file
·223 lines (208 loc) · 7.32 KB
/
mkinitrd
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#!/bin/bash
#
# Copyright (c) 2018 YADRO
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
set -e
declare -a POSITIONAL
declare -a INCLUDES
declare -a DRACUT_OPTS
declare -a KMODS
CURDIR=$(dirname $(realpath "${BASH_SOURCE[0]}"))
GUEST="$CURDIR/guest"
KDUMP_BASE_KMODS+=(virtio_pci virtio_net virtio_blk virtio_console)
KMODS+=(${KDUMP_BASE_KMODS[@]} virtio_scsi virtio-rng sg sd_mod)
MODULES=(base systemd terminfo)
INSTALL=(zcat zless zgrep grep gzip cut sed awk tr ps tar nproc)
source "$CURDIR/lib"
systemddir=/usr/lib/systemd
sysunitdir="$systemddir/system"
targetdeps="$sysunitdir/multi-user.target.wants"
usage() {
cat <<EOF
Usage: $0 [options] <out-file> <kernel-image>
Options:
-k, --with-kdump Build kdump kernel
-v, --verbose Extra output
EOF
}
while [ $# -gt 0 ]; do
case "$1" in
--with-kdump|-k)
KDUMP=1
shift
;;
--verbose|-v)
VERBOSE=-v
shift
;;
--kmoddir)
DRACUT_OPTS+=(-k "$2")
shift 2
;;
--fwdir)
DRACUT_OPTS+=(--fwdir "$2")
shift 2
;;
--module|-m)
KMODS+=($2)
shift 2
;;
--install|-i)
if [ -x "$(pwd)/$2" ]; then
INSTALL+=($(realpath "$(pwd)/$2"))
else
INSTALL+=("$2")
fi
shift 2
;;
--include|-I)
src=$(cut -d: -f1 <<< "$2")
if [ ! -r "$src" ]; then
die "Can't find file at '$src'"
fi
dst=$(cut -d: -f2 <<< "$2")
DRACUT_OPTS+=(--include $src $dst)
shift 2
;;
--net)
NETWORK=y
shift
;;
*)
POSITIONAL+=("$1")
shift
;;
esac
done
if [ ${#POSITIONAL[@]} -ne 2 ]; then
usage
exit 1
fi
OUT="${POSITIONAL[0]}"
KIMG="${POSITIONAL[1]}"
[ -r "$KIMG" ] || die "Can't read kernel: $KIMG"
KVER=$(strings "$KIMG" | grep -oP 'Linux version \K\S+') || :
[ -z "$KVER" ] && KVER=$(file "$KIMG" | grep -oP ', Version \K\S+') || :
[ -n "$KVER" ] || die "Can't extract kernel version from: $KIMG"
emptydir=$(mktemp -d)
ktestdir=$(mktemp -d)
entrypoint="$GUEST/profile"
check_progs() {
local notfound=0
for prog in "$@"; do
if ! command -v "$prog" 2>/dev/null 1>&2; then
echo "ERROR: Can't find \"$prog\" in \$PATH"
((notfound++))
fi
done
if ((notfound > 0)); then
die
fi
}
check_kmods() {
local kmod_dir="/lib/modules/$KVER"
local notfound=0
for mod in "$@"; do
# Handle dash to underscore aliasing
mod=$(sed 's|[-_]|\[-_\]|' <<< "$mod")
grep -qw "$mod" "$kmod_dir/modules."{builtin,dep} && continue
# test if a built-in alias is requested
tr '\0' '\n' < "$kmod_dir/modules.builtin.modinfo" | \
grep -qwE "\w+\.alias=$mod" && continue
echo "ERROR: Kernel module $mod is missing in $kmod_dir"
((notfound++))
done
if ((notfound > 0)); then
die
fi
}
libdirs() {
local -a libdirs
if [[ $(ldd /bin/sh) == */lib64/* ]] && [ -d /lib64 ]; then
libdirs+=(/lib64)
[ -d /usr/lib64 ] && libdirs+=(/usr/lib64)
else
libdirs+=(/lib)
[ -d /usr/lib ] && libdirs+=(/usr/lib)
fi
echo "${libdirs[@]}"
return 0
}
inst_libdir_file() {
for ldir in $(libdirs); do
for p in "$@"; do
match=$(ls $ldir/$p 2>/dev/null) || continue
for m in $match; do
INCLUDES+=(--include "$m" "$m")
done
done
done
}
if [ -n "$NETWORK" ]; then
NET_INSTALL=(ip dhclient arping ping ping6 hostname)
# Install resolver from glibc
_arch=$(uname -m)
inst_libdir_file {"tls/$_arch/",tls/,"$_arch/",}"libnss_dns.so.*" \
{"tls/$_arch/",tls/,"$_arch/",}"libnss_mdns4_minimal.so.*"
INSTALL+=("${NET_INSTALL[@]}")
MODULES+=(kernel-network-modules)
fi
if [ -n "$KDUMP" ]; then
bootdir=$(dirname $OUT)/boot
mkdir -p "$bootdir"
kernel=$(find /boot -name 'vmlinu[x|z]')
cp "$kernel" "$bootdir"
KDUMP_INSTALL=(gzip nproc makedumpfile scp grep cut tar)
check_progs "${KDUMP_INSTALL[@]}"
check_kmods "${KDUMP_BASE_KMODS[@]}"
dracut -N --force \
"${DRACUT_OPTS[@]}" \
-m "base" \
--filesystems "xfs" \
--install "${KDUMP_INSTALL[*]}" \
--include $emptydir /crashes \
--include "$GUEST/collect-crash" /.profile \
--drivers="${KDUMP_BASE_KMODS[*]}" \
$VERBOSE \
"$bootdir/initrd-kdump" "$KVER"
INCLUDES+=(--include "$bootdir" /boot)
INSTALL+=(kexec)
fi
check_progs "${INSTALL[@]}"
check_kmods "${KMODS[@]}"
export DRACUT_RESOLVE_DEPS=1
dracut -N --force \
"${DRACUT_OPTS[@]}" \
-m "${MODULES[*]}" \
--filesystems "ext2" \
--install "${INSTALL[*]}" \
--include $CURDIR/multi-user.target.wants \
$sysunitdir/multi-user.target.wants \
--include $GUEST/cmdline.service $sysunitdir/ktest-cmdline.service \
--include $GUEST/cmdline.sh /bin/ktest-cmdline \
--include $GUEST/debugfs.mount $sysunitdir/sys-kernel-debug.mount \
--include $emptydir /var/lib/dhcp \
--include $GUEST/dhclient-script.sh /sbin/dhclient-script \
--include $GUEST/dhclient.service $sysunitdir/dhclient.service \
--include $entrypoint /.profile \
--include $CURDIR/ktest.service $sysunitdir/ktest.service \
--include $CURDIR/ktest.sh /bin/ktest \
--include $CURDIR/disk-by-serial /bin/disk-by-serial \
"${INCLUDES[@]}" \
--drivers="${KMODS[*]}" \
$VERBOSE \
"$OUT" "$KVER"
if [ -n "$FILE_UID" ]; then
chown $FILE_UID $OUT
fi