]> git.pld-linux.org Git - projects/geninitrd.git/blob - geninitrd
ext4 can use crc32 but has it in softdep only
[projects/geninitrd.git] / geninitrd
1 #!/bin/sh
2
3 # geninitrd
4 #
5 #       by PLD Linux Team
6 #
7 # based on mkinitrd from RedHat Linux
8 #
9
10 VERSION='devel'
11 PROGRAM=${0##*/}
12
13 . /etc/rc.d/init.d/functions
14 . /lib/geninitrd/functions
15 . /etc/sysconfig/system
16
17 # list of geninitrd modules which need setup routine after commandline args parsing
18 GENINITRD_MODS=""
19 COMPRESS=yes
20 STRIP=/usr/bin/strip
21 target=""
22 kernel=""
23 force=""
24 verbose=""
25 MODULES=""
26 img_vers=""
27 fstab=/etc/fstab
28 modext=.o
29 rootdev_nr=0
30 # device node for rootfs from fstab
31 rootdev=""
32
33 # internal variables
34 # is /dev on tmpfs
35 dev_mounted=no
36 # is /proc mounted
37 proc_mounted=no
38 # is /sys mounted
39 sys_mounted=no
40 # is /tmp mounted on tmpfs
41 tmp_mounted=no
42
43 # are /dev nodes already created from /proc/devices info?
44 proc_partitions=no
45
46 usage() {
47         echo "Usage: $PROGRAM [--version] [-v] [-f] [--ifneeded] [--preload <module>]"
48         echo "       [--with=<module>] [--image-version] [--fstab=<fstab>] [--nocompress]"
49         echo "       [--compress=yes|zstd|xz|lzma|bzip2|gzip|lzo]"
50         echo "       [--nostrip ] [--strip PATH/strip] [--strip=PATH/strip]"
51         echo "       [--initrdfs=rom|initramfs|ext2|cram] [--modules-conf=<modules.conf>]"
52         echo "       [--with-bootsplash] [--without-bootsplash]"
53         echo "       [--with-fbsplash] [--without-fbsplash]"
54         echo "       [--with-fbcondecor] [--without-fbcondecor]"
55         echo "       [--lvmtoolsversion=1|2] [--with-udev] [--without-udev]"
56         echo "       [--with-suspend] [--without-suspend]"
57         echo "       [--with-tuxonice] [--without-tuxonice]"
58         echo "       [--without-dmraid]"
59         echo "       [--with-multipath=DEVPATH] [--without-multipath]"
60         echo "       [--without-blkid] [--without-luks]"
61         echo "       <initrd-image> <kernel-version>"
62         echo ""
63         echo "Example:"
64
65         local kdir kver dir=${target:-/boot}
66         for kdir in /lib/modules/*; do
67                 [ -d $kdir ] || continue
68                 kver=${kdir##*/}
69                 echo "  $0 -f --initrdfs=initramfs $dir/initrd-$kver.gz $kver $verbose"
70         done | sort -V
71 }
72
73 msg() {
74         echo "$PROGRAM: $*"
75 }
76
77 warn() {
78         msg "WARNING: $*" >&2
79 }
80
81 verbose() {
82         [ -n "$verbose" ] && msg "$*" >&3
83 }
84
85 debug() {
86         [ x"$verbose" = x"-v -v" ] && msg "$*" >&3
87 }
88
89 # add initrd code to print to kmsg
90 # @param string message
91 # @param int loglevel. defaults to "6" (info)
92 # Log levels can be:
93 # Name          String  Meaning
94 # KERN_EMERG    "0"     Emergency messages, system is about to crash or is unstable
95 # KERN_ALERT    "1"     Something bad happened and action must be taken immediately
96 # KERN_CRIT     "2"     A critical condition occurred like a serious hardware/software failure
97 # KERN_ERR      "3"     An error condition, often used by drivers to indicate difficulties with the hardware
98 # KERN_WARNING  "4"     A warning, meaning nothing serious by itself but might indicate problems
99 # KERN_NOTICE   "5"     Nothing serious, but notably nevertheless. Often used to report security events.
100 # KERN_INFO     "6"     Informational message e.g. startup information at driver initialization
101 # KERN_DEBUG    "7"     Debug messages
102 # KERN_CONT     "c"     "continued" line of log printout (only done after a line that had no enclosing \n)
103 kmsg() {
104         local msg="$1" level=${2:-6}
105         echo "echo '<$level>$msg' > /dev/kmsg" | add_linuxrc
106 }
107
108 # aborts program abnormally
109 die() {
110         local rc=${2:-1}
111         msg "ERROR: $1" >&2
112         exit $rc
113 }
114
115 # find program from specified paths
116 find_tool() {
117         local x p b n
118         local paths="$initrd_dirs /bin /sbin /usr/bin /usr/sbin"
119         for x in "$@"; do
120                 debug "find_tool: checking $x"
121                 if [ -x "$x" ]; then
122                         echo $x
123                         verbose "find_tool: found $x"
124                         return 0
125                 fi
126                 n="$x"
127                 for p in $paths; do
128                         b=$(basename $x)
129                         debug "find_tool: checking $p/$b"
130                         if [ -x "$p/$b" ]; then
131                                 echo $p/$b
132                                 verbose "find_tool: found $p/$b"
133                                 return 0
134                         fi
135                         n="$n $p/$b"
136                 done
137         done
138         debug "find_tool: did not find any of: $n"
139         return 1
140 }
141
142 # loads geninitrd modules
143 geninitrd_load_mods() {
144         local mod
145         for mod in "$@"; do
146                 if [ ! -f /lib/geninitrd/mod-$mod.sh ]; then
147                         die "$mod geninitrd module can't be loaded"
148                 fi
149                 . /lib/geninitrd/mod-$mod.sh
150
151                 GENINITRD_MODS="$GENINITRD_MODS $mod"
152         done
153 }
154
155 # setup geninitrd modules
156 geninitrd_setup_mods() {
157         local mod
158
159         for mod in $GENINITRD_MODS; do
160                 debug "# $mod"
161
162                 # some mods want init
163                 if type setup_mod_$mod > /dev/null; then
164                         eval setup_mod_$mod
165                 fi
166         done
167 }
168
169 # append text to /linuxrc
170 # takes STDIN as input
171 add_linuxrc() {
172         cat >> "$RCFILE"
173 }
174
175 # generate code to mount /dev on tmpfs and create initial nodes
176 # can be called multiple times. /dev is cleaned up (umounted) automatically at
177 # the end of script.
178 mount_dev() {
179         # we already generated tmpfs code; return
180         if is_yes "$dev_mounted"; then
181                 return
182         fi
183
184         dev_mounted=yes
185
186         busybox_applet mount mknod mkdir
187         add_linuxrc <<-EOF
188                 : 'Creating /dev'
189                 if ! mount -t devtmpfs -o mode=0755,nosuid devtmpfs /dev > /dev/null 2>&1; then
190                         mount -o mode=0755,nosuid -t tmpfs tmpfs /dev
191                         mknod -m 600 /dev/console c 5 1
192                         mknod -m 666 /dev/null c 1 3
193                         mknod -m 666 /dev/zero c 1 5
194                         mknod -m 666 /dev/random c 1 8
195                         mknod -m 600 /dev/snapshot c 10 231
196                         mknod -m 666 /dev/urandom c 1 9
197                         mknod -m 666 /dev/ptmx c 5 2
198                         mknod -m 644 /dev/kmsg c 1 11
199                 fi
200                 mkdir /dev/pts
201                 mkdir /dev/shm
202         EOF
203 }
204
205 # load font
206 load_font() {
207         local font
208         [ ! -r /etc/sysconfig/console ] && return
209         . /etc/sysconfig/console
210         if [ -n "$CONSOLEFONT" ]; then
211                 font=$(ls -1 /lib/kbd/consolefonts/${CONSOLEFONT}*.gz 2> /dev/null)
212                 if [ -n "$font" ]; then
213                         verbose "Loading font $font"
214                         busybox_applet loadfont
215                         inst_d "/lib/kbd/consolefonts"
216                         cp -a "$font" "$DESTDIR/lib/kbd/consolefonts/"
217                         gunzip ${DESTDIR}/lib/kbd/consolefonts/${CONSOLEFONT}*.gz
218                         font=${font%.gz}
219                         echo "loadfont < $font" | add_linuxrc
220                 fi
221         fi
222 }
223
224 # generate code to mount /proc on initrd
225 # can be called multiple times
226 mount_proc() {
227         if is_yes "$proc_mounted"; then
228                 return
229         fi
230
231         proc_mounted=yes
232     if [ "$INITRDFS" = "initramfs" ]; then
233                 # /proc is mounted with initramfs 2.6.22.14 kernel
234                 # XXX: remove when it is clear why proc was already mounted
235                 echo "[ -f /proc/cmdline ] || mount -t proc none /proc" | add_linuxrc
236         else
237                 echo "mount -t proc none /proc" | add_linuxrc
238         fi
239 }
240
241 # generate code to mount /sys on initrd
242 # can be called multiple times
243 mount_sys() {
244         if is_yes "$sys_mounted"; then
245                 return
246         fi
247
248         sys_mounted=yes
249         echo "mount -t sysfs none /sys" | add_linuxrc
250 }
251
252 # generate code to mount /tmp on initrd
253 # can be called multiple times
254 mount_tmp() {
255     if [ "$INITRDFS" = "initramfs" ]; then
256                 # initramfs is read-write filesystem, no need for tmpfs
257                 return
258         fi
259
260         if is_yes "$tmp_mounted"; then
261                 return
262         fi
263
264         tmp_mounted=yes
265         echo "mount -t tmpfs none /tmp" | add_linuxrc
266 }
267
268 # generate code to mount /run on initrd
269 # can be called multiple times
270 mount_run() {
271         if is_yes "$run_mounted"; then
272                 return
273         fi
274
275         run_mounted=yes
276         echo "mount -t tmpfs run /run -o mode=0755,noexec,nosuid,nodev" | add_linuxrc
277 }
278
279 # unmount all mountpoints mounted by geninitrd
280 # try to move pseudo filesystems to newroot if possible
281 umount_all() {
282
283         add_linuxrc <<-'EOF'
284         : Last shell before umounting all and giving control over to real init.
285         debugshell
286         EOF
287
288         if is_yes "$run_mounted"; then
289                 add_linuxrc <<-EOF
290                 mount --bind /run /newroot/run
291                 umount /run
292                 EOF
293                 run_mounted=no
294         fi
295         if is_yes "$dev_mounted"; then
296                 add_linuxrc <<-EOF
297                 mount --bind /dev /newroot/dev
298                 umount /dev
299                 EOF
300                 dev_mounted=no
301         fi
302         if is_yes "$sys_mounted"; then
303                 add_linuxrc <<-EOF
304                 mount --bind /sys /newroot/sys
305                 umount /sys
306                 EOF
307                 sys_mounted=no
308         fi
309         if is_yes "$proc_mounted"; then
310                 add_linuxrc <<-EOF
311                 mount --bind /proc /newroot/proc
312                 umount /proc
313                 EOF
314                 proc_mounted=no
315         fi
316         if is_yes "$tmp_mounted"; then
317                 echo 'umount /tmp' | add_linuxrc
318                 tmp_mounted=no
319         fi
320 }
321
322 # Checks if busybox has support for APPLET(s)
323 # Exits from geninitrd if the support is not present.
324 #
325 # NB! XXX do not output to STDOUT, it will appear in initrd images in some cases!
326 busybox_applet() {
327         local err=0 applet
328
329         if [ -z "$busybox_functions" ]; then
330                 local tmp=$($busybox 2>&1)
331
332                 # BusyBox v1.1.3 says applet not found if it's not called 'busybox'.
333                 if [[ "$tmp" = *applet\ not\ found* ]]; then
334                         local t=$(mktemp -d)
335                         ln -s $busybox $t/busybox
336                         local tmp=$($t/busybox 2>&1)
337                         rm -rf $t
338                 fi
339
340                 busybox_functions=$(echo "$tmp" | \
341                         sed -ne '/Currently defined functions:/,$p' | \
342                         xargs | sed -e 's,.*Currently defined functions: ,,'
343                 )
344         fi
345         for applet in $*; do
346                 local have
347                 # try cache
348                 eval have='$'busybox_have_$applet
349                 if [ -z "$have" ]; then
350                         have=$(echo "$busybox_functions" | grep -Ec "( |^)$applet(,|$)")
351                         if [ "$have" = 0 ]; then
352                                 warn "This setup requires busybox-initrd compiled with applet '$applet' support"
353                                 err=1
354                         fi
355                         eval busybox_have_$applet=$have
356                 fi
357         done
358         if [ $err = 1 ]; then
359                 die "Aborted"
360         fi
361 }
362
363 # Extract the .config file from a kernel image
364 # uses extract-ikconfig from kernel sources (scripts/extract-ikconfig)
365 ikconfig() {
366         local kofile=$(modinfo -k $kernel -n configs 2> /dev/null)
367         if [ -n "$kofile" ]; then
368                 /lib/geninitrd/extract-ikconfig $kofile
369                 return
370         fi
371
372         # see if config available as separate file
373         if [ -f /boot/config-$kernel ]; then
374            cat /boot/config-$kernel
375            return
376         fi
377
378         # finally try vmlinuz itself
379         /lib/geninitrd/extract-ikconfig /boot/vmlinuz-$kernel
380 }
381
382 # @param    $module
383 basename_module() {
384         local module=$1
385
386         module=${module##*/}
387         module=${module%$modext*}
388         echo $module
389 }
390
391 # Finds module dependencies
392 #
393 # @param        $module
394 #
395 # Outputs full path to module and it's dependencies
396 find_depmod() {
397         local module="$1"
398         local skiperrors=0
399
400         # if module is prefixed with dash, we should ignore errors if the module
401         # can't be found.
402         if [ ${module#-} != $module ]; then
403                 skiperrors=1
404                 module=${module#-}
405         fi
406
407         # This works when user has module-init-tools installed even on 2.4 kernels
408         local modprobe
409         modprobe=$(modprobe --set-version $kernel --show-depends $module --ignore-install 2>&1)
410
411         if [ $? != 0 ]; then
412                 if [ $skiperrors = 1 ]; then
413                         return 0
414                 fi
415                 echo >&2 "$modprobe"
416
417                 if ! is_no "$EXIT_IF_MISSING"; then
418                         die "$module: module not found for $kernel kernel"
419                 fi
420
421                 warn "$module: module not found for $kernel kernel"
422                 warn "If $module isn't compiled in kernel then this initrd may not start your system."
423         fi
424
425         local smodule
426
427         echo "$modprobe" | \
428         while read insmod modpath options; do
429                 if [ "$insmod" = "insmod" ]; then
430
431                         # XXX: find a away to autodetect
432                         smodule=$(basename_module $modpath)
433                         case "$smodule" in
434                                 btrfs)
435                                         warn "mounting multidevice btrfs volume requires rootfsflags=device=/dev/...,device=/dev/... kernel option"
436                                         find_depmod "-libcrc32c"
437                                         ;;
438                                 ext4)
439                                         find_depmod "-libcrc32c"
440                                         ;;
441                                 crc-t10dif)
442                                         find_depmod "-crct10dif-pclmul"
443                                         find_depmod "-crct10dif"
444                                         ;;
445                                 libcrc32c)
446                                         find_depmod "-crc32c-intel"
447                                         find_depmod "-crc32c"
448                                         ;;
449                                 virtio_blk|virtio_scsi)
450                                         find_depmod "-virtio_pci"
451                                         find_depmod "-virtio_mmio"
452                                         ;;
453                         esac
454
455                         echo $modpath
456                 fi
457         done
458         return 0
459 }
460
461 find_firmware() {
462         local module="$1"
463
464         # no firmware support in 2.4 kernels
465         if [ "$kernel_version_long" -lt "002005048" ]; then
466                 return
467         fi
468         echo -n $(NEW_MODINFO=1 modinfo -k $kernel -F firmware $module 2>/dev/null | xargs)
469 }
470
471 # @param        $module
472 find_module() {
473         local mod depmod module=$1
474
475         depmod=$(find_depmod $module) || exit 1
476         for mod in $depmod; do
477                 mod=${mod#/lib/modules/$kernel/}
478
479                 # add each module only once
480                 local m have=0
481                 for m in $MODULES; do
482                         [ $m = $mod ] && have=1
483                 done
484                 if [ $have = 0 ]; then
485                         MODULES="$MODULES $mod"
486                 fi
487         done
488 }
489
490 # install a file to temporary mount image.
491 # it will operate recursively (copying directories)
492 # and will symlink destinations if source is symlink.
493 inst() {
494         if [ $# -lt 2 ]; then
495                 die 'Usage: inst <file> [<file>] <destination>'
496         fi
497
498         local src i=0 c=$(($# - 1))
499         while [ $i -lt $c ]; do
500                 src="$src $1"
501                 i=$((i + 1))
502                 shift
503         done
504         local dest=$1
505         set -- $src
506         local parentDir=$(dirname $DESTDIR$dest)
507         if [ ! -d "$parentDir" ]; then
508                 verbose "+ mkdir -p DESTDIR${parentDir#$DESTDIR}"
509                 mkdir -p $parentDir
510         fi
511         verbose "+ cp $* DESTDIR$dest"
512         cp -HRp "$@" "$DESTDIR$dest"
513 }
514
515 inst_d() {
516         if [ $# = 0 ]; then
517                 die 'Usage: inst_d <destination> <destination>'
518         fi
519         local dir
520         for dir in "$@"; do
521                 install -d "$DESTDIR$dir"
522         done
523 }
524
525 # install executable and it's shared libraries
526 inst_exec() {
527         if [ $# -lt 2 ]; then
528                 die "Invalid params ($@), Usage: inst_exec <file>[, <file>] <destination>"
529         fi
530         local src i=0 c=$(($# - 1))
531         while [ $i -lt $c ]; do
532                 src="$src $1"
533                 i=$((i + 1))
534                 shift
535         done
536         local dest=$1
537         set -- $src
538
539         inst "$@" $dest
540
541         local obj lib libs libdir
542         for obj in "$@"; do
543                 case "$obj" in
544                         /lib/ld-linux.so.2 | /lib64/ld-linux-x86-64.so.2 | /libx32/ld-linux-x32.so.2)
545                         continue
546                 esac
547
548                 libs=$(ldd "$obj" | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
549                 for lib in $libs; do
550                         libdir=$(cd $(dirname "$lib"); pwd)
551                         if [ ! -f "$DESTDIR/$lib" ]; then
552                                 inst_d $libdir
553                                 inst_exec $lib $libdir
554                         fi
555                 done
556         done
557
558         # hack for uclibc linked binaries requiring this fixed path
559         # XXX: shouldn't rpath be used here instead so th
560         for _lib in $(get_libdir LIBDIR); do
561                 if [ -f $DESTDIR/$_lib/libc.so.0 ]; then
562                         lib=$DESTDIR/$_lib/libc.so.0
563                         lib=$(ldd "$lib" | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
564                         libdir=$(cd $(dirname "$lib"); pwd)
565                         if [ ! -e $DESTDIR$libdir ]; then
566                                 libdir=$(dirname "$libdir")
567                                 inst_d $libdir
568                                 verbose "+ ln -s /$_lib $DESTDIR$libdir"
569                                 ln -s /$_lib $DESTDIR$libdir
570                                 break
571                         fi
572                 fi
573         done
574 }
575
576 # output modules.conf / modprobe.conf
577 modprobe_conf() {
578         echo "$modprobe_conf_cache"
579 }
580
581 # return options for MODULE
582 # @param $1 module name
583 modprobe_options() {
584         local module=$1
585         local options=$(modprobe_conf | awk -vmodule="$module" '{ if ($1 == "options" && $2 == module) { for(i=3;i<=NF;i++) printf("%s ",$i); }}')
586         echo ${options# }
587 }
588
589 #
590 # defaults to modprobe -c if not told otherwise, this means include statements
591 # work from there.
592 cache_modprobe_conf() {
593         if [ "$kernel_version" -lt "002005" ]; then
594                 modulefile=/etc/modules.conf
595                 if [ ! -f "$modulefile" -a -f /etc/conf.modules ]; then
596                         modulefile=/etc/conf.modules
597                 fi
598         fi
599
600         if [ -n "$modulefile" ]; then
601                 debug "Using $modulefile for modules config"
602                 modprobe_conf_cache=$(cat $modulefile | awk '!/^[\t ]*#/ { print }')
603
604         else
605                 debug "Using modprobe -c to get modules config"
606                 modprobe_conf_cache=$(modprobe -c --set-version $kernel | awk '!/^[\t ]*#/ { print }')
607         fi
608 }
609
610 # find modules for $devpath
611 find_modules_for_devpath() {
612         local devpath="$1"
613         if [ -z "$devpath" ]; then
614                 die "No argument passed to find_modules_for_devpath() - is your /etc/fstab correct?"
615         fi
616
617         if [[ "$devpath" = /dev/dm-* ]]; then
618                 # /dev/dm-3 -> /dev/mapper/sil_ahbgadcbchfc3
619                 devpath=$(dm_node "$devpath")
620         fi
621
622         if [ -L "$devpath" ] && ! is_lvm "$devpath" && ! is_luks "$devpath"; then
623                 # sanitize things like:
624                 # /dev/block/104:2 -> /dev/cciss/c0d0p2
625                 devpath=$(readlink -f "$devpath")
626         fi
627
628         verbose "Finding modules for device path $devpath"
629
630         if is_luks "$devpath"; then
631                 find_modules_luks "$devpath"
632                 return
633         fi
634
635         if is_nfs "$devpath"; then
636                 find_modules_nfs "$devpath"
637                 return
638         fi
639
640         if is_md "$devpath"; then
641                 find_modules_md "$devpath"
642                 return
643         fi
644
645         if is_multipath "$devpath"; then
646                 if find_modules_multipath "$devpath"; then
647                         return
648                 fi
649
650                 # fallback
651         fi
652
653         if is_dmraid "$devpath"; then
654                 if find_modules_dmraid "$devpath"; then
655                         return
656                 fi
657                 # fallback
658         fi
659
660         if is_scsi "$devpath"; then
661                 find_modules_scsi "$devpath"
662                 return
663         fi
664
665         if is_ide "$devpath"; then
666                 find_modules_ide "$devpath"
667                 return
668         fi
669
670         if [[ "$devpath" == /dev/bcache* ]]; then
671                 find_modules_bcache "$devpath"
672                 return
673         fi
674
675         if [[ "$devpath" == /dev/rd/* ]]; then
676                 find_module "DAC960"
677                 rootdev_add=/dev/rd/
678                 return
679         fi
680
681         if [[ "$devpath" == /dev/ida/* ]]; then
682                 find_module "cpqarray"
683                 rootdev_add=/dev/ida/
684                 return
685         fi
686
687         if [[ "$devpath" == /dev/cciss/* ]]; then
688                 rootdev_add=/dev/cciss/
689
690                 # load hpsa for future kernels, cciss for backwards compat
691                 if [ "$kernel_version_long" -ge "003000000" ]; then
692                         find_module "hpsa" "-cciss"
693                         find_modules_scsi "$devpath"
694                 else
695                         find_module "cciss"
696                 fi
697
698                 return
699         fi
700
701         if [[ "$devpath" == /dev/ataraid/* ]]; then
702                 find_modules_ide
703                 find_module "ataraid"
704                 ataraidmodules=$(modprobe_conf | awk '/ataraid_hostadapter/ { print $3 }')
705                 if [ -n "$ataraidmodules" ]; then
706                         # FIXME: think about modules compiled in kernel
707                         die "ataraid_hostadapter alias not defined in modprobe.conf! Please set it and run $PROGRAM again."
708                 fi
709                 for n in $ataraidmodules; do
710                         find_module "$n"
711                 done
712                 rootdev_add=/dev/ataraid/
713                 return
714         fi
715
716         # check to see if we need to set up a loopback filesystem
717         if [[ "$devpath" == /dev/loop*  ]]; then
718                 die "Sorry, root on loop device isn't supported."
719                 # TODO: rewrite for bsp and make nfs ready
720                 if [ ! -x /sbin/losetup ]; then
721                         die "losetup is missing"
722                 fi
723                 key="^# $(echo $devpath | awk -F/ '{print($3);}' | tr '[a-z]' '[A-Z]'):"
724                 if ! is_yes "`awk '/'$key'/ { print( "yes"); }' $fstab`"; then
725                         die "The root filesystem is on a $devpath, but there is no magic entry in $fstab for this device. Consult the $PROGRAM man page for more information"
726                 fi
727
728                 line="`awk '/'$key'/ { print $0; }' $fstab`"
729                 loopDev="$(echo $line | awk '{print $3}')"
730                 loopFs="$(echo $line | awk '{print $4}')"
731                 loopFile="$(echo $line | awk '{print $5}')"
732
733                 BASICMODULES="$BASICMODULES -loop"
734                 find_module "-$loopFs"
735                 BASICMODULES="$BASICMODULES -${loopFs}"
736                 return
737         fi
738
739         if is_lvm "$devpath"; then
740                 find_modules_lvm "$devpath"
741                 return
742         fi
743 }
744
745 firmware_install_module() {
746         local module="$1"
747         local firmware_files="$2"
748
749         verbose "Adding Firmwares ($firmware_files) to initrd for module $module"
750         # firmware not yet installed
751         if [ ! -f "$DESTDIR/lib/firmware/firmware.sh" ]; then
752                 inst_d /lib/firmware
753 cat << 'EOF' >> "$DESTDIR/lib/firmware/firmware.sh"
754 #!/bin/sh -e
755 # handle only firmware add requests
756 if [ "$SUBSYSTEM" != "firmware" ]; then
757         exit 0
758 fi
759 if [ "$ACTION" != "add" ]; then
760         exit 0
761 fi
762 echo 1 > /sys$DEVPATH/loading
763 cat "/lib/firmware/$FIRMWARE" > /sys$DEVPATH/data
764 echo 0 > /sys$DEVPATH/loading
765 exit 0
766 EOF
767                 chmod 755 "$DESTDIR/lib/firmware/firmware.sh"
768
769                 # setup firmware loader agent
770                 echo "echo -n "/lib/firmware/firmware.sh" > /proc/sys/kernel/hotplug" | add_linuxrc
771         fi
772
773         for firmware in $firmware_files; do
774                 if [ -f "/lib/firmware/$kernel/$firmware" ]; then
775                         FIRMWAREDIR=${firmware%/*}
776                         [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
777                         inst /lib/firmware/$kernel/$firmware /lib/firmware/$firmware
778                 elif [ -f "/lib/firmware/$firmware" ]; then
779                         FIRMWAREDIR=${firmware%/*}
780                         [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
781                         inst /lib/firmware/$firmware /lib/firmware/$firmware
782                 else
783                         warn "Possible missing firmware file /lib/firmware/$firmware or /lib/firmware/$kernel/$firmware for module $module."
784                 fi
785         done
786
787         mount_sys
788 }
789
790 modules_install() {
791         local modules="$1"
792         local mod
793
794         for mod in $modules; do
795                 MODULEDIR=${mod%/*}
796                 inst_d "/lib/modules/$kernel/$MODULEDIR"
797                 cp -a "/lib/modules/$kernel/$mod" "$DESTDIR/lib/modules/$kernel/$mod"
798                 case $mod in
799                         *.gz)
800                                 gunzip "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress gz"
801                                 mod=${mod%.gz}
802                                 ;;
803                         *.xz)
804                                 xz -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress xz"
805                                 mod=${mod%.xz}
806                                 ;;
807                         *.bz2)
808                                 bzip2 -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress bz2"
809                                 mod=${mod%.bz2}
810                                 ;;
811                 esac
812                 if [ "$STRIP" ] && [ -x "$STRIP" ]; then
813                         $STRIP -g --remove-section=.comment "$DESTDIR/lib/modules/$kernel/${mod}"
814                 fi
815         done
816 }
817
818 modules_add_linuxrc() {
819         local mod modpath
820
821         for mod in "$@"; do
822                 # module path without optional compression
823                 modpath=${mod%.gz}
824                 modpath=${modpath%.xz}
825                 modpath=${modpath%.bz2}
826
827                 # name of the module
828                 local module=${modpath##*/}; module=${module%$modext}
829                 local options=$(modprobe_options "$module")
830                 local genericname=$(echo $module | tr - _)
831                 local usleep=$(eval echo \$MODULE_${genericname}_USLEEP)
832                 local firmware=$(eval echo \$MODULE_${genericname}_FIRMWARE)
833
834                 if [ "$module" = "scsi_mod" -a "$kernel_version_long" -ge "002006030" ]; then
835                         options="scan=sync $options"
836                 fi
837
838                 if [ x"$verbose" = x"-v" ]; then
839                         s=""
840                         if [ "$options" ]; then
841                                 s="$s with options [$options]"
842                         fi
843                         if [ "$usleep" ]; then
844                                 s="$s and $usleep usleep"
845                         fi
846                         verbose "Loading module [$module]$s"
847                 fi
848
849                 if [ -n "$firmware" ]; then
850                         firmware_install_module "$module" "$firmware"
851                 else
852                         for file in $(find_firmware "$module"); do
853                                 firmware_install_module "$module" "$file"
854                         done
855                 fi
856
857                 echo "insmod /lib/modules/$kernel/$modpath $options" | add_linuxrc
858                 if [ -n "$usleep" ]; then
859                         echo "usleep $usleep" | add_linuxrc
860                 fi
861                 if [ "$module" = "scsi_wait_scan" ]; then
862                         if [ "$(busybox_applet rmmod 2>/dev/null; echo $?)" = 0 ]; then
863                                 echo "rmmod scsi_wait_scan" | add_linuxrc
864                         fi
865                 fi
866
867         done
868 }
869
870 # Generates /dev nodes based on /proc/partitions information.
871 # Needs /proc mounted.
872 # Can be called multiple times.
873 initrd_gen_devices() {
874         if is_yes "$proc_partitions"; then
875                 return
876         fi
877         proc_partitions=yes
878
879         mount_dev
880         add_linuxrc <<-'EOF'
881                 : 'Making device nodes'
882                 cat /proc/partitions | (
883                         # ignore first two lines: header, empty line
884                         read b; read b
885
886                         while read major minor blocks dev rest; do
887                                 node=/dev/$dev
888                                 mkdir -p ${node%/*}
889                                 [ -e $node ] || mknod -m 660 $node b $major $minor
890                         done
891                 )
892         EOF
893 }
894
895
896 initrd_gen_setrootdev() {
897         verbose "Adding rootfs finding based on kernel cmdline root= option support."
898         busybox_applet ls
899         debug "Current /proc/partitions:\n$(sed -e 's,^,| ,' /proc/partitions)"
900         add_linuxrc <<-'EOF'
901                 if [ "${ROOT##/dev/}" != "${ROOT}" ]; then
902                         rootnr="$(busybox awk -v rootnode="${ROOT##/dev/}" '$4 == rootnode { print 256 * $1 + $2 }' /proc/partitions)"
903                         # fallback to ls, try two different formats
904                         # http://lists.pld-linux.org/mailman/pipermail/pld-devel-en/2014-May/023915.html
905                         if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
906                                 # busybox up to 1.22
907                                 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $3 + $4; }}')"
908                         fi
909                         if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
910                                 # busybox 1.22 and upwards
911                                 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $5 + $6; }}')"
912                         fi
913                         if [ "${rootnr:-0}" -gt 0 ]; then
914                                 echo "$rootnr" > /proc/sys/kernel/real-root-dev
915                         fi
916                 fi
917         EOF
918 }
919
920 initrd_gen_initramfs_switchroot() {
921         inst_d /newroot
922         if [ "$rootdev" = "/dev/nfs" ]; then
923                 echo "rootfs on NFS root=/dev/nfs"
924         else
925                 [ ! -e "$DESTDIR/$rootdev" ] && inst $rootdev $rootdev
926         fi
927
928         # parse 'root=xxx' kernel commandline
929         # We support passing root as hda3 /dev/hda3 0303 0x0303 and 303
930
931         # from lilo-23.2/readme/README:
932         # root=<device> changes the root device. This overrides settings that may
933         # have been made in the boot image and on the LILO command line. <device> is
934         # either the hexadecimal device number or the full path name of the device,
935         # e.g. /dev/hda3 [*]
936         #
937         #  *  The device names are hard-coded in the kernel. Therefore, only the
938         #         "standard" names are supported and some less common devices may not be
939         #         recognized. In those cases, only numbers can be used.
940         busybox_applet cat
941         add_linuxrc <<-'EOF'
942                 device=
943                 eval "$(busybox awk -v root="$ROOT" '
944                         function h2d(str, hstr, res, num, n, digit, i) {        # http://9fans.net/archive/2006/09/261
945                                 hstr = "0123456789abdcef"; res = 0;
946                                 n = split(tolower(str), digit, "");
947
948                                 for (i = 1; i <= n; i++) {
949                                         num = index(hstr, digit[i]) - 1;
950                                         res = res + (num * 16 ^ (n - i));
951                                 }
952                                 return res;
953                         }
954                         BEGIN {
955                                 num_pattern_short = "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]";
956                                 num_pattern = "[0-9a-fA-F]" num_pattern_short;
957                                 dev_pattern = "[hms][a-z][a-z]([0-9])+";
958                                 partition = ""; min = -1; maj = -1;
959
960                                 if (root ~ "^\/dev\/" dev_pattern "$" || root ~ "^" dev_pattern "$") {  # see if we have /dev/hdX or hdX, we can just take partition name
961                                         partition = root; sub("^/dev/", "", partition);
962                                 } else {        # unify values first
963                                         if (root ~ "^" num_pattern_short "$")  {        # change "303" => "0x0303"
964                                                 root = "0x0" root
965                                         } else if (root ~ "^" num_pattern "$")  {       # change "0303" => "0x0303"
966                                                 root = "0x" root
967                                         }
968                                         maj = h2d(substr(root, 3, 2));
969                                         min = h2d(substr(root, 5, 2));
970                                 }
971                         }
972                         partition && $4 == partition { maj = $1; min = $2; }
973                         $1 == maj && $2 == min { partition = $4; }
974                         END {
975                                 if (maj >= 0 && min >= 0) {     printf("maj=%s; min=%s;\n", maj, min);  }
976                                 if (partition) {                printf("device=/dev/%s;\n", partition); }
977                         }' /proc/partitions)"
978
979                 if [ -z "$device" ]; then
980                         if [ "$DEBUGINITRD" -a "$DEBUGINITRD" != 'sh' ]; then
981                                 cat /proc/partitions
982                         fi
983                         device=$ROOT
984                 fi
985
986                 if [ "$device" -a ! -b $device -a "$maj$min" ]; then
987                         mknod -m 660 $device b $maj $min
988                 fi
989
990                 # XXX hack, fallback to rootdev from geninitrd time
991                 if [ ! -e "$device" ]; then
992         EOF
993         add_linuxrc <<-EOF
994                         device="$rootdev"
995         EOF
996         add_linuxrc <<-'EOF'
997                         echo "DEVICE set to $device based on fstab entry from initrd gen time"
998                 fi
999
1000                 # XXX hack, if no device, try to parse it from /proc/partitions using /proc/sys/kernel/real-root-dev
1001                 if [ ! -e "$device" ]; then
1002                         rrd=$(cat /proc/sys/kernel/real-root-dev)
1003                         major=$(($rrd / 256))
1004                         minor=$(($rrd % 256))
1005
1006                         while read pmajor pminor blocks dev rest; do
1007                                 # skip header and empty line
1008                                 [ -z "$pmajor" -o "$pmajor" = "major" ] && continue
1009
1010                                 if [ $pmajor = $major -a $pminor = $minor ]; then
1011                                         device=/dev/$dev
1012                                         echo "DEVICE set to $device based on real-root-dev"
1013                                 fi
1014                         done < /proc/partitions
1015                 fi
1016
1017                 [ -n "$ROOTFLAGS" ] && ROOTFLAGS="-o $ROOTFLAGS"
1018
1019                 mount -t $ROOTFS -r $device $ROOTFLAGS /newroot || echo "Mount of rootfs failed."
1020                 init=$INIT
1021                 if [ -z "$init" -o ! -x "/newroot$init" ]; then
1022                         init=/sbin/init
1023                 fi
1024         EOF
1025
1026         busybox_applet dmesg
1027         busybox_applet tail
1028         add_linuxrc <<-'EOF'
1029                 if [ "$DEBUGINITRD" -a "$DEBUGINITRD" != 'sh' ]; then
1030                         echo "Last 20 lines of dmesg:"
1031                         dmesg | tail -n 20
1032                 fi
1033
1034         EOF
1035
1036         kmsg "geninitrd/$VERSION switching root"
1037
1038         umount_all
1039         busybox_applet switch_root usleep
1040         add_linuxrc <<-'EOF'
1041                 [ ! -e /newroot/dev/console ] && mknod -m 660 /newroot/dev/console c 5 1
1042
1043                 # switch root to empty dir will make kernel panic, so sleep 10s before it
1044                 # switch_root needs to be pid 1, so there's no other way to recover from here
1045                 # if /dev is missing, switch root will likely fail, give debug shell before that
1046                 if [ ! -d /newroot/dev ]; then
1047                         echo "/dev is missing, switch_root will likely fail"
1048                         echo "if you booted with debugrd=sh, then you be given shell and you might able to recover this situation"
1049                         debugshell
1050                         [ "$DEBUGINITRD" ] || usleep 10000000
1051                 fi
1052
1053                 # systemd[1]: /usr appears to be on its own filesytem and is not
1054                 # already mounted. This is not a supported setup. Some things will
1055                 # probably break (sometimes even silently) in mysterious ways. Consult
1056                 # http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken
1057                 # for more information.
1058                 echo trying to mount /usr
1059                 chroot /newroot mount -n /usr
1060
1061                 exec switch_root /newroot $init ${1:+"$@"}
1062
1063                 # FIXME: this code is never executed, as "exec" does not return!
1064
1065                 echo "Error! initramfs should not reach this place."
1066                 echo "It probably means you've got old version of busybox, with broken"
1067                 echo "initramfs support. Trying to boot anyway, but won't promise anything."
1068
1069                 exec chroot /newroot $init ${1:+"$@"}
1070
1071                 echo "Failed to chroot!"
1072                 debugshell
1073         EOF
1074         # we need /init being real file, not symlink, otherwise the initramfs will
1075         # not be ran by pid 1 which is required for switch_root
1076         mv $DESTDIR/linuxrc $DESTDIR/init
1077         ln -s init $DESTDIR/linuxrc
1078 }
1079
1080 # find if $symbol exists in System.map $mapfile
1081 sym_exists() {
1082         local mapfile="$1"
1083         local symbol="$2"
1084         if [ ! -f $mapfile ]; then
1085                 # missing mapfile (not a pld kernel?)
1086                 return 1
1087         fi
1088
1089         awk -vc=1 -vsymbol="$symbol" '($2 == "T" || $2 == "t") && $3 == symbol {c = 0} END {exit c}' $mapfile
1090 }
1091
1092 # find best compressor (or forced one) for initrd
1093 find_compressor() {
1094         local mode="$1"
1095         local compressors='zstd xz lzma bzip2 gzip lzo'
1096
1097         # a specified one, take it
1098         if ! is_yes "$mode"; then
1099                 compressors="$mode"
1100         fi
1101
1102         verbose "finding compressor: $compressors (via $mode)"
1103         # check for compressor validity
1104         local c prog map=/boot/System.map-$kernel
1105         for c in $compressors; do
1106                 case $c in
1107                 xz)
1108                         sym=unxz
1109                         prog=/usr/bin/xz
1110                         ;;
1111                 lzma)
1112                         sym=unlzma
1113                         prog=/usr/bin/xz
1114                         ;;
1115                 bzip2)
1116                         sym=bzip2
1117                         prog=/usr/bin/bzip2
1118                         ;;
1119                 gzip)
1120                         sym=gunzip
1121                         prog=/bin/gzip
1122                         ;;
1123                 lzo)
1124                         sym=unlzo
1125                         prog=/usr/bin/lzop
1126                         ;;
1127                 zstd)
1128                         sym=zstd
1129                         prog=/usr/bin/zstd
1130                         ;;
1131                 none|no)
1132                         # any existing sym will work
1133                         sym=initrd_load
1134                         prog=/bin/cat
1135                         ;;
1136                 *)
1137                         die "Unknown compressor $c"
1138                         ;;
1139                 esac
1140                 if sym_exists $map $sym && [ -x $prog ]; then
1141                         echo $c
1142                         return
1143                 fi
1144         done
1145
1146         verbose "using gzip for compressor (fallback)"
1147         echo gzip
1148 }
1149
1150 # compresses kernel image image
1151 # in function so we could retry with other compressor on failure
1152 compress_image() {
1153         local compressor="$1" IMAGE="$2" target="$3" tmp
1154         tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1155
1156         case "$compressor" in
1157         xz)
1158                 # don't use -9 here since kernel won't understand it
1159                 xz --format=xz --check=crc32 --lzma2=preset=6e,dict=1MiB < "$IMAGE" > "$tmp" || return $?
1160                 ;;
1161         lzma)
1162                 xz --format=lzma -9 < "$IMAGE" > "$tmp" || return $?
1163                 ;;
1164         bzip2)
1165                 bzip2 -9 < "$IMAGE" > "$tmp" || return $?
1166                 ;;
1167         gzip)
1168                 gzip -9 < "$IMAGE" > "$tmp" || return $?
1169                 ;;
1170         lzo)
1171                 lzop -9 < "$IMAGE" > "$tmp" || return $?
1172                 ;;
1173         zstd)
1174                 zstd -9 < "$IMAGE" > "$tmp" || return $?
1175                 ;;
1176         none|no)
1177                 cat < "$IMAGE" > "$tmp" || return $?
1178                 ;;
1179         esac
1180
1181         mv -f "$tmp" "$target"
1182 }
1183
1184 if [ -r /etc/sysconfig/geninitrd ]; then
1185         . /etc/sysconfig/geninitrd
1186 fi
1187
1188 if [ ! -f /proc/mounts ]; then
1189         warn "/proc filesystem not mounted, may cause wrong results or failure."
1190 fi
1191
1192 geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev tuxonice suspend fbsplash condecor bootsplash uvesafb nfs sata scsi usbkbd bcache
1193
1194 while [ $# -gt 0 ]; do
1195         case $1 in
1196         --fstab=*)
1197                 fstab=${1#--fstab=}
1198                 ;;
1199         --fstab)
1200                 fstab=$2
1201                 shift
1202                 ;;
1203         --modules-conf=*)
1204                 modulefile=${1#--modules-conf=}
1205                 ;;
1206         --modules-conf)
1207                 modulefile=$2
1208                 shift
1209                 ;;
1210         --with-bootsplash)
1211                 BOOT_SPLASH=yes
1212                 ;;
1213         --without-bootsplash)
1214                 BOOT_SPLASH=no
1215                 ;;
1216         --with-fbsplash)
1217                 FB_SPLASH=yes
1218                 ;;
1219         --without-fbsplash)
1220                 FB_SPLASH=no
1221                 ;;
1222         --with-fbcondecor)
1223                 FB_CON_DECOR=yes
1224                 ;;
1225         --without-fbcondecor)
1226                 FB_CON_DECOR=no
1227                 ;;
1228         --with-suspend)
1229                 USE_SUSPEND=yes
1230                 ;;
1231         --without-suspend)
1232                 USE_SUSPEND=no
1233                 ;;
1234         --with-suspend2 | --with-tuxonice)
1235                 USE_TUXONICE=yes
1236                 ;;
1237         --without-suspend2 | --without-tuxonice)
1238                 USE_TUXONICE=no
1239                 ;;
1240         --lvmversion=*)
1241                 LVMTOOLSVERSION=${1#--lvmversion=}
1242                 ;;
1243         --lvmtoolsversion=*)
1244                 LVMTOOLSVERSION=${1#--lvmtoolsversion=}
1245                 ;;
1246         --lvmtoolsversion|--lvmversion)
1247                 LVMTOOLSVERSION=$2
1248                 shift
1249                 ;;
1250         --without-udev)
1251                 USE_UDEV=no
1252                 ;;
1253         --with-udev)
1254                 USE_UDEV=yes
1255                 ;;
1256         --without-dmraid)
1257                 USE_DMRAID=no
1258                 ;;
1259         --without-multipath)
1260                 USE_MULTIPATH=no
1261                 ;;
1262         --with-multipath=*)
1263                 USE_MULTIPATH=${1#--with-multipath=}
1264                 ;;
1265         --without-blkid)
1266                 USE_BLKID=no
1267                 ;;
1268         --without-luks)
1269                 USE_LUKS=no
1270                 ;;
1271         --with=*)
1272                 BASICMODULES="$BASICMODULES ${1#--with=}"
1273                 ;;
1274         --with)
1275                 BASICMODULES="$BASICMODULES $2"
1276                 shift
1277                 ;;
1278         --version)
1279                 echo "$PROGRAM: version $VERSION"
1280                 exit 0
1281                 ;;
1282         -v)
1283                 if [ x"$verbose" = x"-v" ]; then
1284                         verbose="-v -v"
1285                 else
1286                         verbose="-v"
1287                 fi
1288                 exec 3>&1
1289                 ;;
1290         --compress)
1291                 COMPRESS=$2
1292                 ;;
1293         --compress=*)
1294                 COMPRESS="${1#--compress=}"
1295                 ;;
1296         --nocompress)
1297                 COMPRESS=no
1298                 ;;
1299         --nostrip)
1300                 STRIP=
1301                 ;;
1302         --strip=*)
1303                 STRIP="${1#--strip=}"
1304                 ;;
1305         --strip)
1306                 STRIP=$2
1307                 shift
1308                 ;;
1309         --ifneeded)
1310                 ifneeded=1
1311                 ;;
1312         -f)
1313                 force=1
1314                 ;;
1315         --preload=*)
1316                 PREMODS="$PREMODS ${1#--preload=}"
1317                 ;;
1318         --preload)
1319                 PREMODS="$PREMODS $2"
1320                 shift
1321                 ;;
1322         --fs=* | --fs)
1323                 die "--fs option is obsoleted. Use --initrdfs instead"
1324                 ;;
1325         --initrdfs=*)
1326                 INITRDFS=${1#--initrdfs=}
1327                 ;;
1328         --initrdfs)
1329                 INITRDFS=$2
1330                 shift
1331                 ;;
1332         --image-version)
1333                 img_vers=yes
1334                 ;;
1335         --ide-only-root)
1336                 ide_only_root="yes"
1337                 ;;
1338         *)
1339                 if [ -z "$target" ]; then
1340                         target="$1"
1341                 elif [ -z "$kernel" ]; then
1342                         kernel="$1"
1343                 else
1344                         usage
1345                         exit 1
1346                 fi
1347                 ;;
1348         esac
1349
1350         shift
1351 done
1352
1353 if [ -z "$target" -o -z "$kernel" ]; then
1354         usage
1355         exit 1
1356 fi
1357
1358 # main()
1359 if [ "$(id -u)" != 0 ]; then
1360         die "You need to be root to generate initrd"
1361 fi
1362
1363 for dir in libx32 lib64 lib; do
1364         initrd_dir=/usr/$dir/initrd
1365         if [ -d "$initrd_dir" ]; then
1366                 initrd_dirs="$initrd_dirs $initrd_dir"
1367         fi
1368 done
1369
1370 kernel_version=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d",$1,$2)}')
1371 kernel_version_long=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d%03d",$1,$2,$3)}')
1372
1373 verbose "# geninitrd $VERSION"
1374 debug "Using initrd_dir: $initrd_dir"
1375
1376 busybox=$(find_tool $initrd_dir/busybox $initrd_dir/initrd-busybox /bin/initrd-busybox) || die "Couldn't find busybox suitable for initrd"
1377
1378 # we setup mods after parsing command line args
1379 geninitrd_setup_mods
1380
1381 if [ ! -f /boot/vmlinuz-"$kernel" ]; then
1382         warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?"
1383 fi
1384
1385 if [ -z "$INITRDFS" ]; then
1386         if [ -n "$FS" ]; then
1387                 # FS= can came only via /etc/sysconfig/geninitrd likely?
1388                 die "FS configuration option is obsoleted. Use INITRDFS instead"
1389         fi
1390
1391         # default value
1392         if [ "$kernel_version" -ge "002005" ]; then
1393                 INITRDFS="initramfs"
1394         else
1395                 INITRDFS="rom"
1396         fi
1397 fi
1398
1399 check_initrd_fs() {
1400         local s sfound sym p prog map=/boot/System.map-$kernel
1401         case "$INITRDFS" in
1402                 ext2)
1403                         # TODO: symbols to check in case of ext2 used via ext3/4 subsystem
1404                         sym=init_ext2_fs
1405                         prog=/sbin/mke2fs
1406                         ;;
1407                 rom|romfs)
1408                         sym=init_romfs_fs
1409                         prog=/sbin/genromfs
1410                         ;;
1411                 cram|cramfs)
1412                         sym=init_cramfs_fs
1413                         prog=/sbin/mkcramfs
1414                         ;;
1415                 initramfs)
1416                         sym=__initramfs_start
1417                         prog="/bin/cpio /usr/bin/find"
1418                         ;;
1419                 *)
1420                         die "Filesystem $INITRDFS on initrd is not supported by geninitrd"
1421                         ;;
1422         esac
1423
1424         # only one is needed (for cases like ext2 via ext2 or via ext3 or via ext4 subsysytem)
1425         sfound=0
1426         for s in $sym; do
1427                 sym_exists $map $s && sfound=1
1428                 break
1429         done
1430         if [ "$sfound" -eq "0" ]; then
1431                 die "Filesystem $INITRDFS on initrd is not supported by kernel"
1432         fi
1433
1434         for p in $prog; do
1435                 [ ! -x "$p" ] && die "$prog is missing"
1436         done
1437 }
1438 check_initrd_fs
1439
1440 if [ -L "$target" ]; then
1441         target=$(readlink -f "$target")
1442 fi
1443
1444 if [ -n "$img_vers" ]; then
1445         target="$target-$kernel"
1446 fi
1447
1448 if [ -z "$force" -a -f "$target" ]; then
1449         die "$target already exists."
1450 fi
1451
1452 if [ ! -d "/lib/modules/$kernel" ]; then
1453         die "/lib/modules/$kernel is not a directory."
1454 fi
1455
1456 if [ "$kernel_version" -ge "002005" ]; then
1457         modext=".ko"
1458 fi
1459
1460 cache_modprobe_conf
1461
1462 for n in $PREMODS; do
1463         find_module "$n"
1464 done
1465
1466 if [ "$FBMODULE" ]; then
1467         find_module "$FBMODULE"
1468 fi
1469
1470 # autodetect USB keyboards
1471 find_modules_usbkbd
1472
1473 # allow forcing loading SCSI and/or IDE modules
1474 # XXX: where ADDSCSI cames from? drop?
1475 if is_yes "$ADDSCSI"; then
1476         find_modules_scsi
1477 fi
1478
1479 # autodetect SATA modules
1480 find_modules_sata
1481
1482 # XXX: where ADDIDE cames from? drop?
1483 if is_yes "$ADDIDE"; then
1484         find_modules_ide
1485 fi
1486
1487 if is_yes "$USE_SUSPEND"; then
1488         find_modules_suspend
1489 fi
1490
1491 find_root "$fstab" || exit
1492 verbose "Using $rootdev as device for rootfs"
1493
1494 find_modules_for_devpath "$rootdev"
1495
1496 # if USE_MULTIPATH is path to device, scan that too
1497 # this is to bootstrap multipath setup into initrd.
1498 if ! is_no "$USE_MULTIPATH" && ! is_yes "$USE_MULTIPATH"; then
1499         find_modules_multipath $USE_MULTIPATH
1500 fi
1501
1502 find_module "-$rootFs"
1503
1504 for n in $BASICMODULES; do
1505         find_module "$n"
1506 done
1507
1508 if is_yes "$USE_TUXONICE"; then
1509         find_module "-lzf"
1510 fi
1511
1512 find_modules_uvesafb
1513 find_modules_fbsplash
1514
1515 if [ -n "$ifneeded" -a -z "$MODULES" ]; then
1516         verbose "No modules are needed -- not building initrd image."
1517         exit 0
1518 fi
1519
1520 verbose "Building initrd..."
1521 DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
1522 RCFILE="$DESTDIR/linuxrc"
1523 > "$RCFILE"
1524 chmod a+rx "$RCFILE"
1525 ln -s linuxrc $DESTDIR/init
1526
1527 # create dirs that we really need
1528 inst_d /{lib,bin,etc,dev{,/pts,/shm},loopfs,var,proc,run,sys}
1529
1530 modules_install "$MODULES"
1531
1532 # mknod'ing the devices instead of copying them works both with and
1533 # without devfs...
1534 mknod -m 600 "$DESTDIR/dev/console" c 5 1
1535 mknod -m 666 "$DESTDIR/dev/null" c 1 3
1536 mknod -m 666 "$DESTDIR/dev/zero" c 1 5
1537 mknod -m 666 "$DESTDIR/dev/random" c 1 8
1538 mknod -m 666 "$DESTDIR/dev/urandom" c 1 9
1539 mknod -m 644 "$DESTDIR/dev/kmsg" c 1 11
1540
1541 inst_exec $busybox /bin/busybox
1542 ln -s busybox $DESTDIR/bin/sh
1543 # for older busyboxes who had /bin/initrd-busybox as EXEPATH
1544 ln -s busybox $DESTDIR/bin/initrd-busybox
1545
1546 add_linuxrc <<EOF
1547 #!/bin/sh
1548 # initrd generated by geninitrd/$VERSION
1549 # on $(LC_ALL=C date)
1550
1551 EOF
1552 load_font
1553 mount_proc
1554
1555 kmsg "geninitrd/$VERSION starting"
1556
1557 add_linuxrc <<-EOF
1558         # builtin defaults from geninitrd
1559         ROOT=$rootdev
1560         ROOTFS=$rootFs
1561 EOF
1562 add_linuxrc <<-'EOF'
1563         read CMDLINE < /proc/cmdline
1564
1565         for arg in $CMDLINE; do
1566                 if [ "${arg}" = "debuginitrd" ] || [ "${arg}" = "debugrd" ]; then
1567                         DEBUGINITRD=yes
1568                 fi
1569                 if [ "${arg##debuginitrd=}" != "${arg}" ] || [ "${arg##debugrd=}" != "${arg}" ]; then
1570                         DEBUGINITRD=${arg##debug*rd=}
1571                 fi
1572                 if [ "${arg##root=}" != "${arg}" ]; then
1573                         ROOT=${arg##root=}
1574                 fi
1575                 if [ "${arg##rootfs=}" != "${arg}" ]; then
1576                         ROOTFS=${arg##rootfs=}
1577                 fi
1578                 if [ "${arg##rootflags=}" != "${arg}" ]; then
1579                         ROOTFLAGS=${arg##rootflags=}
1580                 fi
1581                 if [ "${arg##rootfsflags=}" != "${arg}" ]; then
1582                         ROOTFSFLAGS=${arg##rootfsflags=}
1583                 fi
1584                 if [ "${arg##init=}" != "${arg}" ]; then
1585                         INIT=${arg##init=}
1586                 fi
1587         done
1588
1589         # handling of invalid, rootfsflags, option
1590         if [ -n "$ROOTFSFLAGS" ]; then
1591                 if [ -n "$ROOTFLAGS" ]; then
1592                         ROOTFLAGS="$ROOTFLAGS,$ROOTFSFLAGS"
1593                 else
1594                         ROOTFLAGS="$ROOTFSFLAGS"
1595                 fi
1596         fi
1597
1598         if [ "$DEBUGINITRD" = "sh" ]; then
1599                 # export some vars to subshell for debug to work
1600                 export CMDLINE ROOT ROOTFS ROOTDEV ROOTFLAGS DEBUGINITRD INIT
1601                 export LVM_ROOTVG LVM_SUSPENDVG LVM_VGVOLUMES
1602                 export rootnr attrs majmin major minor device
1603
1604                 # make debugshell() invoke subshell if $DEBUGINITRD=sh
1605                 debugshell() {
1606 EOF
1607 if is_yes "$RUN_SULOGIN_ON_ERR"; then
1608 add_linuxrc <<-'EOF'
1609         echo "debug shell disabled by RUN_SULOGIN_ON_ERR=yes from /etc/sysconfig/system during initrd generation time"
1610 EOF
1611 else
1612 add_linuxrc <<-'EOF'
1613         sh
1614 EOF
1615 fi
1616 add_linuxrc <<-'EOF'
1617                 }
1618         else
1619                 debugshell() {
1620                         :
1621                 }
1622         fi
1623
1624         if [ "$DEBUGINITRD" ]; then
1625                 set -x
1626         fi
1627 EOF
1628
1629 modules_add_linuxrc $MODULES
1630
1631 # TODO: rewrite for busybox
1632 #if [ -n "$loopDev" ]; then
1633 #       if [ ! -d /initrd ]; then
1634 #               mkdir /initrd
1635 #       fi
1636 #
1637 #       cp -a "$loopDev" "$DESTDIR/dev"
1638 #       cp -a "$rootdev" "$DESTDIR/dev"
1639 #       echo "echo Mounting device containing loopback root filesystem" >> "$RCFILE"
1640 #       echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE"
1641 #       echo "echo Setting up loopback device $rootdev" >> $RCFILE
1642 #       echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE"
1643 #fi
1644
1645 if is_yes "$USE_UDEV"; then
1646         initrd_gen_udev
1647 else
1648         initrd_gen_mdev
1649 fi
1650
1651 initrd_gen_uvesafb
1652 initrd_gen_luks
1653 initrd_gen_dmraid
1654 initrd_gen_multipath
1655 initrd_gen_blkid
1656
1657 if is_yes "$have_nfs"; then
1658         initrd_gen_nfs
1659 else
1660         initrd_gen_md
1661         initrd_gen_lvm
1662         initrd_gen_bcache
1663         initrd_gen_blkid
1664         initrd_gen_luks
1665         initrd_gen_setrootdev
1666 fi
1667
1668 # additional devs always needed
1669 [ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev
1670
1671 initrd_gen_stop_udevd
1672 initrd_gen_stop_mdev
1673 initrd_gen_stop_uvesafb
1674
1675 # resume after killing local processes
1676 initrd_gen_tuxonice
1677 initrd_gen_suspend
1678
1679 # clean up env
1680 add_linuxrc <<-'EOF'
1681 if [ ! "$DEBUGINITRD" ]; then
1682         ifs=$IFS
1683         IFS="
1684         "
1685         for i in $(export -p); do
1686                 i=${i#declare -x } # ksh/bash
1687                 i=${i#export } # busybox
1688
1689                 case "$i" in
1690                 *=*)
1691                         : ;;
1692                 *)
1693                         continue ;;
1694                 esac
1695
1696                 i=${i%%=*}
1697
1698                 [ -z "$i" ] && continue
1699
1700                 case "$i" in
1701                         ROOT|PATH|HOME|TERM)
1702                                 :
1703                                 ;;
1704                         *)
1705                                 unset $i
1706                                 ;;
1707                 esac
1708         done
1709         IFS=$ifs
1710 fi
1711 EOF
1712
1713 if [ "$INITRDFS" = "initramfs" ]; then
1714         initrd_gen_initramfs_switchroot
1715 else
1716         umount_all
1717 fi
1718
1719 initrd_gen_fbsplash
1720 initrd_gen_fbcondecor
1721
1722 debug "Current /linuxrc:\n$(sed -e 's,^,| ,' $DESTDIR/linuxrc)"
1723
1724 IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed"
1725
1726 IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
1727 verbose "image size: $IMAGESIZE KiB ($DESTDIR)"
1728
1729 verbose "Creating $INITRDFS image $IMAGE"
1730 case "$INITRDFS" in
1731   ext2)
1732         dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null
1733         # NOTE: ext2 label is max 16 chars
1734         mke2fs -q -F -b 1024 -m 0 -L "PLD/$kernel" "$IMAGE" 2>/dev/null 1>&2
1735         tune2fs -i 0 "$IMAGE" >/dev/null 2>&1
1736
1737         local tmpmnt=$(mktemp -d -t initrd.mnt-XXXXXX)
1738         debug "Mounting ext2 image $IMAGE to $tmpmnt"
1739         mount -o loop -t ext2 "$IMAGE" "$tmpmnt" || die "mount failed, check dmesg(1)"
1740         # We don't need this directory, so let's save space
1741         rm -rf "$tmpmnt"/lost+found
1742
1743         debug "Copy recursively $DESTDIR -> $tmpmnt"
1744         cp -a $DESTDIR/* $tmpmnt
1745         umount "$IMAGE"
1746         rmdir "$tmpmnt"
1747
1748         ;;
1749   rom|romfs)
1750         genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD Linux/$kernel (geninitrd/$VERSION)"
1751         ;;
1752   cram|cramfs)
1753         mkcramfs "$DESTDIR" "$IMAGE"
1754         ;;
1755   initramfs)
1756         (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
1757         ;;
1758   *)
1759         die "Filesystem $INITRDFS not supported by $PROGRAM"
1760 esac
1761
1762 CONFIG_BLK_DEV_RAM_SIZE=$(ikconfig | awk -F= '/^CONFIG_BLK_DEV_RAM_SIZE/{print $2}')
1763 if [ -z "$CONFIG_BLK_DEV_RAM_SIZE" ]; then
1764         CONFIG_BLK_DEV_RAM_SIZE=4096
1765         warn "No CONFIG_BLK_DEV_RAM_SIZE detected, fallback to $CONFIG_BLK_DEV_RAM_SIZE"
1766 fi
1767
1768 if [ "$IMAGESIZE" -gt $CONFIG_BLK_DEV_RAM_SIZE ]; then
1769         warn "Your image size is larger than $CONFIG_BLK_DEV_RAM_SIZE, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!"
1770 fi
1771
1772 if ! is_no "$COMPRESS"; then
1773         compressor=$(find_compressor "$COMPRESS")
1774         verbose "Compressing $target with $compressor"
1775
1776         # TODO: the image name (specified from kernel.spec) already contains
1777         # extension, which is .gz most of the time.
1778         compress_image "$compressor" "$IMAGE" "$target" || {
1779                 if [ $compressor != gzip ]; then
1780                         warn "Could not compress with $compressor, retrying with gzip"
1781                         compress_image gzip "$IMAGE" "$target" || die "compress failed with gzip" $?
1782                 else
1783                         die "Could not compress image with $compressor"
1784                 fi
1785         }
1786 else
1787         cp -a "$IMAGE" "$target"
1788 fi
1789
1790 # XXX. check if bootsplash can output data to tmp dir not directly to initramfs image.
1791 initrd_gen_bootsplash "$target"
1792
1793 rm -rf "$DESTDIR" "$IMAGE"
1794
1795 # vim:ts=4:sw=4:noet:fdm=marker
This page took 0.566031 seconds and 4 git commands to generate.