]> git.pld-linux.org Git - projects/geninitrd.git/blob - geninitrd
Timeout here is not a good idea. rootfs cannot be mounted and kernel oopses due to...
[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 libs_additional 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                         ;;
547                     /lib/libpthread.so* | /lib64/libpthread.so* | /libx32/libpthread.so*)
548                                 libs_additional="${obj%/libpthread*}/libgcc_s.so.1"
549                         ;;
550                 esac
551
552
553                 libs=$(ldd "$obj" | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
554                 for lib in $libs $libs_additional; do
555                         libdir=$(cd $(dirname "$lib"); pwd)
556                         if [ ! -f "$DESTDIR/$lib" ]; then
557                                 inst_d $libdir
558                                 inst_exec $lib $libdir
559                         fi
560                 done
561         done
562
563         # hack for uclibc linked binaries requiring this fixed path
564         # XXX: shouldn't rpath be used here instead so th
565         for _lib in $(get_libdir LIBDIR); do
566                 if [ -f $DESTDIR/$_lib/libc.so.0 ]; then
567                         lib=$DESTDIR/$_lib/libc.so.0
568                         lib=$(ldd "$lib" | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
569                         libdir=$(cd $(dirname "$lib"); pwd)
570                         if [ ! -e $DESTDIR$libdir ]; then
571                                 libdir=$(dirname "$libdir")
572                                 inst_d $libdir
573                                 verbose "+ ln -s /$_lib $DESTDIR$libdir"
574                                 ln -s /$_lib $DESTDIR$libdir
575                                 break
576                         fi
577                 fi
578         done
579 }
580
581 # output modules.conf / modprobe.conf
582 modprobe_conf() {
583         echo "$modprobe_conf_cache"
584 }
585
586 # return options for MODULE
587 # @param $1 module name
588 modprobe_options() {
589         local module=$1
590         local options=$(modprobe_conf | awk -vmodule="$module" '{ if ($1 == "options" && $2 == module) { for(i=3;i<=NF;i++) printf("%s ",$i); }}')
591         echo ${options# }
592 }
593
594 #
595 # defaults to modprobe -c if not told otherwise, this means include statements
596 # work from there.
597 cache_modprobe_conf() {
598         if [ "$kernel_version" -lt "002005" ]; then
599                 modulefile=/etc/modules.conf
600                 if [ ! -f "$modulefile" -a -f /etc/conf.modules ]; then
601                         modulefile=/etc/conf.modules
602                 fi
603         fi
604
605         if [ -n "$modulefile" ]; then
606                 debug "Using $modulefile for modules config"
607                 modprobe_conf_cache=$(cat $modulefile | awk '!/^[\t ]*#/ { print }')
608
609         else
610                 debug "Using modprobe -c to get modules config"
611                 modprobe_conf_cache=$(modprobe -c --set-version $kernel | awk '!/^[\t ]*#/ { print }')
612         fi
613 }
614
615 # find modules for $devpath
616 find_modules_for_devpath() {
617         local devpath="$1"
618         if [ -z "$devpath" ]; then
619                 die "No argument passed to find_modules_for_devpath() - is your /etc/fstab correct?"
620         fi
621
622         if [[ "$devpath" = /dev/dm-* ]]; then
623                 # /dev/dm-3 -> /dev/mapper/sil_ahbgadcbchfc3
624                 devpath=$(dm_node "$devpath")
625         fi
626
627         if [ -L "$devpath" ] && ! is_lvm "$devpath" && ! is_luks "$devpath"; then
628                 # sanitize things like:
629                 # /dev/block/104:2 -> /dev/cciss/c0d0p2
630                 devpath=$(readlink -f "$devpath")
631         fi
632
633         verbose "Finding modules for device path $devpath"
634
635         if is_luks "$devpath"; then
636                 find_modules_luks "$devpath"
637                 return
638         fi
639
640         if is_nfs "$devpath"; then
641                 find_modules_nfs "$devpath"
642                 return
643         fi
644
645         if is_md "$devpath"; then
646                 find_modules_md "$devpath"
647                 return
648         fi
649
650         if is_multipath "$devpath"; then
651                 if find_modules_multipath "$devpath"; then
652                         return
653                 fi
654
655                 # fallback
656         fi
657
658         if is_dmraid "$devpath"; then
659                 if find_modules_dmraid "$devpath"; then
660                         return
661                 fi
662                 # fallback
663         fi
664
665         if is_scsi "$devpath"; then
666                 find_modules_scsi "$devpath"
667                 return
668         fi
669
670         if is_ide "$devpath"; then
671                 find_modules_ide "$devpath"
672                 return
673         fi
674
675         if [[ "$devpath" == /dev/bcache* ]]; then
676                 find_modules_bcache "$devpath"
677                 return
678         fi
679
680         if [[ "$devpath" == /dev/rd/* ]]; then
681                 find_module "DAC960"
682                 rootdev_add=/dev/rd/
683                 return
684         fi
685
686         if [[ "$devpath" == /dev/ida/* ]]; then
687                 find_module "cpqarray"
688                 rootdev_add=/dev/ida/
689                 return
690         fi
691
692         if [[ "$devpath" == /dev/cciss/* ]]; then
693                 rootdev_add=/dev/cciss/
694
695                 # load hpsa for future kernels, cciss for backwards compat
696                 if [ "$kernel_version_long" -ge "003000000" ]; then
697                         find_module "hpsa" "-cciss"
698                         find_modules_scsi "$devpath"
699                 else
700                         find_module "cciss"
701                 fi
702
703                 return
704         fi
705
706         if [[ "$devpath" == /dev/ataraid/* ]]; then
707                 find_modules_ide
708                 find_module "ataraid"
709                 ataraidmodules=$(modprobe_conf | awk '/ataraid_hostadapter/ { print $3 }')
710                 if [ -n "$ataraidmodules" ]; then
711                         # FIXME: think about modules compiled in kernel
712                         die "ataraid_hostadapter alias not defined in modprobe.conf! Please set it and run $PROGRAM again."
713                 fi
714                 for n in $ataraidmodules; do
715                         find_module "$n"
716                 done
717                 rootdev_add=/dev/ataraid/
718                 return
719         fi
720
721         # check to see if we need to set up a loopback filesystem
722         if [[ "$devpath" == /dev/loop*  ]]; then
723                 die "Sorry, root on loop device isn't supported."
724                 # TODO: rewrite for bsp and make nfs ready
725                 if [ ! -x /sbin/losetup ]; then
726                         die "losetup is missing"
727                 fi
728                 key="^# $(echo $devpath | awk -F/ '{print($3);}' | tr '[a-z]' '[A-Z]'):"
729                 if ! is_yes "`awk '/'$key'/ { print( "yes"); }' $fstab`"; then
730                         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"
731                 fi
732
733                 line="`awk '/'$key'/ { print $0; }' $fstab`"
734                 loopDev="$(echo $line | awk '{print $3}')"
735                 loopFs="$(echo $line | awk '{print $4}')"
736                 loopFile="$(echo $line | awk '{print $5}')"
737
738                 BASICMODULES="$BASICMODULES -loop"
739                 find_module "-$loopFs"
740                 BASICMODULES="$BASICMODULES -${loopFs}"
741                 return
742         fi
743
744         if is_lvm "$devpath"; then
745                 find_modules_lvm "$devpath"
746                 return
747         fi
748 }
749
750 firmware_install_module() {
751         local module="$1"
752         local firmware_files="$2"
753
754         verbose "Adding Firmwares ($firmware_files) to initrd for module $module"
755         # firmware not yet installed
756         if [ ! -f "$DESTDIR/lib/firmware/firmware.sh" ]; then
757                 inst_d /lib/firmware
758 cat << 'EOF' >> "$DESTDIR/lib/firmware/firmware.sh"
759 #!/bin/sh -e
760 # handle only firmware add requests
761 if [ "$SUBSYSTEM" != "firmware" ]; then
762         exit 0
763 fi
764 if [ "$ACTION" != "add" ]; then
765         exit 0
766 fi
767 echo 1 > /sys$DEVPATH/loading
768 cat "/lib/firmware/$FIRMWARE" > /sys$DEVPATH/data
769 echo 0 > /sys$DEVPATH/loading
770 exit 0
771 EOF
772                 chmod 755 "$DESTDIR/lib/firmware/firmware.sh"
773
774                 # setup firmware loader agent
775                 echo "echo -n "/lib/firmware/firmware.sh" > /proc/sys/kernel/hotplug" | add_linuxrc
776         fi
777
778         for firmware in $firmware_files; do
779                 if [ -f "/lib/firmware/$kernel/$firmware" ]; then
780                         FIRMWAREDIR=${firmware%/*}
781                         [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
782                         inst /lib/firmware/$kernel/$firmware /lib/firmware/$firmware
783                 elif [ -f "/lib/firmware/$firmware" ]; then
784                         FIRMWAREDIR=${firmware%/*}
785                         [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
786                         inst /lib/firmware/$firmware /lib/firmware/$firmware
787                 else
788                         warn "Possible missing firmware file /lib/firmware/$firmware or /lib/firmware/$kernel/$firmware for module $module."
789                 fi
790         done
791
792         mount_sys
793 }
794
795 modules_install() {
796         local modules="$1"
797         local mod
798
799         for mod in $modules; do
800                 MODULEDIR=${mod%/*}
801                 inst_d "/lib/modules/$kernel/$MODULEDIR"
802                 cp -a "/lib/modules/$kernel/$mod" "$DESTDIR/lib/modules/$kernel/$mod"
803                 case $mod in
804                         *.gz)
805                                 gunzip "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress gz"
806                                 mod=${mod%.gz}
807                                 ;;
808                         *.xz)
809                                 xz -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress xz"
810                                 mod=${mod%.xz}
811                                 ;;
812                         *.bz2)
813                                 bzip2 -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress bz2"
814                                 mod=${mod%.bz2}
815                                 ;;
816                 esac
817                 if [ "$STRIP" ] && [ -x "$STRIP" ]; then
818                         $STRIP -g --remove-section=.comment "$DESTDIR/lib/modules/$kernel/${mod}"
819                 fi
820         done
821 }
822
823 modules_add_linuxrc() {
824         local mod modpath
825
826         for mod in "$@"; do
827                 # module path without optional compression
828                 modpath=${mod%.gz}
829                 modpath=${modpath%.xz}
830                 modpath=${modpath%.bz2}
831
832                 # name of the module
833                 local module=${modpath##*/}; module=${module%$modext}
834                 local options=$(modprobe_options "$module")
835                 local genericname=$(echo $module | tr - _)
836                 local usleep=$(eval echo \$MODULE_${genericname}_USLEEP)
837                 local firmware=$(eval echo \$MODULE_${genericname}_FIRMWARE)
838
839                 if [ "$module" = "scsi_mod" -a "$kernel_version_long" -ge "002006030" ]; then
840                         options="scan=sync $options"
841                 fi
842
843                 if [ x"$verbose" = x"-v" ]; then
844                         s=""
845                         if [ "$options" ]; then
846                                 s="$s with options [$options]"
847                         fi
848                         if [ "$usleep" ]; then
849                                 s="$s and $usleep usleep"
850                         fi
851                         verbose "Loading module [$module]$s"
852                 fi
853
854                 if [ -n "$firmware" ]; then
855                         firmware_install_module "$module" "$firmware"
856                 else
857                         for file in $(find_firmware "$module"); do
858                                 firmware_install_module "$module" "$file"
859                         done
860                 fi
861
862                 echo "insmod /lib/modules/$kernel/$modpath $options" | add_linuxrc
863                 if [ -n "$usleep" ]; then
864                         echo "usleep $usleep" | add_linuxrc
865                 fi
866                 if [ "$module" = "scsi_wait_scan" ]; then
867                         if [ "$(busybox_applet rmmod 2>/dev/null; echo $?)" = 0 ]; then
868                                 echo "rmmod scsi_wait_scan" | add_linuxrc
869                         fi
870                 fi
871
872         done
873 }
874
875 # Generates /dev nodes based on /proc/partitions information.
876 # Needs /proc mounted.
877 # Can be called multiple times.
878 initrd_gen_devices() {
879         if is_yes "$proc_partitions"; then
880                 return
881         fi
882         proc_partitions=yes
883
884         mount_dev
885         add_linuxrc <<-'EOF'
886                 : 'Making device nodes'
887                 cat /proc/partitions | (
888                         # ignore first two lines: header, empty line
889                         read b; read b
890
891                         while read major minor blocks dev rest; do
892                                 node=/dev/$dev
893                                 mkdir -p ${node%/*}
894                                 [ -e $node ] || mknod -m 660 $node b $major $minor
895                         done
896                 )
897         EOF
898 }
899
900
901 initrd_gen_setrootdev() {
902         verbose "Adding rootfs finding based on kernel cmdline root= option support."
903         busybox_applet ls
904         debug "Current /proc/partitions:\n$(sed -e 's,^,| ,' /proc/partitions)"
905         add_linuxrc <<-'EOF'
906                 if [ "${ROOT##/dev/}" != "${ROOT}" ]; then
907                         rootnr="$(busybox awk -v rootnode="${ROOT##/dev/}" '$4 == rootnode { print 256 * $1 + $2 }' /proc/partitions)"
908                         # fallback to ls, try two different formats
909                         # http://lists.pld-linux.org/mailman/pipermail/pld-devel-en/2014-May/023915.html
910                         if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
911                                 # busybox up to 1.22
912                                 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $3 + $4; }}')"
913                         fi
914                         if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
915                                 # busybox 1.22 and upwards
916                                 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $5 + $6; }}')"
917                         fi
918                         if [ "${rootnr:-0}" -gt 0 ]; then
919                                 echo "$rootnr" > /proc/sys/kernel/real-root-dev
920                         fi
921                 fi
922         EOF
923 }
924
925 initrd_gen_initramfs_switchroot() {
926         inst_d /newroot
927         if [ "$rootdev" = "/dev/nfs" ]; then
928                 echo "rootfs on NFS root=/dev/nfs"
929         else
930                 [ ! -e "$DESTDIR/$rootdev" ] && inst $rootdev $rootdev
931         fi
932
933         # parse 'root=xxx' kernel commandline
934         # We support passing root as hda3 /dev/hda3 0303 0x0303 and 303
935
936         # from lilo-23.2/readme/README:
937         # root=<device> changes the root device. This overrides settings that may
938         # have been made in the boot image and on the LILO command line. <device> is
939         # either the hexadecimal device number or the full path name of the device,
940         # e.g. /dev/hda3 [*]
941         #
942         #  *  The device names are hard-coded in the kernel. Therefore, only the
943         #         "standard" names are supported and some less common devices may not be
944         #         recognized. In those cases, only numbers can be used.
945         busybox_applet cat
946         add_linuxrc <<-'EOF'
947                 device=
948                 eval "$(busybox awk -v root="$ROOT" '
949                         function h2d(str, hstr, res, num, n, digit, i) {        # http://9fans.net/archive/2006/09/261
950                                 hstr = "0123456789abdcef"; res = 0;
951                                 n = split(tolower(str), digit, "");
952
953                                 for (i = 1; i <= n; i++) {
954                                         num = index(hstr, digit[i]) - 1;
955                                         res = res + (num * 16 ^ (n - i));
956                                 }
957                                 return res;
958                         }
959                         BEGIN {
960                                 num_pattern_short = "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]";
961                                 num_pattern = "[0-9a-fA-F]" num_pattern_short;
962                                 dev_pattern = "[hms][a-z][a-z]([0-9])+";
963                                 partition = ""; min = -1; maj = -1;
964
965                                 if (root ~ "^\/dev\/" dev_pattern "$" || root ~ "^" dev_pattern "$") {  # see if we have /dev/hdX or hdX, we can just take partition name
966                                         partition = root; sub("^/dev/", "", partition);
967                                 } else {        # unify values first
968                                         if (root ~ "^" num_pattern_short "$")  {        # change "303" => "0x0303"
969                                                 root = "0x0" root
970                                         } else if (root ~ "^" num_pattern "$")  {       # change "0303" => "0x0303"
971                                                 root = "0x" root
972                                         }
973                                         maj = h2d(substr(root, 3, 2));
974                                         min = h2d(substr(root, 5, 2));
975                                 }
976                         }
977                         partition && $4 == partition { maj = $1; min = $2; }
978                         $1 == maj && $2 == min { partition = $4; }
979                         END {
980                                 if (maj >= 0 && min >= 0) {     printf("maj=%s; min=%s;\n", maj, min);  }
981                                 if (partition) {                printf("device=/dev/%s;\n", partition); }
982                         }' /proc/partitions)"
983
984                 if [ -z "$device" ]; then
985                         if [ "$DEBUGINITRD" -a "$DEBUGINITRD" != 'sh' ]; then
986                                 cat /proc/partitions
987                         fi
988                         device=$ROOT
989                 fi
990
991                 if [ "$device" -a ! -b $device -a "$maj$min" ]; then
992                         mknod -m 660 $device b $maj $min
993                 fi
994
995                 # XXX hack, fallback to rootdev from geninitrd time
996                 if [ ! -e "$device" ]; then
997         EOF
998         add_linuxrc <<-EOF
999                         device="$rootdev"
1000         EOF
1001         add_linuxrc <<-'EOF'
1002                         echo "DEVICE set to $device based on fstab entry from initrd gen time"
1003                 fi
1004
1005                 # XXX hack, if no device, try to parse it from /proc/partitions using /proc/sys/kernel/real-root-dev
1006                 if [ ! -e "$device" ]; then
1007                         rrd=$(cat /proc/sys/kernel/real-root-dev)
1008                         major=$(($rrd / 256))
1009                         minor=$(($rrd % 256))
1010
1011                         while read pmajor pminor blocks dev rest; do
1012                                 # skip header and empty line
1013                                 [ -z "$pmajor" -o "$pmajor" = "major" ] && continue
1014
1015                                 if [ $pmajor = $major -a $pminor = $minor ]; then
1016                                         device=/dev/$dev
1017                                         echo "DEVICE set to $device based on real-root-dev"
1018                                 fi
1019                         done < /proc/partitions
1020                 fi
1021
1022                 [ -n "$ROOTFLAGS" ] && ROOTFLAGS="-o $ROOTFLAGS"
1023
1024                 mount -t $ROOTFS -r $device $ROOTFLAGS /newroot || echo "Mount of rootfs failed."
1025                 init=$INIT
1026                 if [ -z "$init" -o ! -x "/newroot$init" ]; then
1027                         init=/sbin/init
1028                 fi
1029         EOF
1030
1031         busybox_applet dmesg
1032         busybox_applet tail
1033         add_linuxrc <<-'EOF'
1034                 if [ "$DEBUGINITRD" -a "$DEBUGINITRD" != 'sh' ]; then
1035                         echo "Last 20 lines of dmesg:"
1036                         dmesg | tail -n 20
1037                 fi
1038
1039         EOF
1040
1041         kmsg "geninitrd/$VERSION switching root"
1042
1043         umount_all
1044         busybox_applet switch_root usleep
1045         add_linuxrc <<-'EOF'
1046                 [ ! -e /newroot/dev/console ] && mknod -m 660 /newroot/dev/console c 5 1
1047
1048                 # switch root to empty dir will make kernel panic, so sleep 10s before it
1049                 # switch_root needs to be pid 1, so there's no other way to recover from here
1050                 # if /dev is missing, switch root will likely fail, give debug shell before that
1051                 if [ ! -d /newroot/dev ]; then
1052                         echo "/dev is missing, switch_root will likely fail"
1053                         echo "if you booted with debugrd=sh, then you be given shell and you might able to recover this situation"
1054                         debugshell
1055                         [ "$DEBUGINITRD" ] || usleep 10000000
1056                 fi
1057
1058                 # systemd[1]: /usr appears to be on its own filesytem and is not
1059                 # already mounted. This is not a supported setup. Some things will
1060                 # probably break (sometimes even silently) in mysterious ways. Consult
1061                 # http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken
1062                 # for more information.
1063                 echo trying to mount /usr
1064                 chroot /newroot mount -n /usr
1065
1066                 exec switch_root /newroot $init ${1:+"$@"}
1067
1068                 # FIXME: this code is never executed, as "exec" does not return!
1069
1070                 echo "Error! initramfs should not reach this place."
1071                 echo "It probably means you've got old version of busybox, with broken"
1072                 echo "initramfs support. Trying to boot anyway, but won't promise anything."
1073
1074                 exec chroot /newroot $init ${1:+"$@"}
1075
1076                 echo "Failed to chroot!"
1077                 debugshell
1078         EOF
1079         # we need /init being real file, not symlink, otherwise the initramfs will
1080         # not be ran by pid 1 which is required for switch_root
1081         mv $DESTDIR/linuxrc $DESTDIR/init
1082         ln -s init $DESTDIR/linuxrc
1083 }
1084
1085 # find if $symbol exists in System.map $mapfile
1086 sym_exists() {
1087         local mapfile="$1"
1088         local symbol="$2"
1089         if [ ! -f $mapfile ]; then
1090                 # missing mapfile (not a pld kernel?)
1091                 return 1
1092         fi
1093
1094         awk -vc=1 -vsymbol="$symbol" '($2 == "T" || $2 == "t") && $3 == symbol {c = 0} END {exit c}' $mapfile
1095 }
1096
1097 # find best compressor (or forced one) for initrd
1098 find_compressor() {
1099         local mode="$1"
1100         local compressors='zstd xz lzma bzip2 gzip lzo'
1101
1102         # a specified one, take it
1103         if ! is_yes "$mode"; then
1104                 compressors="$mode"
1105         fi
1106
1107         verbose "finding compressor: $compressors (via $mode)"
1108         # check for compressor validity
1109         local c prog map=/boot/System.map-$kernel
1110         for c in $compressors; do
1111                 case $c in
1112                 xz)
1113                         sym=unxz
1114                         prog=/usr/bin/xz
1115                         ;;
1116                 lzma)
1117                         sym=unlzma
1118                         prog=/usr/bin/xz
1119                         ;;
1120                 bzip2)
1121                         sym=bzip2
1122                         prog=/usr/bin/bzip2
1123                         ;;
1124                 gzip)
1125                         sym=gunzip
1126                         prog=/bin/gzip
1127                         ;;
1128                 lzo)
1129                         sym=unlzo
1130                         prog=/usr/bin/lzop
1131                         ;;
1132                 zstd)
1133                         sym=zstd
1134                         prog=/usr/bin/zstd
1135                         ;;
1136                 none|no)
1137                         # any existing sym will work
1138                         sym=initrd_load
1139                         prog=/bin/cat
1140                         ;;
1141                 *)
1142                         die "Unknown compressor $c"
1143                         ;;
1144                 esac
1145                 if sym_exists $map $sym && [ -x $prog ]; then
1146                         echo $c
1147                         return
1148                 fi
1149         done
1150
1151         verbose "using gzip for compressor (fallback)"
1152         echo gzip
1153 }
1154
1155 # compresses kernel image image
1156 # in function so we could retry with other compressor on failure
1157 compress_image() {
1158         local compressor="$1" IMAGE="$2" target="$3" tmp
1159         tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1160
1161         case "$compressor" in
1162         xz)
1163                 # don't use -9 here since kernel won't understand it
1164                 xz --format=xz --check=crc32 --lzma2=preset=6e,dict=1MiB < "$IMAGE" > "$tmp" || return $?
1165                 ;;
1166         lzma)
1167                 xz --format=lzma -9 < "$IMAGE" > "$tmp" || return $?
1168                 ;;
1169         bzip2)
1170                 bzip2 -9 < "$IMAGE" > "$tmp" || return $?
1171                 ;;
1172         gzip)
1173                 gzip -9 < "$IMAGE" > "$tmp" || return $?
1174                 ;;
1175         lzo)
1176                 lzop -9 < "$IMAGE" > "$tmp" || return $?
1177                 ;;
1178         zstd)
1179                 zstd -9 < "$IMAGE" > "$tmp" || return $?
1180                 ;;
1181         none|no)
1182                 cat < "$IMAGE" > "$tmp" || return $?
1183                 ;;
1184         esac
1185
1186         mv -f "$tmp" "$target"
1187 }
1188
1189 if [ -r /etc/sysconfig/geninitrd ]; then
1190         . /etc/sysconfig/geninitrd
1191 fi
1192
1193 if [ ! -f /proc/mounts ]; then
1194         warn "/proc filesystem not mounted, may cause wrong results or failure."
1195 fi
1196
1197 geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev tuxonice suspend fbsplash condecor bootsplash uvesafb nfs sata scsi usbkbd bcache
1198
1199 while [ $# -gt 0 ]; do
1200         case $1 in
1201         --fstab=*)
1202                 fstab=${1#--fstab=}
1203                 ;;
1204         --fstab)
1205                 fstab=$2
1206                 shift
1207                 ;;
1208         --modules-conf=*)
1209                 modulefile=${1#--modules-conf=}
1210                 ;;
1211         --modules-conf)
1212                 modulefile=$2
1213                 shift
1214                 ;;
1215         --with-bootsplash)
1216                 BOOT_SPLASH=yes
1217                 ;;
1218         --without-bootsplash)
1219                 BOOT_SPLASH=no
1220                 ;;
1221         --with-fbsplash)
1222                 FB_SPLASH=yes
1223                 ;;
1224         --without-fbsplash)
1225                 FB_SPLASH=no
1226                 ;;
1227         --with-fbcondecor)
1228                 FB_CON_DECOR=yes
1229                 ;;
1230         --without-fbcondecor)
1231                 FB_CON_DECOR=no
1232                 ;;
1233         --with-suspend)
1234                 USE_SUSPEND=yes
1235                 ;;
1236         --without-suspend)
1237                 USE_SUSPEND=no
1238                 ;;
1239         --with-suspend2 | --with-tuxonice)
1240                 USE_TUXONICE=yes
1241                 ;;
1242         --without-suspend2 | --without-tuxonice)
1243                 USE_TUXONICE=no
1244                 ;;
1245         --lvmversion=*)
1246                 LVMTOOLSVERSION=${1#--lvmversion=}
1247                 ;;
1248         --lvmtoolsversion=*)
1249                 LVMTOOLSVERSION=${1#--lvmtoolsversion=}
1250                 ;;
1251         --lvmtoolsversion|--lvmversion)
1252                 LVMTOOLSVERSION=$2
1253                 shift
1254                 ;;
1255         --without-udev)
1256                 USE_UDEV=no
1257                 ;;
1258         --with-udev)
1259                 USE_UDEV=yes
1260                 ;;
1261         --without-dmraid)
1262                 USE_DMRAID=no
1263                 ;;
1264         --without-multipath)
1265                 USE_MULTIPATH=no
1266                 ;;
1267         --with-multipath=*)
1268                 USE_MULTIPATH=${1#--with-multipath=}
1269                 ;;
1270         --without-blkid)
1271                 USE_BLKID=no
1272                 ;;
1273         --without-luks)
1274                 USE_LUKS=no
1275                 ;;
1276         --with=*)
1277                 BASICMODULES="$BASICMODULES ${1#--with=}"
1278                 ;;
1279         --with)
1280                 BASICMODULES="$BASICMODULES $2"
1281                 shift
1282                 ;;
1283         --version)
1284                 echo "$PROGRAM: version $VERSION"
1285                 exit 0
1286                 ;;
1287         -v)
1288                 if [ x"$verbose" = x"-v" ]; then
1289                         verbose="-v -v"
1290                 else
1291                         verbose="-v"
1292                 fi
1293                 exec 3>&1
1294                 ;;
1295         --compress)
1296                 COMPRESS=$2
1297                 ;;
1298         --compress=*)
1299                 COMPRESS="${1#--compress=}"
1300                 ;;
1301         --nocompress)
1302                 COMPRESS=no
1303                 ;;
1304         --nostrip)
1305                 STRIP=
1306                 ;;
1307         --strip=*)
1308                 STRIP="${1#--strip=}"
1309                 ;;
1310         --strip)
1311                 STRIP=$2
1312                 shift
1313                 ;;
1314         --ifneeded)
1315                 ifneeded=1
1316                 ;;
1317         -f)
1318                 force=1
1319                 ;;
1320         --preload=*)
1321                 PREMODS="$PREMODS ${1#--preload=}"
1322                 ;;
1323         --preload)
1324                 PREMODS="$PREMODS $2"
1325                 shift
1326                 ;;
1327         --fs=* | --fs)
1328                 die "--fs option is obsoleted. Use --initrdfs instead"
1329                 ;;
1330         --initrdfs=*)
1331                 INITRDFS=${1#--initrdfs=}
1332                 ;;
1333         --initrdfs)
1334                 INITRDFS=$2
1335                 shift
1336                 ;;
1337         --image-version)
1338                 img_vers=yes
1339                 ;;
1340         --ide-only-root)
1341                 ide_only_root="yes"
1342                 ;;
1343         *)
1344                 if [ -z "$target" ]; then
1345                         target="$1"
1346                 elif [ -z "$kernel" ]; then
1347                         kernel="$1"
1348                 else
1349                         usage
1350                         exit 1
1351                 fi
1352                 ;;
1353         esac
1354
1355         shift
1356 done
1357
1358 if [ -z "$target" -o -z "$kernel" ]; then
1359         usage
1360         exit 1
1361 fi
1362
1363 # main()
1364 if [ "$(id -u)" != 0 ]; then
1365         die "You need to be root to generate initrd"
1366 fi
1367
1368 for dir in libx32 lib64 lib; do
1369         initrd_dir=/usr/$dir/initrd
1370         if [ -d "$initrd_dir" ]; then
1371                 initrd_dirs="$initrd_dirs $initrd_dir"
1372         fi
1373 done
1374
1375 kernel_version=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d",$1,$2)}')
1376 kernel_version_long=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d%03d",$1,$2,$3)}')
1377
1378 verbose "# geninitrd $VERSION"
1379 debug "Using initrd_dir: $initrd_dir"
1380
1381 busybox=$(find_tool $initrd_dir/busybox $initrd_dir/initrd-busybox /bin/initrd-busybox) || die "Couldn't find busybox suitable for initrd"
1382
1383 # we setup mods after parsing command line args
1384 geninitrd_setup_mods
1385
1386 if [ ! -f /boot/vmlinuz-"$kernel" ]; then
1387         warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?"
1388 fi
1389
1390 if [ -z "$INITRDFS" ]; then
1391         if [ -n "$FS" ]; then
1392                 # FS= can came only via /etc/sysconfig/geninitrd likely?
1393                 die "FS configuration option is obsoleted. Use INITRDFS instead"
1394         fi
1395
1396         # default value
1397         if [ "$kernel_version" -ge "002005" ]; then
1398                 INITRDFS="initramfs"
1399         else
1400                 INITRDFS="rom"
1401         fi
1402 fi
1403
1404 check_initrd_fs() {
1405         local s sfound sym p prog map=/boot/System.map-$kernel
1406         case "$INITRDFS" in
1407                 ext2)
1408                         # TODO: symbols to check in case of ext2 used via ext3/4 subsystem
1409                         sym=init_ext2_fs
1410                         prog=/sbin/mke2fs
1411                         ;;
1412                 rom|romfs)
1413                         sym=init_romfs_fs
1414                         prog=/sbin/genromfs
1415                         ;;
1416                 cram|cramfs)
1417                         sym=init_cramfs_fs
1418                         prog=/sbin/mkcramfs
1419                         ;;
1420                 initramfs)
1421                         sym=__initramfs_start
1422                         prog="/bin/cpio /usr/bin/find"
1423                         ;;
1424                 *)
1425                         die "Filesystem $INITRDFS on initrd is not supported by geninitrd"
1426                         ;;
1427         esac
1428
1429         # only one is needed (for cases like ext2 via ext2 or via ext3 or via ext4 subsysytem)
1430         sfound=0
1431         for s in $sym; do
1432                 sym_exists $map $s && sfound=1
1433                 break
1434         done
1435         if [ "$sfound" -eq "0" ]; then
1436                 die "Filesystem $INITRDFS on initrd is not supported by kernel"
1437         fi
1438
1439         for p in $prog; do
1440                 [ ! -x "$p" ] && die "$prog is missing"
1441         done
1442 }
1443 check_initrd_fs
1444
1445 if [ -L "$target" ]; then
1446         target=$(readlink -f "$target")
1447 fi
1448
1449 if [ -n "$img_vers" ]; then
1450         target="$target-$kernel"
1451 fi
1452
1453 if [ -z "$force" -a -f "$target" ]; then
1454         die "$target already exists."
1455 fi
1456
1457 if [ ! -d "/lib/modules/$kernel" ]; then
1458         die "/lib/modules/$kernel is not a directory."
1459 fi
1460
1461 if [ "$kernel_version" -ge "002005" ]; then
1462         modext=".ko"
1463 fi
1464
1465 cache_modprobe_conf
1466
1467 for n in $PREMODS; do
1468         find_module "$n"
1469 done
1470
1471 if [ "$FBMODULE" ]; then
1472         find_module "$FBMODULE"
1473 fi
1474
1475 # autodetect USB keyboards
1476 find_modules_usbkbd
1477
1478 # allow forcing loading SCSI and/or IDE modules
1479 # XXX: where ADDSCSI cames from? drop?
1480 if is_yes "$ADDSCSI"; then
1481         find_modules_scsi
1482 fi
1483
1484 # autodetect SATA modules
1485 find_modules_sata
1486
1487 # XXX: where ADDIDE cames from? drop?
1488 if is_yes "$ADDIDE"; then
1489         find_modules_ide
1490 fi
1491
1492 if is_yes "$USE_SUSPEND"; then
1493         find_modules_suspend
1494 fi
1495
1496 find_root "$fstab" || exit
1497 verbose "Using $rootdev as device for rootfs"
1498
1499 find_modules_for_devpath "$rootdev"
1500
1501 # if USE_MULTIPATH is path to device, scan that too
1502 # this is to bootstrap multipath setup into initrd.
1503 if ! is_no "$USE_MULTIPATH" && ! is_yes "$USE_MULTIPATH"; then
1504         find_modules_multipath $USE_MULTIPATH
1505 fi
1506
1507 find_module "-$rootFs"
1508
1509 for n in $BASICMODULES; do
1510         find_module "$n"
1511 done
1512
1513 if is_yes "$USE_TUXONICE"; then
1514         find_module "-lzf"
1515 fi
1516
1517 find_modules_uvesafb
1518 find_modules_fbsplash
1519
1520 if [ -n "$ifneeded" -a -z "$MODULES" ]; then
1521         verbose "No modules are needed -- not building initrd image."
1522         exit 0
1523 fi
1524
1525 verbose "Building initrd..."
1526 DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
1527 RCFILE="$DESTDIR/linuxrc"
1528 > "$RCFILE"
1529 chmod a+rx "$RCFILE"
1530 ln -s linuxrc $DESTDIR/init
1531
1532 # create dirs that we really need
1533 inst_d /{lib,bin,sbin,etc,dev{,/pts,/shm},loopfs,var,proc,run,sys,tmp}
1534
1535 modules_install "$MODULES"
1536
1537 # mknod'ing the devices instead of copying them works both with and
1538 # without devfs...
1539 mknod -m 600 "$DESTDIR/dev/console" c 5 1
1540 mknod -m 666 "$DESTDIR/dev/null" c 1 3
1541 mknod -m 666 "$DESTDIR/dev/zero" c 1 5
1542 mknod -m 666 "$DESTDIR/dev/random" c 1 8
1543 mknod -m 666 "$DESTDIR/dev/urandom" c 1 9
1544 mknod -m 644 "$DESTDIR/dev/kmsg" c 1 11
1545
1546 inst_exec $busybox /bin/busybox
1547 ln -s busybox $DESTDIR/bin/sh
1548 # for older busyboxes who had /bin/initrd-busybox as EXEPATH
1549 ln -s busybox $DESTDIR/bin/initrd-busybox
1550
1551 add_linuxrc <<EOF
1552 #!/bin/sh
1553 # initrd generated by geninitrd/$VERSION
1554 # on $(LC_ALL=C date)
1555
1556 EOF
1557 load_font
1558 mount_proc
1559
1560 kmsg "geninitrd/$VERSION starting"
1561
1562 inst_d /lib/geninitrd/
1563 inst /lib/geninitrd/functions.initrd /lib/geninitrd/functions.initrd
1564
1565 add_linuxrc <<-EOF
1566         . /lib/geninitrd/functions.initrd
1567         # builtin defaults from geninitrd
1568         ROOT=$rootdev
1569         ROOTFS=$rootFs
1570 EOF
1571 add_linuxrc <<-'EOF'
1572         read CMDLINE < /proc/cmdline
1573
1574         for arg in $CMDLINE; do
1575                 if [ "${arg}" = "debuginitrd" ] || [ "${arg}" = "debugrd" ]; then
1576                         DEBUGINITRD=yes
1577                 fi
1578                 if [ "${arg##debuginitrd=}" != "${arg}" ] || [ "${arg##debugrd=}" != "${arg}" ]; then
1579                         DEBUGINITRD=${arg##debug*rd=}
1580                 fi
1581                 if [ "${arg##root=}" != "${arg}" ]; then
1582                         ROOT=${arg##root=}
1583                 fi
1584                 if [ "${arg##rootfs=}" != "${arg}" ]; then
1585                         ROOTFS=${arg##rootfs=}
1586                 fi
1587                 if [ "${arg##rootflags=}" != "${arg}" ]; then
1588                         ROOTFLAGS=${arg##rootflags=}
1589                 fi
1590                 if [ "${arg##rootfsflags=}" != "${arg}" ]; then
1591                         ROOTFSFLAGS=${arg##rootfsflags=}
1592                 fi
1593                 if [ "${arg##init=}" != "${arg}" ]; then
1594                         INIT=${arg##init=}
1595                 fi
1596         done
1597
1598         # handling of invalid, rootfsflags, option
1599         if [ -n "$ROOTFSFLAGS" ]; then
1600                 if [ -n "$ROOTFLAGS" ]; then
1601                         ROOTFLAGS="$ROOTFLAGS,$ROOTFSFLAGS"
1602                 else
1603                         ROOTFLAGS="$ROOTFSFLAGS"
1604                 fi
1605         fi
1606
1607         if [ "$DEBUGINITRD" = "sh" ]; then
1608                 # export some vars to subshell for debug to work
1609                 export CMDLINE ROOT ROOTFS ROOTDEV ROOTFLAGS DEBUGINITRD INIT
1610                 export LVM_ROOTVG LVM_SUSPENDVG LVM_VGVOLUMES
1611                 export rootnr attrs majmin major minor device
1612
1613                 # make debugshell() invoke subshell if $DEBUGINITRD=sh
1614                 debugshell() {
1615 EOF
1616 if is_yes "$RUN_SULOGIN_ON_ERR"; then
1617 add_linuxrc <<-'EOF'
1618         echo "debug shell disabled by RUN_SULOGIN_ON_ERR=yes from /etc/sysconfig/system during initrd generation time"
1619 EOF
1620 else
1621 add_linuxrc <<-'EOF'
1622         sh
1623 EOF
1624 fi
1625 add_linuxrc <<-'EOF'
1626                 }
1627         else
1628                 debugshell() {
1629                         :
1630                 }
1631         fi
1632
1633         if [ "$DEBUGINITRD" ]; then
1634                 set -x
1635         fi
1636 EOF
1637
1638 # mount early
1639 mount_tmp
1640
1641 modules_add_linuxrc $MODULES
1642
1643 # TODO: rewrite for busybox
1644 #if [ -n "$loopDev" ]; then
1645 #       if [ ! -d /initrd ]; then
1646 #               mkdir /initrd
1647 #       fi
1648 #
1649 #       cp -a "$loopDev" "$DESTDIR/dev"
1650 #       cp -a "$rootdev" "$DESTDIR/dev"
1651 #       echo "echo Mounting device containing loopback root filesystem" >> "$RCFILE"
1652 #       echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE"
1653 #       echo "echo Setting up loopback device $rootdev" >> $RCFILE
1654 #       echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE"
1655 #fi
1656
1657 if is_yes "$USE_UDEV"; then
1658         initrd_gen_udev
1659 else
1660         initrd_gen_mdev
1661 fi
1662
1663 initrd_gen_uvesafb
1664 initrd_gen_luks
1665 initrd_gen_dmraid
1666 initrd_gen_multipath
1667 initrd_gen_blkid
1668
1669 if is_yes "$have_nfs"; then
1670         initrd_gen_nfs
1671 else
1672         initrd_gen_md
1673         initrd_gen_lvm
1674         initrd_gen_bcache
1675         initrd_gen_blkid
1676         initrd_gen_luks
1677         initrd_gen_setrootdev
1678 fi
1679
1680 # additional devs always needed
1681 [ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev
1682
1683 initrd_gen_stop_udevd
1684 initrd_gen_stop_mdev
1685 initrd_gen_stop_uvesafb
1686
1687 # resume after killing local processes
1688 initrd_gen_tuxonice
1689 initrd_gen_suspend
1690
1691 # clean up env
1692 add_linuxrc <<-'EOF'
1693 if [ ! "$DEBUGINITRD" ]; then
1694         ifs=$IFS
1695         IFS="
1696         "
1697         for i in $(export -p); do
1698                 i=${i#declare -x } # ksh/bash
1699                 i=${i#export } # busybox
1700
1701                 case "$i" in
1702                 *=*)
1703                         : ;;
1704                 *)
1705                         continue ;;
1706                 esac
1707
1708                 i=${i%%=*}
1709
1710                 [ -z "$i" ] && continue
1711
1712                 case "$i" in
1713                         ROOT|PATH|HOME|TERM)
1714                                 :
1715                                 ;;
1716                         *)
1717                                 unset $i
1718                                 ;;
1719                 esac
1720         done
1721         IFS=$ifs
1722 fi
1723 EOF
1724
1725 if [ "$INITRDFS" = "initramfs" ]; then
1726         initrd_gen_initramfs_switchroot
1727 else
1728         umount_all
1729 fi
1730
1731 initrd_gen_fbsplash
1732 initrd_gen_fbcondecor
1733
1734 debug "Current /linuxrc:\n$(sed -e 's,^,| ,' $DESTDIR/linuxrc)"
1735
1736 IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed"
1737
1738 IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
1739 verbose "image size: $IMAGESIZE KiB ($DESTDIR)"
1740
1741 verbose "Creating $INITRDFS image $IMAGE"
1742 case "$INITRDFS" in
1743   ext2)
1744         dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null
1745         # NOTE: ext2 label is max 16 chars
1746         mke2fs -q -F -b 1024 -m 0 -L "PLD/$kernel" "$IMAGE" 2>/dev/null 1>&2
1747         tune2fs -i 0 "$IMAGE" >/dev/null 2>&1
1748
1749         local tmpmnt=$(mktemp -d -t initrd.mnt-XXXXXX)
1750         debug "Mounting ext2 image $IMAGE to $tmpmnt"
1751         mount -o loop -t ext2 "$IMAGE" "$tmpmnt" || die "mount failed, check dmesg(1)"
1752         # We don't need this directory, so let's save space
1753         rm -rf "$tmpmnt"/lost+found
1754
1755         debug "Copy recursively $DESTDIR -> $tmpmnt"
1756         cp -a $DESTDIR/* $tmpmnt
1757         umount "$IMAGE"
1758         rmdir "$tmpmnt"
1759
1760         ;;
1761   rom|romfs)
1762         genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD Linux/$kernel (geninitrd/$VERSION)"
1763         ;;
1764   cram|cramfs)
1765         mkcramfs "$DESTDIR" "$IMAGE"
1766         ;;
1767   initramfs)
1768         (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
1769         ;;
1770   *)
1771         die "Filesystem $INITRDFS not supported by $PROGRAM"
1772 esac
1773
1774 if [ "$INITRDFS" != "initramfs" ]; then
1775         CONFIG_BLK_DEV_RAM_SIZE=$(ikconfig | awk -F= '/^CONFIG_BLK_DEV_RAM_SIZE/{print $2}')
1776         if [ -z "$CONFIG_BLK_DEV_RAM_SIZE" ]; then
1777                 CONFIG_BLK_DEV_RAM_SIZE=4096
1778                 warn "No CONFIG_BLK_DEV_RAM_SIZE detected, fallback to $CONFIG_BLK_DEV_RAM_SIZE"
1779         fi
1780
1781         if [ "$IMAGESIZE" -gt $CONFIG_BLK_DEV_RAM_SIZE ]; then
1782                 warn "Your image size is larger than $CONFIG_BLK_DEV_RAM_SIZE, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!"
1783         fi
1784 fi
1785
1786 if ! is_no "$COMPRESS"; then
1787         compressor=$(find_compressor "$COMPRESS")
1788         verbose "Compressing $target with $compressor"
1789
1790         # TODO: the image name (specified from kernel.spec) already contains
1791         # extension, which is .gz most of the time.
1792         compress_image "$compressor" "$IMAGE" "$target" || {
1793                 if [ $compressor != gzip ]; then
1794                         warn "Could not compress with $compressor, retrying with gzip"
1795                         compress_image gzip "$IMAGE" "$target" || die "compress failed with gzip" $?
1796                 else
1797                         die "Could not compress image with $compressor"
1798                 fi
1799         }
1800 else
1801         cp -a "$IMAGE" "$target"
1802 fi
1803
1804 # XXX. check if bootsplash can output data to tmp dir not directly to initramfs image.
1805 initrd_gen_bootsplash "$target"
1806
1807 rm -rf "$DESTDIR" "$IMAGE"
1808
1809 # vim:ts=4:sw=4:noet:fdm=marker
This page took 0.37459 seconds and 3 git commands to generate.