]> git.pld-linux.org Git - projects/geninitrd.git/blob - geninitrd
handle bcache as rootfs. test: root=LABEL=/ worked
[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 # generate code to mount /proc on initrd
206 # can be called multiple times
207 mount_proc() {
208         if is_yes "$proc_mounted"; then
209                 return
210         fi
211
212         proc_mounted=yes
213     if [ "$INITRDFS" = "initramfs" ]; then
214                 # /proc is mounted with initramfs 2.6.22.14 kernel
215                 # XXX: remove when it is clear why proc was already mounted
216                 echo "[ -f /proc/cmdline ] || mount -t proc none /proc" | add_linuxrc
217         else
218                 echo "mount -t proc none /proc" | add_linuxrc
219         fi
220 }
221
222 # generate code to mount /sys on initrd
223 # can be called multiple times
224 mount_sys() {
225         if is_yes "$sys_mounted"; then
226                 return
227         fi
228
229         sys_mounted=yes
230         echo "mount -t sysfs none /sys" | add_linuxrc
231 }
232
233 # generate code to mount /tmp on initrd
234 # can be called multiple times
235 mount_tmp() {
236     if [ "$INITRDFS" = "initramfs" ]; then
237                 # initramfs is read-write filesystem, no need for tmpfs
238                 return
239         fi
240
241         if is_yes "$tmp_mounted"; then
242                 return
243         fi
244
245         tmp_mounted=yes
246         echo "mount -t tmpfs none /tmp" | add_linuxrc
247 }
248
249 # generate code to mount /run on initrd
250 # can be called multiple times
251 mount_run() {
252         if is_yes "$run_mounted"; then
253                 return
254         fi
255
256         run_mounted=yes
257         echo "mount -t tmpfs run /run" | add_linuxrc
258 }
259
260 # unmount all mountpoints mounted by geninitrd
261 # try to move pseudo filesystems to newroot if possible
262 umount_all() {
263
264         add_linuxrc <<-'EOF'
265         : Last shell before umounting all and giving control over to real init.
266         debugshell
267         EOF
268
269         if is_yes "$run_mounted"; then
270                 add_linuxrc <<-EOF
271                 mount --bind /run /newroot/run
272                 umount /run
273                 EOF
274                 run_mounted=no
275         fi
276         if is_yes "$dev_mounted"; then
277                 add_linuxrc <<-EOF
278                 mount --bind /dev /newroot/dev
279                 umount /dev
280                 EOF
281                 dev_mounted=no
282         fi
283         if is_yes "$sys_mounted"; then
284                 add_linuxrc <<-EOF
285                 mount --bind /sys /newroot/sys
286                 umount /sys
287                 EOF
288                 sys_mounted=no
289         fi
290         if is_yes "$proc_mounted"; then
291                 add_linuxrc <<-EOF
292                 mount --bind /proc /newroot/proc
293                 umount /proc
294                 EOF
295                 proc_mounted=no
296         fi
297         if is_yes "$tmp_mounted"; then
298                 echo 'umount /tmp' | add_linuxrc
299                 tmp_mounted=no
300         fi
301 }
302
303 # Checks if busybox has support for APPLET(s)
304 # Exits from geninitrd if the support is not present.
305 #
306 # NB! XXX do not output to STDOUT, it will appear in initrd images in some cases!
307 busybox_applet() {
308         local err=0 applet
309
310         if [ -z "$busybox_functions" ]; then
311                 local tmp=$($busybox 2>&1)
312
313                 # BusyBox v1.1.3 says applet not found if it's not called 'busybox'.
314                 if [[ "$tmp" = *applet\ not\ found* ]]; then
315                         local t=$(mktemp -d)
316                         ln -s $busybox $t/busybox
317                         local tmp=$($t/busybox 2>&1)
318                         rm -rf $t
319                 fi
320
321                 busybox_functions=$(echo "$tmp" | \
322                         sed -ne '/Currently defined functions:/,$p' | \
323                         xargs | sed -e 's,.*Currently defined functions: ,,'
324                 )
325         fi
326         for applet in $*; do
327                 local have
328                 # try cache
329                 eval have='$'busybox_have_$applet
330                 if [ -z "$have" ]; then
331                         have=$(echo "$busybox_functions" | grep -Ec "( |^)$applet(,|$)")
332                         if [ "$have" = 0 ]; then
333                                 warn "This setup requires busybox-initrd compiled with applet '$applet' support"
334                                 err=1
335                         fi
336                         eval busybox_have_$applet=$have
337                 fi
338         done
339         if [ $err = 1 ]; then
340                 die "Aborted"
341         fi
342 }
343
344 # Extract the .config file from a kernel image
345 # uses extract-ikconfig from kernel sources (scripts/extract-ikconfig)
346 ikconfig() {
347         local kofile=$(modinfo -k $kernel -n configs 2> /dev/null)
348         if [ -n "$kofile" ]; then
349                 /lib/geninitrd/extract-ikconfig $kofile
350                 return
351         fi
352
353         # see if config available as separate file
354         if [ -f /boot/config-$kernel ]; then
355            cat /boot/config-$kernel
356            return
357         fi
358
359         # finally try vmlinuz itself
360         /lib/geninitrd/extract-ikconfig /boot/vmlinuz-$kernel
361 }
362
363 # @param    $module
364 basename_module() {
365         local module=$1
366
367         module=${module##*/}
368         module=${module%$modext*}
369         echo $module
370 }
371
372 # Finds module dependencies
373 #
374 # @param        $module
375 #
376 # Outputs full path to module and it's dependencies
377 find_depmod() {
378         local module="$1"
379         local skiperrors=0
380
381         # if module is prefixed with dash, we should ignore errors if the module
382         # can't be found.
383         if [ ${module#-} != $module ]; then
384                 skiperrors=1
385                 module=${module#-}
386         fi
387
388         # This works when user has module-init-tools installed even on 2.4 kernels
389         local modprobe
390         modprobe=$(modprobe --set-version $kernel --show-depends $module --ignore-install 2>&1)
391
392         if [ $? != 0 ]; then
393                 if [ $skiperrors = 1 ]; then
394                         return 0
395                 fi
396                 echo >&2 "$modprobe"
397
398                 if ! is_no "$EXIT_IF_MISSING"; then
399                         die "$module: module not found for $kernel kernel"
400                 fi
401
402                 warn "$module: module not found for $kernel kernel"
403                 warn "If $module isn't compiled in kernel then this initrd may not start your system."
404         fi
405
406         local smodule
407
408         echo "$modprobe" | \
409         while read insmod modpath options; do
410                 if [ "$insmod" = "insmod" ]; then
411
412                         # XXX: find a away to autodetect
413                         smodule=$(basename_module $modpath)
414                         case "$smodule" in
415                                 crc-t10dif)
416                                         find_depmod "-crct10dif-pclmul"
417                                         find_depmod "-crct10dif"
418                                         ;;
419                                 libcrc32c)
420                                         find_depmod "-crc32c-intel"
421                                         find_depmod "-crc32c"
422                                         ;;
423                                 virtio_blk|virtio_scsi)
424                                         find_depmod "-virtio_pci"
425                                         find_depmod "-virtio_mmio"
426                                         ;;
427                         esac
428
429                         echo $modpath
430                 fi
431         done
432         return 0
433 }
434
435 find_firmware() {
436         local module="$1"
437
438         # no firmware support in 2.4 kernels
439         if [ "$kernel_version_long" -lt "002005048" ]; then
440                 return
441         fi
442         echo -n $(NEW_MODINFO=1 modinfo -k $kernel -F firmware $module 2>/dev/null | xargs)
443 }
444
445 # @param        $module
446 find_module() {
447         local mod depmod module=$1
448
449         depmod=$(find_depmod $module) || exit 1
450         for mod in $depmod; do
451                 mod=${mod#/lib/modules/$kernel/}
452
453                 # add each module only once
454                 local m have=0
455                 for m in $MODULES; do
456                         [ $m = $mod ] && have=1
457                 done
458                 if [ $have = 0 ]; then
459                         MODULES="$MODULES $mod"
460                 fi
461         done
462 }
463
464 # install a file to temporary mount image.
465 # it will operate recursively (copying directories)
466 # and will symlink destinations if source is symlink.
467 inst() {
468         if [ $# -lt 2 ]; then
469                 die 'Usage: inst <file> [<file>] <destination>'
470         fi
471
472         local src i=0 c=$(($# - 1))
473         while [ $i -lt $c ]; do
474                 src="$src $1"
475                 i=$((i + 1))
476                 shift
477         done
478         local dest=$1
479         set -- $src
480         local parentDir=$(dirname $DESTDIR$dest)
481         if [ ! -d "$parentDir" ]; then
482                 verbose "+ mkdir -p $parentDir"
483                 mkdir -p $parentDir
484         fi
485         verbose "+ cp $* $DESTDIR$dest"
486         cp -HR "$@" "$DESTDIR$dest"
487 }
488
489 inst_d() {
490         if [ $# = 0 ]; then
491                 die 'Usage: inst_d <destination> <destination>'
492         fi
493         for dir in "$@"; do
494                 install -d "$DESTDIR$dir"
495         done
496 }
497
498 # install executable and it's shared libraries
499 inst_exec() {
500         if [ $# -lt 2 ]; then
501                 die "Invalid params ($@), Usage: inst_exec <file>[, <file>] <destination>"
502         fi
503         local src i=0 c=$(($# - 1))
504         while [ $i -lt $c ]; do
505                 src="$src $1"
506                 i=$((i + 1))
507                 shift
508         done
509         local dest=$1
510         set -- $src
511
512         inst "$@" $dest
513
514         local obj lib libs
515         for obj in "$@"; do
516                 case "$obj" in
517                         /lib/ld-linux.so.2 | /lib64/ld-linux-x86-64.so.2)
518                         continue
519                 esac
520
521                 libs=$(ldd "$obj" | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
522                 for lib in $libs; do
523                         if [ ! -f "$DESTDIR/$_lib/${lib##*/}" ]; then
524                                 inst_d /$_lib
525                                 inst_exec $lib /$_lib
526                         fi
527                 done
528         done
529
530         # hack for uclibc linked binaries requiring this fixed path
531         # XXX: shouldn't rpath be used here instead so th
532         if [ -f $DESTDIR/$_lib/libc.so.0 ]; then
533                 local lib=$DESTDIR/$_lib/libc.so.0
534                 lib=$(ldd "$lib" | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
535                 local libdir=$(cd $(dirname "$lib"); pwd)
536                 if [ ! -e $DESTDIR$libdir ]; then
537                         libdir=$(dirname "$libdir")
538                         inst_d $libdir
539                         verbose "+ ln -s /$_lib $DESTDIR$libdir"
540                         ln -s /$_lib $DESTDIR$libdir
541                 fi
542         fi
543 }
544
545 # output modules.conf / modprobe.conf
546 modprobe_conf() {
547         echo "$modprobe_conf_cache"
548 }
549
550 # return options for MODULE
551 # @param $1 module name
552 modprobe_options() {
553         local module=$1
554         local options=$(modprobe_conf | awk -vmodule="$module" '{ if ($1 == "options" && $2 == module) { for(i=3;i<=NF;i++) printf("%s ",$i); }}')
555         echo ${options# }
556 }
557
558 #
559 # defaults to modprobe -c if not told otherwise, this means include statements
560 # work from there.
561 cache_modprobe_conf() {
562         if [ "$kernel_version" -lt "002005" ]; then
563                 modulefile=/etc/modules.conf
564                 if [ ! -f "$modulefile" -a -f /etc/conf.modules ]; then
565                         modulefile=/etc/conf.modules
566                 fi
567         fi
568
569         if [ -n "$modulefile" ]; then
570                 debug "Using $modulefile for modules config"
571                 modprobe_conf_cache=$(cat $modulefile | awk '!/^[\t ]*#/ { print }')
572
573         else
574                 debug "Using modprobe -c to get modules config"
575                 modprobe_conf_cache=$(modprobe -c --set-version $kernel | awk '!/^[\t ]*#/ { print }')
576         fi
577 }
578
579 # find modules for $devpath
580 find_modules_for_devpath() {
581         local devpath="$1"
582         if [ -z "$devpath" ]; then
583                 die "No argument passed to find_modules_for_devpath() - is your /etc/fstab correct?"
584         fi
585
586         if [[ "$devpath" = /dev/dm-* ]]; then
587                 # /dev/dm-3 -> /dev/mapper/sil_ahbgadcbchfc3
588                 devpath=$(dm_node "$devpath")
589         fi
590
591         if [ -L "$devpath" ] && ! is_lvm "$devpath" && ! is_luks "$devpath"; then
592                 # sanitize things like:
593                 # /dev/block/104:2 -> /dev/cciss/c0d0p2
594                 devpath=$(readlink -f "$devpath")
595         fi
596
597         verbose "Finding modules for device path $devpath"
598
599         if is_luks "$devpath"; then
600                 find_modules_luks "$devpath"
601                 return
602         fi
603
604         if is_nfs "$devpath"; then
605                 find_modules_nfs "$devpath"
606                 return
607         fi
608
609         if is_md "$devpath"; then
610                 find_modules_md "$devpath"
611                 return
612         fi
613
614         if is_multipath "$devpath"; then
615                 if find_modules_multipath "$devpath"; then
616                         return
617                 fi
618
619                 # fallback
620         fi
621
622         if is_dmraid "$devpath"; then
623                 if find_modules_dmraid "$devpath"; then
624                         return
625                 fi
626                 # fallback
627         fi
628
629         if is_scsi "$devpath"; then
630                 find_modules_scsi "$devpath"
631                 return
632         fi
633
634         if is_ide "$devpath"; then
635                 find_modules_ide "$devpath"
636                 return
637         fi
638
639         if [[ "$devpath" == /dev/bcache* ]]; then
640                 find_modules_bcache "$devpath"
641                 return
642         fi
643
644         if [[ "$devpath" == /dev/rd/* ]]; then
645                 find_module "DAC960"
646                 rootdev_add=/dev/rd/
647                 return
648         fi
649
650         if [[ "$devpath" == /dev/ida/* ]]; then
651                 find_module "cpqarray"
652                 rootdev_add=/dev/ida/
653                 return
654         fi
655
656         if [[ "$devpath" == /dev/cciss/* ]]; then
657                 rootdev_add=/dev/cciss/
658
659                 # load hpsa for future kernels, cciss for backwards compat
660                 if [ "$kernel_version_long" -ge "003000000" ]; then
661                         find_module "hpsa" "-cciss"
662                         find_modules_scsi "$devpath"
663                 else
664                         find_module "cciss"
665                 fi
666
667                 return
668         fi
669
670         if [[ "$devpath" == /dev/ataraid/* ]]; then
671                 find_modules_ide
672                 find_module "ataraid"
673                 ataraidmodules=$(modprobe_conf | awk '/ataraid_hostadapter/ { print $3 }')
674                 if [ -n "$ataraidmodules" ]; then
675                         # FIXME: think about modules compiled in kernel
676                         die "ataraid_hostadapter alias not defined in modprobe.conf! Please set it and run $PROGRAM again."
677                 fi
678                 for n in $ataraidmodules; do
679                         find_module "$n"
680                 done
681                 rootdev_add=/dev/ataraid/
682                 return
683         fi
684
685         # check to see if we need to set up a loopback filesystem
686         if [[ "$devpath" == /dev/loop*  ]]; then
687                 die "Sorry, root on loop device isn't supported."
688                 # TODO: rewrite for bsp and make nfs ready
689                 if [ ! -x /sbin/losetup ]; then
690                         die "losetup is missing"
691                 fi
692                 key="^# $(echo $devpath | awk -F/ '{print($3);}' | tr '[a-z]' '[A-Z]'):"
693                 if ! is_yes "`awk '/'$key'/ { print( "yes"); }' $fstab`"; then
694                         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"
695                 fi
696
697                 line="`awk '/'$key'/ { print $0; }' $fstab`"
698                 loopDev="$(echo $line | awk '{print $3}')"
699                 loopFs="$(echo $line | awk '{print $4}')"
700                 loopFile="$(echo $line | awk '{print $5}')"
701
702                 BASICMODULES="$BASICMODULES -loop"
703                 find_module "-$loopFs"
704                 BASICMODULES="$BASICMODULES -${loopFs}"
705                 return
706         fi
707
708         if is_lvm "$devpath"; then
709                 find_modules_lvm "$devpath"
710                 return
711         fi
712 }
713
714 firmware_install_module() {
715         local module="$1"
716         local firmware_files="$2"
717
718         verbose "Adding Firmwares ($firmware_files) to initrd for module $module"
719         # firmware not yet installed
720         if [ ! -f "$DESTDIR/lib/firmware/firmware.sh" ]; then
721                 inst_d /lib/firmware
722 cat << 'EOF' >> "$DESTDIR/lib/firmware/firmware.sh"
723 #!/bin/sh -e
724 echo 1 > /sys$DEVPATH/loading
725 cat "/lib/firmware/$FIRMWARE" > /sys$DEVPATH/data
726 echo 0 > /sys$DEVPATH/loading
727 exit 0
728 EOF
729                 chmod 755 "$DESTDIR/lib/firmware/firmware.sh"
730
731                 # setup firmware loader agent
732                 echo "echo -n "/lib/firmware/firmware.sh" > /proc/sys/kernel/hotplug" | add_linuxrc
733         fi
734
735         for firmware in $firmware_files; do
736                 if [ -f "/lib/firmware/$kernel/$firmware" ]; then
737                         FIRMWAREDIR=${firmware%/*}
738                         [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
739                         inst /lib/firmware/$kernel/$firmware /lib/firmware/$firmware
740                 elif [ -f "/lib/firmware/$firmware" ]; then
741                         FIRMWAREDIR=${firmware%/*}
742                         [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
743                         inst /lib/firmware/$firmware /lib/firmware/$firmware
744                 else
745                         warn "Possible missing firmware file /lib/firmware/$firmware or /lib/firmware/$kernel/$firmware for module $module."
746                 fi
747         done
748
749         mount_sys
750 }
751
752 modules_install() {
753         local modules="$1"
754         local mod
755
756         for mod in $modules; do
757                 MODULEDIR=${mod%/*}
758                 inst_d "/lib/modules/$kernel/$MODULEDIR"
759                 cp -a "/lib/modules/$kernel/$mod" "$DESTDIR/lib/modules/$kernel/$mod"
760                 gunzip "$DESTDIR/lib/modules/$kernel/$mod" 2> /dev/null
761                 if [ "$STRIP" ] && [ -x "$STRIP" ]; then
762                         $STRIP -g --remove-section=.comment "$DESTDIR/lib/modules/$kernel/${mod%.gz}"
763                 fi
764         done
765 }
766
767 modules_add_linuxrc() {
768         local mod modpath
769
770         for mod in "$@"; do
771                 # module path without optional compression
772                 modpath=${mod%.gz}
773
774                 # name of the module
775                 local module=${modpath##*/}; module=${module%$modext}
776                 local options=$(modprobe_options "$module")
777                 local genericname=$(echo $module | tr - _)
778                 local usleep=$(eval echo \$MODULE_${genericname}_USLEEP)
779                 local firmware=$(eval echo \$MODULE_${genericname}_FIRMWARE)
780
781                 if [ "$module" = "scsi_mod" -a "$kernel_version_long" -ge "002006030" ]; then
782                         options="scan=sync $options"
783                 fi
784
785                 if [ x"$verbose" = x"-v" ]; then
786                         s=""
787                         if [ "$options" ]; then
788                                 s="$s with options [$options]"
789                         fi
790                         if [ "$usleep" ]; then
791                                 s="$s and $usleep usleep"
792                         fi
793                         verbose "Loading module [$module]$s"
794                 fi
795
796                 if [ -n "$firmware" ]; then
797                         firmware_install_module "$module" "$firmware"
798                 else
799                         for file in $(find_firmware "$module"); do
800                                 firmware_install_module "$module" "$file"
801                         done
802                 fi
803
804                 echo "insmod /lib/modules/$kernel/$modpath $options" | add_linuxrc
805                 if [ -n "$usleep" ]; then
806                         echo "usleep $usleep" | add_linuxrc
807                 fi
808                 if [ "$module" = "scsi_wait_scan" ]; then
809                         if [ "$(busybox_applet rmmod 2>/dev/null; echo $?)" = 0 ]; then
810                                 echo "rmmod scsi_wait_scan" | add_linuxrc
811                         fi
812                 fi
813
814         done
815 }
816
817 # Generates /dev nodes based on /proc/partitions information.
818 # Needs /proc mounted.
819 # Can be called multiple times.
820 initrd_gen_devices() {
821         if is_yes "$proc_partitions"; then
822                 return
823         fi
824         proc_partitions=yes
825
826         mount_dev
827         add_linuxrc <<-'EOF'
828                 : 'Making device nodes'
829                 cat /proc/partitions | (
830                         # ignore first two lines: header, empty line
831                         read b; read b
832
833                         while read major minor blocks dev rest; do
834                                 node=/dev/$dev
835                                 mkdir -p ${node%/*}
836                                 [ -e $node ] || mknod -m 660 $node b $major $minor
837                         done
838                 )
839         EOF
840 }
841
842
843 initrd_gen_setrootdev() {
844         verbose "Adding rootfs finding based on kernel cmdline root= option support."
845         busybox_applet ls
846         debug "Current /proc/partitions:\n$(sed -e 's,^,| ,' /proc/partitions)"
847         add_linuxrc <<-'EOF'
848                 if [ "${ROOT##/dev/}" != "${ROOT}" ]; then
849                         rootnr="$(busybox awk -v rootnode="${ROOT##/dev/}" '$4 == rootnode { print 256 * $1 + $2 }' /proc/partitions)"
850                         # fallback to ls
851                         if [ -z "$rootnr" -a -e "$ROOT" ]; then
852                                 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $3 + $4; }}')"
853                         fi
854                         if [ -n "$rootnr" ]; then
855                                 echo "$rootnr" > /proc/sys/kernel/real-root-dev
856                         fi
857                 fi
858         EOF
859 }
860
861 initrd_gen_initramfs_switchroot() {
862         inst_d /newroot
863         if [ "$rootdev" = "/dev/nfs" ]; then
864                 echo "rootfs on NFS root=/dev/nfs"
865         else
866                 [ ! -e "$DESTDIR/$rootdev" ] && inst $rootdev $rootdev
867         fi
868
869         # parse 'root=xxx' kernel commandline
870         # We support passing root as hda3 /dev/hda3 0303 0x0303 and 303
871
872         # from lilo-23.2/readme/README:
873         # root=<device> changes the root device. This overrides settings that may
874         # have been made in the boot image and on the LILO command line. <device> is
875         # either the hexadecimal device number or the full path name of the device,
876         # e.g. /dev/hda3 [*]
877         #
878         #  *  The device names are hard-coded in the kernel. Therefore, only the
879         #         "standard" names are supported and some less common devices may not be
880         #         recognized. In those cases, only numbers can be used.
881         busybox_applet cat
882         add_linuxrc <<-'EOF'
883                 device=
884                 eval "$(busybox awk -v root="$ROOT" '
885                         # http://9fans.net/archive/2006/09/261
886                         function h2d(str, hstr, res, num, n, digit, i) {
887                                 hstr = "0123456789abdcef";
888                                 res = 0;
889                                 n = split(tolower(str), digit, "");
890
891                                 for (i = 1; i <= n; i++) {
892                                         num = index(hstr, digit[i]) - 1;
893                                         res = res + (num * 16 ^ (n - i));
894                                 }
895
896                                 return res;
897                         }
898                         BEGIN {
899
900                                 num_pattern_short = "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]";
901                                 num_pattern = "[0-9a-fA-F]" num_pattern_short;
902                                 dev_pattern = "[hms][a-z][a-z]([0-9])+";
903                                 partition = "";
904                                 min = -1; maj = -1;
905
906                                 # see if we have /dev/hdX or hdX, we can just take partition name
907                                 if (root ~ "^\/dev\/" dev_pattern "$" || root ~ "^" dev_pattern "$") {
908                                         partition = root
909                                         sub("^/dev/", "", partition);
910
911                                 } else {
912                                         # unify values first
913                                         if (root ~ "^" num_pattern_short "$")  {
914                                                 # change "303" => "0x0303"
915                                                 root = "0x0" root
916                                         } else if (root ~ "^" num_pattern "$")  {
917                                                 # change "0303" => "0x0303"
918                                                 root = "0x" root
919                                         }
920
921                                         maj = h2d(substr(root, 3, 2));
922                                         min = h2d(substr(root, 5, 2));
923                                 }
924                         }
925
926                         partition && $4 == partition { maj = $1; min = $2; }
927                         $1 == maj && $2 == min { partition = $4; }
928
929                         END {
930                                 if (maj >= 0 && min >= 0) {
931                                         printf("maj=%s; min=%s;\n", maj, min);
932                                 }
933                                 if (partition) {
934                                         printf("device=/dev/%s;\n", partition);
935                                 }
936                         }
937                         ' /proc/partitions)"
938
939                 if [ -z "$device" ]; then
940                         if [ "$DEBUGINITRD" ]; then
941                                 cat /proc/partitions
942                         fi
943                         device=$ROOT
944                 fi
945
946                 if [ "$device" -a ! -b $device -a "$maj$min" ]; then
947                         mknod -m 660 $device b $maj $min
948                 fi
949
950                 # XXX hack, if no device, try to parse it from /proc/partitions using /proc/sys/kernel/real-root-dev
951                 if [ ! -e "$device" ]; then
952                         rrd=$(cat /proc/sys/kernel/real-root-dev)
953                         major=$(($rrd / 256))
954                         minor=$(($rrd % 256))
955
956                         while read pmajor pminor blocks dev rest; do
957                                 # skip header and empty line
958                                 [ -z "$pmajor" -o "$pmajor" = "major" ] && continue
959
960                                 if [ $pmajor = $major -a $pminor = $minor ]; then
961                                         device=/dev/$dev
962                                         echo "DEVICE set to $device based on real-root-dev"
963                                 fi
964                         done < /proc/partitions
965                 fi
966
967                 [ -n "$ROOTFSFLAGS" ] && ROOTFSFLAGS="-o $ROOTFSFLAGS"
968
969                 mount -t $ROOTFS -r $device $ROOTFSFLAGS /newroot || echo "Mount of rootfs failed."
970                 init=$INIT
971                 if [ -z "$init" -o ! -x "/newroot$init" ]; then
972                         init=/sbin/init
973                 fi
974         EOF
975
976         busybox_applet dmesg
977         busybox_applet tail
978         add_linuxrc <<-'EOF'
979                 if [ "$DEBUGINITRD" ]; then
980                         echo "Last 20 lines of dmesg:"
981                         dmesg | tail -n 20
982                 fi
983
984         EOF
985
986         kmsg "geninitrd/$VERSION switching root"
987
988         umount_all
989         busybox_applet switch_root usleep
990         add_linuxrc <<-'EOF'
991                 [ ! -e /newroot/dev/console ] && mknod -m 660 /newroot/dev/console c 5 1
992
993                 # switch root to empty dir will make kernel panic, so sleep 10s before it
994                 # switch_root needs to be pid 1, so there's no other way to recover from here
995                 # if /dev is missing, switch root will likely fail, give debug shell before that
996                 if [ ! -d /newroot/dev ]; then
997                         echo "/dev is missing, switch_root will likely fail"
998                         echo "if you booted with debugrd=sh, then you be given shell and you might able to recover this situation"
999                         debugshell
1000                         [ "$DEBUGINITRD" ] || usleep 10000000
1001                 fi
1002
1003                 exec switch_root /newroot $init ${1:+"$@"}
1004
1005                 # FIXME: this code is never executed, as "exec" does not return!
1006
1007                 echo "Error! initramfs should not reach this place."
1008                 echo "It probably means you've got old version of busybox, with broken"
1009                 echo "initramfs support. Trying to boot anyway, but won't promise anything."
1010
1011                 exec chroot /newroot $init ${1:+"$@"}
1012
1013                 echo "Failed to chroot!"
1014                 debugshell
1015         EOF
1016         # we need /init being real file, not symlink, otherwise the initramfs will
1017         # not be ran by pid 1 which is required for switch_root
1018         mv $DESTDIR/linuxrc $DESTDIR/init
1019         ln -s init $DESTDIR/linuxrc
1020 }
1021
1022 # find if $symbol exists in System.map $mapfile
1023 sym_exists() {
1024         local mapfile="$1"
1025         local symbol="$2"
1026         if [ ! -f $mapfile ]; then
1027                 # missing mapfile (not a pld kernel?)
1028                 return 1
1029         fi
1030
1031         awk -vc=1 -vsymbol="$symbol" '$2 == "T" && $3 == symbol {c = 0} END {exit c}' $mapfile
1032 }
1033
1034 # find best compressor (or forced one) for initrd
1035 find_compressor() {
1036         local mode="$1"
1037         # fastest initrd decompression speed is first
1038         local compressors='lzo gzip xz lzma bzip2'
1039
1040         # a specified one, take it
1041         if ! is_yes "$mode"; then
1042                 compressors="$mode"
1043         fi
1044
1045         verbose "finding compressor: $compressors (via $mode)"
1046         # check for compressor validity
1047         local c prog map=/boot/System.map-$kernel
1048         for c in $compressors; do
1049                 case $c in
1050                 xz)
1051                         sym=unxz
1052                         prog=/usr/bin/xz
1053                         ;;
1054                 lzma)
1055                         sym=unlzma
1056                         prog=/usr/bin/xz
1057                         ;;
1058                 bzip2)
1059                         sym=bzip2
1060                         prog=/usr/bin/bzip2
1061                         ;;
1062                 gzip)
1063                         sym=gunzip
1064                         prog=/bin/gzip
1065                         ;;
1066                 lzo)
1067                         sym=unlzo
1068                         prog=/usr/bin/lzop
1069                         ;;
1070                 none|no)
1071                         # any existing sym will work
1072                         sym=initrd_load
1073                         prog=/bin/cat
1074                         ;;
1075                 *)
1076                         die "Unknown compressor $c"
1077                         ;;
1078                 esac
1079                 if sym_exists $map $sym && [ -x $prog ]; then
1080                         echo $c
1081                         return
1082                 fi
1083         done
1084
1085         verbose "using gzip for compressor (fallback)"
1086         echo gzip
1087 }
1088
1089 # compresses kernel image image
1090 # in function so we could retry with other compressor on failure
1091 compress_image() {
1092         local compressor="$1" IMAGE="$2" target="$3" tmp
1093         tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1094
1095         case "$compressor" in
1096         xz)
1097                 # don't use -9 here since kernel won't understand it
1098                 xz --format=xz --check=crc32 --lzma2=preset=6e,dict=1MiB < "$IMAGE" > "$tmp" || return $?
1099                 ;;
1100         lzma)
1101                 xz --format=lzma -9 < "$IMAGE" > "$tmp" || return $?
1102                 ;;
1103         bzip2)
1104                 bzip2 -9 < "$IMAGE" > "$tmp" || return $?
1105                 ;;
1106         gzip)
1107                 gzip -9 < "$IMAGE" > "$tmp" || return $?
1108                 ;;
1109         lzo)
1110                 lzop -9 < "$IMAGE" > "$tmp" || return $?
1111                 ;;
1112         none|no)
1113                 cat < "$IMAGE" > "$tmp" || return $?
1114                 ;;
1115         esac
1116
1117         mv -f "$tmp" "$target"
1118 }
1119
1120 if [ -r /etc/sysconfig/geninitrd ]; then
1121         . /etc/sysconfig/geninitrd
1122 fi
1123
1124 if [ ! -f /proc/mounts ]; then
1125         warn "/proc filesystem not mounted, may cause wrong results or failure."
1126 fi
1127
1128 geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev tuxonice suspend fbsplash condecor bootsplash uvesafb nfs sata scsi usbkbd bcache
1129
1130 while [ $# -gt 0 ]; do
1131         case $1 in
1132         --fstab=*)
1133                 fstab=${1#--fstab=}
1134                 ;;
1135         --fstab)
1136                 fstab=$2
1137                 shift
1138                 ;;
1139         --modules-conf=*)
1140                 modulefile=${1#--modules-conf=}
1141                 ;;
1142         --modules-conf)
1143                 modulefile=$2
1144                 shift
1145                 ;;
1146         --with-bootsplash)
1147                 BOOT_SPLASH=yes
1148                 ;;
1149         --without-bootsplash)
1150                 BOOT_SPLASH=no
1151                 ;;
1152         --with-fbsplash)
1153                 FB_SPLASH=yes
1154                 ;;
1155         --without-fbsplash)
1156                 FB_SPLASH=no
1157                 ;;
1158         --with-fbcondecor)
1159                 FB_CON_DECOR=yes
1160                 ;;
1161         --without-fbcondecor)
1162                 FB_CON_DECOR=no
1163                 ;;
1164         --with-suspend)
1165                 USE_SUSPEND=yes
1166                 ;;
1167         --without-suspend)
1168                 USE_SUSPEND=no
1169                 ;;
1170         --with-suspend2 | --with-tuxonice)
1171                 USE_TUXONICE=yes
1172                 ;;
1173         --without-suspend2 | --without-tuxonice)
1174                 USE_TUXONICE=no
1175                 ;;
1176         --lvmversion=*)
1177                 LVMTOOLSVERSION=${1#--lvmversion=}
1178                 ;;
1179         --lvmtoolsversion=*)
1180                 LVMTOOLSVERSION=${1#--lvmtoolsversion=}
1181                 ;;
1182         --lvmtoolsversion|--lvmversion)
1183                 LVMTOOLSVERSION=$2
1184                 shift
1185                 ;;
1186         --without-udev)
1187                 USE_UDEV=no
1188                 ;;
1189         --with-udev)
1190                 USE_UDEV=yes
1191                 ;;
1192         --without-dmraid)
1193                 USE_DMRAID=no
1194                 ;;
1195         --without-multipath)
1196                 USE_MULTIPATH=no
1197                 ;;
1198         --with-multipath=*)
1199                 USE_MULTIPATH=${1#--with-multipath=}
1200                 ;;
1201         --without-blkid)
1202                 USE_BLKID=no
1203                 ;;
1204         --without-luks)
1205                 USE_LUKS=no
1206                 ;;
1207         --with=*)
1208                 BASICMODULES="$BASICMODULES ${1#--with=}"
1209                 ;;
1210         --with)
1211                 BASICMODULES="$BASICMODULES $2"
1212                 shift
1213                 ;;
1214         --version)
1215                 echo "$PROGRAM: version $VERSION"
1216                 exit 0
1217                 ;;
1218         -v)
1219                 if [ x"$verbose" = x"-v" ]; then
1220                         verbose="-v -v"
1221                 else
1222                         verbose="-v"
1223                 fi
1224                 exec 3>&1
1225                 ;;
1226         --compress)
1227                 COMPRESS=$2
1228                 ;;
1229         --compress=*)
1230                 COMPRESS="${1#--compress=}"
1231                 ;;
1232         --nocompress)
1233                 COMPRESS=no
1234                 ;;
1235         --nostrip)
1236                 STRIP=
1237                 ;;
1238         --strip=*)
1239                 STRIP="${1#--strip=}"
1240                 ;;
1241         --strip)
1242                 STRIP=$2
1243                 shift
1244                 ;;
1245         --ifneeded)
1246                 ifneeded=1
1247                 ;;
1248         -f)
1249                 force=1
1250                 ;;
1251         --preload=*)
1252                 PREMODS="$PREMODS ${1#--preload=}"
1253                 ;;
1254         --preload)
1255                 PREMODS="$PREMODS $2"
1256                 shift
1257                 ;;
1258         --fs=* | --fs)
1259                 die "--fs option is obsoleted. Use --initrdfs instead"
1260                 ;;
1261         --initrdfs=*)
1262                 INITRDFS=${1#--initrdfs=}
1263                 ;;
1264         --initrdfs)
1265                 INITRDFS=$2
1266                 shift
1267                 ;;
1268         --image-version)
1269                 img_vers=yes
1270                 ;;
1271         --ide-only-root)
1272                 ide_only_root="yes"
1273                 ;;
1274         *)
1275                 if [ -z "$target" ]; then
1276                         target="$1"
1277                 elif [ -z "$kernel" ]; then
1278                         kernel="$1"
1279                 else
1280                         usage
1281                         exit 1
1282                 fi
1283                 ;;
1284         esac
1285
1286         shift
1287 done
1288
1289 if [ -z "$target" -o -z "$kernel" ]; then
1290         usage
1291         exit 1
1292 fi
1293
1294 # main()
1295 if [ "$(id -u)" != 0 ]; then
1296         die "You need to be root to generate initrd"
1297 fi
1298
1299 if [ -d /lib64 -a -d /usr/lib64 ]; then
1300         _lib=lib64
1301 else
1302         _lib=lib
1303 fi
1304
1305 initrd_dir=/usr/$_lib/initrd
1306 kernel_version=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d",$1,$2)}')
1307 kernel_version_long=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d%03d",$1,$2,$3)}')
1308
1309 verbose "# geninitrd $VERSION"
1310 debug "Using _lib: $_lib"
1311 debug "Using initrd_dir: $initrd_dir"
1312
1313 busybox=$(find_tool $initrd_dir/busybox $initrd_dir/initrd-busybox /bin/initrd-busybox) || die "Couldn't find busybox suitable for initrd"
1314
1315 # we setup mods after parsing command line args
1316 geninitrd_setup_mods
1317
1318 if [ ! -f /boot/vmlinuz-"$kernel" ]; then
1319         warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?"
1320 fi
1321
1322 if [ -z "$INITRDFS" ]; then
1323         if [ -n "$FS" ]; then
1324                 # FS= can came only via /etc/sysconfig/geninitrd likely?
1325                 die "FS configuration option is obsoleted. Use INITRDFS instead"
1326         fi
1327
1328         # default value
1329         if [ "$kernel_version" -ge "002005" ]; then
1330                 INITRDFS="initramfs"
1331         else
1332                 INITRDFS="rom"
1333         fi
1334 fi
1335
1336 case "$INITRDFS" in
1337   ext2)
1338         [ -x /sbin/mke2fs ] || die "/sbin/mke2fs is missing"
1339         ;;
1340   rom|romfs)
1341         [ -x /sbin/genromfs ] || die "/sbin/genromfs is missing"
1342         ;;
1343   cram|cramfs)
1344         [ -x /sbin/mkcramfs ] || die "/sbin/mkcramfs is missing"
1345         ;;
1346   initramfs)
1347         [ -x /bin/cpio ] || die "/bin/cpio is missing"
1348         [ -x /usr/bin/find ] || die "/usr/bin/find is missing"
1349         ;;
1350   *)
1351         die "Filesystem $INITRDFS on initrd is not supported"
1352         ;;
1353 esac
1354
1355 if [ -L "$target" ]; then
1356         target=$(readlink -f "$target")
1357 fi
1358
1359 if [ -n "$img_vers" ]; then
1360         target="$target-$kernel"
1361 fi
1362
1363 if [ -z "$force" -a -f "$target" ]; then
1364         die "$target already exists."
1365 fi
1366
1367 if [ ! -d "/lib/modules/$kernel" ]; then
1368         die "/lib/modules/$kernel is not a directory."
1369 fi
1370
1371 if [ "$kernel_version" -ge "002005" ]; then
1372         modext=".ko"
1373 fi
1374
1375 cache_modprobe_conf
1376
1377 for n in $PREMODS; do
1378         find_module "$n"
1379 done
1380
1381 if [ "$FBMODULE" ]; then
1382         find_module "$FBMODULE"
1383 fi
1384
1385 # autodetect USB keyboards
1386 find_modules_usbkbd
1387
1388 # allow forcing loading SCSI and/or IDE modules
1389 # XXX: where ADDSCSI cames from? drop?
1390 if is_yes "$ADDSCSI"; then
1391         find_modules_scsi
1392 fi
1393
1394 # autodetect SATA modules
1395 find_modules_sata
1396
1397 # XXX: where ADDIDE cames from? drop?
1398 if is_yes "$ADDIDE"; then
1399         find_modules_ide
1400 fi
1401
1402 if is_yes "$USE_SUSPEND"; then
1403         find_modules_suspend
1404 fi
1405
1406 find_root "$fstab" || exit
1407 verbose "Using $rootdev as device for rootfs"
1408
1409 find_modules_for_devpath "$rootdev"
1410
1411 # if USE_MULTIPATH is path to device, scan that too
1412 # this is to bootstrap multipath setup into initrd.
1413 if ! is_no "$USE_MULTIPATH" && ! is_yes "$USE_MULTIPATH"; then
1414         find_modules_multipath $USE_MULTIPATH
1415 fi
1416
1417 find_module "-$rootFs"
1418
1419 for n in $BASICMODULES; do
1420         find_module "$n"
1421 done
1422
1423 if is_yes "$USE_TUXONICE"; then
1424         find_module "-lzf"
1425 fi
1426
1427 find_modules_uvesafb
1428 find_modules_fbsplash
1429
1430 if [ -n "$ifneeded" -a -z "$MODULES" ]; then
1431         verbose "No modules are needed -- not building initrd image."
1432         exit 0
1433 fi
1434
1435 verbose "Building initrd..."
1436 DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
1437 RCFILE="$DESTDIR/linuxrc"
1438 > "$RCFILE"
1439 chmod a+rx "$RCFILE"
1440 ln -s linuxrc $DESTDIR/init
1441
1442 # create dirs that we really need
1443 inst_d /{lib,bin,etc,dev{,/pts,/shm},loopfs,var,proc,run,sys}
1444
1445 modules_install "$MODULES"
1446
1447 # mknod'ing the devices instead of copying them works both with and
1448 # without devfs...
1449 mknod -m 600 "$DESTDIR/dev/console" c 5 1
1450 mknod -m 666 "$DESTDIR/dev/null" c 1 3
1451 mknod -m 666 "$DESTDIR/dev/zero" c 1 5
1452 mknod -m 666 "$DESTDIR/dev/random" c 1 8
1453 mknod -m 666 "$DESTDIR/dev/urandom" c 1 9
1454 mknod -m 644 "$DESTDIR/dev/kmsg" c 1 11
1455
1456 inst_exec $busybox /bin/busybox
1457 ln -s busybox $DESTDIR/bin/sh
1458 # for older busyboxes who had /bin/initrd-busybox as EXEPATH
1459 ln -s busybox $DESTDIR/bin/initrd-busybox
1460
1461 add_linuxrc <<EOF
1462 #!/bin/sh
1463 # initrd generated by geninitrd/$VERSION
1464 # on $(LC_ALL=C date)
1465
1466 EOF
1467 mount_proc
1468
1469 kmsg "geninitrd/$VERSION starting"
1470
1471 add_linuxrc <<-EOF
1472         # builtin defaults from geninitrd
1473         ROOT=$rootdev
1474         ROOTFS=$rootFs
1475 EOF
1476 add_linuxrc <<-'EOF'
1477         read CMDLINE < /proc/cmdline
1478
1479         for arg in $CMDLINE; do
1480                 if [ "${arg}" = "debuginitrd" ] || [ "${arg}" = "debugrd" ]; then
1481                         DEBUGINITRD=yes
1482                 fi
1483                 if [ "${arg##debuginitrd=}" != "${arg}" ] || [ "${arg##debugrd=}" != "${arg}" ]; then
1484                         DEBUGINITRD=${arg##debug*rd=}
1485                 fi
1486                 if [ "${arg##root=}" != "${arg}" ]; then
1487                         ROOT=${arg##root=}
1488                 fi
1489                 if [ "${arg##rootfsflags=}" != "${arg}" ]; then
1490                         ROOTFSFLAGS=${arg##rootfsflags=}
1491                 fi
1492                 if [ "${arg##init=}" != "${arg}" ]; then
1493                         INIT=${arg##init=}
1494                 fi
1495         done
1496
1497         if [ "$DEBUGINITRD" = "sh" ]; then
1498                 # export some vars to subshell for debug to work
1499                 export CMDLINE ROOT ROOTFS ROOTDEV ROOTFSFLAGS DEBUGINITRD INIT
1500                 export LVM_ROOTVG LVM_SUSPENDVG LVM_VGVOLUMES
1501                 export rootnr attrs majmin major minor device
1502
1503                 # make debugshell() invoke subshell if $DEBUGINITRD=sh
1504                 debugshell() {
1505 EOF
1506 if is_yes "$RUN_SULOGIN_ON_ERR"; then
1507 add_linuxrc <<-'EOF'
1508         echo "debug shell disabled by RUN_SULOGIN_ON_ERR=yes from /etc/sysconfig/system during initrd generation time"
1509 EOF
1510 else
1511 add_linuxrc <<-'EOF'
1512         sh
1513 EOF
1514 fi
1515 add_linuxrc <<-'EOF'
1516                 }
1517         else
1518                 debugshell() {
1519                         :
1520                 }
1521         fi
1522
1523         if [ "$DEBUGINITRD" ]; then
1524                 set -x
1525         fi
1526 EOF
1527
1528 modules_add_linuxrc $MODULES
1529
1530 # TODO: rewrite for busybox
1531 #if [ -n "$loopDev" ]; then
1532 #       if [ ! -d /initrd ]; then
1533 #               mkdir /initrd
1534 #       fi
1535 #
1536 #       cp -a "$loopDev" "$DESTDIR/dev"
1537 #       cp -a "$rootdev" "$DESTDIR/dev"
1538 #       echo "echo Mounting device containing loopback root filesystem" >> "$RCFILE"
1539 #       echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE"
1540 #       echo "echo Setting up loopback device $rootdev" >> $RCFILE
1541 #       echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE"
1542 #fi
1543
1544 if is_yes "$USE_UDEV"; then
1545         initrd_gen_udev
1546 else
1547         initrd_gen_mdev
1548 fi
1549
1550 initrd_gen_uvesafb
1551 initrd_gen_luks
1552 initrd_gen_dmraid
1553 initrd_gen_multipath
1554 initrd_gen_blkid
1555
1556 if is_yes "$have_nfs"; then
1557         initrd_gen_nfs
1558 else
1559         initrd_gen_md
1560         initrd_gen_lvm
1561         initrd_gen_bcache
1562         initrd_gen_blkid
1563         initrd_gen_luks
1564         initrd_gen_setrootdev
1565 fi
1566
1567 # additional devs always needed
1568 [ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev
1569
1570 initrd_gen_stop_udevd
1571 initrd_gen_stop_mdev
1572 initrd_gen_stop_uvesafb
1573
1574 # resume after killing local processes
1575 initrd_gen_tuxonice
1576 initrd_gen_suspend
1577
1578 # clean up env
1579 add_linuxrc <<-'EOF'
1580 if [ ! "$DEBUGINITRD" ]; then
1581         ifs=$IFS
1582         IFS="
1583         "
1584         for i in $(export -p); do
1585                 i=${i#declare -x } # ksh/bash
1586                 i=${i#export } # busybox
1587
1588                 case "$i" in
1589                 *=*)
1590                         : ;;
1591                 *)
1592                         continue ;;
1593                 esac
1594
1595                 i=${i%%=*}
1596
1597                 [ -z "$i" ] && continue
1598
1599                 case "$i" in
1600                         ROOT|PATH|HOME|TERM)
1601                                 :
1602                                 ;;
1603                         *)
1604                                 unset $i
1605                                 ;;
1606                 esac
1607         done
1608         IFS=$ifs
1609 fi
1610 EOF
1611
1612 if [ "$INITRDFS" = "initramfs" ]; then
1613         initrd_gen_initramfs_switchroot
1614 else
1615         umount_all
1616 fi
1617
1618 initrd_gen_fbsplash
1619 initrd_gen_fbcondecor
1620
1621 debug "Current /linuxrc:\n$(sed -e 's,^,| ,' $DESTDIR/linuxrc)"
1622
1623 IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed"
1624
1625 IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
1626 verbose "image size: $IMAGESIZE KiB ($DESTDIR)"
1627
1628 verbose "Creating $INITRDFS image $IMAGE"
1629 case "$INITRDFS" in
1630   ext2)
1631         dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null
1632         # NOTE: ext2 label is max 16 chars
1633         mke2fs -q -F -b 1024 -m 0 -L "PLD/$kernel" "$IMAGE" 2>/dev/null 1>&2
1634         tune2fs -i 0 "$IMAGE" >/dev/null 2>&1
1635
1636         local tmpmnt=$(mktemp -d -t initrd.mnt-XXXXXX)
1637         debug "Mounting ext2 image $IMAGE to $tmpmnt"
1638         mount -o loop -t ext2 "$IMAGE" "$tmpmnt" || die "mount failed, check dmesg(1)"
1639         # We don't need this directory, so let's save space
1640         rm -rf "$tmpmnt"/lost+found
1641
1642         debug "Copy recursively $DESTDIR -> $tmpmnt"
1643         cp -a $DESTDIR/* $tmpmnt
1644         umount "$IMAGE"
1645         rmdir "$tmpmnt"
1646
1647         ;;
1648   rom|romfs)
1649         genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD Linux/$kernel (geninitrd/$VERSION)"
1650         ;;
1651   cram|cramfs)
1652         mkcramfs "$DESTDIR" "$IMAGE"
1653         ;;
1654   initramfs)
1655         (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
1656         ;;
1657   *)
1658         die "Filesystem $INITRDFS not supported by $PROGRAM"
1659 esac
1660
1661 CONFIG_BLK_DEV_RAM_SIZE=$(ikconfig | awk -F= '/^CONFIG_BLK_DEV_RAM_SIZE/{print $2}')
1662 if [ -z "$CONFIG_BLK_DEV_RAM_SIZE" ]; then
1663         CONFIG_BLK_DEV_RAM_SIZE=4096
1664         warn "No CONFIG_BLK_DEV_RAM_SIZE detected, fallback to $CONFIG_BLK_DEV_RAM_SIZE"
1665 fi
1666
1667 if [ "$IMAGESIZE" -gt $CONFIG_BLK_DEV_RAM_SIZE ]; then
1668         warn "Your image size is larger than $CONFIG_BLK_DEV_RAM_SIZE, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!"
1669 fi
1670
1671 if ! is_no "$COMPRESS"; then
1672         compressor=$(find_compressor "$COMPRESS")
1673         verbose "Compressing $target with $compressor"
1674
1675         # TODO: the image name (specified from kernel.spec) already contains
1676         # extension, which is .gz most of the time.
1677         compress_image "$compressor" "$IMAGE" "$target" || {
1678                 if [ $compressor != gzip ]; then
1679                         warn "Could not compress with $compressor, retrying with gzip"
1680                         compress_image gzip "$IMAGE" "$target" || die "compress failed with gzip" $?
1681                 else
1682                         die "Could not compress image with $compressor"
1683                 fi
1684         }
1685 else
1686         cp -a "$IMAGE" "$target"
1687 fi
1688
1689 # XXX. check if bootsplash can output data to tmp dir not directly to initramfs image.
1690 initrd_gen_bootsplash "$target"
1691
1692 rm -rf "$DESTDIR" "$IMAGE"
1693
1694 # vim:ts=4:sw=4:noet:fdm=marker
This page took 0.232192 seconds and 4 git commands to generate.