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