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