7 # based on mkinitrd from RedHat Linux
13 . /etc/rc.d/init.d/functions
14 . /lib/geninitrd/functions
15 . /etc/sysconfig/system
17 # list of geninitrd modules which need setup routine after commandline args parsing
30 # device node for rootfs from fstab
40 # is /tmp mounted on tmpfs
43 # are /dev nodes already created from /proc/devices info?
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>"
65 local kdir kver dir=${target:-/boot}
66 for kdir in /lib/modules/*; do
67 [ -d $kdir ] || continue
69 echo " $0 -f --initrdfs=initramfs $dir/initrd-$kver.gz $kver $verbose"
82 [ -n "$verbose" ] && msg "$*" >&3
86 [ x"$verbose" = x"-v -v" ] && msg "$*" >&3
89 # add initrd code to print to kmsg
90 # @param string message
91 # @param int loglevel. defaults to "6" (info)
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)
104 local msg="$1" level=${2:-6}
105 echo "echo '<$level>$msg' > /dev/kmsg" | add_linuxrc
108 # aborts program abnormally
115 # find program from specified paths
118 local paths="$initrd_dir /bin /sbin /usr/bin /usr/sbin"
120 debug "find_tool: checking $x"
123 verbose "find_tool: found $x"
129 debug "find_tool: checking $p/$b"
130 if [ -x "$p/$b" ]; then
132 verbose "find_tool: found $p/$b"
138 debug "find_tool: did not find any of: $n"
142 # loads geninitrd modules
143 geninitrd_load_mods() {
146 if [ ! -f /lib/geninitrd/mod-$mod.sh ]; then
147 die "$mod geninitrd module can't be loaded"
149 . /lib/geninitrd/mod-$mod.sh
151 GENINITRD_MODS="$GENINITRD_MODS $mod"
155 # setup geninitrd modules
156 geninitrd_setup_mods() {
159 for mod in $GENINITRD_MODS; do
162 # some mods want init
163 if type setup_mod_$mod > /dev/null; then
169 # append text to /linuxrc
170 # takes STDIN as input
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
179 # we already generated tmpfs code; return
180 if is_yes "$dev_mounted"; then
186 busybox_applet mount mknod mkdir
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
205 # generate code to mount /proc on initrd
206 # can be called multiple times
208 if is_yes "$proc_mounted"; then
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
218 echo "mount -t proc none /proc" | add_linuxrc
222 # generate code to mount /sys on initrd
223 # can be called multiple times
225 if is_yes "$sys_mounted"; then
230 echo "mount -t sysfs none /sys" | add_linuxrc
233 # generate code to mount /tmp on initrd
234 # can be called multiple times
236 if [ "$INITRDFS" = "initramfs" ]; then
237 # initramfs is read-write filesystem, no need for tmpfs
241 if is_yes "$tmp_mounted"; then
246 echo "mount -t tmpfs none /tmp" | add_linuxrc
249 # generate code to mount /run on initrd
250 # can be called multiple times
252 if is_yes "$run_mounted"; then
257 echo "mount -t tmpfs run /run" | add_linuxrc
260 # unmount all mountpoints mounted by geninitrd
261 # try to move pseudo filesystems to newroot if possible
265 : Last shell before umounting all and giving control over to real init.
269 if is_yes "$run_mounted"; then
271 mount --bind /run /newroot/run
276 if is_yes "$dev_mounted"; then
278 mount --bind /dev /newroot/dev
283 if is_yes "$sys_mounted"; then
285 mount --bind /sys /newroot/sys
290 if is_yes "$proc_mounted"; then
292 mount --bind /proc /newroot/proc
297 if is_yes "$tmp_mounted"; then
298 echo 'umount /tmp' | add_linuxrc
303 # Checks if busybox has support for APPLET(s)
304 # Exits from geninitrd if the support is not present.
306 # NB! XXX do not output to STDOUT, it will appear in initrd images in some cases!
310 if [ -z "$busybox_functions" ]; then
311 local tmp=$($busybox 2>&1)
313 # BusyBox v1.1.3 says applet not found if it's not called 'busybox'.
314 if [[ "$tmp" = *applet\ not\ found* ]]; then
316 ln -s $busybox $t/busybox
317 local tmp=$($t/busybox 2>&1)
321 busybox_functions=$(echo "$tmp" | \
322 sed -ne '/Currently defined functions:/,$p' | \
323 xargs | sed -e 's,.*Currently defined functions: ,,'
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"
336 eval busybox_have_$applet=$have
339 if [ $err = 1 ]; then
344 # Extract the .config file from a kernel image
345 # uses extract-ikconfig from kernel sources (scripts/extract-ikconfig)
347 local kofile=$(modinfo -k $kernel -n configs 2> /dev/null)
348 if [ -n "$kofile" ]; then
349 /lib/geninitrd/extract-ikconfig $kofile
353 # see if config available as separate file
354 if [ -f /boot/config-$kernel ]; then
355 cat /boot/config-$kernel
359 # finally try vmlinuz itself
360 /lib/geninitrd/extract-ikconfig /boot/vmlinuz-$kernel
368 module=${module%$modext*}
372 # Finds module dependencies
376 # Outputs full path to module and it's dependencies
381 # if module is prefixed with dash, we should ignore errors if the module
383 if [ ${module#-} != $module ]; then
388 # This works when user has module-init-tools installed even on 2.4 kernels
390 modprobe=$(modprobe --set-version $kernel --show-depends $module --ignore-install 2>&1)
393 if [ $skiperrors = 1 ]; then
398 if ! is_no "$EXIT_IF_MISSING"; then
399 die "$module: module not found for $kernel kernel"
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."
409 while read insmod modpath options; do
410 if [ "$insmod" = "insmod" ]; then
412 # XXX: find a away to autodetect
413 smodule=$(basename_module $modpath)
416 find_depmod "-crct10dif-pclmul"
417 find_depmod "-crct10dif"
420 find_depmod "-crc32c-intel"
421 find_depmod "-crc32c"
423 virtio_blk|virtio_scsi)
424 find_depmod "-virtio_pci"
425 find_depmod "-virtio_mmio"
438 # no firmware support in 2.4 kernels
439 if [ "$kernel_version_long" -lt "002005048" ]; then
442 echo -n $(NEW_MODINFO=1 modinfo -k $kernel -F firmware $module 2>/dev/null | xargs)
447 local mod depmod module=$1
449 depmod=$(find_depmod $module) || exit 1
450 for mod in $depmod; do
451 mod=${mod#/lib/modules/$kernel/}
453 # add each module only once
455 for m in $MODULES; do
456 [ $m = $mod ] && have=1
458 if [ $have = 0 ]; then
459 MODULES="$MODULES $mod"
464 # install a file to temporary mount image.
465 # it will operate recursively (copying directories)
466 # and will symlink destinations if source is symlink.
468 if [ $# -lt 2 ]; then
469 die 'Usage: inst <file> [<file>] <destination>'
472 local src i=0 c=$(($# - 1))
473 while [ $i -lt $c ]; do
480 local parentDir=$(dirname $DESTDIR$dest)
481 if [ ! -d "$parentDir" ]; then
482 verbose "+ mkdir -p $parentDir"
485 verbose "+ cp $* $DESTDIR$dest"
486 cp -HR "$@" "$DESTDIR$dest"
491 die 'Usage: inst_d <destination> <destination>'
494 install -d "$DESTDIR$dir"
498 # install executable and it's shared libraries
500 if [ $# -lt 2 ]; then
501 die "Invalid params ($@), Usage: inst_exec <file>[, <file>] <destination>"
503 local src i=0 c=$(($# - 1))
504 while [ $i -lt $c ]; do
517 /lib/ld-linux.so.2 | /lib64/ld-linux-x86-64.so.2)
521 libs=$(ldd "$obj" | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
523 if [ ! -f "$DESTDIR/$_lib/${lib##*/}" ]; then
525 inst_exec $lib /$_lib
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")
539 verbose "+ ln -s /$_lib $DESTDIR$libdir"
540 ln -s /$_lib $DESTDIR$libdir
545 # output modules.conf / modprobe.conf
547 echo "$modprobe_conf_cache"
550 # return options for MODULE
551 # @param $1 module name
554 local options=$(modprobe_conf | awk -vmodule="$module" '{ if ($1 == "options" && $2 == module) { for(i=3;i<=NF;i++) printf("%s ",$i); }}')
559 # defaults to modprobe -c if not told otherwise, this means include statements
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
569 if [ -n "$modulefile" ]; then
570 debug "Using $modulefile for modules config"
571 modprobe_conf_cache=$(cat $modulefile | awk '!/^[\t ]*#/ { print }')
574 debug "Using modprobe -c to get modules config"
575 modprobe_conf_cache=$(modprobe -c --set-version $kernel | awk '!/^[\t ]*#/ { print }')
579 # find modules for $devpath
580 find_modules_for_devpath() {
582 if [ -z "$devpath" ]; then
583 die "No argument passed to find_modules_for_devpath() - is your /etc/fstab correct?"
586 if [[ "$devpath" = /dev/dm-* ]]; then
587 # /dev/dm-3 -> /dev/mapper/sil_ahbgadcbchfc3
588 devpath=$(dm_node "$devpath")
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")
597 verbose "Finding modules for device path $devpath"
599 if is_luks "$devpath"; then
600 find_modules_luks "$devpath"
604 if is_nfs "$devpath"; then
605 find_modules_nfs "$devpath"
609 if is_md "$devpath"; then
610 find_modules_md "$devpath"
614 if is_multipath "$devpath"; then
615 if find_modules_multipath "$devpath"; then
622 if is_dmraid "$devpath"; then
623 if find_modules_dmraid "$devpath"; then
629 if is_scsi "$devpath"; then
630 find_modules_scsi "$devpath"
634 if is_ide "$devpath"; then
635 find_modules_ide "$devpath"
639 if [[ "$devpath" == /dev/bcache* ]]; then
640 find_modules_bcache "$devpath"
644 if [[ "$devpath" == /dev/rd/* ]]; then
650 if [[ "$devpath" == /dev/ida/* ]]; then
651 find_module "cpqarray"
652 rootdev_add=/dev/ida/
656 if [[ "$devpath" == /dev/cciss/* ]]; then
657 rootdev_add=/dev/cciss/
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"
670 if [[ "$devpath" == /dev/ataraid/* ]]; then
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."
678 for n in $ataraidmodules; do
681 rootdev_add=/dev/ataraid/
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"
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"
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}')"
702 BASICMODULES="$BASICMODULES -loop"
703 find_module "-$loopFs"
704 BASICMODULES="$BASICMODULES -${loopFs}"
708 if is_lvm "$devpath"; then
709 find_modules_lvm "$devpath"
714 firmware_install_module() {
716 local firmware_files="$2"
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
722 cat << 'EOF' >> "$DESTDIR/lib/firmware/firmware.sh"
724 echo 1 > /sys$DEVPATH/loading
725 cat "/lib/firmware/$FIRMWARE" > /sys$DEVPATH/data
726 echo 0 > /sys$DEVPATH/loading
729 chmod 755 "$DESTDIR/lib/firmware/firmware.sh"
731 # setup firmware loader agent
732 echo "echo -n "/lib/firmware/firmware.sh" > /proc/sys/kernel/hotplug" | add_linuxrc
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
745 warn "Possible missing firmware file /lib/firmware/$firmware or /lib/firmware/$kernel/$firmware for module $module."
756 for mod in $modules; do
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}"
767 modules_add_linuxrc() {
771 # module path without optional compression
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)
781 if [ "$module" = "scsi_mod" -a "$kernel_version_long" -ge "002006030" ]; then
782 options="scan=sync $options"
785 if [ x"$verbose" = x"-v" ]; then
787 if [ "$options" ]; then
788 s="$s with options [$options]"
790 if [ "$usleep" ]; then
791 s="$s and $usleep usleep"
793 verbose "Loading module [$module]$s"
796 if [ -n "$firmware" ]; then
797 firmware_install_module "$module" "$firmware"
799 for file in $(find_firmware "$module"); do
800 firmware_install_module "$module" "$file"
804 echo "insmod /lib/modules/$kernel/$modpath $options" | add_linuxrc
805 if [ -n "$usleep" ]; then
806 echo "usleep $usleep" | add_linuxrc
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
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
828 : 'Making device nodes'
829 cat /proc/partitions | (
830 # ignore first two lines: header, empty line
833 while read major minor blocks dev rest; do
836 [ -e $node ] || mknod -m 660 $node b $major $minor
843 initrd_gen_setrootdev() {
844 verbose "Adding rootfs finding based on kernel cmdline root= option support."
846 debug "Current /proc/partitions:\n$(sed -e 's,^,| ,' /proc/partitions)"
848 if [ "${ROOT##/dev/}" != "${ROOT}" ]; then
849 rootnr="$(busybox awk -v rootnode="${ROOT##/dev/}" '$4 == rootnode { print 256 * $1 + $2 }' /proc/partitions)"
851 if [ -z "$rootnr" -a -e "$ROOT" ]; then
852 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $3 + $4; }}')"
854 if [ -n "$rootnr" ]; then
855 echo "$rootnr" > /proc/sys/kernel/real-root-dev
861 initrd_gen_initramfs_switchroot() {
863 if [ "$rootdev" = "/dev/nfs" ]; then
864 echo "rootfs on NFS root=/dev/nfs"
866 [ ! -e "$DESTDIR/$rootdev" ] && inst $rootdev $rootdev
869 # parse 'root=xxx' kernel commandline
870 # We support passing root as hda3 /dev/hda3 0303 0x0303 and 303
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,
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.
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";
889 n = split(tolower(str), digit, "");
891 for (i = 1; i <= n; i++) {
892 num = index(hstr, digit[i]) - 1;
893 res = res + (num * 16 ^ (n - i));
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])+";
906 # see if we have /dev/hdX or hdX, we can just take partition name
907 if (root ~ "^\/dev\/" dev_pattern "$" || root ~ "^" dev_pattern "$") {
909 sub("^/dev/", "", partition);
913 if (root ~ "^" num_pattern_short "$") {
914 # change "303" => "0x0303"
916 } else if (root ~ "^" num_pattern "$") {
917 # change "0303" => "0x0303"
921 maj = h2d(substr(root, 3, 2));
922 min = h2d(substr(root, 5, 2));
926 partition && $4 == partition { maj = $1; min = $2; }
927 $1 == maj && $2 == min { partition = $4; }
930 if (maj >= 0 && min >= 0) {
931 printf("maj=%s; min=%s;\n", maj, min);
934 printf("device=/dev/%s;\n", partition);
939 if [ -z "$device" ]; then
940 if [ "$DEBUGINITRD" ]; then
946 if [ "$device" -a ! -b $device -a "$maj$min" ]; then
947 mknod -m 660 $device b $maj $min
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))
956 while read pmajor pminor blocks dev rest; do
957 # skip header and empty line
958 [ -z "$pmajor" -o "$pmajor" = "major" ] && continue
960 if [ $pmajor = $major -a $pminor = $minor ]; then
962 echo "DEVICE set to $device based on real-root-dev"
964 done < /proc/partitions
967 [ -n "$ROOTFSFLAGS" ] && ROOTFSFLAGS="-o $ROOTFSFLAGS"
969 mount -t $ROOTFS -r $device $ROOTFSFLAGS /newroot || echo "Mount of rootfs failed."
971 if [ -z "$init" -o ! -x "/newroot$init" ]; then
979 if [ "$DEBUGINITRD" ]; then
980 echo "Last 20 lines of dmesg:"
986 kmsg "geninitrd/$VERSION switching root"
989 busybox_applet switch_root usleep
991 [ ! -e /newroot/dev/console ] && mknod -m 660 /newroot/dev/console c 5 1
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"
1000 [ "$DEBUGINITRD" ] || usleep 10000000
1003 exec switch_root /newroot $init ${1:+"$@"}
1005 # FIXME: this code is never executed, as "exec" does not return!
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."
1011 exec chroot /newroot $init ${1:+"$@"}
1013 echo "Failed to chroot!"
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
1022 # find if $symbol exists in System.map $mapfile
1026 if [ ! -f $mapfile ]; then
1027 # missing mapfile (not a pld kernel?)
1031 awk -vc=1 -vsymbol="$symbol" '$2 == "T" && $3 == symbol {c = 0} END {exit c}' $mapfile
1034 # find best compressor (or forced one) for initrd
1037 # fastest initrd decompression speed is first
1038 local compressors='lzo gzip xz lzma bzip2'
1040 # a specified one, take it
1041 if ! is_yes "$mode"; then
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
1071 # any existing sym will work
1076 die "Unknown compressor $c"
1079 if sym_exists $map $sym && [ -x $prog ]; then
1085 verbose "using gzip for compressor (fallback)"
1089 # compresses kernel image image
1090 # in function so we could retry with other compressor on failure
1092 local compressor="$1" IMAGE="$2" target="$3" tmp
1093 tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1095 case "$compressor" in
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 $?
1101 xz --format=lzma -9 < "$IMAGE" > "$tmp" || return $?
1104 bzip2 -9 < "$IMAGE" > "$tmp" || return $?
1107 gzip -9 < "$IMAGE" > "$tmp" || return $?
1110 lzop -9 < "$IMAGE" > "$tmp" || return $?
1113 cat < "$IMAGE" > "$tmp" || return $?
1117 mv -f "$tmp" "$target"
1120 if [ -r /etc/sysconfig/geninitrd ]; then
1121 . /etc/sysconfig/geninitrd
1124 if [ ! -f /proc/mounts ]; then
1125 warn "/proc filesystem not mounted, may cause wrong results or failure."
1128 geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev tuxonice suspend fbsplash condecor bootsplash uvesafb nfs sata scsi usbkbd bcache
1130 while [ $# -gt 0 ]; do
1140 modulefile=${1#--modules-conf=}
1149 --without-bootsplash)
1161 --without-fbcondecor)
1170 --with-suspend2 | --with-tuxonice)
1173 --without-suspend2 | --without-tuxonice)
1177 LVMTOOLSVERSION=${1#--lvmversion=}
1179 --lvmtoolsversion=*)
1180 LVMTOOLSVERSION=${1#--lvmtoolsversion=}
1182 --lvmtoolsversion|--lvmversion)
1195 --without-multipath)
1199 USE_MULTIPATH=${1#--with-multipath=}
1208 BASICMODULES="$BASICMODULES ${1#--with=}"
1211 BASICMODULES="$BASICMODULES $2"
1215 echo "$PROGRAM: version $VERSION"
1219 if [ x"$verbose" = x"-v" ]; then
1230 COMPRESS="${1#--compress=}"
1239 STRIP="${1#--strip=}"
1252 PREMODS="$PREMODS ${1#--preload=}"
1255 PREMODS="$PREMODS $2"
1259 die "--fs option is obsoleted. Use --initrdfs instead"
1262 INITRDFS=${1#--initrdfs=}
1275 if [ -z "$target" ]; then
1277 elif [ -z "$kernel" ]; then
1289 if [ -z "$target" -o -z "$kernel" ]; then
1295 if [ "$(id -u)" != 0 ]; then
1296 die "You need to be root to generate initrd"
1299 if [ -d /lib64 -a -d /usr/lib64 ]; then
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)}')
1309 verbose "# geninitrd $VERSION"
1310 debug "Using _lib: $_lib"
1311 debug "Using initrd_dir: $initrd_dir"
1313 busybox=$(find_tool $initrd_dir/busybox $initrd_dir/initrd-busybox /bin/initrd-busybox) || die "Couldn't find busybox suitable for initrd"
1315 # we setup mods after parsing command line args
1316 geninitrd_setup_mods
1318 if [ ! -f /boot/vmlinuz-"$kernel" ]; then
1319 warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?"
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"
1329 if [ "$kernel_version" -ge "002005" ]; then
1330 INITRDFS="initramfs"
1338 [ -x /sbin/mke2fs ] || die "/sbin/mke2fs is missing"
1341 [ -x /sbin/genromfs ] || die "/sbin/genromfs is missing"
1344 [ -x /sbin/mkcramfs ] || die "/sbin/mkcramfs is missing"
1347 [ -x /bin/cpio ] || die "/bin/cpio is missing"
1348 [ -x /usr/bin/find ] || die "/usr/bin/find is missing"
1351 die "Filesystem $INITRDFS on initrd is not supported"
1355 if [ -L "$target" ]; then
1356 target=$(readlink -f "$target")
1359 if [ -n "$img_vers" ]; then
1360 target="$target-$kernel"
1363 if [ -z "$force" -a -f "$target" ]; then
1364 die "$target already exists."
1367 if [ ! -d "/lib/modules/$kernel" ]; then
1368 die "/lib/modules/$kernel is not a directory."
1371 if [ "$kernel_version" -ge "002005" ]; then
1377 for n in $PREMODS; do
1381 if [ "$FBMODULE" ]; then
1382 find_module "$FBMODULE"
1385 # autodetect USB keyboards
1388 # allow forcing loading SCSI and/or IDE modules
1389 # XXX: where ADDSCSI cames from? drop?
1390 if is_yes "$ADDSCSI"; then
1394 # autodetect SATA modules
1397 # XXX: where ADDIDE cames from? drop?
1398 if is_yes "$ADDIDE"; then
1402 if is_yes "$USE_SUSPEND"; then
1403 find_modules_suspend
1406 find_root "$fstab" || exit
1407 verbose "Using $rootdev as device for rootfs"
1409 find_modules_for_devpath "$rootdev"
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
1417 find_module "-$rootFs"
1419 for n in $BASICMODULES; do
1423 if is_yes "$USE_TUXONICE"; then
1427 find_modules_uvesafb
1428 find_modules_fbsplash
1430 if [ -n "$ifneeded" -a -z "$MODULES" ]; then
1431 verbose "No modules are needed -- not building initrd image."
1435 verbose "Building initrd..."
1436 DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
1437 RCFILE="$DESTDIR/linuxrc"
1439 chmod a+rx "$RCFILE"
1440 ln -s linuxrc $DESTDIR/init
1442 # create dirs that we really need
1443 inst_d /{lib,bin,etc,dev{,/pts,/shm},loopfs,var,proc,run,sys}
1445 modules_install "$MODULES"
1447 # mknod'ing the devices instead of copying them works both with and
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
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
1463 # initrd generated by geninitrd/$VERSION
1464 # on $(LC_ALL=C date)
1469 kmsg "geninitrd/$VERSION starting"
1472 # builtin defaults from geninitrd
1476 add_linuxrc <<-'EOF'
1477 read CMDLINE < /proc/cmdline
1479 for arg in $CMDLINE; do
1480 if [ "${arg}" = "debuginitrd" ] || [ "${arg}" = "debugrd" ]; then
1483 if [ "${arg##debuginitrd=}" != "${arg}" ] || [ "${arg##debugrd=}" != "${arg}" ]; then
1484 DEBUGINITRD=${arg##debug*rd=}
1486 if [ "${arg##root=}" != "${arg}" ]; then
1489 if [ "${arg##rootfsflags=}" != "${arg}" ]; then
1490 ROOTFSFLAGS=${arg##rootfsflags=}
1492 if [ "${arg##init=}" != "${arg}" ]; then
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
1503 # make debugshell() invoke subshell if $DEBUGINITRD=sh
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"
1511 add_linuxrc <<-'EOF'
1515 add_linuxrc <<-'EOF'
1523 if [ "$DEBUGINITRD" ]; then
1528 modules_add_linuxrc $MODULES
1530 # TODO: rewrite for busybox
1531 #if [ -n "$loopDev" ]; then
1532 # if [ ! -d /initrd ]; then
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"
1544 if is_yes "$USE_UDEV"; then
1553 initrd_gen_multipath
1556 if is_yes "$have_nfs"; then
1564 initrd_gen_setrootdev
1567 # additional devs always needed
1568 [ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev
1570 initrd_gen_stop_udevd
1571 initrd_gen_stop_mdev
1572 initrd_gen_stop_uvesafb
1574 # resume after killing local processes
1579 add_linuxrc <<-'EOF'
1580 if [ ! "$DEBUGINITRD" ]; then
1584 for i in $(export -p); do
1585 i=${i#declare -x } # ksh/bash
1586 i=${i#export } # busybox
1597 [ -z "$i" ] && continue
1600 ROOT|PATH|HOME|TERM)
1612 if [ "$INITRDFS" = "initramfs" ]; then
1613 initrd_gen_initramfs_switchroot
1619 initrd_gen_fbcondecor
1621 debug "Current /linuxrc:\n$(sed -e 's,^,| ,' $DESTDIR/linuxrc)"
1623 IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed"
1625 IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
1626 verbose "image size: $IMAGESIZE KiB ($DESTDIR)"
1628 verbose "Creating $INITRDFS image $IMAGE"
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
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
1642 debug "Copy recursively $DESTDIR -> $tmpmnt"
1643 cp -a $DESTDIR/* $tmpmnt
1649 genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD Linux/$kernel (geninitrd/$VERSION)"
1652 mkcramfs "$DESTDIR" "$IMAGE"
1655 (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
1658 die "Filesystem $INITRDFS not supported by $PROGRAM"
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"
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!"
1671 if ! is_no "$COMPRESS"; then
1672 compressor=$(find_compressor "$COMPRESS")
1673 verbose "Compressing $target with $compressor"
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" $?
1682 die "Could not compress image with $compressor"
1686 cp -a "$IMAGE" "$target"
1689 # XXX. check if bootsplash can output data to tmp dir not directly to initramfs image.
1690 initrd_gen_bootsplash "$target"
1692 rm -rf "$DESTDIR" "$IMAGE"
1694 # vim:ts=4:sw=4:noet:fdm=marker