]> git.pld-linux.org Git - projects/geninitrd.git/blob - geninitrd
Always force firmware install.
[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 # TODO:
10 # - make udev start before insmods
11 # - make proper use of USE_UDEV - don't copy rules if USE_UDEV is off no!
12 #
13
14 RCSID='$Id$'
15 R=${RCSID#* * }; VERSION=${R%% *}
16 PROGRAM=${0##*/}
17
18 . /etc/rc.d/init.d/functions
19 . /etc/geninitrd/functions
20 . /etc/sysconfig/system
21
22 COMPRESS=yes
23 USERAIDSTART=yes
24 USEMDADMSTATIC=no
25 USEINSMODSTATIC=no
26 USE_SUSPEND=yes
27 USE_TUXONICE=no
28 # it should be safe to remove scsi_mod from here, but I'm not sure...
29 PRESCSIMODS="-scsi_mod unknown -sd_mod"
30 PREIDEMODS="-ide-core unknown -ide-detect -ide-disk"
31 PREIDEMODSOLD="-ide-probe -ide-probe-mod -ide-disk"
32 target=""
33 kernel=""
34 force=""
35 verbose=""
36 MODULES=""
37 img_vers=""
38 fstab=/etc/fstab
39 insmod=insmod
40 modext=.o
41 rootdev_nr=0
42 # device node for rootfs from fstab
43 rootdev=""
44 # requires bootsplash package to operate
45 BOOT_SPLASH=no
46 # requires splashutils package to operate
47 FB_SPLASH=no
48 # requires splashutils package to operate
49 FB_CON_DECOR=no
50
51 # internal variables
52 # is /dev on tmpfs
53 dev_mounted=no
54 # is /proc mounted
55 proc_mounted=no
56 # is /sys mounted
57 sys_mounted=no
58 # is /tmp mounted on tmpfs
59 tmp_mounted=no
60
61 # are /dev nodes already created from /proc/devices info?
62 proc_partitions=no
63
64 # LVM devices that should not be included in vgscan on initrd
65 lvm_ignore_devices=''
66
67 # whether v86d should be installed
68 need_v86d=0
69
70 # LVM volumes that are needed to activate
71 # VG for root dev
72 ROOTVG=""
73 # VG for suspend resume dev
74 SUSPENDVG=""
75
76 # resume device
77 resume_dev=""
78
79 # if we should init NFS at boot
80 have_nfs=no
81 # if we should init LVM at boot
82 have_lvm=no
83 # if we should init md (softraid) at boot
84 have_md=no
85 # if we should init dmraid at boot
86 have_dmraid=no
87 # if we should init dm-multipath at boot
88 have_multipath=no
89 # dm-multipath wwid which is used for rootfs
90 MPATH_WWID=
91
92 usage() {
93         uname_r=$(uname -r)
94         echo "usage: $PROGRAM [--version] [-v] [-f] [--ifneeded] [--preload <module>]"
95         echo "       [--with=<module>] [--image-version] [--fstab=<fstab>] [--nocompress]"
96         echo "       [--initrdfs=rom|initramfs|ext2|cram] [--modules-conf=<modules.conf>]"
97         echo "       [--with-raidstart] [--without-raidstart] [--with-insmod-static]"
98         echo "       [--with-bootsplash] [--without-bootsplash]"
99         echo "       [--with-fbsplash] [--without-fbsplash]"
100         echo "       [--with-fbcondecor] [--without-fbcondecor]"
101         echo "       [--lvmtoolsversion=1|2] [--with-udev] [--without-udev]"
102         echo "       [--with-suspend] [--without-suspend]"
103         echo "       [--with-tuxonice] [--without-tuxonice]"
104         echo "       [--without-dmraid] [--without-multipath]"
105         echo "       [--without-blkid]"
106         echo "       <initrd-image> <kernel-version>"
107         echo ""
108         echo "example:"
109         echo "  $PROGRAM -f --initrdfs=rom /boot/initrd-$uname_r.gz $uname_r"
110         exit 1
111 }
112
113 msg() {
114         echo "$PROGRAM: $*"
115 }
116
117 warn() {
118         msg "WARNING: $*" >&2
119 }
120
121 debug() {
122         [ -n "$verbose" ] && msg "$*" >&2
123 }
124
125 # aborts program abnormally
126 die() {
127         local rc=${2:-1}
128         warn "ERROR: $1"
129         exit $rc
130 }
131
132 # append text to /linuxrc
133 # takes STDIN as input
134 add_linuxrc() {
135         cat >> "$RCFILE"
136 }
137
138 # generate code to mount /dev on tmpfs and create initial nodes
139 # can be called multiple times. /dev is cleaned up (umounted) automatically at
140 # the end of script.
141 mount_dev() {
142     if [ "$INITRDFS" = "initramfs" ]; then
143                 # initramfs is read-write filesystem, no need for tmpfs
144                 return
145         fi
146
147         # we already generated tmpfs code; return
148         if is_yes "$dev_mounted"; then
149                 return
150         fi
151
152         dev_mounted=yes
153
154         busybox_applet mount mknod mkdir
155         add_linuxrc <<-EOF
156                 : 'Creating /dev'
157                 mount -o mode=0755 -t tmpfs none /dev
158                 mknod /dev/console c 5 1
159                 mknod /dev/null c 1 3
160                 mknod /dev/zero c 1 5
161                 mkdir /dev/pts
162                 mkdir /dev/shm
163         EOF
164 }
165
166 # generate code to mount /proc on initrd
167 # can be called multiple times
168 mount_proc() {
169         if is_yes "$proc_mounted"; then
170                 return
171         fi
172
173         proc_mounted=yes
174     if [ "$INITRDFS" = "initramfs" ]; then
175                 # /proc is mounted with initramfs 2.6.22.14 kernel
176                 # XXX: remove when it is clear why proc was already mounted
177                 echo "[ -f /proc/cmdline ] || mount -t proc none /proc" | add_linuxrc
178         else
179                 echo "mount -t proc none /proc" | add_linuxrc
180         fi
181 }
182
183 # generate code to mount /sys on initrd
184 # can be called multiple times
185 mount_sys() {
186         if is_yes "$sys_mounted"; then
187                 return
188         fi
189
190         sys_mounted=yes
191         echo "mount -t sysfs none /sys" | add_linuxrc
192 }
193
194 # generate code to mount /tmp on initrd
195 # can be called multiple times
196 mount_tmp() {
197     if [ "$INITRDFS" = "initramfs" ]; then
198                 # initramfs is read-write filesystem, no need for tmpfs
199                 return
200         fi
201
202         if is_yes "$tmp_mounted"; then
203                 return
204         fi
205
206         tmp_mounted=yes
207         echo "mount -t tmpfs none /tmp" | add_linuxrc
208 }
209
210 # unmount all mountpoints mounted by geninitrd
211 umount_all() {
212
213         add_linuxrc <<-'EOF'
214         : Last shell before umounting all and giving control over to real init.
215         debugshell
216         EOF
217
218         if is_yes "$dev_mounted"; then
219                 echo 'umount /dev' | add_linuxrc
220                 dev_mounted=no
221         fi
222         if is_yes "$proc_mounted"; then
223                 echo 'umount /proc' | add_linuxrc
224                 proc_mounted=no
225         fi
226         if is_yes "$sys_mounted"; then
227                 echo 'umount /sys' | add_linuxrc
228                 sys_mounted=no
229         fi
230         if is_yes "$tmp_mounted"; then
231                 echo 'umount /tmp' | add_linuxrc
232                 tmp_mounted=no
233         fi
234 }
235
236
237 # Checks if busybox has support for APPLET(s)
238 # Exits from geninitrd if the support is not present.
239 #
240 # NB! XXX do not output to STDOUT, it will appear in initrd images in some cases!
241 busybox_applet() {
242         local err=0
243
244         if [ -z "$busybox_functions" ]; then
245                 local tmp=$(/bin/initrd-busybox 2>&1)
246
247                 # BusyBox v1.1.3 says applet not found if it's not called 'busybox'.
248                 if [[ "$tmp" = *applet\ not\ found* ]]; then
249                         local t=$(mktemp -d)
250                         ln -s /bin/initrd-busybox $t/busybox
251                         local tmp=$($t/busybox 2>&1)
252                         rm -rf $t
253                 fi
254
255                 busybox_functions=$(echo "$tmp" | \
256                         sed -ne '/Currently defined functions:/,$p' | \
257                         xargs | sed -e 's,.*Currently defined functions: ,,'
258                 )
259         fi
260         for applet in $*; do
261                 local have
262                 # try cache
263                 eval have='$'busybox_have_$applet
264                 if [ -z "$have" ]; then
265                         have=$(echo "$busybox_functions" | egrep -c "( |^)$applet(,|$)")
266                         if [ "$have" = 0 ]; then
267                                 warn "This setup requires busybox-initrd compiled with applet '$applet' support"
268                                 err=1
269                         fi
270                         eval busybox_have_$applet=$have
271                 fi
272         done
273         if [ $err = 1 ]; then
274                 die "Aborted"
275         fi
276 }
277
278 # Finds module dependencies
279 #
280 # @param        $module
281 # @param        $mode   [silent]
282 #
283 # Outputs each dependant module full path including the module itself.
284 find_depmod() {
285         local module="$1"
286         local mode="$2"
287
288         # backwards compatible, process $mode
289         local modfile
290         if [ "$mode" = "silent" ]; then
291                 modfile=$(modinfo -k $kernel -n $module 2>/dev/null)
292         else
293                 modfile=$(modinfo -k $kernel -n $module)
294         fi
295         if [ ! -f "$modfile" ]; then
296                 if [ "$mode" != "silent" ]; then
297                         warn "$module: module not found for $kernel kernel"
298                 fi
299                 if ! is_no "$EXIT_IF_MISSING"; then
300                         exit 1
301                 else
302                         warn "If $module isn't compiled in kernel then this initrd may not start your system."
303                 fi
304         fi
305
306         # This works when user has module-init-tools installed even on 2.4 kernels
307         modprobe --set-version $kernel --show-depends $module | \
308         while read insmod modpath options; do
309                 echo $modpath
310         done
311 }
312
313 find_firmware() {
314         local module="$1"
315         echo -n $(modinfo -k $kernel -F firmware $module 2>/dev/null | xargs)
316 }
317
318 findmodule() {
319         local skiperrors=""
320         local modName=$1
321
322         if [ ${modName#-} != $modName ]; then
323                 skiperrors=1
324                 modName=${modName#-}
325         fi
326
327         # what's that?
328         if [ "$modName" = "pluto" ]; then
329                 findmodule fc4
330                 findmodule soc
331         fi
332         if [ "$modName" = "fcal" ]; then
333                 findmodule fc4
334                 findmodule socal
335         fi
336
337         local mod depmod
338         if [ "$skiperrors" = 1 ]; then
339                 depmod=$(find_depmod $modName silent)
340         else
341                 depmod=$(find_depmod $modName)
342                 if [ $? != 0 ]; then
343                         exit 1
344                 fi
345         fi
346
347         for mod in $depmod; do
348                 mod=${mod#/lib/modules/$kernel/}
349
350                 # add each module only once
351                 local m have=0
352                 for m in $MODULES; do
353                         [ $m = $mod ] && have=1
354                 done
355                 if [ $have = 0 ]; then
356                         MODULES="$MODULES $mod" 
357
358                         # if we are adding uvesafb, we need v86d as well
359                         if [ "$modName" = "uvesafb" ]; then
360                                 need_v86d=yes
361                         fi                              
362                 fi
363         done
364 }
365
366 # install a file to temporary mount image.
367 # it will operate recursively (copying directories)
368 # and will symlink destinations if source is symlink.
369 inst() {
370         if [ $# -lt 2 ]; then
371                 die 'Usage: inst <file> [<file>] <destination>'
372         fi
373
374         local src i=0 c=$(($# - 1))
375         while [ $i -lt $c ]; do
376                 src="$src $1"
377                 i=$((i + 1))
378                 shift
379         done
380         local dest=$1
381         set -- $src
382
383         debug "+ cp $* $DESTDIR$dest"
384         cp -HR "$@" "$DESTDIR$dest"
385 }
386
387 inst_d() {
388         if [ $# = 0 ]; then
389                 die 'Usage: inst_d <destination> <destination>'
390         fi
391         for dir in "$@"; do
392                 install -d "$DESTDIR$dir"
393         done
394 }
395
396 # install executable and it's shared libraries
397 inst_exec() {
398         if [ $# -lt 2 ]; then
399                 die 'Usage: inst_exec <file> [, <file>] <destination>'
400         fi
401         local src i=0 c=$(($# - 1))
402         while [ $i -lt $c ]; do
403                 src="$src $1"
404                 i=$((i + 1))
405                 shift
406         done
407         local dest=$1
408         set -- $src
409
410         inst "$@" $dest
411
412         local lib libs=$(ldd "$@" | awk '/statically|linux-gate\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
413         for lib in $libs; do
414                 if [ ! -f "$DESTDIR/$_lib/${lib##*/}" ]; then
415                         inst_d /$_lib
416                         inst_exec $lib /$_lib
417                 fi
418         done
419 }
420
421 # output modules.conf / modprobe.conf
422 modprobe_conf() {
423         echo "$modprobe_conf_cache"
424 }
425
426 #
427 # defaults to modprobe -c if not told otherwise, this means include statements
428 # work from there.
429 cache_modprobe_conf() {
430         if [ "$pack_version" -lt "002005" ]; then
431                 modulefile=/etc/modules.conf
432                 if [ ! -f "$modulefile" -a -f /etc/conf.modules ]; then
433                         modulefile=/etc/conf.modules
434                 fi
435         fi
436
437         if [ -n "$modulefile" ]; then
438                 debug "Using $modulefile for modules config"
439                 modprobe_conf_cache=$(cat $modulefile)
440         else
441                 debug "Using modprobe -c to get modules config"
442                 modprobe_conf_cache=$(modprobe -c)
443         fi
444 }
445
446 find_modules_md() {
447         local found raidlevel
448
449         if [ -f /etc/mdadm.conf ]; then
450                 debug "Finding RAID details using mdadm for rootdev=$1"
451                 eval `/sbin/mdadm -v --examine --scan --config=/etc/mdadm.conf | awk -v rootdev="$1" '
452                 BEGIN {
453                         found = "no";
454                         dev_list = "";
455                         raidlevel = ""
456                         rootdev_devfs = rootdev;
457                         if (rootdev ~ /\/dev\/md\/[0-9]/) {
458                                 gsub(/\/dev\/md\//,"/dev/md",rootdev_devfs);
459                         }
460                 }
461
462                 /^ARRAY/ {
463                         if (($2 == rootdev) || ($2 == rootdev_devfs)) {
464                                 raidlevel=$3;
465                                 gsub(/level=/,NUL,raidlevel);
466                                 if (raidlevel ~ /^raid([0-6]|10)/) {
467                                         gsub(/raid/,NUL,raidlevel);
468                                 };
469                                 found="yes";
470                                 getline x;
471                                 if (x ~ /devices=/) {
472                                         dev_list = x;
473                                         gsub(".*devices=", NUL, dev_list);
474                                         gsub(",", " ", dev_list);
475                                 }
476                         }
477                 }
478
479                 END {
480                         print "have_md=" found;
481                         print "raidlevel=" raidlevel;
482                         print "dev_list=\"" dev_list "\"";
483                 }'`
484         fi
485
486         if [ "$have_md" != "yes" -a -f /etc/raidtab ]; then
487                 die "raidtools are not longer supported. Please migrate to mdadm setup!"
488         fi
489
490         if is_yes "$have_md"; then
491                 case "$raidlevel" in
492                 [01]|10)
493                         findmodule "raid$raidlevel"
494                         ;;
495                 [456])
496                         findmodule "-raid$raidlevel"
497                         findmodule "-raid456"
498                         ;;
499                 linear)
500                         findmodule "linear"
501                         ;;
502                 *)
503                         warn "raid level $number (in mdadm config) not recognized"
504                         ;;
505                 esac
506         else
507                 die "RAID devices not found for \"$1\", check your configuration!"
508         fi
509
510         rootdev_nr=$(( $rootdev_nr + 1 ))
511         eval "rootdev${rootdev_nr}=\"$1\""
512         eval "dev_list${rootdev_nr}=\"${dev_list}\""
513
514         for device in $dev_list; do
515                 find_modules_for_devpath $device
516         done
517 }
518
519 find_modules_scsi() {
520         local n
521         for n in $PRESCSIMODS; do
522                 if [ "X$n" = "Xunknown" ]; then
523                         debug "Finding SCSI modules using scsi_hostadapter"
524                         local mod scsimodules=$(modprobe_conf | awk '/scsi_hostadapter/ && ! /^[\t ]*#/ { print $3; }')
525                         for mod in $scsimodules; do
526                                 # for now allow scsi modules to come from anywhere. There are some
527                                 # RAID controllers with drivers in block
528                                 findmodule "$mod"
529                         done
530                 else
531                         findmodule "$n"
532                 fi
533         done
534         findmodule "-scsi_wait_scan"
535 }
536
537 find_modules_ide() {
538         local devpath=$1
539         # remove partition, if any
540         local disk=${devpath%[0-9]*}
541         # set blockdev for rootfs (hda, sdc, ...)
542         local rootblkdev=${disk#/dev/}
543
544         local n
545         if [ "$pack_version_long" -lt "002004021" ]; then
546                 debug "Finding IDE modules for kernels <= 2.4.20"
547                 for n in $PREIDEMODSOLD; do
548                         findmodule "$n"
549                 done
550         else
551                 local tryauto=1
552                 for n in $PREIDEMODS; do
553                         if [ "X$n" = "Xunknown" ]; then
554                                 debug "Finding IDE modules using ide_hostadapter"
555                                 local mod idemodules=$(modprobe_conf | awk '/ide_hostadapter/ && ! /^[\t ]*#/ { print $3; }')
556                                 for mod in $idemodules; do
557                                         tryauto=0;
558                                         findmodule "$mod"
559                                 done
560
561                                 if [ "$tryauto" -eq 1 ]; then
562                                         # If tryauto {{{
563                                         if [ -r /usr/share/pci-database/ide.pci -a -r /proc/bus/pci/devices ]; then
564                                                 debug "Finding IDE modules using PCI ID database"
565                                                 # Finding IDE modules using PCI ID database {{{
566                                                 if is_yes "${ide_only_root}"; then
567                                                         if [ -f /sys/block/${rootblkdev}/device/../../vendor -a -f /sys/block/${rootblkdev}/device/../../device ]; then
568                                                                 vendorid="$(awk ' { gsub(/0x/,NUL); print $0 } ' /sys/block/${rootblkdev}/device/../../vendor)"
569                                                                 deviceid="$(awk ' { gsub(/0x/,NUL); print $0 } ' /sys/block/${rootblkdev}/device/../../device)"
570                                                                 searchpciid="${vendorid}${deviceid}"
571                                                         elif [ -f /proc/ide/${rootblkdev}/../config ]; then
572                                                                 searchpciid="$(awk ' /pci bus/ { print $7$9 } ' /proc/ide/${rootblkdev}/../config)"
573                                                         fi
574                                                 fi
575
576                                                 if [ -z "${searchpciid}" ]; then
577                                                         searchpciid="$(awk ' { print $2 } ' /proc/bus/pci/devices)"
578                                                 fi
579
580                                                 idemodules=""
581
582                                                 for nb in $searchpciid; do
583                                                         eval `awk -v pciid="$nb" '{
584                                                                 gsub("\t"," ");
585                                                                 gsub("  +", " ");
586                                                                 gsub("^ ","");
587                                                                 if (/^[\t ]*#/)
588                                                                         next;
589                                                                 compmod = $1 "";        # make sure comparison type will be string
590                                                                                         # cause pci IDs are hexadecimal numeric
591                                                                 if (compmod == pciid) {
592                                                                         module=$2;
593                                                         #               min_kernel=$3;  # now in ide.pci $3,$4 = vendor and device name
594                                                         #               max_kernel=$4;  #
595                                                                         exit 0;
596                                                                 }
597                                                         }
598
599                                                         END {
600                                                                 print "module=" module "\nmin_kernel=" min_kernel "\nmax_kernel=\"" max_kernel "\"\n";
601                                                         }' /usr/share/pci-database/ide.pci`
602                                                         [ -n "$module" ] && idemodules="$idemodules $module"
603                                                 done
604                                                 if is_yes "$(awk ' /ide=reverse/ { print "yes" } ' /proc/cmdline)"; then
605                                                         new_idemodules=""
606                                                         for nc in idemodules; do
607                                                                 new_idemodules="$nc $new_idemodules"
608                                                         done
609                                                         idemodules="${new_idemodules}"
610                                                 fi
611
612                                                 if [ -z "$idemodules" ]; then
613                                                         echo "WARNING: rootfs on IDE device but no related modules found, loading ide-generic."
614                                                         idemodules="ide-generic"
615                                                 fi
616
617                                                 # }}}
618                                                 for nd in $idemodules; do
619                                                         findmodule "-$nd"
620                                                 done
621                                         # }}}
622                                         # else tryauto {{{
623                                         else
624                                                 [ -r /usr/share/pci-database/ide.pci ] || echo "WARNING: /usr/share/pci-database/ide.pci missing."
625                                                 [ -r /proc/bus/pci/devices ] || echo "WARNING: /proc/bus/pci/devices missing."
626                                                 echo "Automatic IDE modules finding not available."
627                                         fi
628                                         # }}}
629                                 fi
630                         else
631                                 findmodule "$n"
632                         fi
633                 done
634         fi
635 }
636
637 # return true if node is lvm node
638 is_lvm_node() {
639         local node="$1"
640         if [ ! -e "$node" ]; then
641                 warn "WARNING: check_lvm(): node $node doesn't exist!"
642                 return 1
643         fi
644
645         # block-major-58 is lvm1
646         ls -lL "$node" 2> /dev/null | awk '{if (/^b/) { if ($5 == "58,") { exit 0; } else { exit 1; } } else { exit 1; }}'
647         rc=$?
648
649         if [ $rc = 0 ]; then
650                 debug "LVM check: $node is LVM v1 node"
651                 # is lvm1
652                 return 0
653         fi
654
655         if [ ! -x /sbin/lvm ]; then
656                 debug "LVM check: no lvm2 tools present to check"
657                 return 0
658         fi
659
660         /sbin/lvm lvdisplay "$node" > /dev/null 2>&1
661         rc=$?
662         if [ $rc -gt 127 ]; then
663                 # lvdisplay terminated by signal! most likely it segfaulted.
664                 die "Unexpected exit from 'lvdisplay $node': $rc - are your lvm tools broken?"
665         fi
666
667         if [ $rc = 0 ]; then
668                 debug "LVM check: $node is LVM v2 node"
669         else
670                 debug "LVM check: $node is not any LVM node"
671         fi
672         return $rc
673 }
674
675 # return dependencies MAJOR:MINOR [MAJOR:MINOR] for DM_NAME
676 # TODO: patch `dmsetup export`
677 dm_deps() {
678         local dm_name="$1"
679         dmsetup deps $dm_name | sed -e 's/, /:/g;s/^.\+ dependencies[^:]: //;s/[()]//g;'
680 }
681
682 # export info from dmsetup
683 # param can be:
684 # - MAJOR:MINOR
685 # - /dev/dm-MINOR
686 # - /dev/mapper/DM_NAME
687 dm_export() {
688         local arg="$1"
689
690         case "$arg" in
691         *:*)
692                 local maj=${arg%:*} min=${arg#*:}
693                 dmsetup -j $maj -m $min export
694                 ;;
695         /dev/dm-*)
696                 local min=${arg#*dm-}
697                 local maj=$(awk '$2 == "device-mapper" {print $1}' /proc/devices)
698                 dm_export $maj:$min
699                 ;;
700         /dev/mapper/*)
701                 local dm_name=${arg#/dev/mapper/}
702                 dmsetup export $dm_name
703                 ;;
704         *)
705                 die "dm_export: unexpected $arg"
706                 ;;
707         esac
708 }
709
710 # find dm-multipath modules for $devpath
711 # returns false if $devpath is not dm-multipath
712 find_modules_multipath() {
713         local devpath="$1"
714
715         DM_NAME=
716         eval $(dm_export "$devpath")
717         if [ -z "$DM_NAME" ]; then
718                 die "dm_export failed unexpectedly"
719         fi
720
721         # Partition:
722         #  DM_NAME=LUN-28p1
723         #  DM_UUID=part1-mpath-36006016002c11800a0aa05fbfae0db11
724         # Disk:
725         #  DM_NAME=LUN-28
726         #  DM_UUID=mpath-36006016002c11800a0aa05fbfae0db11
727         MPATH_WWID=${DM_UUID##*-}
728
729         local info=$(multipath -l $MPATH_WWID)
730         if [ -z "$info" ]; then
731                 return 1
732         fi
733
734         debug "Finding modules for dm-multipath (WWID=$MPATH_WWID)"
735         have_multipath=yes
736         local dev phydevs=$(echo "$info" | awk '$2 ~ /^[0-9]+:[0-9]+:[0-9]+:[0-9]+$/{printf("/dev/%s\n", $3)}')
737         for dev in $phydevs; do
738                 find_modules_for_devpath $dev
739                 lvm_ignore_devices="$lvm_ignore_devices $dev"
740         done
741
742         local hw hwhandlers=$(echo "$info" | awk '/hwhandler=1/{sub(/.*hwhandler=1 /, ""); sub(/\]$/, ""); print}')
743         for hw in $hwhandlers; do
744                 findmodule "dm-$hw"
745         done
746
747         local target targets=$(echo "$info" | awk '/prio=/{print $2}' | sort -u)
748         for target in $targets; do
749                 findmodule "dm-$target"
750         done
751
752         findmodule "dm-mod"
753         return 0
754 }
755
756 # find dmraid modules for $devpath
757 # returns false if $devpath is not on dmraid
758 find_modules_dmraid() {
759         local devpath="$1"
760
761         # get blockdev itself (without partition)
762         # /dev/mapper/sil_ahbgadcbchfc3 -> /dev/mapper/sil_ahbgadcbchfc
763         local blockdev=${devpath%%[0-9]*}
764         local raidname=${blockdev#/dev/mapper/}
765         local found=0
766
767         local dev phydevs=$(dmraid -r -cdevpath,raidname | awk -F, -vv="$raidname" '{if ($2 == v) print $1}')
768         for dev in $phydevs; do
769                 find_modules_for_devpath $dev
770                 lvm_ignore_devices="$lvm_ignore_devices $dev"
771                 found=1
772         done
773
774         if [ $found = 0 ]; then
775                 return 1
776         fi
777
778         findmodule "dm-mirror"
779         have_dmraid=yes
780         return 0
781 }
782
783 # find modules for $devpath
784 find_modules_for_devpath() {
785         local devpath="$1"
786         if [ -z "$devpath" ]; then
787                 die "No argument passed to find_modules_for_devpath() - is your /etc/fstab correct?"
788         fi
789
790         # /dev/dm-3 -> /dev/mapper/sil_ahbgadcbchfc3
791         case "$devpath" in
792         /dev/dm-*)
793                 devpath=$(dm_longname "$devpath")
794                 ;;
795         esac
796         debug "Finding modules for device path $devpath"
797
798         if is_yes "`echo "$devpath" | awk '/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:|\/dev\/nfs)/ { print "yes"; }'`"; then
799                 if [ ! -x /usr/bin/pcidev -a -z "$NFS_ETH_MODULES" ]; then
800                         die "root on NFS but /usr/bin/pcidev not found. Please install correct pci-database package and rerun $PROGRAM."
801                 fi
802                 if [ ! -f /proc/bus/pci/devices ]; then
803                         warn "Remember to add network card modules in /etc/sysconfig/geninitrd, example:"
804                         warn "BASICMODULES=\"e1000 ne2k-pci mii 8139too 3c59x\""
805                 else
806                         local m
807                         [ -z "$NFS_ETH_MODULES" ] && NFS_ETH_MODULES=$(/usr/bin/pcidev /m net | xargs)
808                         warn "NOTE: Network card(s) module(s) $NFS_ETH_MODULES is for this machine"
809                         for m in $NFS_ETH_MODULES; do
810                                 findmodule "$m"
811                         done
812                 fi
813                 findmodule "-ipv4"
814                 findmodule "nfs"
815                 have_nfs=yes
816                 warn "Remember to use \`root=/dev/ram0 init=/linuxrc' when starting kernel"
817                 warn "or you will have problems like init(xx) being child process of swapper(1)."
818                 return
819         fi
820
821         if [[ "$devpath" == /dev/md* ]]; then
822                 find_modules_md "$devpath"
823                 return
824         fi
825
826         if is_yes "$USE_MULTIPATH" && [[ "$devpath" == /dev/mapper/* ]]; then
827                 if find_modules_multipath "$devpath"; then
828                         return
829                 fi
830                 # fallback
831         fi
832
833         if is_yes "$USE_DMRAID" && is_yes "$(echo "$devpath" | awk '/^\/dev\/mapper\/(sil|hpt37x|hpt45x|isw|lsi|nvidia|pdc|sil|via|dos)_/ { print "yes"; }')"; then
834                 if find_modules_dmraid "$devpath"; then
835                         return
836                 fi
837                 # fallback
838         fi
839
840         if is_yes "$(echo "$devpath" | awk '/^\/dev\/(sd|scsi)/ { print "yes"; }')"; then
841                 find_modules_scsi
842                 return
843         fi
844
845         if is_yes "$(echo "$devpath" | awk '/^\/dev\/(hd|ide)/ { print "yes"; }')"; then
846                 find_modules_ide "$devpath"
847                 return
848         fi
849
850         if [[ "$devpath" == /dev/rd/* ]]; then
851                 findmodule "DAC960"
852                 rootdev_add="/dev/rd"
853                 return
854         fi
855
856         if [[ "$devpath" == /dev/ida/* ]]; then
857                 findmodule "cpqarray"
858                 rootdev_add="/dev/ida"
859                 return
860         fi
861
862         if [[ "$devpath" == /dev/cciss/* ]]; then
863                 findmodule "cciss"
864                 rootdev_add="/dev/cciss/"
865                 return
866         fi
867
868         if [[ "$devpath" == /dev/ataraid/* ]]; then
869                 find_modules_ide
870                 findmodule "ataraid"
871                 ataraidmodules=$(modprobe_conf | awk '/ataraid_hostadapter/ && ! /^[\t ]*#/ { print $3; }')
872                 if [ -n "$ataraidmodules" ]; then
873                         # FIXME: think about modules compiled in kernel
874                         die "ataraid_hostadapter alias not defined in modprobe.conf! Please set it and run $PROGRAM again."
875                 fi
876                 for n in $ataraidmodules; do
877                         findmodule "$n"
878                 done
879                 rootdev_add="/dev/ataraid/"
880                 return
881         fi
882
883         # check to see if we need to set up a loopback filesystem
884         if [[ "$devpath" == /dev/loop*  ]]; then
885                 die "Sorry, root on loop device isn't supported."
886                 # TODO: rewrite for bsp and make nfs ready
887                 if [ ! -x /sbin/losetup ]; then
888                         die "losetup is missing"
889                 fi
890                 key="^# $(echo $devpath | awk -F/ '{print($3);}' | tr '[a-z]' '[A-Z]'):"
891                 if ! is_yes "`awk '/'$key'/ { print( "yes"); }' $fstab`"; then
892                         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"
893                 fi
894
895                 line="`awk '/'$key'/ { print $0; }' $fstab`"
896                 loopDev="$(echo $line | awk '{print $3}')"
897                 loopFs="$(echo $line | awk '{print $4}')"
898                 loopFile="$(echo $line | awk '{print $5}')"
899
900                 BASICMODULES="$BASICMODULES -loop"
901                 findmodule "-$loopFs"
902                 BASICMODULES="$BASICMODULES -${loopFs}"
903                 return
904         fi
905
906         if is_lvm_node "$devpath"; then
907                 node="$devpath"
908
909                 if [ ! -f /sbin/initrd-lvm -o ! -x /sbin/lvdisplay -o ! -x /sbin/pvdisplay ]; then
910                         die "root on LVM but /sbin/initrd-lvm, /sbin/lvdisplay and /sbin/pvdisplay not found. Please install lvm(2) and lvm(2)-initrd package and rerun $PROGRAM."
911                 fi
912                 if [ -z "$LVMTOOLSVERSION" ]; then
913                         LVMTOOLSVERSION=$(/sbin/initrd-lvm vgchange --version 2>/dev/null|head -n 1|awk '{gsub("vgchange: Logical Volume Manager ",NIL); gsub("LVM version:     ",NIL); gsub(/\..*/,NIL); print $1}')
914                         if [ -z "$LVMTOOLSVERSION" ]; then
915                                 die "Can't determine LVM tools version. Please set LVMTOOLSVERSION and rerun $PROGRAM."
916                         fi
917                 fi
918
919                 local vg=$(/sbin/lvdisplay -c "$node" 2> /dev/null | awk -F":" ' { print $2 } ')
920                 VGVOLUMES=$(echo $VGVOLUMES $vg | tr ' ' '\n' | sort -u)
921                 local pv=$(/sbin/pvdisplay -c 2>/dev/null | awk -F":" -v vg="$vg" ' BEGIN { devices="" } { if ($2 == vg) { devices = devices " " $1 } } END { print devices } ')
922                 PVDEVICES=$(echo $PVDEVICES $pv | tr ' ' '\n' | sort -u)
923
924                 if [ -n "$PVDEVICES" ]; then
925                         for device in $PVDEVICES; do
926                                 find_modules_for_devpath $device
927                         done
928                 else
929                         die "I wasn't able to find PV (via lvdisplay and pvdisplay). You can try to set PVDEVICES in /etc/sysconfig/geninitrd."
930                 fi
931                 if [ "$LVMTOOLSVERSION" = "2" ]; then
932                         findmodule "-dm-mod"
933                 elif [ "$LVMTOOLSVERSION" = "1" ]; then
934                         findmodule "-lvm"
935                         findmodule "-lvm-mod"
936                 else
937                         die "LVM version $LVMTOOLSVERSION is not supported yet."
938                 fi
939                 debug "LVM v$LVMTOOLSVERSION enabled"
940                 have_lvm=yes
941                 return
942         fi
943 }
944
945 firmware_install_module() {
946         local module="$1"
947         local firmware_files="$2"
948
949         debug "Adding Firmwares ($firmware_files) to initrd for module $module"
950         # firmware not yet installed
951         if [ ! -f "$DESTDIR/lib/firmware/firmware.sh" ]; then
952                 inst_d /lib/firmware
953 cat << 'EOF' >> "$DESTDIR/lib/firmware/firmware.sh"
954 #!/bin/sh -e
955 echo 1 > /sys$DEVPATH/loading
956 cat "/lib/firmware/$FIRMWARE" > /sys$DEVPATH/data
957 echo 0 > /sys$DEVPATH/loading
958 exit 0
959 EOF
960                 chmod 755 "$DESTDIR/lib/firmware/firmware.sh"
961         fi
962
963         for firmware in $firmware_files; do
964                 if [ ! -f "/lib/firmware/$firmware" ]; then
965                                 die "firmware file /lib/firmware/$firmware doesn't exist."
966                 else
967                         FIRMWAREDIR=${firmware%/*}
968                         [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
969                         inst /lib/firmware/$firmware $DESTDIR/lib/firmware/$firmware
970                 fi
971         done
972
973         mount_sys
974         echo "echo -n "/lib/firmware/firmware.sh" > /proc/sys/kernel/hotplug" | add_linuxrc
975 }
976
977 modules_install() {
978         local modules="$1"
979         local mod
980
981         for mod in $modules; do
982                 MODULEDIR=${mod%/*}
983                 inst_d "/lib/modules/$kernel/$MODULEDIR"
984                 cp -a "/lib/modules/$kernel/$mod" "$DESTDIR/lib/modules/$kernel/$mod"
985                 gunzip "$DESTDIR/lib/modules/$kernel/$mod" 2> /dev/null
986         done
987 }
988
989 modules_add_linuxrc() {
990         local mod modpath
991
992         for mod in "$@"; do
993                 # module path without optional compression
994                 modpath=${mod%.gz}
995
996                 # name of the module
997                 module=${modpath##*/}
998                 module=${module%$modext}
999
1000                 options=$(modprobe_conf | awk -vmodule="$module" '{ if ($1 == "options" && $2 == module) { for(i=3;i<=NF;i++) printf("%s ",$i); }}' | xargs)
1001
1002                 generic_module=$(echo $module | tr - _)
1003                 sleep_var=$(eval echo \$MODULE_${generic_module}_USLEEP)
1004                 firmware_var=$(eval echo \$MODULE_${generic_module}_FIRMWARE)
1005
1006                 if [ -n "$verbose" ]; then
1007                         s=""
1008                         if [ "$options" ]; then
1009                                 s="$s with options [$options]"
1010                         fi
1011                         if [ "$sleep_var" ]; then
1012                                 s="$s and $sleep_var usleep"
1013                         fi
1014                         debug "Loading module [$module]$s"
1015                 fi
1016
1017                 if [ -n "$firmware_var" ]; then
1018                         firmware_install_module "$module" "$firmware_var"
1019                 else
1020                         firmware_files=$(find_firmware "$module")
1021                         if [ -n "$firmware_files" ]; then
1022                                 for file in $firmware_files; do
1023                                         firmware_install_module "$module" "$file"
1024                                 done
1025                         fi
1026                 fi
1027
1028                 echo "$insmod /lib/modules/$kernel/$modpath $options" | add_linuxrc
1029                 if [ -n "$sleep_var" ]; then
1030                         echo "usleep $sleep_var" | add_linuxrc
1031                 fi
1032         done
1033 }
1034
1035 find_modules_suspend() {
1036         if [ ! -x /usr/${_lib}/suspend/resume -a ! -x /usr/sbin/resume ]; then
1037                 die "/usr/${_lib}/suspend/resume is missing!"
1038         fi
1039         resume_dev="$(awk '/^resume device =/ { print $4 } ' /etc/suspend.conf)"
1040
1041         local vgvolumes=$VGVOLUMES
1042         find_modules_for_devpath $resume_dev
1043
1044         if [ "$VGVOLUMES" != "$vgvolumes" ]; then
1045                 # save our VG to be able to differenciate between rootfs VG
1046                 SUSPENDVG=$VGVOLUMES
1047                 VGVOLUMES=$vgvolumes
1048                 debug "suspend device is on LVM"
1049         fi
1050 }
1051
1052 initrd_gen_suspend() {
1053         mknod $DESTDIR/dev/snapshot c 10 231
1054         mkdir -p $DESTDIR${resume_dev%/*}
1055         inst $resume_dev $resume_dev
1056
1057         inst /etc/suspend.conf /etc/suspend.conf
1058         if [ -x /usr/${_lib}/suspend/resume ]; then
1059                 inst /usr/${_lib}/suspend/resume /bin/resume
1060         else
1061                 inst /usr/sbin/resume /bin/resume
1062         fi
1063
1064         add_linuxrc <<-'EOF'
1065         resume=no
1066         for arg in $CMDLINE; do
1067                 if [ "${arg##resume=}" != "${arg}" ]; then
1068                         resume=yes
1069                 fi
1070         done
1071         if [ "$resume" = "yes" ]; then
1072                 resume
1073         fi
1074         EOF
1075 }
1076
1077 initrd_gen_tuxonice() {
1078         mount_sys
1079         add_linuxrc <<-'EOF'
1080                 resume=no
1081                 for arg in $CMDLINE; do
1082                         if [ "${arg##resume=}" != "${arg}" -o "${arg##resume2=}" != "${arg}" ]; then
1083                                 resume=yes
1084                         fi
1085                 done
1086                 if [ "$resume" = "yes" ]; then
1087                         [ -e /proc/suspend2/do_resume ] && echo > /proc/suspend2/do_resume
1088                         [ -e /sys/power/suspend2/do_resume ] && echo > /sys/power/suspend2/do_resume
1089                         [ -e /sys/power/tuxonice/do_resume ] && echo > /sys/power/tuxonice/do_resume
1090                 fi
1091         EOF
1092 }
1093
1094 initrd_gen_v86d() {
1095         debug "initrd_gen_v86d"
1096         mknod $DESTDIR/dev/mem c 1 1
1097         mknod $DESTDIR/dev/tty1 c 4 1
1098         inst_d /sbin
1099         inst_exec /sbin/v86d /sbin
1100 }
1101
1102 initrd_gen_udev() {
1103         debug "Setting up udev..."
1104         inst_d /sbin /etc/udev
1105
1106         if [ ! -x /sbin/initrd-udevd ]; then
1107                 die "/sbin/initrd-udevd not present"
1108         fi
1109
1110         inst /sbin/initrd-udevd /sbin/udevd
1111         inst /etc/udev/udev.conf /etc/udev/udev.conf
1112
1113         mount_dev
1114         mount_sys
1115         add_linuxrc <<-'EOF'
1116                 : 'Starting udev'
1117                 /sbin/udevd --daemon
1118         EOF
1119
1120         inst /sbin/initrd-udevadm /sbin/udevadm
1121         ln -s udevadm $DESTDIR/sbin/udevsettle
1122         ln -s udevadm $DESTDIR/sbin/udevtrigger
1123         add_linuxrc <<-'EOF'
1124                 /sbin/udevtrigger
1125                 /sbin/udevsettle
1126         EOF
1127
1128         busybox_applet killall
1129         add_linuxrc     <<-'EOF'
1130                 killall udevd
1131         EOF
1132 }
1133
1134 initrd_gen_multipath() {
1135         inst_d /sbin /lib/udev /etc/multipath
1136         inst_exec /sbin/kpartx /sbin
1137         inst_exec /sbin/multipath /sbin
1138         # for udev callouts
1139         inst_exec /sbin/scsi_id /lib/udev
1140         inst_exec /sbin/mpath* /sbin
1141         egrep -v '^([   ]*$|#)' /etc/multipath.conf > $DESTDIR/etc/multipath.conf
1142
1143         if [ -f /etc/multipath/bindings ]; then
1144                 egrep -v '^([   ]*$|#)' /etc/multipath/bindings > $DESTDIR/etc/multipath/bindings
1145         else
1146                 touch $DESTDIR/etc/multipath/bindings
1147         fi
1148
1149         mount_dev
1150         initrd_gen_devices
1151
1152         mount_sys
1153         echo "export MPATH_WWID=$MPATH_WWID" | add_linuxrc
1154         add_linuxrc <<-'EOF'
1155                 # parse mpath_wwid= from kernel commandline
1156                 for arg in $CMDLINE; do
1157                         if [ "${arg##mpath_wwid=}" != "${arg}" ]; then
1158                                 MPATH_WWID=${arg##mpath_wwid=}
1159                                 if [ "$MPATH_WWID" = "*" ]; then
1160                                         # '*' would mean activate all WWID-s
1161                                         MPATH_WWID=
1162                                         echo "multipath: Activating all WWID-s"
1163                                 else
1164                                         echo "multipath: Activating WWID=$WWID"
1165                                 fi
1166                         fi
1167                 done
1168
1169                 debugshell
1170                 /sbin/multipath -v 0 $MPATH_WWID
1171
1172                 for a in /dev/mapper/*; do
1173                         [ $a = /dev/mapper/control ] && continue
1174                         /sbin/kpartx -a -p p $a
1175                 done
1176                 debugshell
1177         EOF
1178 }
1179
1180 initrd_gen_dmraid() {
1181         if [ ! -x /sbin/dmraid-initrd ]; then
1182                 die "/sbin/dmraid-initrd is missing!"
1183         fi
1184
1185         inst_d /sbin
1186         inst /sbin/dmraid-initrd /sbin/dmraid
1187
1188         mount_dev
1189         mount_sys
1190         initrd_gen_devices
1191         add_linuxrc <<-EOF
1192                 # 2 secs was enough for my system to initialize. but really this is udev issue?
1193                 usleep 2000000
1194                 : 'Activating Device-Mapper RAID(s)'
1195                 /sbin/dmraid -ay -i
1196
1197                 debugshell
1198         EOF
1199 }
1200
1201 initrd_gen_bootsplash() {
1202         local target="$1"
1203
1204         debug "Generating bootsplash"
1205
1206         if [ ! -x /bin/splash.bin ]; then
1207                 warn "Failed to execute /bin/splash.bin. Is bootsplash package installed?"
1208                 return
1209         fi
1210
1211         if [ -r /etc/sysconfig/bootsplash ]; then
1212                 . /etc/sysconfig/bootsplash
1213         fi
1214
1215         if [ -z "$THEME" ]; then
1216                 warn "Please configure your /etc/sysconfig/bootsplash first."
1217                 warn "Generating bootsplashes skipped."
1218                 return
1219         fi
1220
1221         if [ -z "$BOOT_SPLASH_RESOLUTIONS" ]; then
1222                 warn "No BOOT_SPLASH_RESOLUTIONS specified in /etc/sysconfig/bootsplash."
1223                 warn "Not adding bootsplash to initrd."
1224         fi
1225
1226         for res in $BOOT_SPLASH_RESOLUTIONS; do
1227                 if [ -f "/etc/bootsplash/themes/$THEME/config/bootsplash-$res.cfg" ]; then
1228                         /bin/splash.bin -s -f "/etc/bootsplash/themes/$THEME/config/bootsplash-$res.cfg" >> "$target" && \
1229                         debug "Added $res $THEME theme to initrd."
1230                 else
1231                         warn "/etc/bootsplash/themes/$THEME/config/bootsplash-$res.cfg doesn't exist, skipped"
1232                 fi
1233         done
1234 }
1235
1236 initrd_gen_fbsplash() {
1237         debug "Generating fbsplash"
1238
1239         if [ ! -x /usr/bin/splash_geninitramfs -a ! -x /usr/sbin/splash_geninitramfs ]; then
1240                 warn "Failed to find splash_geninitramfs. Is splashutils package installed?"
1241                 return
1242         fi
1243         splash_geninitramfs_bin=/usr/sbin/splash_geninitramfs
1244         [ -f /usr/bin/splash_geninitramfs ] && splash_geninitramfs_bin=/usr/bin/splash_geninitramfs
1245
1246         if [ -r /etc/sysconfig/fbsplash ]; then
1247                 . /etc/sysconfig/fbsplash
1248         fi
1249
1250         if [ -z "$SPLASH_THEME" ]; then
1251                 warn "Please configure your /etc/sysconfig/fbsplash first."
1252                 warn "Generating fbsplashes skipped."
1253                 return
1254         fi
1255
1256         if [ -z "$FB_SPLASH_RESOLUTIONS" ]; then
1257                 warn "No FB_SPLASH_RESOLUTIONS specified in /etc/sysconfig/fbsplash."
1258                 warn "Not adding fbsplash to initramfs."
1259                 return
1260         fi
1261
1262         for res in $FB_SPLASH_RESOLUTIONS; do
1263                 if [ -f "/etc/splash/$SPLASH_THEME/$res.cfg" ]; then
1264                         $splash_geninitramfs_bin -c $DESTDIR -r $res $SPLASH_THEME && \
1265                         debug "Added $res $SPLASH_THEME theme to initramfs."
1266                 else
1267                         warn "/etc/splash/$SPLASH_THEME/$res.cfg doesn't exist, skipped"
1268                 fi
1269         done
1270 }
1271
1272 initrd_gen_fbcondecor() {
1273         debug "Generating fbcondecor"
1274
1275         if [ ! -x /usr/bin/splash_geninitramfs -a ! -x /usr/sbin/splash_geninitramfs ]; then
1276                 warn "Failed to find splash_geninitramfs. Is splashutils package installed?"
1277                 return
1278         fi
1279         splash_geninitramfs_bin=/usr/sbin/splash_geninitramfs
1280         [ -f /usr/bin/splash_geninitramfs ] && splash_geninitramfs_bin=/usr/bin/splash_geninitramfs
1281
1282         if [ -r /etc/sysconfig/splash ]; then
1283                 . /etc/sysconfig/splash
1284         fi
1285
1286         if [ -z "$SPLASH_THEME" ]; then
1287                 warn "Please configure your /etc/sysconfig/splash first."
1288                 warn "Generating of splashes skipped."
1289                 return
1290         fi
1291
1292         if [ -z "$FB_SPLASH_RESOLUTIONS" ]; then
1293                 warn "No FB_SPLASH_RESOLUTIONS specified in /etc/sysconfig/splash."
1294                 warn "Not adding fbcondecor to initramfs."
1295                 return
1296         fi
1297
1298         for res in $FB_SPLASH_RESOLUTIONS; do
1299                 if [ -f "/etc/splash/$SPLASH_THEME/$res.cfg" ]; then
1300                         $splash_geninitramfs_bin -c $DESTDIR -r $res $SPLASH_THEME && \
1301                         debug "Added $res $SPLASH_THEME theme to initramfs."
1302                 else
1303                         warn "/etc/splash/$SPLASH_THEME/$res.cfg doesn't exist, skipped"
1304                 fi
1305         done
1306 }
1307
1308 # Generates /dev nodes based on /proc/partitions information.
1309 # Needs /proc mounted.
1310 # Can be called multiple times.
1311 initrd_gen_devices() {
1312         if is_yes "$proc_partitions"; then
1313                 return
1314         fi
1315         proc_partitions=yes
1316
1317         mount_dev
1318         add_linuxrc <<-'EOF'
1319                 : 'Making device nodes'
1320                 cat /proc/partitions | (
1321                         # ignore first two lines: header, empty line
1322                         read b; read b
1323
1324                         while read major minor blocks dev rest; do
1325                                 node=/dev/$dev
1326                                 mkdir -p ${node%/*}
1327                                 [ -e $node ] || mknod $node b $major $minor
1328                         done
1329                 )
1330         EOF
1331 }
1332
1333 initrd_gen_md() {
1334         debug "Setting up mdadm..."
1335
1336         if [ ! -x /sbin/mdadm -o ! -x /sbin/initrd-mdassemble ]; then
1337                 die "/sbin/mdadm or /sbin/initrd-mdassemble is missing!"
1338         fi
1339
1340         inst /sbin/initrd-mdassemble /bin/mdassemble
1341
1342         # LVM on RAID case
1343         dev_list_extra=$(awk '/^DEVICE / { for (i=2; i<=NF; i++) { printf "%s ", $i; }; } ' /etc/mdadm.conf)
1344         if [ "$dev_list_extra" = "partitions" ]; then
1345                 # FIXME: handle this case (see man mdadm.conf)
1346                 echo "DEVICE partitions" >> "$DESTDIR/etc/mdadm.conf"
1347                 dev_list_extra=""
1348         else
1349                 for ex_dev in $dev_list_extra; do
1350                         echo "DEVICE $ex_dev" >> "$DESTDIR/etc/mdadm.conf"
1351                 done
1352         fi
1353         do_md0=1
1354         for nr in `seq 1 $rootdev_nr`; do
1355                 eval cr_rootdev="\$rootdev${nr}"
1356                 eval cr_dev_list="\$dev_list${nr}"
1357                 debug echo "Setting up array ($cr_rootdev = $cr_dev_list)"
1358
1359                 [ "$cr_rootdev" = "/dev/md0" ] && do_md0=0
1360
1361                 echo "DEVICE $cr_dev_list" >> "$DESTDIR/etc/mdadm.conf"
1362                 cr_dev_list_md="$(echo "$cr_dev_list" | xargs | awk ' { gsub(/ +/,",",$0); print $0; }')"
1363                 cr_md_conf=$(/sbin/mdadm --detail --brief --config=/etc/mdadm.conf $cr_rootdev | awk ' { gsub(/spares=[0-9]+/, "", $0); print $0; }')
1364                 if [ -n "$cr_md_conf" ]; then
1365                         echo "$cr_md_conf" >> "$DESTDIR/etc/mdadm.conf"
1366                 else
1367                         echo "ARRAY $cr_rootdev devices=$cr_dev_list_md" >> "$DESTDIR/etc/mdadm.conf"
1368                 fi
1369
1370                 for f in $cr_dev_list $cr_rootdev $dev_list_extra; do
1371                         # mkdir in case of devfs name
1372                         inst_d $(dirname $f)
1373                         [ -e "$DESTDIR/$f" ] && continue
1374                         # this works fine with and without devfs
1375                         inst $f $f
1376                 done
1377         done
1378
1379         echo "mdassemble" | add_linuxrc
1380
1381         # needed to determine md-version
1382         if [ "$do_md0" -eq 1 ]; then
1383                 mknod $DESTDIR/dev/md0 b 9 0
1384         fi
1385 }
1386
1387 initrd_gen_nfs() {
1388         # use root=/dev/ram0 init=/linuxrc when starting kernel or you will
1389         # have problems like init(XX) being child process of swapper(1).
1390         debug "Adding rootfs on NFS support to initrd (dhcp)"
1391         mknod "$DESTDIR/dev/urandom" c 1 9
1392         mkdir "$DESTDIR/newroot"
1393         add_linuxrc <<-'EOF'
1394                 ifconfig lo 127.0.0.1 up
1395                 route add -net 127.0.0.0 mask 255.0.0.0 lo
1396                 ifconfig eth0 up
1397                 udhcpc -i eth0 -f -q -s /bin/setdhcp
1398
1399                 cd /newroot
1400                 pivot_root . initrd
1401                 [ -x /sbin/chroot ] && exec /sbin/chroot . /sbin/init -i < dev/console > dev/console 2>&1
1402                 exec /usr/sbin/chroot . /sbin/init -i < dev/console > dev/console 2>&1
1403         EOF
1404
1405         cat <<-'EOF' > "$DESTDIR/bin/setdhcp"
1406                 #!/bin/sh
1407                 [ "$1" != "bound" ] && exit
1408                 [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
1409                 [ -n "$subnet" ] && NETMASK="netmask $subnet"
1410                 ifconfig $interface $ip $BROADCAST $NETMASK up
1411                 if [ -n "$router" ]; then
1412                         for r in $router; do
1413                                 route add default gw $r dev $interface
1414                         done
1415                 fi
1416
1417                 for o in $CMDLINE; do
1418                         case $o in
1419                         nfsroot=*)
1420                                 rootpath=${o#nfsroot=}
1421                                 ;;
1422                         esac
1423                 done
1424
1425                 if [ -n "$rootpath" ]; then
1426                         mount -n -t nfs -o ro,nolock,posix,tcp,wsize=8192,rsize=8192 $rootpath /newroot
1427                 else
1428                         echo "Missing rootpath in what DHCP server sent to us. Failing..."
1429                         echo "All seen variables are listed below:"
1430                         set
1431                 fi
1432         EOF
1433
1434         chmod 755 "$DESTDIR/bin/setdhcp"
1435 }
1436
1437 initrd_gen_lvm() {
1438         debug "Adding LVM support to initrd"
1439         inst_d /tmp /newroot
1440         inst /sbin/initrd-lvm /bin/lvm.static
1441
1442         # always make /dev on tmpfs for LVM2
1443         if [ "$LVMTOOLSVERSION" = "2" ]; then
1444                 mount_dev
1445         fi
1446
1447         if ! is_yes "$dev_mounted"; then
1448                 inst_d /dev/mapper
1449                 mknod $DESTDIR/dev/mapper/control c 10 63
1450                 for device in $PVDEVICES; do
1451                         # if LVM on RAID then device might be copied already in gen_md
1452                         [ -e "$DESTDIR/dev/$(basename $device)" ] && continue
1453                         inst $device /dev
1454                 done
1455         fi
1456
1457         mount_tmp
1458         if [ "$LVMTOOLSVERSION" = "1" ]; then
1459                 add_linuxrc <<-EOF
1460                         lvm vgscan -T
1461                         for vg in $VGVOLUMES; do
1462                                 lvm vgchange -T -a y $vg
1463                         done
1464                 EOF
1465         else
1466                 echo "cat /etc/lvm.conf > /tmp/lvm.conf" | add_linuxrc
1467                 echo "global {" > "$DESTDIR/etc/lvm.conf"
1468                 echo "  locking_type = 0" >> "$DESTDIR/etc/lvm.conf"
1469                 echo "  locking_dir = \"/tmp\"" >> "$DESTDIR/etc/lvm.conf"
1470                 echo "}" >> "$DESTDIR/etc/lvm.conf"
1471                 echo "devices {" >> "$DESTDIR/etc/lvm.conf"
1472                 echo "  sysfs_scan=0" >> "$DESTDIR/etc/lvm.conf"
1473                 if is_yes "$have_md"; then
1474                         echo "  md_component_detection = 1" >> "$DESTDIR/etc/lvm.conf"
1475                 fi
1476                 if is_yes "$have_dmraid" || is_yes "$have_multipath"; then
1477                         echo '  types = [ "device-mapper", 254 ]' >> "$DESTDIR/etc/lvm.conf"
1478                 fi
1479                 if [ "$lvm_ignore_devices" ]; then
1480                         # TODO: think of merging with lvm dumpconfig output
1481                         echo '  filter = [' >> "$DESTDIR/etc/lvm.conf"
1482                         local dev
1483                         for dev in $lvm_ignore_devices; do
1484                                 debug "LVM v2: ignore device $dev"
1485                                 printf '  "r|^%s.*|",\n' $dev
1486                         done >> "$DESTDIR/etc/lvm.conf"
1487                         echo ']' >> "$DESTDIR/etc/lvm.conf"
1488                 fi
1489                 # XXX filter= must be on one line!
1490                 lvm dumpconfig | awk '/filter=/' >> "$DESTDIR/etc/lvm.conf"
1491                 echo "}" >> "$DESTDIR/etc/lvm.conf"
1492
1493                 initrd_gen_devices
1494
1495                 add_linuxrc <<-EOF
1496                         export ROOTDEV=$rootdev
1497                         export ROOTVG="$VGVOLUMES"
1498                         export SUSPENDVG=$SUSPENDVG
1499                 EOF
1500                 add_linuxrc <<-'EOF'
1501                         # parse rootdev from kernel commandline
1502                         if [ "$ROOT" != "$ROOTDEV" ]; then
1503                                 ROOTDEV=$ROOT
1504                                 echo "LVM: Using 'root=$ROOTDEV' from kernel commandline"
1505                                 local tmp=${ROOTDEV#/dev/}
1506                                 if [ "$tmp" != "$ROOTDEV" ]; then
1507                                         ROOTVG=${tmp%/*}
1508                                         echo "LVM: Using Volume Group '$ROOTVG' for rootfs"
1509                                 fi
1510                         fi
1511
1512                         # skip duplicate VG
1513                         if [ "$SUSPENDVG" = "$ROOTVG" ]; then
1514                                 export VGVOLUMES="$ROOTVG"
1515                         else
1516                                 export VGVOLUMES="$SUSPENDVG $ROOTVG"
1517                         fi
1518
1519                         # disable noise from LVM accessing devices that aren't ready.
1520                         read printk < /proc/sys/kernel/printk
1521                         if [ ! "$DEBUGINITRD" ]; then
1522                                 echo 0 > /proc/sys/kernel/printk
1523                         fi
1524
1525                         export LVM_SYSTEM_DIR=/tmp
1526                         : 'Scanning for Volume Groups'
1527                         lvm.static vgscan --mknodes --ignorelockingfailure 2>/dev/null
1528
1529                         : 'Activating Volume Groups'
1530                         for vol in $VGVOLUMES; do
1531                                 lvm.static vgchange --ignorelockingfailure -a y $vol 2>/dev/null
1532                         done
1533
1534                         echo "$printk" > /proc/sys/kernel/printk
1535
1536                         # Find out major/minor
1537                         attrs="$(lvm.static lvdisplay --ignorelockingfailure -c $ROOTDEV 2>/dev/null)"
1538                         if [ "$attrs" ]; then
1539                                 majmin="${attrs#*$ROOTDEV*:*:*:*:*:*:*:*:*:*:*:*}"
1540                                 if [ "$majmin" != "$attrs" ]; then
1541                                         major="${majmin%:*}"
1542                                         minor="${majmin#*:}"
1543                                 fi
1544                         fi
1545
1546                         if [ "$major" -a "$minor" ]; then
1547                                 # Pass it to kernel
1548                                 echo $((256 * $major + $minor)) > /proc/sys/kernel/real-root-dev
1549                         else
1550                                 echo 2>&1 "Error figuring out real root device for $ROOTDEV!"
1551                                 echo 2>&1 "System will not most likely boot up! So dropping you to a shell!"
1552                                 echo 2>&1 ""
1553                                 sh
1554                         fi
1555                 EOF
1556         fi
1557 }
1558
1559 initrd_gen_blkid()
1560 {
1561         debug "Adding BLKID support to initrd"
1562         inst /sbin/initrd-blkid /bin/blkid
1563         initrd_gen_devices
1564         add_linuxrc <<-'EOF'
1565                 # if built with blkid change ROOT=LABEL=something into ROOT=/dev/somethingelse -
1566                 # parsed by blkid
1567                 if [ "${ROOT##LABEL=}" != "${ROOT}" -o "${ROOT##UUID=}" != "${ROOT}" ]; then
1568                         ROOT="$(/bin/blkid -t $ROOT -o device -l)"
1569                 fi
1570         EOF
1571 }
1572
1573 initrd_gen_setrootdev() {
1574         debug "Adding rootfs finding based on kernel cmdline root= option support."
1575         add_linuxrc <<-'EOF'
1576                 if [ "${ROOT##/dev/}" != "${ROOT}" ]; then
1577                         rootnr="$(busybox awk -v rootnode="${ROOT##/dev/}" '$4 == rootnode { print 256 * $1 + $2 }' /proc/partitions)"
1578                         if [ -n "$rootnr" ]; then
1579                                 echo "$rootnr" > /proc/sys/kernel/real-root-dev
1580                         fi
1581                 fi
1582         EOF
1583 }
1584
1585 # main()
1586 if [ "$(id -u)" != 0 ]; then
1587         die "You need to be root to generate initrd"
1588 fi
1589
1590 if [ -f /etc/udev/udev.conf -a -x /sbin/initrd-udevd ]; then
1591         USE_UDEV=yes
1592         . /etc/udev/udev.conf
1593 fi
1594
1595 if [ -x /sbin/dmraid-initrd ]; then
1596         USE_DMRAID=yes
1597 fi
1598
1599 if [ -x /sbin/multipath ]; then
1600         USE_MULTIPATH=yes
1601 fi
1602
1603 if [ -x /sbin/initrd-blkid ]; then
1604         USE_BLKID=yes
1605 fi
1606
1607 if [ -r /etc/sysconfig/geninitrd ]; then
1608         . /etc/sysconfig/geninitrd
1609 fi
1610
1611 if [ ! -x /bin/initrd-busybox ]; then
1612         die "/bin/initrd-busybox is missing!"
1613 fi
1614
1615 # backwards compatible
1616 if [ "$USE_SUSPEND2" ]; then
1617         USE_TUXONICE=$USE_SUSPEND2
1618         warn "USE_SUSPEND2 is deprecated, use USE_TUXONICE now instead."
1619 fi
1620
1621 while [ $# -gt 0 ]; do
1622         case $1 in
1623         --fstab=*)
1624                 fstab=${1#--fstab=}
1625                 ;;
1626         --fstab)
1627                 fstab=$2
1628                 shift
1629                 ;;
1630         --modules-conf=*)
1631                 modulefile=${1#--modules-conf=}
1632                 ;;
1633         --modules-conf)
1634                 modulefile=$2
1635                 shift
1636                 ;;
1637         --use-raidstart|--with-raidstart)
1638                 USERAIDSTART=yes
1639                 ;;
1640         --without-raidstart)
1641                 USERAIDSTART=no
1642                 ;;
1643         --use-insmod-static|--with-insmod-static)
1644                 USEINSMODSTATIC=yes
1645                 ;;
1646         --without-insmod-static)
1647                 USEINSMODSTATIC=no
1648                 ;;
1649         --with-bootsplash)
1650                 BOOT_SPLASH=yes
1651                 ;;
1652         --without-bootsplash)
1653                 BOOT_SPLASH=no
1654                 ;;
1655         --with-fbsplash)
1656                 FB_SPLASH=yes
1657                 ;;
1658         --without-fbsplash)
1659                 FB_SPLASH=no
1660                 ;;
1661         --with-fbcondecor)
1662                 FB_CON_DECOR=yes
1663                 ;;
1664         --without-fbcondecor)
1665                 FB_CON_DECOR=no
1666                 ;;
1667         --with-suspend)
1668                 USE_SUSPEND=yes
1669                 ;;
1670         --without-suspend)
1671                 USE_SUSPEND=no
1672                 ;;
1673         --with-suspend2 | --with-tuxonice)
1674                 USE_TUXONICE=yes
1675                 ;;
1676         --without-suspend2 | --without-tuxonice)
1677                 USE_TUXONICE=no
1678                 ;;
1679         --lvmtoolsversion=|--lvmversion=)
1680                 LVMTOOLSVERSION=${1#--lvmtoolsversion=}
1681                 LVMTOOLSVERSION=${1#--lvmversion=}
1682                 ;;
1683         --lvmtoolsversion|--lvmversion)
1684                 LVMTOOLSVERSION=$2
1685                 shift
1686                 ;;
1687         --without-udev)
1688                 USE_UDEV=no
1689                 ;;
1690         --with-udev)
1691                 USE_UDEV=yes
1692                 ;;
1693         --without-dmraid)
1694                 USE_DMRAID=no
1695                 ;;
1696         --without-multipath)
1697                 USE_MULTPATH=no
1698                 ;;
1699         --without-blkid)
1700                 USE_BLKID=no
1701                 ;;
1702         --with=*)
1703                 BASICMODULES="$BASICMODULES ${1#--with=}"
1704                 ;;
1705         --with)
1706                 BASICMODULES="$BASICMODULES $2"
1707                 shift
1708                 ;;
1709         --version)
1710                 echo "$PROGRAM: version $VERSION"
1711                 exit 0
1712                 ;;
1713         -v)
1714                 verbose=-v
1715                 ;;
1716         --nocompress)
1717                 COMPRESS=no
1718                 ;;
1719         --ifneeded)
1720                 ifneeded=1
1721                 ;;
1722         -f)
1723                 force=1
1724                 ;;
1725         --preload=*)
1726                 PREMODS="$PREMODS ${1#--preload=}"
1727                 ;;
1728         --preload)
1729                 PREMODS="$PREMODS $2"
1730                 shift
1731                 ;;
1732         --fs=*)
1733                 warn "Warning: --fs option is obsoleted. Use --initrdfs instead"
1734                 INITRDFS=${1#--fs=}
1735                 ;;
1736         --fs)
1737                 warn "Warning: --fs option is obsoleted. Use --initrdfs instead"
1738                 INITRDFS=$2
1739                 shift
1740                 ;;
1741         --initrdfs=*)
1742                 INITRDFS=${1#--initrdfs=}
1743                 ;;
1744         --initrdfs)
1745                 INITRDFS=$2
1746                 shift
1747                 ;;
1748         --image-version)
1749                 img_vers=yes
1750                 ;;
1751         --ide-only-root)
1752                 ide_only_root="yes"
1753                 ;;
1754         *)
1755                 if [ -z "$target" ]; then
1756                         target="$1"
1757                 elif [ -z "$kernel" ]; then
1758                         kernel="$1"
1759                 else
1760                         usage
1761                 fi
1762                 ;;
1763         esac
1764
1765         shift
1766 done
1767
1768 if [ -z "$target" -o -z "$kernel" ]; then
1769         usage
1770 fi
1771
1772 if [ ! -f /boot/vmlinuz-"$kernel" ]; then
1773         warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?"
1774 fi
1775
1776 pack_version=$(echo "$kernel" | awk -F. '{print sprintf("%03d%03d",$1,$2)}')
1777 pack_version_long=$(echo "$kernel" | awk -F. '{print sprintf("%03d%03d%03d",$1,$2,$3)}')
1778
1779 if [ -z "$INITRDFS" ]; then
1780         if [ -z "$FS" ]; then
1781                 # default value
1782                 if [ "$pack_version" -ge "002005" ]; then
1783                         INITRDFS="initramfs"
1784                 else
1785                         INITRDFS="rom"
1786                 fi
1787         else
1788                 warn "Warning: FS configuration options is obsoleted. Use INITRDFS instead"
1789                 INITRDFS="$FS"
1790         fi
1791 fi
1792
1793 if [ "$pack_version" -lt "002006" ]; then
1794         USE_UDEV=no
1795         USE_DMRAID=no
1796 fi
1797
1798 if [ "$pack_version" -ge "002005" ]; then
1799         modext=".ko"
1800         insmod="insmod"
1801 fi
1802
1803 if is_yes "$USEINSMODSTATIC"; then
1804         insmod="insmod.static"
1805         INSMOD="/sbin/insmod.static"
1806         if [ "$pack_version" -lt "002005" -a -f /sbin/insmod.static.modutils ]; then
1807                 INSMOD="/sbin/insmod.static.modutils"
1808         fi
1809         if [ ! -f "$INSMOD" ]; then
1810                 die "insmod.static requested but /sbin/insmod.static not found!"
1811         fi
1812 fi
1813
1814 case "$INITRDFS" in
1815         ext2)
1816                 if [ ! -x /sbin/mke2fs ]; then
1817                         die "/sbin/mke2fs is missing"
1818                 fi
1819                 ;;
1820         rom|romfs)
1821                 if [ ! -x /sbin/genromfs ]; then
1822                         die "/sbin/genromfs is missing"
1823                 fi
1824                 ;;
1825         cram|cramfs)
1826                 if [ ! -x /sbin/mkcramfs ]; then
1827                         die "/sbin/mkcramfs is missing"
1828                 fi
1829                 ;;
1830         initramfs)
1831                 if [ ! -x /bin/cpio ]; then
1832                         die "/bin/cpio is missing"
1833                 fi
1834                 if [ ! -x /usr/bin/find ]; then
1835                         die "/usr/bin/find is missing"
1836                 fi
1837                 ;;
1838         *)
1839                 die "Filesystem $INITRDFS on initrd is not supported"
1840                 ;;
1841 esac
1842
1843 if [ -L "$target" ]; then
1844         target=$(readlink -f "$target")
1845 fi
1846
1847 if [ -n "$img_vers" ]; then
1848         target="$target-$kernel"
1849 fi
1850
1851 if [ -z "$force" -a -f "$target" ]; then
1852         die "$target already exists."
1853 fi
1854
1855 if [ ! -d "/lib/modules/$kernel" ]; then
1856         die "/lib/modules/$kernel is not a directory."
1857 fi
1858
1859 if [ "$INITRDFS" != "initramfs" ]; then
1860         if is_yes "$FB_SPLASH"; then
1861                 warn "Using fbsplash requires INITRDFS=initramfs; skipping fbsplash generation"
1862                 FB_SPLASH=no
1863         fi
1864         if is_yes "$FB_CON_DECOR"; then
1865                 warn "Using fbcondecor requires INITRDFS=initramfs; skipping fbcondecor generation"
1866                 FB_CON_DECOR=no
1867         fi
1868 fi
1869
1870 if is_yes "$USE_SUSPEND" && is_yes "$USE_TUXONICE"; then
1871         warn "Tuxonice and mainline suspend are exclusive!"
1872 fi
1873
1874 if is_yes "$FB_SPLASH"  && is_yes "$BOOT_SPLASH"; then
1875         warn "bootsplash and fbsplash are exclusive!"
1876 fi
1877
1878 if [ ! -f /proc/mounts ]; then
1879         warn "WARNING: /proc filesystem not mounted, may cause wrong results or failure."
1880 fi
1881
1882 if [ -d /usr/lib64 ]; then
1883         _lib=lib64
1884 else
1885         _lib=lib
1886 fi
1887 debug "Using libdir: $_lib"
1888
1889 cache_modprobe_conf
1890
1891 for n in $PREMODS; do
1892         findmodule "$n"
1893 done
1894
1895 if [ "$FBMODULE" ]; then
1896         findmodule "$FBMODULE"
1897 fi
1898
1899 # allow forcing loading SCSI and/or IDE modules
1900 if is_yes "$ADDSCSI"; then
1901         find_modules_scsi
1902 fi
1903
1904 if is_yes "$ADDIDE"; then
1905         find_modules_ide
1906 fi
1907
1908 if is_yes "$USE_SUSPEND"; then
1909         find_modules_suspend
1910 fi
1911
1912 find_root "$fstab" || exit
1913 debug "Using $rootdev as device for rootfs"
1914
1915 find_modules_for_devpath "$rootdev"
1916 [ -n "$rootdev_add" ] && find_modules_for_devpath "$rootdev_add"
1917
1918 findmodule "-$rootFs"
1919
1920 for n in $BASICMODULES; do
1921         findmodule "$n"
1922 done
1923
1924 if is_yes "$USE_TUXONICE"; then
1925         findmodule "-lzf"
1926 fi
1927
1928 if is_yes "$FB_SPLASH"; then
1929         findmodule "-evdev"
1930 fi
1931
1932 if [ -n "$ifneeded" -a -z "$MODULES" ]; then
1933         debug "No modules are needed -- not building initrd image."
1934         exit 0
1935 fi
1936
1937 DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
1938 RCFILE="$DESTDIR/linuxrc"
1939 > "$RCFILE"
1940 chmod a+rx "$RCFILE"
1941 ln -s linuxrc $DESTDIR/init
1942
1943 # create dirs that we really need
1944 inst_d /{lib,bin,etc,dev{,/pts,/shm},loopfs,var,proc,sys}
1945
1946 modules_install "$MODULES"
1947
1948 # mknod'ing the devices instead of copying them works both with and
1949 # without devfs...
1950 mknod "$DESTDIR/dev/console" c 5 1
1951 mknod "$DESTDIR/dev/null" c 1 3
1952 mknod "$DESTDIR/dev/zero" c 1 5
1953
1954 inst /bin/initrd-busybox /bin/initrd-busybox
1955 ln -s initrd-busybox $DESTDIR/bin/sh
1956 ln -s initrd-busybox $DESTDIR/bin/busybox # for older busyboxes who had /bin/busybox as EXEPATH
1957
1958 if is_yes "$USEINSMODSTATIC"; then
1959         inst "$INSMOD" /bin/insmod.static
1960 fi
1961
1962 add_linuxrc <<EOF
1963 #!/bin/sh
1964 # initrd generated by:
1965 # $RCSID
1966
1967 EOF
1968 mount_proc
1969 add_linuxrc <<-'EOF'
1970         read CMDLINE < /proc/cmdline; export CMDLINE
1971
1972         for arg in $CMDLINE; do
1973                 if [ "${arg}" = "debuginitrd" ]; then
1974                         DEBUGINITRD=yes
1975                 fi
1976                 if [ "${arg##debuginitrd=}" != "${arg}" ]; then
1977                         DEBUGINITRD=${arg##debuginitrd=}
1978                 fi
1979                 if [ "${arg##root=}" != "${arg}" ]; then
1980                         ROOT=${arg##root=}
1981                 fi
1982         done
1983
1984         # make debugshell() invoke subshell if $DEBUGINITRD=sh
1985         if [ "$DEBUGINITRD" = "sh" ]; then
1986                 debugshell() {
1987 EOF
1988 if is_yes "$RUN_SULOGIN_ON_ERR"; then
1989 add_linuxrc <<-'EOF'
1990         echo "debug shell disabled by /etc/sysconfig/system:RUN_SULOGIN_ON_ERR setting"
1991 EOF
1992 else
1993 add_linuxrc <<-'EOF'
1994         sh
1995 EOF
1996 fi
1997 add_linuxrc <<-'EOF'
1998                 }
1999         else
2000                 debugshell() {
2001                         :
2002                 }
2003         fi
2004
2005         if [ "$DEBUGINITRD" ]; then
2006                 set -x
2007         fi
2008 EOF
2009
2010 modules_add_linuxrc $MODULES
2011
2012 # TODO: rewrite for busybox
2013 #if [ -n "$loopDev" ]; then
2014 #       if [ ! -d /initrd ]; then
2015 #               mkdir /initrd
2016 #       fi
2017 #
2018 #       cp -a "$loopDev" "$DESTDIR/dev"
2019 #       cp -a "$rootdev" "$DESTDIR/dev"
2020 #       echo "echo Mounting device containing loopback root filesystem" >> "$RCFILE"
2021 #       echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE"
2022 #       echo "echo Setting up loopback device $rootdev" >> $RCFILE
2023 #       echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE"
2024 #fi
2025
2026 if is_yes "$USE_UDEV"; then
2027         initrd_gen_udev
2028 fi
2029
2030 if is_yes "$USE_TUXONICE"; then
2031         initrd_gen_tuxonice
2032 fi
2033
2034 if is_yes "$need_v86d"; then
2035         initrd_gen_v86d
2036 fi
2037
2038 if is_yes "$have_dmraid"; then
2039         initrd_gen_dmraid
2040 fi
2041
2042 if is_yes "$have_multipath"; then
2043         initrd_gen_multipath
2044 fi
2045
2046 if is_yes "$USE_BLKID"; then
2047         initrd_gen_blkid
2048 fi
2049
2050 if is_yes "$have_nfs"; then
2051         initrd_gen_nfs
2052 elif is_yes "$USERAIDSTART" && is_yes "$have_md"; then
2053         initrd_gen_md
2054         if is_yes "$have_lvm"; then
2055                 initrd_gen_lvm
2056         else
2057                 initrd_gen_setrootdev
2058         fi
2059 elif is_yes "$have_lvm"; then
2060         initrd_gen_lvm
2061 else
2062         initrd_gen_setrootdev
2063 fi
2064
2065 if is_yes "$USE_SUSPEND"; then
2066         initrd_gen_suspend
2067 fi
2068
2069 # additional devs always needed
2070 [ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev
2071
2072 if [ "$INITRDFS" = "initramfs" ]; then
2073         inst_d /newroot
2074         if [ "$rootdev" = "/dev/nfs" ]; then
2075                 echo "rootfs on NFS root=/dev/nfs"
2076         else
2077                 [ ! -e "$DESTDIR/$rootdev" ] && inst $rootdev $rootdev
2078         fi
2079         # Parsing root parameter
2080         # We support passing root as hda3 /dev/hda3 0303 0x0303 and 303
2081         add_linuxrc <<-'EOF'
2082                 device=/dev/no_partition_found
2083                 eval "$(busybox awk -v c="$ROOT" '
2084                         BEGIN {
2085                                 num_pattern_short = "[0-9a-f][0-9a-f][0-9a-f]";
2086                                 num_pattern = "[0-9a-f]" num_pattern_short;
2087                                 dev_pattern = "[hms][a-z][a-z]([0-9])+";
2088                                 partition = "no_partition_found";
2089                                 min = -1; maj = -1;
2090
2091                                 sub("^0x", "", c);
2092                                 if (c ~ "^" num_pattern_short "$") sub("^", "0", c);
2093                                 if (c ~ "^" num_pattern  "$") {
2094                                         maj = sprintf("%s",substr(c,1,2));
2095                                         min = sprintf("%s",substr(c,3));
2096                                 }
2097                                 if (c ~ "^\/dev\/" dev_pattern "$") sub("^/dev/","", c);
2098                                 if (c ~ "^" dev_pattern "$") partition = c;
2099                         }
2100
2101                         $4 ~ partition { maj = $1; min = $2; }
2102                         $1 ~ maj && $2 ~ min { partition = $4; }
2103
2104                         END {
2105                                 print sprintf("device=/dev/%s\nmaj=%s\nmin=%s",
2106                                         partition, maj, min);
2107                         }
2108                         ' /proc/partitions)"
2109                 if [ "$device" != '/dev/no_partition_found' -a ! -b $device ]; then
2110                         mknod $device b $maj $min
2111                 fi
2112         EOF
2113
2114         add_linuxrc <<-EOF
2115                 rootdev=$rootdev
2116                 rootfs=$rootFs
2117         EOF
2118
2119         add_linuxrc <<-'EOF'
2120                 if [ "$device" = '/dev/no_partition_found' ]; then
2121                         device=$rootdev
2122                 fi
2123
2124                 mount -t $rootfs -r $device /newroot
2125                 init="$(echo "$CMDLINE" | busybox awk '/init=\// { gsub(/.*init=/,NIL,$0); gsub(/ .*/,NIL,$0); print }')"
2126                 if [ -z "$init" -o ! -x "/newroot$init" ]; then
2127                         init=/sbin/init
2128                 fi
2129         EOF
2130
2131         umount_all
2132         busybox_applet switch_root
2133         add_linuxrc <<-'EOF'
2134                 exec switch_root /newroot $init
2135
2136                 echo "Error! initramfs should not reach this place."
2137                 echo "It probably means you've got old version of busybox, with broken"
2138                 echo "initramfs support. Trying to boot anyway, but won't promise anything."
2139
2140                 exec chroot /newroot $init
2141
2142                 echo "Failed to chroot!"
2143         EOF
2144         # we need /init being real file, not symlink, otherwise the initramfs will
2145         # not be ran by pid 1 which is required for switch_root
2146         mv $DESTDIR/linuxrc $DESTDIR/init
2147         ln -s init $DESTDIR/linuxrc
2148 else
2149         # other than initramfs
2150         umount_all
2151 fi
2152
2153 if is_yes "$FB_SPLASH"; then
2154         initrd_gen_fbsplash
2155 fi
2156
2157 if is_yes "$FB_CON_DECOR"; then
2158         initrd_gen_fbcondecor
2159 fi
2160
2161 IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed"
2162
2163 debug "Creating $INITRDFS image $IMAGE"
2164 case "$INITRDFS" in
2165         ext2)
2166                 IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
2167                 debug   "ext2 image size: $IMAGESIZE ($DESTDIR)"
2168                 if [ "$IMAGESIZE" -gt 4096 ]; then
2169                         warn "Your image size is larger than 4096, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!"
2170                 fi
2171
2172                 dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null
2173                 mke2fs -q -F -b 1024 -m 0 "$IMAGE" 2>/dev/null 1>&2
2174                 tune2fs -i 0 "$IMAGE" >/dev/null 2>&1
2175
2176                 local tmpmnt=$(mktemp -d -t initrd.mnt-XXXXXX)
2177                 debug "Mounting ext2 image $IMAGE to $tmpmnt"
2178                 mount -o loop -t ext2 "$IMAGE" "$tmpmnt"
2179                 # We don't need this directory, so let's save space
2180                 rm -rf "$tmpmnt"/lost+found
2181
2182                 debug "Copy recursively $DESTDIR -> $tmpmnt"
2183                 cp -a $DESTDIR/* $tmpmnt
2184                 umount "$IMAGE"
2185                 rmdir "$tmpmnt"
2186
2187                 ;;
2188         rom|romfs)
2189                 genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD initrd for kernel $kernel"
2190                 IMAGESIZE=$(stat -c %s $IMAGE | awk '{print int((($1/1024)+1023)/1024)*1024}')
2191                 debug "Image size for romfs: ${IMAGESIZE}KiB ($IMAGE)"
2192                 if [ "$IMAGESIZE" -gt 4096 ]; then
2193                         warn "Your image size is larger than 4096, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!"
2194                 fi
2195                 ;;
2196         cram|cramfs)
2197                 mkcramfs "$DESTDIR" "$IMAGE"
2198                 ;;
2199         initramfs)
2200                 (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
2201                 ;;
2202         *)
2203                 echo "Filesystem $INITRDFS not supported by $PROGRAM";
2204 esac
2205
2206 if is_yes "$COMPRESS"; then
2207         tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
2208         debug "Compressing $target"
2209         gzip -9 < "$IMAGE" > "$tmp"
2210         mv -f "$tmp" "$target"
2211 else
2212         cp -a "$IMAGE" "$target"
2213 fi
2214
2215 # XXX. check if bootsplash can output data to tmp dir not directly to initramfs image.
2216 if is_yes "$BOOT_SPLASH"; then
2217         initrd_gen_bootsplash "$target"
2218 fi
2219
2220 rm -rf "$DESTDIR" "$IMAGE"
2221
2222 # vim:ts=4:sw=4:noet:fdm=marker
This page took 0.200818 seconds and 4 git commands to generate.