crypt/parse-crypt.sh: fixed rule creation
[dracut.git] / dracut
blob15a5ee54d9e757f46f1d599593baeb6f2435c615
1 #!/bin/bash
2 # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
3 # ex: ts=8 sw=4 sts=4 et filetype=sh
4 #
5 # Generator script for a dracut initramfs
6 # Tries to retain some degree of compatibility with the command line
7 # of the various mkinitrd implementations out there
10 # Copyright 2005-2010 Red Hat, Inc. All rights reserved.
12 # This program is free software; you can redistribute it and/or modify
13 # it under the terms of the GNU General Public License as published by
14 # the Free Software Foundation; either version 2 of the License, or
15 # (at your option) any later version.
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # GNU General Public License for more details.
22 # You should have received a copy of the GNU General Public License
23 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 # store for logging
27 dracut_args="$@"
29 usage() {
30 # 80x25 linebreak here ^
31 cat << EOF
32 Usage: $0 [OPTION]... <initramfs> <kernel-version>
33 Creates initial ramdisk images for preloading modules
35 -f, --force Overwrite existing initramfs file.
36 -m, --modules [LIST] Specify a space-separated list of dracut modules to
37 call when building the initramfs. Modules are located
38 in /usr/share/dracut/modules.d.
39 -o, --omit [LIST] Omit a space-separated list of dracut modules.
40 -a, --add [LIST] Add a space-separated list of dracut modules.
41 -d, --drivers [LIST] Specify a space-separated list of kernel modules to
42 exclusively include in the initramfs.
43 --add-drivers [LIST] Specify a space-separated list of kernel
44 modules to add to the initramfs.
45 --filesystems [LIST] Specify a space-separated list of kernel filesystem
46 modules to exclusively include in the generic
47 initramfs.
48 -k, --kmoddir [DIR] Specify the directory, where to look for kernel
49 modules
50 --fwdir [DIR] Specify additional directories, where to look for
51 firmwares, separated by :
52 --kernel-only Only install kernel drivers and firmware files
53 --no-kernel Do not install kernel drivers and firmware files
54 --strip Strip binaries in the initramfs
55 --nostrip Do not strip binaries in the initramfs (default)
56 --mdadmconf Include local /etc/mdadm.conf
57 --nomdadmconf Do not include local /etc/mdadm.conf
58 --lvmconf Include local /etc/lvm/lvm.conf
59 --nolvmconf Do not include local /etc/lvm/lvm.conf
60 -h, --help This message
61 --debug Output debug information of the build process
62 -L, --stdlog [0-6] Specify logging level (to standard error)
63 0 - suppress any messages
64 1 - only fatal errors
65 2 - all errors
66 3 - warnings
67 4 - info (default)
68 5 - debug info (here starts lots of output)
69 6 - trace info (and even more)
70 -v, --verbose Increase verbosity level (default is info(4))
71 -q, --quiet Decrease verbosity level (default is info(4))
72 -c, --conf [FILE] Specify configuration file to use.
73 Default: /etc/dracut.conf
74 --confdir [DIR] Specify configuration directory to use *.conf files
75 from. Default: /etc/dracut.conf.d
76 -l, --local Local mode. Use modules from the current working
77 directory instead of the system-wide installed in
78 /usr/share/dracut/modules.d.
79 Useful when running dracut from a git checkout.
80 -H, --hostonly Host-Only mode: Install only what is needed for
81 booting the local host instead of a generic host.
82 --fstab Use /etc/fstab to determine the root device.
83 -i, --include [SOURCE] [TARGET]
84 Include the files in the SOURCE directory into the
85 Target directory in the final initramfs.
86 If SOURCE is a file, it will be installed to TARGET
87 in the final initramfs.
88 -I, --install [LIST] Install the space separated list of files into the
89 initramfs.
90 --gzip Compress the generated initramfs using gzip.
91 This will be done by default, unless another
92 compression option or --no-compress is passed.
93 --bzip2 Compress the generated initramfs using bzip2.
94 Make sure your kernel has bzip2 decompression support
95 compiled in, otherwise you will not be able to boot.
96 --lzma Compress the generated initramfs using lzma.
97 Make sure your kernel has lzma support compiled in,
98 otherwise you will not be able to boot.
99 --xz Compress the generated initramfs using xz.
100 Make sure that your kernel has xz support compiled
101 in, otherwise you will not be able to boot.
102 --compress [COMPRESSION] Compress the generated initramfs with the
103 passed compression program. Make sure your kernel
104 knows how to decompress the generated initramfs,
105 otherwise you will not be able to boot.
106 --no-compress Do not compress the generated initramfs. This will
107 override any other compression options.
108 --list-modules List all available dracut modules.
109 -M, --show-modules Print included module's name to standard output during
110 build.
114 # function push()
115 # push values to a stack
116 # $1 = stack variable
117 # $2.. values
118 # example:
119 # push stack 1 2 "3 4"
120 push() {
121 local __stack=$1; shift
122 for i in "$@"; do
123 eval ${__stack}'[${#'${__stack}'[@]}]="$i"'
124 done
127 # function pop()
128 # pops the last value from a stack
129 # assigns value to second argument variable
130 # or echo to stdout, if no second argument
131 # $1 = stack variable
132 # $2 = optional variable to store the value
133 # example:
134 # pop stack val
135 # val=$(pop stack)
136 pop() {
137 local __stack=$1; shift
138 local __resultvar=$1
139 local myresult;
140 # check for empty stack
141 eval '[[ ${#'${__stack}'[@]} -eq 0 ]] && return 1'
143 eval myresult='${'${__stack}'[${#'${__stack}'[@]}-1]}'
145 if [[ "$__resultvar" ]]; then
146 eval $__resultvar="'$myresult'"
147 else
148 echo "$myresult"
150 eval unset ${__stack}'[${#'${__stack}'[@]}-1]'
151 return 0
154 # Little helper function for reading args from the commandline.
155 # it automatically handles -a b and -a=b variants, and returns 1 if
156 # we need to shift $3.
157 read_arg() {
158 # $1 = arg name
159 # $2 = arg value
160 # $3 = arg parameter
161 local rematch='^[^=]*=(.*)$'
162 if [[ $2 =~ $rematch ]]; then
163 read "$1" <<< "${BASH_REMATCH[1]}"
164 else
165 read "$1" <<< "$3"
166 # There is no way to shift our callers args, so
167 # return 1 to indicate they should do it instead.
168 return 1
172 # Little helper function for reading args from the commandline to a stack.
173 # it automatically handles -a b and -a=b variants, and returns 1 if
174 # we need to shift $3.
175 push_arg() {
176 # $1 = arg name
177 # $2 = arg value
178 # $3 = arg parameter
179 local rematch='^[^=]*=(.*)$'
180 if [[ $2 =~ $rematch ]]; then
181 push "$1" "${BASH_REMATCH[1]}"
182 else
183 push "$1" "$3"
184 # There is no way to shift our callers args, so
185 # return 1 to indicate they should do it instead.
186 return 1
190 verbosity_mod_l=0
192 while (($# > 0)); do
193 case ${1%%=*} in
194 -a|--add) push_arg add_dracutmodules_l "$@" || shift;;
195 --add-drivers) push_arg add_drivers_l "$@" || shift;;
196 -m|--modules) push_arg dracutmodules_l "$@" || shift;;
197 -o|--omit) push_arg omit_dracutmodules_l "$@" || shift;;
198 -d|--drivers) push_arg drivers_l "$@" || shift;;
199 --filesystems) push_arg filesystems_l "$@" || shift;;
200 -I|--install) push_arg install_items "$@" || shift;;
201 --fwdir) push_arg fw_dir_l "$@" || shift;;
202 -k|--kmoddir) read_arg drivers_dir_l "$@" || shift;;
203 -c|--conf) read_arg conffile "$@" || shift;;
204 --confdir) read_arg confdir "$@" || shift;;
205 -L|--stdlog) read_arg stdloglvl_l "$@" || shift;;
206 -I|--install) read_arg install_items "$@" || shift;;
207 --fwdir) read_arg fw_dir_l "$@" || shift;;
208 --compress) read_arg compress_l "$@" || shift;;
209 -f|--force) force=yes;;
210 --kernel-only) kernel_only="yes"; no_kernel="no";;
211 --no-kernel) kernel_only="no"; no_kernel="yes";;
212 --strip) do_strip_l="yes";;
213 --nostrip) do_strip_l="no";;
214 --mdadmconf) mdadmconf_l="yes";;
215 --nomdadmconf) mdadmconf_l="no";;
216 --lvmconf) lvmconf_l="yes";;
217 --nolvmconf) lvmconf_l="no";;
218 --debug) debug="yes";;
219 -v|--verbose) ((verbosity_mod_l++));;
220 -q|--quiet) ((verbosity_mod_l--));;
221 -l|--local) allowlocal="yes" ;;
222 -H|--hostonly) hostonly_l="yes" ;;
223 --fstab) use_fstab_l="yes" ;;
224 -h|--help) usage; exit 1 ;;
225 -i|--include) push include_src "$2"
226 push include_target "$3"
227 shift 2;;
228 --bzip2) compress_l="bzip2";;
229 --lzma) compress_l="lzma";;
230 --xz) compress_l="xz";;
231 --no-compress) _no_compress_l="cat";;
232 --gzip) compress_l="gzip";;
233 --list-modules)
234 do_list="yes";
236 -M|--show-modules)
237 show_modules_l="yes"
239 -*) printf "\nUnknown option: %s\n\n" "$1" >&2; usage; exit 1;;
241 if ! [[ ${outfile+x} ]]; then
242 outfile=$1
243 elif ! [[ ${kernel+x} ]]; then
244 kernel=$1
245 else
246 usage; exit 1;
249 esac
250 shift
251 done
252 if ! [[ $kernel ]]; then
253 kernel=$(uname -r)
255 [[ $outfile ]] || outfile="/boot/initramfs-$kernel.img"
257 PATH=/sbin:/bin:/usr/sbin:/usr/bin
258 export PATH
260 [[ $debug ]] && {
261 export PS4='${BASH_SOURCE}@${LINENO}(${FUNCNAME[0]}): ';
262 set -x
265 [[ $dracutbasedir ]] || dracutbasedir=/usr/share/dracut
267 [[ $allowlocal && -f "$(readlink -f ${0%/*})/dracut-functions" ]] && \
268 dracutbasedir="$(readlink -f ${0%/*})"
270 # if we were not passed a config file, try the default one
271 if [[ ! -f $conffile ]]; then
272 [[ $allowlocal ]] && conffile="$dracutbasedir/dracut.conf" || \
273 conffile="/etc/dracut.conf"
276 if [[ ! -d $confdir ]]; then
277 [[ $allowlocal ]] && confdir="$dracutbasedir/dracut.conf.d" || \
278 confdir="/etc/dracut.conf.d"
281 # source our config file
282 [[ -f $conffile ]] && . "$conffile"
284 # source our config dir
285 if [[ $confdir && -d $confdir ]]; then
286 for f in "$confdir"/*.conf; do
287 [[ -e $f ]] && . "$f"
288 done
291 # these optins add to the stuff in the config file
292 if (( ${#add_dracutmodules_l[@]} )); then
293 while pop add_dracutmodules_l val; do
294 add_dracutmodules+=" $val "
295 done
298 if (( ${#add_drivers_l[@]} )); then
299 while pop add_drivers_l val; do
300 add_drivers+=" $val "
301 done
304 # these options override the stuff in the config file
305 if (( ${#dracutmodules_l[@]} )); then
306 dracutmodules=''
307 while pop dracutmodules_l val; do
308 dracutmodules+="$val "
309 done
312 if (( ${#omit_dracutmodules_l[@]} )); then
313 omit_dracutmodules=''
314 while pop omit_dracutmodules_l val; do
315 omit_dracutmodules+="$val "
316 done
319 if (( ${#drivers_l[@]} )); then
320 drivers=''
321 while pop drivers_l val; do
322 drivers+="$val "
323 done
326 if (( ${#filesystems_l[@]} )); then
327 filesystems=''
328 while pop filesystems_l val; do
329 filesystems+="$val "
330 done
333 if (( ${#fw_dir_l[@]} )); then
334 fw_dir=''
335 while pop fw_dir_l val; do
336 fw_dir+="$val "
337 done
340 [[ $stdloglvl_l ]] && stdloglvl=$stdloglvl_l
341 [[ ! $stdloglvl ]] && stdloglvl=4
342 stdloglvl=$((stdloglvl + verbosity_mod_l))
343 ((stdloglvl > 6)) && stdloglvl=6
344 ((stdloglvl < 0)) && stdloglvl=0
346 [[ $drivers_dir_l ]] && drivers_dir=$drivers_dir_l
347 [[ $do_strip_l ]] && do_strip=$do_strip_l
348 [[ $hostonly_l ]] && hostonly=$hostonly_l
349 [[ $use_fstab_l ]] && use_fstab=$use_fstab_l
350 [[ $mdadmconf_l ]] && mdadmconf=$mdadmconf_l
351 [[ $lvmconf_l ]] && lvmconf=$lvmconf_l
352 [[ $dracutbasedir ]] || dracutbasedir=/usr/share/dracut
353 [[ $fw_dir ]] || fw_dir="/lib/firmware/updates /lib/firmware"
354 [[ $do_strip ]] || do_strip=no
355 [[ $compress_l ]] && compress=$compress_l
356 [[ $show_modules_l ]] && show_modules=$show_modules_l
357 # eliminate IFS hackery when messing with fw_dir
358 fw_dir=${fw_dir//:/ }
360 # handle compression options.
361 case $compress in
362 bzip2) compress="bzip -9";;
363 lzma) compress="lzma -9";;
364 xz) compress="xz --check=crc32 --lzma2=dict=1MiB";;
365 gzip) type pigz > /dev/null 2>&1 && compress="pigz -9" || \
366 compress="gzip -9";;
367 esac
368 if [[ $_no_compress_l = "cat" ]]; then
369 compress="cat"
372 [[ $hostonly = yes ]] && hostonly="-h"
373 [[ $hostonly != "-h" ]] && unset hostonly
374 [[ $compress ]] || compress="gzip -9"
376 if [[ -f $dracutbasedir/dracut-functions ]]; then
377 . $dracutbasedir/dracut-functions
378 else
379 echo "Cannot find $dracutbasedir/dracut-functions." >&2
380 echo "Are you running from a git checkout?" >&2
381 echo "Try passing -l as an argument to $0" >&2
382 exit 1
385 dracutfunctions=$dracutbasedir/dracut-functions
386 export dracutfunctions
388 ddebug "Executing $0 $dracut_args"
390 [[ $do_list = yes ]] && {
391 for mod in $dracutbasedir/modules.d/*; do
392 [[ -d $mod ]] || continue;
393 [[ -e $mod/install || -e $mod/installkernel || \
394 -e $mod/module-setup.sh ]] || continue
395 echo ${mod##*/??}
396 done
397 exit 0
400 # Detect lib paths
401 [[ $libdir ]] || for libdir in /lib64 /lib; do
402 [[ -d $libdir ]] && break
403 done || {
404 dfatal 'No lib directory?!!!'
405 exit 1
408 [[ $usrlibdir ]] || for usrlibdir in /usr/lib64 /usr/lib; do
409 [[ -d $usrlibdir ]] && break
410 done || dwarn 'No usr/lib directory!'
412 # This is kinda legacy -- eventually it should go away.
413 case $dracutmodules in
414 ""|auto) dracutmodules="all" ;;
415 esac
417 abs_outfile=$(readlink -f "$outfile") && outfile="$abs_outfile"
419 srcmods="/lib/modules/$kernel/"
420 [[ $drivers_dir ]] && {
421 if vercmp $(modprobe --version | cut -d' ' -f3) lt 3.7; then
422 dfatal 'To use --kmoddir option module-init-tools >= 3.7 is required.'
423 exit 1
425 srcmods="$drivers_dir"
427 export srcmods
429 if [[ -f $outfile && ! $force ]]; then
430 dfatal "Will not override existing initramfs ($outfile) without --force"
431 exit 1
434 outdir=${outfile%/*}
435 [[ $outdir ]] || outdir="/"
437 if [[ ! -d "$outdir" ]]; then
438 dfatal "Can't write $outfile: Directory $outdir does not exist."
439 exit 1
440 elif [[ ! -w "$outdir" ]]; then
441 dfatal "No permission to write $outdir."
442 exit 1
443 elif [[ -f "$outfile" && ! -w "$outfile" ]]; then
444 dfatal "No permission to write $outfile."
445 exit 1
448 [[ $TMPDIR && ! -w $TMPDIR ]] && unset TMPDIR
449 readonly initdir=$(mktemp -d -t initramfs.XXXXXX)
451 # clean up after ourselves no matter how we die.
452 trap 'ret=$?;rm -rf "$initdir";exit $ret;' EXIT
453 # clean up after ourselves no matter how we die.
454 trap 'exit 1;' SIGINT
456 # Need to be able to have non-root users read stuff (rpcbind etc)
457 chmod 755 "$initdir"
459 export initdir dracutbasedir dracutmodules drivers \
460 fw_dir drivers_dir debug no_kernel kernel_only \
461 add_drivers mdadmconf lvmconf filesystems \
462 use_fstab libdir usrlibdir \
463 stdloglvl sysloglvl fileloglvl kmsgloglvl logfile \
464 debug
466 if [[ $kernel_only != yes ]]; then
467 # Create some directory structure first
468 for d in bin sbin usr/bin usr/sbin usr/lib etc \
469 proc sys sysroot tmp dev/pts var/run; do
470 inst_dir "/$d";
471 done
474 # check all our modules to see if they should be sourced.
475 # This builds a list of modules that we will install next.
476 check_module_dir
478 # source our modules.
479 for moddir in "$dracutbasedir/modules.d"/[0-9][0-9]*; do
480 mod=${moddir##*/}; mod=${mod#[0-9][0-9]}
481 if strstr "$mods_to_load" " $mod "; then
482 [[ $show_modules = yes ]] && echo "$mod" || \
483 dinfo "*** Including module: $mod ***"
484 if [[ $kernel_only = yes ]]; then
485 module_installkernel $mod
486 else
487 module_install $mod
488 if [[ $no_kernel != yes ]]; then
489 module_installkernel $mod
492 mods_to_load=${mods_to_load// $mod /}
494 done
495 unset moddir
496 dinfo "*** Including modules done ***"
498 ## final stuff that has to happen
500 # generate module dependencies for the initrd
501 if [[ -d $initdir/lib/modules/$kernel ]] && \
502 ! depmod -a -b "$initdir" $kernel; then
503 dfatal "\"depmod -a $kernel\" failed."
504 exit 1
507 while pop include_src src && pop include_target tgt; do
508 if [[ $src && $tgt ]]; then
509 if [[ -f $src ]]; then
510 inst $src $tgt
511 else
512 ddebug "Including directory: $src"
513 mkdir -p "${initdir}/${tgt}"
514 cp -a -t "${initdir}/${tgt}" "$src"/*
517 done
519 while pop install_items items; do
520 for item in $items; do
521 dracut_install "$item"
522 done
523 done
524 unset item
526 # make sure that library links are correct and up to date
527 for f in /etc/ld.so.conf /etc/ld.so.conf.d/*; do
528 [[ -e $f ]] && dracut_install "$f"
529 done
530 if ! ldconfig -r "$initdir"; then
531 if [[ $UID = 0 ]]; then
532 derror "ldconfig exited ungracefully"
533 else
534 derror "ldconfig might need uid=0 (root) for chroot()"
538 if (($maxloglvl >= 5)); then
539 ddebug "Listing sizes of included files:"
540 du -c "$initdir" | sort -n | ddebug
543 # strip binaries
544 if [[ $do_strip = yes ]] ; then
545 for p in strip grep find; do
546 if ! type -P $p >/dev/null; then
547 derror "Could not find '$p'. You should run $0 with '--nostrip'."
548 do_strip=no
550 done
553 if [[ $do_strip = yes ]] ; then
554 for f in $(find "$initdir" -type f \
555 \( -perm -0100 -or -perm -0010 -or -perm -0001 \
556 -or -path '*/lib/modules/*.ko' \) ); do
557 dinfo "Stripping $f"
558 strip -g "$f" 2>/dev/null|| :
559 done
562 type hardlink &>/dev/null && {
563 hardlink "$initdir" 2>&1
566 if ! ( cd "$initdir"; find . |cpio -R 0:0 -H newc -o --quiet | \
567 $compress > "$outfile"; ); then
568 dfatal "dracut: creation of $outfile failed"
569 exit 1
572 dinfo "Wrote $outfile:"
573 dinfo "$(ls -l "$outfile")"
575 exit 0