]> git.pld-linux.org Git - projects/geninitrd.git/blob - geninitrd
Revert "revert bogus commit"
[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 -o mode=0755,noexec,nosuid,nodev" | add_linuxrc
277 }
278
279 # unmount all mountpoints mounted by geninitrd
280 # try to move pseudo filesystems to newroot if possible
281 umount_all() {
282
283         add_linuxrc <<-'EOF'
284         : Last shell before umounting all and giving control over to real init.
285         debugshell
286         EOF
287
288         if is_yes "$run_mounted"; then
289                 add_linuxrc <<-EOF
290                 mount --bind /run /newroot/run
291                 umount /run
292                 EOF
293                 run_mounted=no
294         fi
295         if is_yes "$dev_mounted"; then
296                 add_linuxrc <<-EOF
297                 mount --bind /dev /newroot/dev
298                 umount /dev
299                 EOF
300                 dev_mounted=no
301         fi
302         if is_yes "$sys_mounted"; then
303                 add_linuxrc <<-EOF
304                 mount --bind /sys /newroot/sys
305                 umount /sys
306                 EOF
307                 sys_mounted=no
308         fi
309         if is_yes "$proc_mounted"; then
310                 add_linuxrc <<-EOF
311                 mount --bind /proc /newroot/proc
312                 umount /proc
313                 EOF
314                 proc_mounted=no
315         fi
316         if is_yes "$tmp_mounted"; then
317                 echo 'umount /tmp' | add_linuxrc
318                 tmp_mounted=no
319         fi
320 }
321
322 # Checks if busybox has support for APPLET(s)
323 # Exits from geninitrd if the support is not present.
324 #
325 # NB! XXX do not output to STDOUT, it will appear in initrd images in some cases!
326 busybox_applet() {
327         local err=0 applet
328
329         if [ -z "$busybox_functions" ]; then
330                 local tmp=$($busybox 2>&1)
331
332                 # BusyBox v1.1.3 says applet not found if it's not called 'busybox'.
333                 if [[ "$tmp" = *applet\ not\ found* ]]; then
334                         local t=$(mktemp -d)
335                         ln -s $busybox $t/busybox
336                         local tmp=$($t/busybox 2>&1)
337                         rm -rf $t
338                 fi
339
340                 busybox_functions=$(echo "$tmp" | \
341                         sed -ne '/Currently defined functions:/,$p' | \
342                         xargs | sed -e 's,.*Currently defined functions: ,,'
343                 )
344         fi
345         for applet in $*; do
346                 local have
347                 # try cache
348                 eval have='$'busybox_have_$applet
349                 if [ -z "$have" ]; then
350                         have=$(echo "$busybox_functions" | grep -Ec "( |^)$applet(,|$)")
351                         if [ "$have" = 0 ]; then
352                                 warn "This setup requires busybox-initrd compiled with applet '$applet' support"
353                                 err=1
354                         fi
355                         eval busybox_have_$applet=$have
356                 fi
357         done
358         if [ $err = 1 ]; then
359                 die "Aborted"
360         fi
361 }
362
363 # Extract the .config file from a kernel image
364 # uses extract-ikconfig from kernel sources (scripts/extract-ikconfig)
365 ikconfig() {
366         local kofile=$(modinfo -k $kernel -n configs 2> /dev/null)
367         if [ -n "$kofile" ]; then
368                 /lib/geninitrd/extract-ikconfig $kofile
369                 return
370         fi
371
372         # see if config available as separate file
373         if [ -f /boot/config-$kernel ]; then
374            cat /boot/config-$kernel
375            return
376         fi
377
378         # finally try vmlinuz itself
379         /lib/geninitrd/extract-ikconfig /boot/vmlinuz-$kernel
380 }
381
382 # @param    $module
383 basename_module() {
384         local module=$1
385
386         module=${module##*/}
387         module=${module%$modext*}
388         echo $module
389 }
390
391 # Finds module dependencies
392 #
393 # @param        $module
394 #
395 # Outputs full path to module and it's dependencies
396 find_depmod() {
397         local module="$1"
398         local skiperrors=0
399
400         # if module is prefixed with dash, we should ignore errors if the module
401         # can't be found.
402         if [ ${module#-} != $module ]; then
403                 skiperrors=1
404                 module=${module#-}
405         fi
406
407         # This works when user has module-init-tools installed even on 2.4 kernels
408         local modprobe
409         modprobe=$(modprobe --set-version $kernel --show-depends $module --ignore-install 2>&1)
410
411         if [ $? != 0 ]; then
412                 if [ $skiperrors = 1 ]; then
413                         return 0
414                 fi
415                 echo >&2 "$modprobe"
416
417                 if ! is_no "$EXIT_IF_MISSING"; then
418                         die "$module: module not found for $kernel kernel"
419                 fi
420
421                 warn "$module: module not found for $kernel kernel"
422                 warn "If $module isn't compiled in kernel then this initrd may not start your system."
423         fi
424
425         local smodule
426
427         echo "$modprobe" | \
428         while read insmod modpath options; do
429                 if [ "$insmod" = "insmod" ]; then
430
431                         # XXX: find a away to autodetect
432                         smodule=$(basename_module $modpath)
433                         case "$smodule" in
434                                 btrfs)
435                                         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                         function h2d(str, hstr, res, num, n, digit, i) {        # http://9fans.net/archive/2006/09/261
941                                 hstr = "0123456789abdcef"; res = 0;
942                                 n = split(tolower(str), digit, "");
943
944                                 for (i = 1; i <= n; i++) {
945                                         num = index(hstr, digit[i]) - 1;
946                                         res = res + (num * 16 ^ (n - i));
947                                 }
948                                 return res;
949                         }
950                         BEGIN {
951                                 num_pattern_short = "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]";
952                                 num_pattern = "[0-9a-fA-F]" num_pattern_short;
953                                 dev_pattern = "[hms][a-z][a-z]([0-9])+";
954                                 partition = ""; min = -1; maj = -1;
955
956                                 if (root ~ "^\/dev\/" dev_pattern "$" || root ~ "^" dev_pattern "$") {  # see if we have /dev/hdX or hdX, we can just take partition name
957                                         partition = root; sub("^/dev/", "", partition);
958                                 } else {        # unify values first
959                                         if (root ~ "^" num_pattern_short "$")  {        # change "303" => "0x0303"
960                                                 root = "0x0" root
961                                         } else if (root ~ "^" num_pattern "$")  {       # change "0303" => "0x0303"
962                                                 root = "0x" root
963                                         }
964                                         maj = h2d(substr(root, 3, 2));
965                                         min = h2d(substr(root, 5, 2));
966                                 }
967                         }
968                         partition && $4 == partition { maj = $1; min = $2; }
969                         $1 == maj && $2 == min { partition = $4; }
970                         END {
971                                 if (maj >= 0 && min >= 0) {     printf("maj=%s; min=%s;\n", maj, min);  }
972                                 if (partition) {                printf("device=/dev/%s;\n", partition); }
973                         }' /proc/partitions)"
974
975                 if [ -z "$device" ]; then
976                         if [ "$DEBUGINITRD" -a "$DEBUGINITRD" != 'sh' ]; then
977                                 cat /proc/partitions
978                         fi
979                         device=$ROOT
980                 fi
981
982                 if [ "$device" -a ! -b $device -a "$maj$min" ]; then
983                         mknod -m 660 $device b $maj $min
984                 fi
985
986                 # XXX hack, fallback to rootdev from geninitrd time
987                 if [ ! -e "$device" ]; then
988         EOF
989         add_linuxrc <<-EOF
990                         device="$rootdev"
991         EOF
992         add_linuxrc <<-'EOF'
993                         echo "DEVICE set to $device based on fstab entry from initrd gen time"
994                 fi
995
996                 # XXX hack, if no device, try to parse it from /proc/partitions using /proc/sys/kernel/real-root-dev
997                 if [ ! -e "$device" ]; then
998                         rrd=$(cat /proc/sys/kernel/real-root-dev)
999                         major=$(($rrd / 256))
1000                         minor=$(($rrd % 256))
1001
1002                         while read pmajor pminor blocks dev rest; do
1003                                 # skip header and empty line
1004                                 [ -z "$pmajor" -o "$pmajor" = "major" ] && continue
1005
1006                                 if [ $pmajor = $major -a $pminor = $minor ]; then
1007                                         device=/dev/$dev
1008                                         echo "DEVICE set to $device based on real-root-dev"
1009                                 fi
1010                         done < /proc/partitions
1011                 fi
1012
1013                 [ -n "$ROOTFLAGS" ] && ROOTFLAGS="-o $ROOTFLAGS"
1014
1015                 mount -t $ROOTFS -r $device $ROOTFLAGS /newroot || echo "Mount of rootfs failed."
1016                 init=$INIT
1017                 if [ -z "$init" -o ! -x "/newroot$init" ]; then
1018                         init=/sbin/init
1019                 fi
1020         EOF
1021
1022         busybox_applet dmesg
1023         busybox_applet tail
1024         add_linuxrc <<-'EOF'
1025                 if [ "$DEBUGINITRD" -a "$DEBUGINITRD" != 'sh' ]; then
1026                         echo "Last 20 lines of dmesg:"
1027                         dmesg | tail -n 20
1028                 fi
1029
1030         EOF
1031
1032         kmsg "geninitrd/$VERSION switching root"
1033
1034         umount_all
1035         busybox_applet switch_root usleep
1036         add_linuxrc <<-'EOF'
1037                 [ ! -e /newroot/dev/console ] && mknod -m 660 /newroot/dev/console c 5 1
1038
1039                 # switch root to empty dir will make kernel panic, so sleep 10s before it
1040                 # switch_root needs to be pid 1, so there's no other way to recover from here
1041                 # if /dev is missing, switch root will likely fail, give debug shell before that
1042                 if [ ! -d /newroot/dev ]; then
1043                         echo "/dev is missing, switch_root will likely fail"
1044                         echo "if you booted with debugrd=sh, then you be given shell and you might able to recover this situation"
1045                         debugshell
1046                         [ "$DEBUGINITRD" ] || usleep 10000000
1047                 fi
1048
1049                 # systemd[1]: /usr appears to be on its own filesytem and is not
1050                 # already mounted. This is not a supported setup. Some things will
1051                 # probably break (sometimes even silently) in mysterious ways. Consult
1052                 # http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken
1053                 # for more information.
1054                 echo trying to mount /usr
1055                 chroot /newroot mount -n /usr
1056
1057                 exec switch_root /newroot $init ${1:+"$@"}
1058
1059                 # FIXME: this code is never executed, as "exec" does not return!
1060
1061                 echo "Error! initramfs should not reach this place."
1062                 echo "It probably means you've got old version of busybox, with broken"
1063                 echo "initramfs support. Trying to boot anyway, but won't promise anything."
1064
1065                 exec chroot /newroot $init ${1:+"$@"}
1066
1067                 echo "Failed to chroot!"
1068                 debugshell
1069         EOF
1070         # we need /init being real file, not symlink, otherwise the initramfs will
1071         # not be ran by pid 1 which is required for switch_root
1072         mv $DESTDIR/linuxrc $DESTDIR/init
1073         ln -s init $DESTDIR/linuxrc
1074 }
1075
1076 # find if $symbol exists in System.map $mapfile
1077 sym_exists() {
1078         local mapfile="$1"
1079         local symbol="$2"
1080         if [ ! -f $mapfile ]; then
1081                 # missing mapfile (not a pld kernel?)
1082                 return 1
1083         fi
1084
1085         awk -vc=1 -vsymbol="$symbol" '($2 == "T" || $2 == "t") && $3 == symbol {c = 0} END {exit c}' $mapfile
1086 }
1087
1088 # find best compressor (or forced one) for initrd
1089 find_compressor() {
1090         local mode="$1"
1091         local compressors='xz lzma bzip2 gzip lzo'
1092
1093         # a specified one, take it
1094         if ! is_yes "$mode"; then
1095                 compressors="$mode"
1096         fi
1097
1098         verbose "finding compressor: $compressors (via $mode)"
1099         # check for compressor validity
1100         local c prog map=/boot/System.map-$kernel
1101         for c in $compressors; do
1102                 case $c in
1103                 xz)
1104                         sym=unxz
1105                         prog=/usr/bin/xz
1106                         ;;
1107                 lzma)
1108                         sym=unlzma
1109                         prog=/usr/bin/xz
1110                         ;;
1111                 bzip2)
1112                         sym=bzip2
1113                         prog=/usr/bin/bzip2
1114                         ;;
1115                 gzip)
1116                         sym=gunzip
1117                         prog=/bin/gzip
1118                         ;;
1119                 lzo)
1120                         sym=unlzo
1121                         prog=/usr/bin/lzop
1122                         ;;
1123                 none|no)
1124                         # any existing sym will work
1125                         sym=initrd_load
1126                         prog=/bin/cat
1127                         ;;
1128                 *)
1129                         die "Unknown compressor $c"
1130                         ;;
1131                 esac
1132                 if sym_exists $map $sym && [ -x $prog ]; then
1133                         echo $c
1134                         return
1135                 fi
1136         done
1137
1138         verbose "using gzip for compressor (fallback)"
1139         echo gzip
1140 }
1141
1142 # compresses kernel image image
1143 # in function so we could retry with other compressor on failure
1144 compress_image() {
1145         local compressor="$1" IMAGE="$2" target="$3" tmp
1146         tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1147
1148         case "$compressor" in
1149         xz)
1150                 # don't use -9 here since kernel won't understand it
1151                 xz --format=xz --check=crc32 --lzma2=preset=6e,dict=1MiB < "$IMAGE" > "$tmp" || return $?
1152                 ;;
1153         lzma)
1154                 xz --format=lzma -9 < "$IMAGE" > "$tmp" || return $?
1155                 ;;
1156         bzip2)
1157                 bzip2 -9 < "$IMAGE" > "$tmp" || return $?
1158                 ;;
1159         gzip)
1160                 gzip -9 < "$IMAGE" > "$tmp" || return $?
1161                 ;;
1162         lzo)
1163                 lzop -9 < "$IMAGE" > "$tmp" || return $?
1164                 ;;
1165         none|no)
1166                 cat < "$IMAGE" > "$tmp" || return $?
1167                 ;;
1168         esac
1169
1170         mv -f "$tmp" "$target"
1171 }
1172
1173 if [ -r /etc/sysconfig/geninitrd ]; then
1174         . /etc/sysconfig/geninitrd
1175 fi
1176
1177 if [ ! -f /proc/mounts ]; then
1178         warn "/proc filesystem not mounted, may cause wrong results or failure."
1179 fi
1180
1181 geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev tuxonice suspend fbsplash condecor bootsplash uvesafb nfs sata scsi usbkbd bcache
1182
1183 while [ $# -gt 0 ]; do
1184         case $1 in
1185         --fstab=*)
1186                 fstab=${1#--fstab=}
1187                 ;;
1188         --fstab)
1189                 fstab=$2
1190                 shift
1191                 ;;
1192         --modules-conf=*)
1193                 modulefile=${1#--modules-conf=}
1194                 ;;
1195         --modules-conf)
1196                 modulefile=$2
1197                 shift
1198                 ;;
1199         --with-bootsplash)
1200                 BOOT_SPLASH=yes
1201                 ;;
1202         --without-bootsplash)
1203                 BOOT_SPLASH=no
1204                 ;;
1205         --with-fbsplash)
1206                 FB_SPLASH=yes
1207                 ;;
1208         --without-fbsplash)
1209                 FB_SPLASH=no
1210                 ;;
1211         --with-fbcondecor)
1212                 FB_CON_DECOR=yes
1213                 ;;
1214         --without-fbcondecor)
1215                 FB_CON_DECOR=no
1216                 ;;
1217         --with-suspend)
1218                 USE_SUSPEND=yes
1219                 ;;
1220         --without-suspend)
1221                 USE_SUSPEND=no
1222                 ;;
1223         --with-suspend2 | --with-tuxonice)
1224                 USE_TUXONICE=yes
1225                 ;;
1226         --without-suspend2 | --without-tuxonice)
1227                 USE_TUXONICE=no
1228                 ;;
1229         --lvmversion=*)
1230                 LVMTOOLSVERSION=${1#--lvmversion=}
1231                 ;;
1232         --lvmtoolsversion=*)
1233                 LVMTOOLSVERSION=${1#--lvmtoolsversion=}
1234                 ;;
1235         --lvmtoolsversion|--lvmversion)
1236                 LVMTOOLSVERSION=$2
1237                 shift
1238                 ;;
1239         --without-udev)
1240                 USE_UDEV=no
1241                 ;;
1242         --with-udev)
1243                 USE_UDEV=yes
1244                 ;;
1245         --without-dmraid)
1246                 USE_DMRAID=no
1247                 ;;
1248         --without-multipath)
1249                 USE_MULTIPATH=no
1250                 ;;
1251         --with-multipath=*)
1252                 USE_MULTIPATH=${1#--with-multipath=}
1253                 ;;
1254         --without-blkid)
1255                 USE_BLKID=no
1256                 ;;
1257         --without-luks)
1258                 USE_LUKS=no
1259                 ;;
1260         --with=*)
1261                 BASICMODULES="$BASICMODULES ${1#--with=}"
1262                 ;;
1263         --with)
1264                 BASICMODULES="$BASICMODULES $2"
1265                 shift
1266                 ;;
1267         --version)
1268                 echo "$PROGRAM: version $VERSION"
1269                 exit 0
1270                 ;;
1271         -v)
1272                 if [ x"$verbose" = x"-v" ]; then
1273                         verbose="-v -v"
1274                 else
1275                         verbose="-v"
1276                 fi
1277                 exec 3>&1
1278                 ;;
1279         --compress)
1280                 COMPRESS=$2
1281                 ;;
1282         --compress=*)
1283                 COMPRESS="${1#--compress=}"
1284                 ;;
1285         --nocompress)
1286                 COMPRESS=no
1287                 ;;
1288         --nostrip)
1289                 STRIP=
1290                 ;;
1291         --strip=*)
1292                 STRIP="${1#--strip=}"
1293                 ;;
1294         --strip)
1295                 STRIP=$2
1296                 shift
1297                 ;;
1298         --ifneeded)
1299                 ifneeded=1
1300                 ;;
1301         -f)
1302                 force=1
1303                 ;;
1304         --preload=*)
1305                 PREMODS="$PREMODS ${1#--preload=}"
1306                 ;;
1307         --preload)
1308                 PREMODS="$PREMODS $2"
1309                 shift
1310                 ;;
1311         --fs=* | --fs)
1312                 die "--fs option is obsoleted. Use --initrdfs instead"
1313                 ;;
1314         --initrdfs=*)
1315                 INITRDFS=${1#--initrdfs=}
1316                 ;;
1317         --initrdfs)
1318                 INITRDFS=$2
1319                 shift
1320                 ;;
1321         --image-version)
1322                 img_vers=yes
1323                 ;;
1324         --ide-only-root)
1325                 ide_only_root="yes"
1326                 ;;
1327         *)
1328                 if [ -z "$target" ]; then
1329                         target="$1"
1330                 elif [ -z "$kernel" ]; then
1331                         kernel="$1"
1332                 else
1333                         usage
1334                         exit 1
1335                 fi
1336                 ;;
1337         esac
1338
1339         shift
1340 done
1341
1342 if [ -z "$target" -o -z "$kernel" ]; then
1343         usage
1344         exit 1
1345 fi
1346
1347 # main()
1348 if [ "$(id -u)" != 0 ]; then
1349         die "You need to be root to generate initrd"
1350 fi
1351
1352 for dir in libx32 lib64 lib; do
1353         initrd_dir=/usr/$dir/initrd
1354         if [ -d "$initrd_dir" ]; then
1355                 initrd_dirs="$initrd_dirs $initrd_dir"
1356         fi
1357 done
1358
1359 kernel_version=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d",$1,$2)}')
1360 kernel_version_long=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d%03d",$1,$2,$3)}')
1361
1362 verbose "# geninitrd $VERSION"
1363 debug "Using initrd_dir: $initrd_dir"
1364
1365 busybox=$(find_tool $initrd_dir/busybox $initrd_dir/initrd-busybox /bin/initrd-busybox) || die "Couldn't find busybox suitable for initrd"
1366
1367 # we setup mods after parsing command line args
1368 geninitrd_setup_mods
1369
1370 if [ ! -f /boot/vmlinuz-"$kernel" ]; then
1371         warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?"
1372 fi
1373
1374 if [ -z "$INITRDFS" ]; then
1375         if [ -n "$FS" ]; then
1376                 # FS= can came only via /etc/sysconfig/geninitrd likely?
1377                 die "FS configuration option is obsoleted. Use INITRDFS instead"
1378         fi
1379
1380         # default value
1381         if [ "$kernel_version" -ge "002005" ]; then
1382                 INITRDFS="initramfs"
1383         else
1384                 INITRDFS="rom"
1385         fi
1386 fi
1387
1388 check_initrd_fs() {
1389         local s sfound sym p prog map=/boot/System.map-$kernel
1390         case "$INITRDFS" in
1391                 ext2)
1392                         # TODO: symbols to check in case of ext2 used via ext3/4 subsystem
1393                         sym=init_ext2_fs
1394                         prog=/sbin/mke2fs
1395                         ;;
1396                 rom|romfs)
1397                         sym=init_romfs_fs
1398                         prog=/sbin/genromfs
1399                         ;;
1400                 cram|cramfs)
1401                         sym=init_cramfs_fs
1402                         prog=/sbin/mkcramfs
1403                         ;;
1404                 initramfs)
1405                         sym=__initramfs_start
1406                         prog="/bin/cpio /usr/bin/find"
1407                         ;;
1408                 *)
1409                         die "Filesystem $INITRDFS on initrd is not supported by geninitrd"
1410                         ;;
1411         esac
1412
1413         # only one is needed (for cases like ext2 via ext2 or via ext3 or via ext4 subsysytem)
1414         sfound=0
1415         for s in $sym; do
1416                 sym_exists $map $s && sfound=1
1417                 break
1418         done
1419         if [ "$sfound" -eq "0" ]; then
1420                 die "Filesystem $INITRDFS on initrd is not supported by kernel"
1421         fi
1422
1423         for p in $prog; do
1424                 [ ! -x "$p" ] && die "$prog is missing"
1425         done
1426 }
1427 check_initrd_fs
1428
1429 if [ -L "$target" ]; then
1430         target=$(readlink -f "$target")
1431 fi
1432
1433 if [ -n "$img_vers" ]; then
1434         target="$target-$kernel"
1435 fi
1436
1437 if [ -z "$force" -a -f "$target" ]; then
1438         die "$target already exists."
1439 fi
1440
1441 if [ ! -d "/lib/modules/$kernel" ]; then
1442         die "/lib/modules/$kernel is not a directory."
1443 fi
1444
1445 if [ "$kernel_version" -ge "002005" ]; then
1446         modext=".ko"
1447 fi
1448
1449 cache_modprobe_conf
1450
1451 for n in $PREMODS; do
1452         find_module "$n"
1453 done
1454
1455 if [ "$FBMODULE" ]; then
1456         find_module "$FBMODULE"
1457 fi
1458
1459 # autodetect USB keyboards
1460 find_modules_usbkbd
1461
1462 # allow forcing loading SCSI and/or IDE modules
1463 # XXX: where ADDSCSI cames from? drop?
1464 if is_yes "$ADDSCSI"; then
1465         find_modules_scsi
1466 fi
1467
1468 # autodetect SATA modules
1469 find_modules_sata
1470
1471 # XXX: where ADDIDE cames from? drop?
1472 if is_yes "$ADDIDE"; then
1473         find_modules_ide
1474 fi
1475
1476 if is_yes "$USE_SUSPEND"; then
1477         find_modules_suspend
1478 fi
1479
1480 find_root "$fstab" || exit
1481 verbose "Using $rootdev as device for rootfs"
1482
1483 find_modules_for_devpath "$rootdev"
1484
1485 # if USE_MULTIPATH is path to device, scan that too
1486 # this is to bootstrap multipath setup into initrd.
1487 if ! is_no "$USE_MULTIPATH" && ! is_yes "$USE_MULTIPATH"; then
1488         find_modules_multipath $USE_MULTIPATH
1489 fi
1490
1491 find_module "-$rootFs"
1492
1493 for n in $BASICMODULES; do
1494         find_module "$n"
1495 done
1496
1497 if is_yes "$USE_TUXONICE"; then
1498         find_module "-lzf"
1499 fi
1500
1501 find_modules_uvesafb
1502 find_modules_fbsplash
1503
1504 if [ -n "$ifneeded" -a -z "$MODULES" ]; then
1505         verbose "No modules are needed -- not building initrd image."
1506         exit 0
1507 fi
1508
1509 verbose "Building initrd..."
1510 DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
1511 RCFILE="$DESTDIR/linuxrc"
1512 > "$RCFILE"
1513 chmod a+rx "$RCFILE"
1514 ln -s linuxrc $DESTDIR/init
1515
1516 # create dirs that we really need
1517 inst_d /{lib,bin,etc,dev{,/pts,/shm},loopfs,var,proc,run,sys}
1518
1519 modules_install "$MODULES"
1520
1521 # mknod'ing the devices instead of copying them works both with and
1522 # without devfs...
1523 mknod -m 600 "$DESTDIR/dev/console" c 5 1
1524 mknod -m 666 "$DESTDIR/dev/null" c 1 3
1525 mknod -m 666 "$DESTDIR/dev/zero" c 1 5
1526 mknod -m 666 "$DESTDIR/dev/random" c 1 8
1527 mknod -m 666 "$DESTDIR/dev/urandom" c 1 9
1528 mknod -m 644 "$DESTDIR/dev/kmsg" c 1 11
1529
1530 inst_exec $busybox /bin/busybox
1531 ln -s busybox $DESTDIR/bin/sh
1532 # for older busyboxes who had /bin/initrd-busybox as EXEPATH
1533 ln -s busybox $DESTDIR/bin/initrd-busybox
1534
1535 add_linuxrc <<EOF
1536 #!/bin/sh
1537 # initrd generated by geninitrd/$VERSION
1538 # on $(LC_ALL=C date)
1539
1540 EOF
1541 load_font
1542 mount_proc
1543
1544 kmsg "geninitrd/$VERSION starting"
1545
1546 add_linuxrc <<-EOF
1547         # builtin defaults from geninitrd
1548         ROOT=$rootdev
1549         ROOTFS=$rootFs
1550 EOF
1551 add_linuxrc <<-'EOF'
1552         read CMDLINE < /proc/cmdline
1553
1554         for arg in $CMDLINE; do
1555                 if [ "${arg}" = "debuginitrd" ] || [ "${arg}" = "debugrd" ]; then
1556                         DEBUGINITRD=yes
1557                 fi
1558                 if [ "${arg##debuginitrd=}" != "${arg}" ] || [ "${arg##debugrd=}" != "${arg}" ]; then
1559                         DEBUGINITRD=${arg##debug*rd=}
1560                 fi
1561                 if [ "${arg##root=}" != "${arg}" ]; then
1562                         ROOT=${arg##root=}
1563                 fi
1564                 if [ "${arg##rootfs=}" != "${arg}" ]; then
1565                         ROOTFS=${arg##rootfs=}
1566                 fi
1567                 if [ "${arg##rootflags=}" != "${arg}" ]; then
1568                         ROOTFLAGS=${arg##rootflags=}
1569                 fi
1570                 if [ "${arg##rootfsflags=}" != "${arg}" ]; then
1571                         ROOTFSFLAGS=${arg##rootfsflags=}
1572                 fi
1573                 if [ "${arg##init=}" != "${arg}" ]; then
1574                         INIT=${arg##init=}
1575                 fi
1576         done
1577
1578         # handling of invalid, rootfsflags, option
1579         if [ -n "$ROOTFSFLAGS" ]; then
1580                 if [ -n "$ROOTFLAGS" ]; then
1581                         ROOTFLAGS="$ROOTFLAGS,$ROOTFSFLAGS"
1582                 else
1583                         ROOTFLAGS="$ROOTFSFLAGS"
1584                 fi
1585         fi
1586
1587         if [ "$DEBUGINITRD" = "sh" ]; then
1588                 # export some vars to subshell for debug to work
1589                 export CMDLINE ROOT ROOTFS ROOTDEV ROOTFLAGS DEBUGINITRD INIT
1590                 export LVM_ROOTVG LVM_SUSPENDVG LVM_VGVOLUMES
1591                 export rootnr attrs majmin major minor device
1592
1593                 # make debugshell() invoke subshell if $DEBUGINITRD=sh
1594                 debugshell() {
1595 EOF
1596 if is_yes "$RUN_SULOGIN_ON_ERR"; then
1597 add_linuxrc <<-'EOF'
1598         echo "debug shell disabled by RUN_SULOGIN_ON_ERR=yes from /etc/sysconfig/system during initrd generation time"
1599 EOF
1600 else
1601 add_linuxrc <<-'EOF'
1602         sh
1603 EOF
1604 fi
1605 add_linuxrc <<-'EOF'
1606                 }
1607         else
1608                 debugshell() {
1609                         :
1610                 }
1611         fi
1612
1613         if [ "$DEBUGINITRD" ]; then
1614                 set -x
1615         fi
1616 EOF
1617
1618 modules_add_linuxrc $MODULES
1619
1620 # TODO: rewrite for busybox
1621 #if [ -n "$loopDev" ]; then
1622 #       if [ ! -d /initrd ]; then
1623 #               mkdir /initrd
1624 #       fi
1625 #
1626 #       cp -a "$loopDev" "$DESTDIR/dev"
1627 #       cp -a "$rootdev" "$DESTDIR/dev"
1628 #       echo "echo Mounting device containing loopback root filesystem" >> "$RCFILE"
1629 #       echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE"
1630 #       echo "echo Setting up loopback device $rootdev" >> $RCFILE
1631 #       echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE"
1632 #fi
1633
1634 if is_yes "$USE_UDEV"; then
1635         initrd_gen_udev
1636 else
1637         initrd_gen_mdev
1638 fi
1639
1640 initrd_gen_uvesafb
1641 initrd_gen_luks
1642 initrd_gen_dmraid
1643 initrd_gen_multipath
1644 initrd_gen_blkid
1645
1646 if is_yes "$have_nfs"; then
1647         initrd_gen_nfs
1648 else
1649         initrd_gen_md
1650         initrd_gen_lvm
1651         initrd_gen_bcache
1652         initrd_gen_blkid
1653         initrd_gen_luks
1654         initrd_gen_setrootdev
1655 fi
1656
1657 # additional devs always needed
1658 [ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev
1659
1660 initrd_gen_stop_udevd
1661 initrd_gen_stop_mdev
1662 initrd_gen_stop_uvesafb
1663
1664 # resume after killing local processes
1665 initrd_gen_tuxonice
1666 initrd_gen_suspend
1667
1668 # clean up env
1669 add_linuxrc <<-'EOF'
1670 if [ ! "$DEBUGINITRD" ]; then
1671         ifs=$IFS
1672         IFS="
1673         "
1674         for i in $(export -p); do
1675                 i=${i#declare -x } # ksh/bash
1676                 i=${i#export } # busybox
1677
1678                 case "$i" in
1679                 *=*)
1680                         : ;;
1681                 *)
1682                         continue ;;
1683                 esac
1684
1685                 i=${i%%=*}
1686
1687                 [ -z "$i" ] && continue
1688
1689                 case "$i" in
1690                         ROOT|PATH|HOME|TERM)
1691                                 :
1692                                 ;;
1693                         *)
1694                                 unset $i
1695                                 ;;
1696                 esac
1697         done
1698         IFS=$ifs
1699 fi
1700 EOF
1701
1702 if [ "$INITRDFS" = "initramfs" ]; then
1703         initrd_gen_initramfs_switchroot
1704 else
1705         umount_all
1706 fi
1707
1708 initrd_gen_fbsplash
1709 initrd_gen_fbcondecor
1710
1711 debug "Current /linuxrc:\n$(sed -e 's,^,| ,' $DESTDIR/linuxrc)"
1712
1713 IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed"
1714
1715 IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
1716 verbose "image size: $IMAGESIZE KiB ($DESTDIR)"
1717
1718 verbose "Creating $INITRDFS image $IMAGE"
1719 case "$INITRDFS" in
1720   ext2)
1721         dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null
1722         # NOTE: ext2 label is max 16 chars
1723         mke2fs -q -F -b 1024 -m 0 -L "PLD/$kernel" "$IMAGE" 2>/dev/null 1>&2
1724         tune2fs -i 0 "$IMAGE" >/dev/null 2>&1
1725
1726         local tmpmnt=$(mktemp -d -t initrd.mnt-XXXXXX)
1727         debug "Mounting ext2 image $IMAGE to $tmpmnt"
1728         mount -o loop -t ext2 "$IMAGE" "$tmpmnt" || die "mount failed, check dmesg(1)"
1729         # We don't need this directory, so let's save space
1730         rm -rf "$tmpmnt"/lost+found
1731
1732         debug "Copy recursively $DESTDIR -> $tmpmnt"
1733         cp -a $DESTDIR/* $tmpmnt
1734         umount "$IMAGE"
1735         rmdir "$tmpmnt"
1736
1737         ;;
1738   rom|romfs)
1739         genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD Linux/$kernel (geninitrd/$VERSION)"
1740         ;;
1741   cram|cramfs)
1742         mkcramfs "$DESTDIR" "$IMAGE"
1743         ;;
1744   initramfs)
1745         (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
1746         ;;
1747   *)
1748         die "Filesystem $INITRDFS not supported by $PROGRAM"
1749 esac
1750
1751 CONFIG_BLK_DEV_RAM_SIZE=$(ikconfig | awk -F= '/^CONFIG_BLK_DEV_RAM_SIZE/{print $2}')
1752 if [ -z "$CONFIG_BLK_DEV_RAM_SIZE" ]; then
1753         CONFIG_BLK_DEV_RAM_SIZE=4096
1754         warn "No CONFIG_BLK_DEV_RAM_SIZE detected, fallback to $CONFIG_BLK_DEV_RAM_SIZE"
1755 fi
1756
1757 if [ "$IMAGESIZE" -gt $CONFIG_BLK_DEV_RAM_SIZE ]; then
1758         warn "Your image size is larger than $CONFIG_BLK_DEV_RAM_SIZE, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!"
1759 fi
1760
1761 if ! is_no "$COMPRESS"; then
1762         compressor=$(find_compressor "$COMPRESS")
1763         verbose "Compressing $target with $compressor"
1764
1765         # TODO: the image name (specified from kernel.spec) already contains
1766         # extension, which is .gz most of the time.
1767         compress_image "$compressor" "$IMAGE" "$target" || {
1768                 if [ $compressor != gzip ]; then
1769                         warn "Could not compress with $compressor, retrying with gzip"
1770                         compress_image gzip "$IMAGE" "$target" || die "compress failed with gzip" $?
1771                 else
1772                         die "Could not compress image with $compressor"
1773                 fi
1774         }
1775 else
1776         cp -a "$IMAGE" "$target"
1777 fi
1778
1779 # XXX. check if bootsplash can output data to tmp dir not directly to initramfs image.
1780 initrd_gen_bootsplash "$target"
1781
1782 rm -rf "$DESTDIR" "$IMAGE"
1783
1784 # vim:ts=4:sw=4:noet:fdm=marker
This page took 0.185557 seconds and 4 git commands to generate.