]>
Commit | Line | Data |
---|---|---|
2b3e22d6 | 1 | #!/bin/bash --norc |
2b3e22d6 HR |
2 | # |
3 | # mkinitrd compability wrapper for SUSE. | |
4 | # | |
5 | # Copyright (c) 2013 SUSE Linux Products GmbH. All rights reserved. | |
6 | # | |
7 | # This program is free software; you can redistribute it and/or modify | |
8 | # it under the terms of the GNU General Public License as published by | |
9 | # the Free Software Foundation; either version 2 of the License, or | |
10 | # (at your option) any later version. | |
11 | # | |
12 | # This program is distributed in the hope that it will be useful, | |
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | # GNU General Public License for more details. | |
16 | # | |
17 | # You should have received a copy of the GNU General Public License | |
18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | # | |
20 | ||
21 | boot_dir="/boot" | |
22 | quiet=0 | |
2b3e22d6 HR |
23 | logfile=/var/log/YaST2/mkinitrd.log |
24 | dracut_cmd=dracut | |
25 | ||
26 | error() { echo "$@" >&2; } | |
27 | ||
28 | usage () { | |
29 | [[ $1 = '-n' ]] && cmd=echo || cmd=error | |
30 | ||
31 | $cmd "usage: ${0##*/} [options]" | |
32 | $cmd "" | |
33 | $cmd " Create initial ramdisk images that contain all kernel modules needed" | |
34 | $cmd " in the early boot process, before the root file system becomes" | |
35 | $cmd " available." | |
36 | $cmd " This usually includes SCSI and/or RAID modules, a file system module" | |
37 | $cmd " for the root file system, or a network interface driver module for dhcp." | |
38 | $cmd "" | |
39 | $cmd " options:" | |
40 | $cmd " -f \"feature list\" Features to be enabled when generating initrd." | |
41 | $cmd " Available features are:" | |
42 | $cmd " iscsi, md, multipath, lvm, lvm2," | |
43 | $cmd " ifup, fcoe, dcbd" | |
44 | $cmd " -k \"kernel list\" List of kernel images for which initrd files are" | |
45 | $cmd " created. Defaults to all kernels found in /boot." | |
46 | $cmd " -i \"initrd list\" List of file names for the initrd; position have" | |
47 | $cmd " match to \"kernel list\". Defaults to all kernels" | |
48 | $cmd " found in /boot." | |
49 | $cmd " -b boot_dir Boot directory. Defaults to /boot." | |
50 | $cmd " -t tmp_dir Temporary directory. Defaults to /var/tmp." | |
51 | $cmd " -M map System.map file to use." | |
52 | $cmd " -A Create a so called \"monster initrd\" which" | |
53 | $cmd " includes all features and modules possible." | |
54 | $cmd " -B Do not update bootloader configuration." | |
55 | $cmd " -v Verbose mode." | |
56 | $cmd " -L Disable logging." | |
57 | $cmd " -h This help screen." | |
58 | $cmd " -m \"module list\" Modules to include in initrd. Defaults to the" | |
59 | $cmd " INITRD_MODULES variable in /etc/sysconfig/kernel" | |
60 | $cmd " -u \"DomU module list\" Modules to include in initrd. Defaults to the" | |
61 | $cmd " DOMU_INITRD_MODULES variable in" | |
62 | $cmd " /etc/sysconfig/kernel." | |
63 | $cmd " -d root_device Root device. Defaults to the device from" | |
64 | $cmd " which / is mounted. Overrides the rootdev" | |
65 | $cmd " enviroment variable if set." | |
66 | $cmd " -j device Journal device" | |
67 | $cmd " -D interface Run dhcp on the specified interface." | |
68 | $cmd " -I interface Configure the specified interface statically." | |
552c37e1 | 69 | $cmd " -a acpi_dsdt Obsolete, do not use." |
2b3e22d6 HR |
70 | $cmd " -s size Add splash animation and bootscreen to initrd." |
71 | ||
72 | [[ $1 = '-n' ]] && exit 0 | |
73 | exit 1 | |
74 | } | |
75 | ||
76 | # Little helper function for reading args from the commandline. | |
77 | # it automatically handles -a b and -a=b variants, and returns 1 if | |
78 | # we need to shift $3. | |
79 | read_arg() { | |
80 | # $1 = arg name | |
81 | # $2 = arg value | |
82 | # $3 = arg parameter | |
83 | param="$1" | |
84 | local rematch='^[^=]*=(.*)$' result | |
85 | if [[ $2 =~ $rematch ]]; then | |
86 | read "$param" <<< "${BASH_REMATCH[1]}" | |
87 | else | |
88 | for ((i=3; $i <= $#; i++)); do | |
89 | # Only read next arg if it not an arg itself. | |
90 | if [[ ${@:$i:1} = -* ]];then | |
91 | break | |
92 | fi | |
93 | result="$result ${@:$i:1}" | |
94 | # There is no way to shift our callers args, so | |
95 | # return "no of args" to indicate they should do it instead. | |
96 | done | |
97 | read "$1" <<< "$result" | |
98 | return $(($i - 3)) | |
99 | fi | |
100 | } | |
101 | ||
102 | # Helper functions to calculate ipconfig command line | |
103 | calc_netmask() { | |
104 | local prefix=$1 | |
105 | ||
106 | [ -z "$prefix" ] && return | |
7cf2c217 | 107 | mask=$(( 0xffffffff << (32 - $prefix) )) |
2b3e22d6 HR |
108 | byte1=$(( mask >> 24 )) |
109 | byte2=$(( mask >> 16 )) | |
110 | byte3=$(( mask >> 8 )) | |
111 | byte4=$(( mask & 0xff )) | |
112 | netmask=$(printf "%d.%d.%d.%d" $(( byte1 & 0xff )) $(( byte2 & 0xff )) $(( byte3 & 0xff )) $byte4); | |
113 | ||
114 | echo $netmask | |
115 | } | |
116 | ||
117 | ipconfig() { | |
118 | local interface=$1 | |
119 | local iplink macaddr broadcast gateway ipaddr prefix netmask | |
120 | ||
121 | iplink=$(ip addr show dev $interface | sed -n 's/ *inet \(.*\) brd.*/\1/p') | |
122 | macaddr=$(ip addr show dev $interface | sed -n 's/.*ether \(.*\) brd.*/\1/p') | |
123 | broadcast=$(ip addr show dev $interface | sed -n 's/.*brd \(.*\) scope.*/\1/p') | |
124 | gateway=$(ip route show dev $interface | sed -n 's/default via \([0-9\.]*\).*/\1/p') | |
125 | ||
126 | ipaddr=${iplink%%/*} | |
127 | prefix=${iplink##*/} | |
128 | netmask=$(calc_netmask $prefix) | |
129 | ||
130 | echo "${ipaddr}:${serveraddr}:${gateway}:${netmask}:${hostname}:${interface}:none::${macaddr}" | |
131 | } | |
132 | ||
133 | is_xen_kernel() { | |
134 | local kversion=$1 | |
135 | local root_dir=$2 | |
136 | local cfg | |
137 | ||
138 | for cfg in ${root_dir}/boot/config-$kversion $root_dir/lib/modules/$kversion/build/.config | |
139 | do | |
140 | test -r $cfg || continue | |
141 | grep -q "^CONFIG_XEN=y\$" $cfg | |
142 | return | |
143 | done | |
144 | test $kversion != "${kversion%-xen*}" | |
145 | return | |
146 | } | |
147 | ||
162daf0c TR |
148 | # kernel_image_gz_from_image() and kernel_version_from_image() are helpers |
149 | # for arm* kernels which produce zImage files which cannot be read from | |
150 | # get_kernel_version -> get rid of this workaround if possible | |
151 | kernel_image_gz_from_image() { | |
152 | local arch=$(uname -i) | |
153 | local r=${1}.gz | |
154 | ||
155 | # uImage kernels can't be extracted directly. Use the vmlinux.gz instead | |
156 | r=${r//uImage/vmlinux} | |
157 | ||
158 | # on ARM a zImage can't be extracted directly. Other platforms define it | |
159 | # as a gzipped vmlinux file, but not ARM. So only on ARM, use vmlinux.gz. | |
160 | if [[ $arch =~ arm ]] || [[ $arch =~ aarch ]]; then | |
161 | r=${r//zImage/vmlinux} | |
162 | fi | |
163 | ||
164 | echo $r | |
165 | } | |
166 | ||
167 | kernel_version_from_image() { | |
168 | local kernel_image="$1" kernel_image_gz=$(kernel_image_gz_from_image "$1") | |
169 | ||
170 | if get_kernel_version "$kernel_image" 2>/dev/null; then | |
171 | return | |
172 | fi | |
173 | get_kernel_version "$kernel_image_gz" 2>/dev/null | |
174 | } | |
2b3e22d6 HR |
175 | |
176 | # Taken over from SUSE mkinitrd | |
177 | default_kernel_images() { | |
178 | local regex kernel_image kernel_version version_version initrd_image | |
179 | local qf='%{NAME}-%{VERSION}-%{RELEASE}\n' | |
180 | ||
181 | case "$(uname -m)" in | |
182 | s390|s390x) | |
183 | regex='image' | |
184 | ;; | |
185 | ppc|ppc64) | |
186 | regex='vmlinux' | |
187 | ;; | |
188 | i386|x86_64) | |
189 | regex='vmlinuz' | |
190 | ;; | |
191 | arm*) | |
192 | regex='[uz]Image' | |
193 | ;; | |
194 | aarch64) | |
195 | regex='Image' | |
196 | ;; | |
197 | *) regex='vmlinu.' | |
198 | ;; | |
199 | esac | |
200 | ||
201 | kernel_images="" | |
202 | initrd_images="" | |
203 | for kernel_image in $(ls $boot_dir \ | |
204 | | sed -ne "\|^$regex\(-[0-9.]\+-[0-9]\+-[a-z0-9]\+$\)\?|p" \ | |
205 | | grep -v kdump$ ) ; do | |
206 | ||
207 | # Note that we cannot check the RPM database here -- this | |
208 | # script is itself called from within the binary kernel | |
209 | # packages, and rpm does not allow recursive calls. | |
210 | ||
211 | [ -L "$boot_dir/$kernel_image" ] && continue | |
212 | [ "${kernel_image%%.gz}" != "$kernel_image" ] && continue | |
162daf0c TR |
213 | |
214 | kernel_version=$(kernel_version_from_image \ | |
2b3e22d6 HR |
215 | $boot_dir/$kernel_image 2> /dev/null) |
216 | initrd_image=$(echo $kernel_image | sed -e "s|${regex}|initrd|") | |
217 | if [ "$kernel_image" != "$initrd_image" -a \ | |
218 | -n "$kernel_version" -a \ | |
219 | -d "/lib/modules/$kernel_version" ]; then | |
220 | kernel_images="$kernel_images $boot_dir/$kernel_image" | |
221 | initrd_images="$initrd_images $boot_dir/$initrd_image" | |
222 | fi | |
223 | done | |
224 | for kernel_image in $kernel_images;do | |
225 | kernels="$kernels ${kernel_image#*-}" | |
226 | done | |
227 | for initrd_image in $initrd_images;do | |
228 | targets="$targets $initrd_image" | |
229 | done | |
2b3e22d6 HR |
230 | } |
231 | ||
232 | while (($# > 0)); do | |
233 | case ${1%%=*} in | |
234 | -f) read_arg feature_list "$@" || shift $? | |
235 | # Could be several features | |
236 | ;; | |
237 | -k) # Would be nice to get a list of images here | |
238 | read_arg kernel_images "$@" || shift $? | |
239 | for kernel_image in $kernel_images;do | |
7957bd01 | 240 | [ -L "/boot/$kernel_image" ] && kernel_image="$(readlink "/boot/$kernel_image")" |
2b3e22d6 HR |
241 | kernels="$kernels ${kernel_image#*-}" |
242 | done | |
2b3e22d6 HR |
243 | ;; |
244 | -i) read_arg initrd_images "$@" || shift $? | |
245 | for initrd_image in $initrd_images;do | |
7957bd01 | 246 | [ -L "/boot/$initrd_image" ] && initrd_image="$(readlink "/boot/$initrd_image")" |
2b3e22d6 HR |
247 | # Check if the initrd_image contains a path. |
248 | # if not, then add the default boot_dir | |
249 | dname=`dirname $initrd_image` | |
250 | if [ "$dname" == "." ]; then | |
251 | targets="$targets $boot_dir/$initrd_image"; | |
252 | else | |
253 | targets="$targets $initrd_image"; | |
254 | fi | |
255 | done | |
256 | ;; | |
257 | -b) read_arg boot_dir "$@" || shift $? | |
258 | if [ ! -d $boot_dir ];then | |
259 | error "Boot directory $boot_dir does not exist" | |
260 | exit 1 | |
261 | fi | |
262 | ;; | |
263 | -t) read_arg tmp_dir "$@" || shift $? | |
264 | dracut_args="${dracut_args} --tmpdir $tmp_dir" | |
265 | ;; | |
266 | -M) read_arg map_file "$@" || shift $? | |
267 | ;; | |
39ee4fdf | 268 | -A) dracut_args="${dracut_args} --no-host-only";; |
2b3e22d6 HR |
269 | -B) skip_update_bootloader=1;; |
270 | -v|--verbose) dracut_args="${dracut_args} -v";; | |
271 | -L) logfile=;; | |
272 | -h|--help) usage -n;; | |
273 | -m) read_arg module_list "$@" || shift $? ;; | |
274 | -u) read_arg domu_module_list "$@" || shift $? | |
275 | echo "mkinitrd: DomU modules not yet supported" ;; | |
276 | -d) read_arg rootfs "$@" || shift $? | |
277 | dracut_args="${dracut_args} --filesystems $rootfs" ;; | |
278 | -D) read_arg dhcp_if "$@" || shift $? | |
279 | dracut_cmdline="${dracut_cmdline} ip=${dhcp_if}:dhcp" | |
280 | ;; | |
281 | -I) read_arg static_if "$@" || shift $? | |
282 | dracut_cmdline="${dracut_cmdline} ip=$(ipconfig $static_if)": | |
283 | ;; | |
284 | -a) read_arg acpi_dsdt "$@" || shift $? | |
552c37e1 | 285 | echo "Obsolete -a param, use acpi_table_dir= and acpi_override= variables in /etc/dracut.conf.d/" |
2b3e22d6 HR |
286 | exit 1 |
287 | ;; | |
288 | -s) read_arg boot_splash "$@" || shift $? | |
289 | echo "mkinitrd: boot splash not yet supported" | |
290 | exit 1 | |
291 | ;; | |
292 | -V) echo "mkinitrd: vendor scipts are no longer supported" | |
293 | exit 1;; | |
294 | --dracut) | |
295 | read_arg dracut_cmd "$@" || shift $? ;; | |
296 | --version|-R) | |
297 | echo "mkinitrd: dracut compatibility wrapper" | |
298 | exit 0;; | |
2b3e22d6 HR |
299 | --quiet|-q) quiet=1;; |
300 | *) if [[ ! $targets ]]; then | |
301 | targets=$1 | |
302 | elif [[ ! $kernels ]]; then | |
303 | kernels=$1 | |
304 | else | |
305 | usage | |
306 | fi;; | |
307 | esac | |
308 | shift | |
309 | done | |
310 | ||
311 | [[ $targets && $kernels ]] || default_kernel_images | |
552c37e1 | 312 | if [[ ! $targets || ! $kernels ]];then |
01e60ca4 TR |
313 | error "No kernel found in $boot_dir or bad modules dir in /lib/modules" |
314 | exit 1 | |
552c37e1 | 315 | fi |
2b3e22d6 HR |
316 | |
317 | # We can have several targets/kernels, transform the list to an array | |
318 | targets=( $targets ) | |
319 | [[ $kernels ]] && kernels=( $kernels ) | |
320 | ||
321 | [[ $logfile ]] && dracut_args="${dracut_args} --logfile $logfile" | |
552c37e1 TR |
322 | dracut_args="${dracut_args} --force" |
323 | ||
2b3e22d6 HR |
324 | [[ $dracut_cmdline ]] && dracut_args="${dracut_args} --kernel-cmdline ${dracut_cmdline}" |
325 | [ -z "$(type -p update-bootloader)" ] && skip_update_bootloader=1 | |
326 | ||
327 | # Update defaults from /etc/sysconfig/kernel | |
328 | if [ -f /etc/sysconfig/kernel ] ; then | |
329 | . /etc/sysconfig/kernel | |
330 | fi | |
331 | [[ $module_list ]] || module_list="${INITRD_MODULES}" | |
2b3e22d6 | 332 | [[ $domu_module_list ]] || domu_module_list="${DOMU_INITRD_MODULES}" |
552c37e1 | 333 | shopt -s extglob |
2b3e22d6 | 334 | |
01e60ca4 TR |
335 | failed="" |
336 | ||
2b3e22d6 HR |
337 | for ((i=0 ; $i<${#targets[@]} ; i++)); do |
338 | ||
339 | if [[ $img_vers ]];then | |
340 | target="${targets[$i]}-${kernels[$i]}" | |
341 | else | |
342 | target="${targets[$i]}" | |
343 | fi | |
344 | kernel="${kernels[$i]}" | |
345 | ||
552c37e1 TR |
346 | if is_xen_kernel $kernel $rootfs ; then |
347 | modules_all="${module_list} ${domu_module_list}" | |
348 | else | |
349 | modules_all="${module_list}" | |
350 | fi | |
351 | ||
352 | # Remove leading and trailing spaces needs (set above): shopt -s extglob | |
353 | modules_all=${modules_all%%+([[:space:]])} | |
354 | modules_all=${modules_all##+([[:space:]])} | |
355 | ||
356 | echo "Creating initrd: $target" | |
357 | ||
2b3e22d6 HR |
358 | # Duplicate code: No way found how to redirect output based on $quiet |
359 | if [[ $quiet == 1 ]];then | |
552c37e1 TR |
360 | # Duplicate code: --force-drivers must not be called with empty string |
361 | # -> dracut bug workarounded ugly, because of complex whitespace | |
362 | # expansion magics | |
363 | if [ -n "${modules_all}" ];then | |
364 | $dracut_cmd $dracut_args --force-drivers "${modules_all}" "$target" "$kernel" &>/dev/null | |
01e60ca4 | 365 | [ $? -ne 0 ] && failed="$failed $target" |
552c37e1 | 366 | else |
2b3e22d6 | 367 | $dracut_cmd $dracut_args "$target" "$kernel" &>/dev/null |
01e60ca4 | 368 | [ $? -ne 0 ] && failed="$failed $target" |
552c37e1 | 369 | fi |
2b3e22d6 | 370 | else |
552c37e1 TR |
371 | if [ -n "${modules_all}" ];then |
372 | $dracut_cmd $dracut_args --force-drivers "${modules_all}" "$target" "$kernel" | |
01e60ca4 | 373 | [ $? -ne 0 ] && failed="$failed $target" |
552c37e1 | 374 | else |
2b3e22d6 | 375 | $dracut_cmd $dracut_args "$target" "$kernel" |
01e60ca4 | 376 | [ $? -ne 0 ] && failed="$failed $target" |
552c37e1 | 377 | fi |
2b3e22d6 HR |
378 | fi |
379 | done | |
380 | ||
381 | if [ "$skip_update_bootloader" ] ; then | |
382 | echo 2>&1 "Did not refresh the bootloader. You might need to refresh it manually." | |
383 | else | |
384 | update-bootloader --refresh | |
01e60ca4 TR |
385 | [ $? -ne 0 ] && echo "Updating bootloader failed" && exit 1 |
386 | fi | |
387 | ||
388 | if [ "$failed" != "" ]; then | |
389 | echo "Generating $failed targets failed" | |
390 | exit 1 | |
2b3e22d6 | 391 | fi |
01e60ca4 TR |
392 | |
393 | exit 0 |