]> git.pld-linux.org Git - projects/geninitrd.git/blob - geninitrd
Allow usage of UUID/LABEL in /etc/crypttab.
[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|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" | 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                                         find_depmod "-libcrc32c"
436                                         ;;
437                                 crc-t10dif)
438                                         find_depmod "-crct10dif-pclmul"
439                                         find_depmod "-crct10dif"
440                                         ;;
441                                 libcrc32c)
442                                         find_depmod "-crc32c-intel"
443                                         find_depmod "-crc32c"
444                                         ;;
445                                 virtio_blk|virtio_scsi)
446                                         find_depmod "-virtio_pci"
447                                         find_depmod "-virtio_mmio"
448                                         ;;
449                         esac
450
451                         echo $modpath
452                 fi
453         done
454         return 0
455 }
456
457 find_firmware() {
458         local module="$1"
459
460         # no firmware support in 2.4 kernels
461         if [ "$kernel_version_long" -lt "002005048" ]; then
462                 return
463         fi
464         echo -n $(NEW_MODINFO=1 modinfo -k $kernel -F firmware $module 2>/dev/null | xargs)
465 }
466
467 # @param        $module
468 find_module() {
469         local mod depmod module=$1
470
471         depmod=$(find_depmod $module) || exit 1
472         for mod in $depmod; do
473                 mod=${mod#/lib/modules/$kernel/}
474
475                 # add each module only once
476                 local m have=0
477                 for m in $MODULES; do
478                         [ $m = $mod ] && have=1
479                 done
480                 if [ $have = 0 ]; then
481                         MODULES="$MODULES $mod"
482                 fi
483         done
484 }
485
486 # install a file to temporary mount image.
487 # it will operate recursively (copying directories)
488 # and will symlink destinations if source is symlink.
489 inst() {
490         if [ $# -lt 2 ]; then
491                 die 'Usage: inst <file> [<file>] <destination>'
492         fi
493
494         local src i=0 c=$(($# - 1))
495         while [ $i -lt $c ]; do
496                 src="$src $1"
497                 i=$((i + 1))
498                 shift
499         done
500         local dest=$1
501         set -- $src
502         local parentDir=$(dirname $DESTDIR$dest)
503         if [ ! -d "$parentDir" ]; then
504                 verbose "+ mkdir -p DESTDIR${parentDir#$DESTDIR}"
505                 mkdir -p $parentDir
506         fi
507         verbose "+ cp $* DESTDIR$dest"
508         cp -HRp "$@" "$DESTDIR$dest"
509 }
510
511 inst_d() {
512         if [ $# = 0 ]; then
513                 die 'Usage: inst_d <destination> <destination>'
514         fi
515         local dir
516         for dir in "$@"; do
517                 install -d "$DESTDIR$dir"
518         done
519 }
520
521 # install executable and it's shared libraries
522 inst_exec() {
523         if [ $# -lt 2 ]; then
524                 die "Invalid params ($@), Usage: inst_exec <file>[, <file>] <destination>"
525         fi
526         local src i=0 c=$(($# - 1))
527         while [ $i -lt $c ]; do
528                 src="$src $1"
529                 i=$((i + 1))
530                 shift
531         done
532         local dest=$1
533         set -- $src
534
535         inst "$@" $dest
536
537         local obj lib libs libdir
538         for obj in "$@"; do
539                 case "$obj" in
540                         /lib/ld-linux.so.2 | /lib64/ld-linux-x86-64.so.2 | /libx32/ld-linux-x32.so.2)
541                         continue
542                 esac
543
544                 libs=$(ldd "$obj" | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
545                 for lib in $libs; do
546                         libdir=$(cd $(dirname "$lib"); pwd)
547                         if [ ! -f "$DESTDIR/$lib" ]; then
548                                 inst_d $libdir
549                                 inst_exec $lib $libdir
550                         fi
551                 done
552         done
553
554         # hack for uclibc linked binaries requiring this fixed path
555         # XXX: shouldn't rpath be used here instead so th
556         for _lib in $(get_libdir LIBDIR); do
557                 if [ -f $DESTDIR/$_lib/libc.so.0 ]; then
558                         lib=$DESTDIR/$_lib/libc.so.0
559                         lib=$(ldd "$lib" | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
560                         libdir=$(cd $(dirname "$lib"); pwd)
561                         if [ ! -e $DESTDIR$libdir ]; then
562                                 libdir=$(dirname "$libdir")
563                                 inst_d $libdir
564                                 verbose "+ ln -s /$_lib $DESTDIR$libdir"
565                                 ln -s /$_lib $DESTDIR$libdir
566                                 break
567                         fi
568                 fi
569         done
570 }
571
572 # output modules.conf / modprobe.conf
573 modprobe_conf() {
574         echo "$modprobe_conf_cache"
575 }
576
577 # return options for MODULE
578 # @param $1 module name
579 modprobe_options() {
580         local module=$1
581         local options=$(modprobe_conf | awk -vmodule="$module" '{ if ($1 == "options" && $2 == module) { for(i=3;i<=NF;i++) printf("%s ",$i); }}')
582         echo ${options# }
583 }
584
585 #
586 # defaults to modprobe -c if not told otherwise, this means include statements
587 # work from there.
588 cache_modprobe_conf() {
589         if [ "$kernel_version" -lt "002005" ]; then
590                 modulefile=/etc/modules.conf
591                 if [ ! -f "$modulefile" -a -f /etc/conf.modules ]; then
592                         modulefile=/etc/conf.modules
593                 fi
594         fi
595
596         if [ -n "$modulefile" ]; then
597                 debug "Using $modulefile for modules config"
598                 modprobe_conf_cache=$(cat $modulefile | awk '!/^[\t ]*#/ { print }')
599
600         else
601                 debug "Using modprobe -c to get modules config"
602                 modprobe_conf_cache=$(modprobe -c --set-version $kernel | awk '!/^[\t ]*#/ { print }')
603         fi
604 }
605
606 # find modules for $devpath
607 find_modules_for_devpath() {
608         local devpath="$1"
609         if [ -z "$devpath" ]; then
610                 die "No argument passed to find_modules_for_devpath() - is your /etc/fstab correct?"
611         fi
612
613         if [[ "$devpath" = /dev/dm-* ]]; then
614                 # /dev/dm-3 -> /dev/mapper/sil_ahbgadcbchfc3
615                 devpath=$(dm_node "$devpath")
616         fi
617
618         if [ -L "$devpath" ] && ! is_lvm "$devpath" && ! is_luks "$devpath"; then
619                 # sanitize things like:
620                 # /dev/block/104:2 -> /dev/cciss/c0d0p2
621                 devpath=$(readlink -f "$devpath")
622         fi
623
624         verbose "Finding modules for device path $devpath"
625
626         if is_luks "$devpath"; then
627                 find_modules_luks "$devpath"
628                 return
629         fi
630
631         if is_nfs "$devpath"; then
632                 find_modules_nfs "$devpath"
633                 return
634         fi
635
636         if is_md "$devpath"; then
637                 find_modules_md "$devpath"
638                 return
639         fi
640
641         if is_multipath "$devpath"; then
642                 if find_modules_multipath "$devpath"; then
643                         return
644                 fi
645
646                 # fallback
647         fi
648
649         if is_dmraid "$devpath"; then
650                 if find_modules_dmraid "$devpath"; then
651                         return
652                 fi
653                 # fallback
654         fi
655
656         if is_scsi "$devpath"; then
657                 find_modules_scsi "$devpath"
658                 return
659         fi
660
661         if is_ide "$devpath"; then
662                 find_modules_ide "$devpath"
663                 return
664         fi
665
666         if [[ "$devpath" == /dev/bcache* ]]; then
667                 find_modules_bcache "$devpath"
668                 return
669         fi
670
671         if [[ "$devpath" == /dev/rd/* ]]; then
672                 find_module "DAC960"
673                 rootdev_add=/dev/rd/
674                 return
675         fi
676
677         if [[ "$devpath" == /dev/ida/* ]]; then
678                 find_module "cpqarray"
679                 rootdev_add=/dev/ida/
680                 return
681         fi
682
683         if [[ "$devpath" == /dev/cciss/* ]]; then
684                 rootdev_add=/dev/cciss/
685
686                 # load hpsa for future kernels, cciss for backwards compat
687                 if [ "$kernel_version_long" -ge "003000000" ]; then
688                         find_module "hpsa" "-cciss"
689                         find_modules_scsi "$devpath"
690                 else
691                         find_module "cciss"
692                 fi
693
694                 return
695         fi
696
697         if [[ "$devpath" == /dev/ataraid/* ]]; then
698                 find_modules_ide
699                 find_module "ataraid"
700                 ataraidmodules=$(modprobe_conf | awk '/ataraid_hostadapter/ { print $3 }')
701                 if [ -n "$ataraidmodules" ]; then
702                         # FIXME: think about modules compiled in kernel
703                         die "ataraid_hostadapter alias not defined in modprobe.conf! Please set it and run $PROGRAM again."
704                 fi
705                 for n in $ataraidmodules; do
706                         find_module "$n"
707                 done
708                 rootdev_add=/dev/ataraid/
709                 return
710         fi
711
712         # check to see if we need to set up a loopback filesystem
713         if [[ "$devpath" == /dev/loop*  ]]; then
714                 die "Sorry, root on loop device isn't supported."
715                 # TODO: rewrite for bsp and make nfs ready
716                 if [ ! -x /sbin/losetup ]; then
717                         die "losetup is missing"
718                 fi
719                 key="^# $(echo $devpath | awk -F/ '{print($3);}' | tr '[a-z]' '[A-Z]'):"
720                 if ! is_yes "`awk '/'$key'/ { print( "yes"); }' $fstab`"; then
721                         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"
722                 fi
723
724                 line="`awk '/'$key'/ { print $0; }' $fstab`"
725                 loopDev="$(echo $line | awk '{print $3}')"
726                 loopFs="$(echo $line | awk '{print $4}')"
727                 loopFile="$(echo $line | awk '{print $5}')"
728
729                 BASICMODULES="$BASICMODULES -loop"
730                 find_module "-$loopFs"
731                 BASICMODULES="$BASICMODULES -${loopFs}"
732                 return
733         fi
734
735         if is_lvm "$devpath"; then
736                 find_modules_lvm "$devpath"
737                 return
738         fi
739 }
740
741 firmware_install_module() {
742         local module="$1"
743         local firmware_files="$2"
744
745         verbose "Adding Firmwares ($firmware_files) to initrd for module $module"
746         # firmware not yet installed
747         if [ ! -f "$DESTDIR/lib/firmware/firmware.sh" ]; then
748                 inst_d /lib/firmware
749 cat << 'EOF' >> "$DESTDIR/lib/firmware/firmware.sh"
750 #!/bin/sh -e
751 # handle only firmware add requests
752 if [ "$SUBSYSTEM" != "firmware" ]; then
753         exit 0
754 fi
755 if [ "$ACTION" != "add" ]; then
756         exit 0
757 fi
758 echo 1 > /sys$DEVPATH/loading
759 cat "/lib/firmware/$FIRMWARE" > /sys$DEVPATH/data
760 echo 0 > /sys$DEVPATH/loading
761 exit 0
762 EOF
763                 chmod 755 "$DESTDIR/lib/firmware/firmware.sh"
764
765                 # setup firmware loader agent
766                 echo "echo -n "/lib/firmware/firmware.sh" > /proc/sys/kernel/hotplug" | add_linuxrc
767         fi
768
769         for firmware in $firmware_files; do
770                 if [ -f "/lib/firmware/$kernel/$firmware" ]; then
771                         FIRMWAREDIR=${firmware%/*}
772                         [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
773                         inst /lib/firmware/$kernel/$firmware /lib/firmware/$firmware
774                 elif [ -f "/lib/firmware/$firmware" ]; then
775                         FIRMWAREDIR=${firmware%/*}
776                         [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
777                         inst /lib/firmware/$firmware /lib/firmware/$firmware
778                 else
779                         warn "Possible missing firmware file /lib/firmware/$firmware or /lib/firmware/$kernel/$firmware for module $module."
780                 fi
781         done
782
783         mount_sys
784 }
785
786 modules_install() {
787         local modules="$1"
788         local mod
789
790         for mod in $modules; do
791                 MODULEDIR=${mod%/*}
792                 inst_d "/lib/modules/$kernel/$MODULEDIR"
793                 cp -a "/lib/modules/$kernel/$mod" "$DESTDIR/lib/modules/$kernel/$mod"
794                 case $mod in
795                         *.gz)
796                                 gunzip "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress gz"
797                                 mod=${mod%.gz}
798                                 ;;
799                         *.xz)
800                                 xz -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress xz"
801                                 mod=${mod%.xz}
802                                 ;;
803                         *.bz2)
804                                 bzip2 -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress bz2"
805                                 mod=${mod%.bz2}
806                                 ;;
807                 esac
808                 if [ "$STRIP" ] && [ -x "$STRIP" ]; then
809                         $STRIP -g --remove-section=.comment "$DESTDIR/lib/modules/$kernel/${mod}"
810                 fi
811         done
812 }
813
814 modules_add_linuxrc() {
815         local mod modpath
816
817         for mod in "$@"; do
818                 # module path without optional compression
819                 modpath=${mod%.gz}
820                 modpath=${modpath%.xz}
821                 modpath=${modpath%.bz2}
822
823                 # name of the module
824                 local module=${modpath##*/}; module=${module%$modext}
825                 local options=$(modprobe_options "$module")
826                 local genericname=$(echo $module | tr - _)
827                 local usleep=$(eval echo \$MODULE_${genericname}_USLEEP)
828                 local firmware=$(eval echo \$MODULE_${genericname}_FIRMWARE)
829
830                 if [ "$module" = "scsi_mod" -a "$kernel_version_long" -ge "002006030" ]; then
831                         options="scan=sync $options"
832                 fi
833
834                 if [ x"$verbose" = x"-v" ]; then
835                         s=""
836                         if [ "$options" ]; then
837                                 s="$s with options [$options]"
838                         fi
839                         if [ "$usleep" ]; then
840                                 s="$s and $usleep usleep"
841                         fi
842                         verbose "Loading module [$module]$s"
843                 fi
844
845                 if [ -n "$firmware" ]; then
846                         firmware_install_module "$module" "$firmware"
847                 else
848                         for file in $(find_firmware "$module"); do
849                                 firmware_install_module "$module" "$file"
850                         done
851                 fi
852
853                 echo "insmod /lib/modules/$kernel/$modpath $options" | add_linuxrc
854                 if [ -n "$usleep" ]; then
855                         echo "usleep $usleep" | add_linuxrc
856                 fi
857                 if [ "$module" = "scsi_wait_scan" ]; then
858                         if [ "$(busybox_applet rmmod 2>/dev/null; echo $?)" = 0 ]; then
859                                 echo "rmmod scsi_wait_scan" | add_linuxrc
860                         fi
861                 fi
862
863         done
864 }
865
866 # Generates /dev nodes based on /proc/partitions information.
867 # Needs /proc mounted.
868 # Can be called multiple times.
869 initrd_gen_devices() {
870         if is_yes "$proc_partitions"; then
871                 return
872         fi
873         proc_partitions=yes
874
875         mount_dev
876         add_linuxrc <<-'EOF'
877                 : 'Making device nodes'
878                 cat /proc/partitions | (
879                         # ignore first two lines: header, empty line
880                         read b; read b
881
882                         while read major minor blocks dev rest; do
883                                 node=/dev/$dev
884                                 mkdir -p ${node%/*}
885                                 [ -e $node ] || mknod -m 660 $node b $major $minor
886                         done
887                 )
888         EOF
889 }
890
891
892 initrd_gen_setrootdev() {
893         verbose "Adding rootfs finding based on kernel cmdline root= option support."
894         busybox_applet ls
895         debug "Current /proc/partitions:\n$(sed -e 's,^,| ,' /proc/partitions)"
896         add_linuxrc <<-'EOF'
897                 if [ "${ROOT##/dev/}" != "${ROOT}" ]; then
898                         rootnr="$(busybox awk -v rootnode="${ROOT##/dev/}" '$4 == rootnode { print 256 * $1 + $2 }' /proc/partitions)"
899                         # fallback to ls, try two different formats
900                         # http://lists.pld-linux.org/mailman/pipermail/pld-devel-en/2014-May/023915.html
901                         if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
902                                 # busybox up to 1.22
903                                 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $3 + $4; }}')"
904                         fi
905                         if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
906                                 # busybox 1.22 and upwards
907                                 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $5 + $6; }}')"
908                         fi
909                         if [ "${rootnr:-0}" -gt 0 ]; then
910                                 echo "$rootnr" > /proc/sys/kernel/real-root-dev
911                         fi
912                 fi
913         EOF
914 }
915
916 initrd_gen_initramfs_switchroot() {
917         inst_d /newroot
918         if [ "$rootdev" = "/dev/nfs" ]; then
919                 echo "rootfs on NFS root=/dev/nfs"
920         else
921                 [ ! -e "$DESTDIR/$rootdev" ] && inst $rootdev $rootdev
922         fi
923
924         # parse 'root=xxx' kernel commandline
925         # We support passing root as hda3 /dev/hda3 0303 0x0303 and 303
926
927         # from lilo-23.2/readme/README:
928         # root=<device> changes the root device. This overrides settings that may
929         # have been made in the boot image and on the LILO command line. <device> is
930         # either the hexadecimal device number or the full path name of the device,
931         # e.g. /dev/hda3 [*]
932         #
933         #  *  The device names are hard-coded in the kernel. Therefore, only the
934         #         "standard" names are supported and some less common devices may not be
935         #         recognized. In those cases, only numbers can be used.
936         busybox_applet cat
937         add_linuxrc <<-'EOF'
938                 device=
939                 eval "$(busybox awk -v root="$ROOT" '
940                         # http://9fans.net/archive/2006/09/261
941                         function h2d(str, hstr, res, num, n, digit, i) {
942                                 hstr = "0123456789abdcef";
943                                 res = 0;
944                                 n = split(tolower(str), digit, "");
945
946                                 for (i = 1; i <= n; i++) {
947                                         num = index(hstr, digit[i]) - 1;
948                                         res = res + (num * 16 ^ (n - i));
949                                 }
950
951                                 return res;
952                         }
953                         BEGIN {
954
955                                 num_pattern_short = "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]";
956                                 num_pattern = "[0-9a-fA-F]" num_pattern_short;
957                                 dev_pattern = "[hms][a-z][a-z]([0-9])+";
958                                 partition = "";
959                                 min = -1; maj = -1;
960
961                                 # see if we have /dev/hdX or hdX, we can just take partition name
962                                 if (root ~ "^\/dev\/" dev_pattern "$" || root ~ "^" dev_pattern "$") {
963                                         partition = root
964                                         sub("^/dev/", "", partition);
965
966                                 } else {
967                                         # unify values first
968                                         if (root ~ "^" num_pattern_short "$")  {
969                                                 # change "303" => "0x0303"
970                                                 root = "0x0" root
971                                         } else if (root ~ "^" num_pattern "$")  {
972                                                 # change "0303" => "0x0303"
973                                                 root = "0x" root
974                                         }
975
976                                         maj = h2d(substr(root, 3, 2));
977                                         min = h2d(substr(root, 5, 2));
978                                 }
979                         }
980
981                         partition && $4 == partition { maj = $1; min = $2; }
982                         $1 == maj && $2 == min { partition = $4; }
983
984                         END {
985                                 if (maj >= 0 && min >= 0) {
986                                         printf("maj=%s; min=%s;\n", maj, min);
987                                 }
988                                 if (partition) {
989                                         printf("device=/dev/%s;\n", partition);
990                                 }
991                         }
992                         ' /proc/partitions)"
993
994                 if [ -z "$device" ]; then
995                         if [ "$DEBUGINITRD" ]; then
996                                 cat /proc/partitions
997                         fi
998                         device=$ROOT
999                 fi
1000
1001                 if [ "$device" -a ! -b $device -a "$maj$min" ]; then
1002                         mknod -m 660 $device b $maj $min
1003                 fi
1004
1005                 # XXX hack, fallback to rootdev from geninitrd time
1006                 if [ ! -e "$device" ]; then
1007                         device="$rootdev"
1008                         echo "DEVICE set to $device based on fstab entry from initrd gen time"
1009                 fi
1010
1011                 # XXX hack, if no device, try to parse it from /proc/partitions using /proc/sys/kernel/real-root-dev
1012                 if [ ! -e "$device" ]; then
1013                         rrd=$(cat /proc/sys/kernel/real-root-dev)
1014                         major=$(($rrd / 256))
1015                         minor=$(($rrd % 256))
1016
1017                         while read pmajor pminor blocks dev rest; do
1018                                 # skip header and empty line
1019                                 [ -z "$pmajor" -o "$pmajor" = "major" ] && continue
1020
1021                                 if [ $pmajor = $major -a $pminor = $minor ]; then
1022                                         device=/dev/$dev
1023                                         echo "DEVICE set to $device based on real-root-dev"
1024                                 fi
1025                         done < /proc/partitions
1026                 fi
1027
1028                 [ -n "$ROOTFLAGS" ] && ROOTFLAGS="-o $ROOTFLAGS"
1029
1030                 mount -t $ROOTFS -r $device $ROOTFLAGS /newroot || echo "Mount of rootfs failed."
1031                 init=$INIT
1032                 if [ -z "$init" -o ! -x "/newroot$init" ]; then
1033                         init=/sbin/init
1034                 fi
1035         EOF
1036
1037         busybox_applet dmesg
1038         busybox_applet tail
1039         add_linuxrc <<-'EOF'
1040                 if [ "$DEBUGINITRD" ]; then
1041                         echo "Last 20 lines of dmesg:"
1042                         dmesg | tail -n 20
1043                 fi
1044
1045         EOF
1046
1047         kmsg "geninitrd/$VERSION switching root"
1048
1049         umount_all
1050         busybox_applet switch_root usleep
1051         add_linuxrc <<-'EOF'
1052                 [ ! -e /newroot/dev/console ] && mknod -m 660 /newroot/dev/console c 5 1
1053
1054                 # switch root to empty dir will make kernel panic, so sleep 10s before it
1055                 # switch_root needs to be pid 1, so there's no other way to recover from here
1056                 # if /dev is missing, switch root will likely fail, give debug shell before that
1057                 if [ ! -d /newroot/dev ]; then
1058                         echo "/dev is missing, switch_root will likely fail"
1059                         echo "if you booted with debugrd=sh, then you be given shell and you might able to recover this situation"
1060                         debugshell
1061                         [ "$DEBUGINITRD" ] || usleep 10000000
1062                 fi
1063
1064                 # systemd[1]: /usr appears to be on its own filesytem and is not
1065                 # already mounted. This is not a supported setup. Some things will
1066                 # probably break (sometimes even silently) in mysterious ways. Consult
1067                 # http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken
1068                 # for more information.
1069                 echo trying to mount /usr
1070                 chroot /newroot mount -n /usr
1071
1072                 exec switch_root /newroot $init ${1:+"$@"}
1073
1074                 # FIXME: this code is never executed, as "exec" does not return!
1075
1076                 echo "Error! initramfs should not reach this place."
1077                 echo "It probably means you've got old version of busybox, with broken"
1078                 echo "initramfs support. Trying to boot anyway, but won't promise anything."
1079
1080                 exec chroot /newroot $init ${1:+"$@"}
1081
1082                 echo "Failed to chroot!"
1083                 debugshell
1084         EOF
1085         # we need /init being real file, not symlink, otherwise the initramfs will
1086         # not be ran by pid 1 which is required for switch_root
1087         mv $DESTDIR/linuxrc $DESTDIR/init
1088         ln -s init $DESTDIR/linuxrc
1089 }
1090
1091 # find if $symbol exists in System.map $mapfile
1092 sym_exists() {
1093         local mapfile="$1"
1094         local symbol="$2"
1095         if [ ! -f $mapfile ]; then
1096                 # missing mapfile (not a pld kernel?)
1097                 return 1
1098         fi
1099
1100         awk -vc=1 -vsymbol="$symbol" '$2 == "T" && $3 == symbol {c = 0} END {exit c}' $mapfile
1101 }
1102
1103 # find best compressor (or forced one) for initrd
1104 find_compressor() {
1105         local mode="$1"
1106         # fastest initrd decompression speed is first
1107         local compressors='lzo gzip xz lzma bzip2'
1108
1109         # a specified one, take it
1110         if ! is_yes "$mode"; then
1111                 compressors="$mode"
1112         fi
1113
1114         verbose "finding compressor: $compressors (via $mode)"
1115         # check for compressor validity
1116         local c prog map=/boot/System.map-$kernel
1117         for c in $compressors; do
1118                 case $c in
1119                 xz)
1120                         sym=unxz
1121                         prog=/usr/bin/xz
1122                         ;;
1123                 lzma)
1124                         sym=unlzma
1125                         prog=/usr/bin/xz
1126                         ;;
1127                 bzip2)
1128                         sym=bzip2
1129                         prog=/usr/bin/bzip2
1130                         ;;
1131                 gzip)
1132                         sym=gunzip
1133                         prog=/bin/gzip
1134                         ;;
1135                 lzo)
1136                         sym=unlzo
1137                         prog=/usr/bin/lzop
1138                         ;;
1139                 none|no)
1140                         # any existing sym will work
1141                         sym=initrd_load
1142                         prog=/bin/cat
1143                         ;;
1144                 *)
1145                         die "Unknown compressor $c"
1146                         ;;
1147                 esac
1148                 if sym_exists $map $sym && [ -x $prog ]; then
1149                         echo $c
1150                         return
1151                 fi
1152         done
1153
1154         verbose "using gzip for compressor (fallback)"
1155         echo gzip
1156 }
1157
1158 # compresses kernel image image
1159 # in function so we could retry with other compressor on failure
1160 compress_image() {
1161         local compressor="$1" IMAGE="$2" target="$3" tmp
1162         tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1163
1164         case "$compressor" in
1165         xz)
1166                 # don't use -9 here since kernel won't understand it
1167                 xz --format=xz --check=crc32 --lzma2=preset=6e,dict=1MiB < "$IMAGE" > "$tmp" || return $?
1168                 ;;
1169         lzma)
1170                 xz --format=lzma -9 < "$IMAGE" > "$tmp" || return $?
1171                 ;;
1172         bzip2)
1173                 bzip2 -9 < "$IMAGE" > "$tmp" || return $?
1174                 ;;
1175         gzip)
1176                 gzip -9 < "$IMAGE" > "$tmp" || return $?
1177                 ;;
1178         lzo)
1179                 lzop -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 case "$INITRDFS" in
1405   ext2)
1406         [ -x /sbin/mke2fs ] || die "/sbin/mke2fs is missing"
1407         ;;
1408   rom|romfs)
1409         [ -x /sbin/genromfs ] || die "/sbin/genromfs is missing"
1410         ;;
1411   cram|cramfs)
1412         [ -x /sbin/mkcramfs ] || die "/sbin/mkcramfs is missing"
1413         ;;
1414   initramfs)
1415         [ -x /bin/cpio ] || die "/bin/cpio is missing"
1416         [ -x /usr/bin/find ] || die "/usr/bin/find is missing"
1417         ;;
1418   *)
1419         die "Filesystem $INITRDFS on initrd is not supported"
1420         ;;
1421 esac
1422
1423 if [ -L "$target" ]; then
1424         target=$(readlink -f "$target")
1425 fi
1426
1427 if [ -n "$img_vers" ]; then
1428         target="$target-$kernel"
1429 fi
1430
1431 if [ -z "$force" -a -f "$target" ]; then
1432         die "$target already exists."
1433 fi
1434
1435 if [ ! -d "/lib/modules/$kernel" ]; then
1436         die "/lib/modules/$kernel is not a directory."
1437 fi
1438
1439 if [ "$kernel_version" -ge "002005" ]; then
1440         modext=".ko"
1441 fi
1442
1443 cache_modprobe_conf
1444
1445 for n in $PREMODS; do
1446         find_module "$n"
1447 done
1448
1449 if [ "$FBMODULE" ]; then
1450         find_module "$FBMODULE"
1451 fi
1452
1453 # autodetect USB keyboards
1454 find_modules_usbkbd
1455
1456 # allow forcing loading SCSI and/or IDE modules
1457 # XXX: where ADDSCSI cames from? drop?
1458 if is_yes "$ADDSCSI"; then
1459         find_modules_scsi
1460 fi
1461
1462 # autodetect SATA modules
1463 find_modules_sata
1464
1465 # XXX: where ADDIDE cames from? drop?
1466 if is_yes "$ADDIDE"; then
1467         find_modules_ide
1468 fi
1469
1470 if is_yes "$USE_SUSPEND"; then
1471         find_modules_suspend
1472 fi
1473
1474 find_root "$fstab" || exit
1475 verbose "Using $rootdev as device for rootfs"
1476
1477 find_modules_for_devpath "$rootdev"
1478
1479 # if USE_MULTIPATH is path to device, scan that too
1480 # this is to bootstrap multipath setup into initrd.
1481 if ! is_no "$USE_MULTIPATH" && ! is_yes "$USE_MULTIPATH"; then
1482         find_modules_multipath $USE_MULTIPATH
1483 fi
1484
1485 find_module "-$rootFs"
1486
1487 for n in $BASICMODULES; do
1488         find_module "$n"
1489 done
1490
1491 if is_yes "$USE_TUXONICE"; then
1492         find_module "-lzf"
1493 fi
1494
1495 find_modules_uvesafb
1496 find_modules_fbsplash
1497
1498 if [ -n "$ifneeded" -a -z "$MODULES" ]; then
1499         verbose "No modules are needed -- not building initrd image."
1500         exit 0
1501 fi
1502
1503 verbose "Building initrd..."
1504 DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
1505 RCFILE="$DESTDIR/linuxrc"
1506 > "$RCFILE"
1507 chmod a+rx "$RCFILE"
1508 ln -s linuxrc $DESTDIR/init
1509
1510 # create dirs that we really need
1511 inst_d /{lib,bin,etc,dev{,/pts,/shm},loopfs,var,proc,run,sys}
1512
1513 modules_install "$MODULES"
1514
1515 # mknod'ing the devices instead of copying them works both with and
1516 # without devfs...
1517 mknod -m 600 "$DESTDIR/dev/console" c 5 1
1518 mknod -m 666 "$DESTDIR/dev/null" c 1 3
1519 mknod -m 666 "$DESTDIR/dev/zero" c 1 5
1520 mknod -m 666 "$DESTDIR/dev/random" c 1 8
1521 mknod -m 666 "$DESTDIR/dev/urandom" c 1 9
1522 mknod -m 644 "$DESTDIR/dev/kmsg" c 1 11
1523
1524 inst_exec $busybox /bin/busybox
1525 ln -s busybox $DESTDIR/bin/sh
1526 # for older busyboxes who had /bin/initrd-busybox as EXEPATH
1527 ln -s busybox $DESTDIR/bin/initrd-busybox
1528
1529 add_linuxrc <<EOF
1530 #!/bin/sh
1531 # initrd generated by geninitrd/$VERSION
1532 # on $(LC_ALL=C date)
1533
1534 EOF
1535 load_font
1536 mount_proc
1537
1538 kmsg "geninitrd/$VERSION starting"
1539
1540 add_linuxrc <<-EOF
1541         # builtin defaults from geninitrd
1542         ROOT=$rootdev
1543         ROOTFS=$rootFs
1544 EOF
1545 add_linuxrc <<-'EOF'
1546         read CMDLINE < /proc/cmdline
1547
1548         for arg in $CMDLINE; do
1549                 if [ "${arg}" = "debuginitrd" ] || [ "${arg}" = "debugrd" ]; then
1550                         DEBUGINITRD=yes
1551                 fi
1552                 if [ "${arg##debuginitrd=}" != "${arg}" ] || [ "${arg##debugrd=}" != "${arg}" ]; then
1553                         DEBUGINITRD=${arg##debug*rd=}
1554                 fi
1555                 if [ "${arg##root=}" != "${arg}" ]; then
1556                         ROOT=${arg##root=}
1557                 fi
1558                 if [ "${arg##rootflags=}" != "${arg}" ]; then
1559                         ROOTFLAGS=${arg##rootflags=}
1560                 fi
1561                 if [ "${arg##rootfsflags=}" != "${arg}" ]; then
1562                         ROOTFSFLAGS=${arg##rootfsflags=}
1563                 fi
1564                 if [ "${arg##init=}" != "${arg}" ]; then
1565                         INIT=${arg##init=}
1566                 fi
1567         done
1568
1569         # handling of invalid, rootfsflags, option
1570         if [ -n "$ROOTFSFLAGS" ]; then
1571                 if [ -n "$ROOTFLAGS" ]; then
1572                         ROOTFLAGS="$ROOTFLAGS,$ROOTFSFLAGS"
1573                 else
1574                         ROOTFLAGS="$ROOTFSFLAGS"
1575                 fi
1576         fi
1577
1578         if [ "$DEBUGINITRD" = "sh" ]; then
1579                 # export some vars to subshell for debug to work
1580                 export CMDLINE ROOT ROOTFS ROOTDEV ROOTFLAGS DEBUGINITRD INIT
1581                 export LVM_ROOTVG LVM_SUSPENDVG LVM_VGVOLUMES
1582                 export rootnr attrs majmin major minor device
1583
1584                 # make debugshell() invoke subshell if $DEBUGINITRD=sh
1585                 debugshell() {
1586 EOF
1587 if is_yes "$RUN_SULOGIN_ON_ERR"; then
1588 add_linuxrc <<-'EOF'
1589         echo "debug shell disabled by RUN_SULOGIN_ON_ERR=yes from /etc/sysconfig/system during initrd generation time"
1590 EOF
1591 else
1592 add_linuxrc <<-'EOF'
1593         sh
1594 EOF
1595 fi
1596 add_linuxrc <<-'EOF'
1597                 }
1598         else
1599                 debugshell() {
1600                         :
1601                 }
1602         fi
1603
1604         if [ "$DEBUGINITRD" ]; then
1605                 set -x
1606         fi
1607 EOF
1608
1609 modules_add_linuxrc $MODULES
1610
1611 # TODO: rewrite for busybox
1612 #if [ -n "$loopDev" ]; then
1613 #       if [ ! -d /initrd ]; then
1614 #               mkdir /initrd
1615 #       fi
1616 #
1617 #       cp -a "$loopDev" "$DESTDIR/dev"
1618 #       cp -a "$rootdev" "$DESTDIR/dev"
1619 #       echo "echo Mounting device containing loopback root filesystem" >> "$RCFILE"
1620 #       echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE"
1621 #       echo "echo Setting up loopback device $rootdev" >> $RCFILE
1622 #       echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE"
1623 #fi
1624
1625 if is_yes "$USE_UDEV"; then
1626         initrd_gen_udev
1627 else
1628         initrd_gen_mdev
1629 fi
1630
1631 initrd_gen_uvesafb
1632 initrd_gen_luks
1633 initrd_gen_dmraid
1634 initrd_gen_multipath
1635 initrd_gen_blkid
1636
1637 if is_yes "$have_nfs"; then
1638         initrd_gen_nfs
1639 else
1640         initrd_gen_md
1641         initrd_gen_lvm
1642         initrd_gen_bcache
1643         initrd_gen_blkid
1644         initrd_gen_luks
1645         initrd_gen_setrootdev
1646 fi
1647
1648 # additional devs always needed
1649 [ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev
1650
1651 initrd_gen_stop_udevd
1652 initrd_gen_stop_mdev
1653 initrd_gen_stop_uvesafb
1654
1655 # resume after killing local processes
1656 initrd_gen_tuxonice
1657 initrd_gen_suspend
1658
1659 # clean up env
1660 add_linuxrc <<-'EOF'
1661 if [ ! "$DEBUGINITRD" ]; then
1662         ifs=$IFS
1663         IFS="
1664         "
1665         for i in $(export -p); do
1666                 i=${i#declare -x } # ksh/bash
1667                 i=${i#export } # busybox
1668
1669                 case "$i" in
1670                 *=*)
1671                         : ;;
1672                 *)
1673                         continue ;;
1674                 esac
1675
1676                 i=${i%%=*}
1677
1678                 [ -z "$i" ] && continue
1679
1680                 case "$i" in
1681                         ROOT|PATH|HOME|TERM)
1682                                 :
1683                                 ;;
1684                         *)
1685                                 unset $i
1686                                 ;;
1687                 esac
1688         done
1689         IFS=$ifs
1690 fi
1691 EOF
1692
1693 if [ "$INITRDFS" = "initramfs" ]; then
1694         initrd_gen_initramfs_switchroot
1695 else
1696         umount_all
1697 fi
1698
1699 initrd_gen_fbsplash
1700 initrd_gen_fbcondecor
1701
1702 debug "Current /linuxrc:\n$(sed -e 's,^,| ,' $DESTDIR/linuxrc)"
1703
1704 IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed"
1705
1706 IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
1707 verbose "image size: $IMAGESIZE KiB ($DESTDIR)"
1708
1709 verbose "Creating $INITRDFS image $IMAGE"
1710 case "$INITRDFS" in
1711   ext2)
1712         dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null
1713         # NOTE: ext2 label is max 16 chars
1714         mke2fs -q -F -b 1024 -m 0 -L "PLD/$kernel" "$IMAGE" 2>/dev/null 1>&2
1715         tune2fs -i 0 "$IMAGE" >/dev/null 2>&1
1716
1717         local tmpmnt=$(mktemp -d -t initrd.mnt-XXXXXX)
1718         debug "Mounting ext2 image $IMAGE to $tmpmnt"
1719         mount -o loop -t ext2 "$IMAGE" "$tmpmnt" || die "mount failed, check dmesg(1)"
1720         # We don't need this directory, so let's save space
1721         rm -rf "$tmpmnt"/lost+found
1722
1723         debug "Copy recursively $DESTDIR -> $tmpmnt"
1724         cp -a $DESTDIR/* $tmpmnt
1725         umount "$IMAGE"
1726         rmdir "$tmpmnt"
1727
1728         ;;
1729   rom|romfs)
1730         genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD Linux/$kernel (geninitrd/$VERSION)"
1731         ;;
1732   cram|cramfs)
1733         mkcramfs "$DESTDIR" "$IMAGE"
1734         ;;
1735   initramfs)
1736         (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
1737         ;;
1738   *)
1739         die "Filesystem $INITRDFS not supported by $PROGRAM"
1740 esac
1741
1742 CONFIG_BLK_DEV_RAM_SIZE=$(ikconfig | awk -F= '/^CONFIG_BLK_DEV_RAM_SIZE/{print $2}')
1743 if [ -z "$CONFIG_BLK_DEV_RAM_SIZE" ]; then
1744         CONFIG_BLK_DEV_RAM_SIZE=4096
1745         warn "No CONFIG_BLK_DEV_RAM_SIZE detected, fallback to $CONFIG_BLK_DEV_RAM_SIZE"
1746 fi
1747
1748 if [ "$IMAGESIZE" -gt $CONFIG_BLK_DEV_RAM_SIZE ]; then
1749         warn "Your image size is larger than $CONFIG_BLK_DEV_RAM_SIZE, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!"
1750 fi
1751
1752 if ! is_no "$COMPRESS"; then
1753         compressor=$(find_compressor "$COMPRESS")
1754         verbose "Compressing $target with $compressor"
1755
1756         # TODO: the image name (specified from kernel.spec) already contains
1757         # extension, which is .gz most of the time.
1758         compress_image "$compressor" "$IMAGE" "$target" || {
1759                 if [ $compressor != gzip ]; then
1760                         warn "Could not compress with $compressor, retrying with gzip"
1761                         compress_image gzip "$IMAGE" "$target" || die "compress failed with gzip" $?
1762                 else
1763                         die "Could not compress image with $compressor"
1764                 fi
1765         }
1766 else
1767         cp -a "$IMAGE" "$target"
1768 fi
1769
1770 # XXX. check if bootsplash can output data to tmp dir not directly to initramfs image.
1771 initrd_gen_bootsplash "$target"
1772
1773 rm -rf "$DESTDIR" "$IMAGE"
1774
1775 # vim:ts=4:sw=4:noet:fdm=marker
This page took 0.778854 seconds and 3 git commands to generate.