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