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/rd/* ]]; then
645 if [[ "$devpath" == /dev/ida/* ]]; then
646 find_module "cpqarray"
647 rootdev_add=/dev/ida/
651 if [[ "$devpath" == /dev/cciss/* ]]; then
652 rootdev_add=/dev/cciss/
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"
665 if [[ "$devpath" == /dev/ataraid/* ]]; then
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."
673 for n in $ataraidmodules; do
676 rootdev_add=/dev/ataraid/
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"
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"
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}')"
697 BASICMODULES="$BASICMODULES -loop"
698 find_module "-$loopFs"
699 BASICMODULES="$BASICMODULES -${loopFs}"
703 if is_lvm "$devpath"; then
704 find_modules_lvm "$devpath"
709 firmware_install_module() {
711 local firmware_files="$2"
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
717 cat << 'EOF' >> "$DESTDIR/lib/firmware/firmware.sh"
719 echo 1 > /sys$DEVPATH/loading
720 cat "/lib/firmware/$FIRMWARE" > /sys$DEVPATH/data
721 echo 0 > /sys$DEVPATH/loading
724 chmod 755 "$DESTDIR/lib/firmware/firmware.sh"
726 # setup firmware loader agent
727 echo "echo -n "/lib/firmware/firmware.sh" > /proc/sys/kernel/hotplug" | add_linuxrc
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
740 warn "Possible missing firmware file /lib/firmware/$firmware or /lib/firmware/$kernel/$firmware for module $module."
751 for mod in $modules; do
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}"
762 modules_add_linuxrc() {
766 # module path without optional compression
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)
776 if [ "$module" = "scsi_mod" -a "$kernel_version_long" -ge "002006030" ]; then
777 options="scan=sync $options"
780 if [ x"$verbose" = x"-v" ]; then
782 if [ "$options" ]; then
783 s="$s with options [$options]"
785 if [ "$usleep" ]; then
786 s="$s and $usleep usleep"
788 verbose "Loading module [$module]$s"
791 if [ -n "$firmware" ]; then
792 firmware_install_module "$module" "$firmware"
794 for file in $(find_firmware "$module"); do
795 firmware_install_module "$module" "$file"
799 echo "insmod /lib/modules/$kernel/$modpath $options" | add_linuxrc
800 if [ -n "$usleep" ]; then
801 echo "usleep $usleep" | add_linuxrc
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
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
823 : 'Making device nodes'
824 cat /proc/partitions | (
825 # ignore first two lines: header, empty line
828 while read major minor blocks dev rest; do
831 [ -e $node ] || mknod -m 660 $node b $major $minor
838 initrd_gen_setrootdev() {
839 verbose "Adding rootfs finding based on kernel cmdline root= option support."
841 debug "Current /proc/partitions:\n$(sed -e 's,^,| ,' /proc/partitions)"
843 if [ "${ROOT##/dev/}" != "${ROOT}" ]; then
844 rootnr="$(busybox awk -v rootnode="${ROOT##/dev/}" '$4 == rootnode { print 256 * $1 + $2 }' /proc/partitions)"
846 if [ -z "$rootnr" -a -e "$ROOT" ]; then
847 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $3 + $4; }}')"
849 if [ -n "$rootnr" ]; then
850 echo "$rootnr" > /proc/sys/kernel/real-root-dev
856 initrd_gen_initramfs_switchroot() {
858 if [ "$rootdev" = "/dev/nfs" ]; then
859 echo "rootfs on NFS root=/dev/nfs"
861 [ ! -e "$DESTDIR/$rootdev" ] && inst $rootdev $rootdev
864 # parse 'root=xxx' kernel commandline
865 # We support passing root as hda3 /dev/hda3 0303 0x0303 and 303
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,
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.
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";
884 n = split(tolower(str), digit, "");
886 for (i = 1; i <= n; i++) {
887 num = index(hstr, digit[i]) - 1;
888 res = res + (num * 16 ^ (n - i));
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])+";
901 # see if we have /dev/hdX or hdX, we can just take partition name
902 if (root ~ "^\/dev\/" dev_pattern "$" || root ~ "^" dev_pattern "$") {
904 sub("^/dev/", "", partition);
908 if (root ~ "^" num_pattern_short "$") {
909 # change "303" => "0x0303"
911 } else if (root ~ "^" num_pattern "$") {
912 # change "0303" => "0x0303"
916 maj = h2d(substr(root, 3, 2));
917 min = h2d(substr(root, 5, 2));
921 partition && $4 == partition { maj = $1; min = $2; }
922 $1 == maj && $2 == min { partition = $4; }
925 if (maj >= 0 && min >= 0) {
926 printf("maj=%s; min=%s;\n", maj, min);
929 printf("device=/dev/%s;\n", partition);
934 if [ -z "$device" ]; then
935 if [ "$DEBUGINITRD" ]; then
941 if [ "$device" -a ! -b $device -a "$maj$min" ]; then
942 mknod -m 660 $device b $maj $min
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))
951 while read pmajor pminor blocks dev rest; do
952 # skip header and empty line
953 [ -z "$pmajor" -o "$pmajor" = "major" ] && continue
955 if [ $pmajor = $major -a $pminor = $minor ]; then
957 echo "DEVICE set to $device based on real-root-dev"
959 done < /proc/partitions
962 [ -n "$ROOTFSFLAGS" ] && ROOTFSFLAGS="-o $ROOTFSFLAGS"
964 mount -t $ROOTFS -r $device $ROOTFSFLAGS /newroot || echo "Mount of rootfs failed."
966 if [ -z "$init" -o ! -x "/newroot$init" ]; then
974 if [ "$DEBUGINITRD" ]; then
975 echo "Last 20 lines of dmesg:"
981 kmsg "geninitrd/$VERSION switching root"
984 busybox_applet switch_root usleep
986 [ ! -e /newroot/dev/console ] && mknod -m 660 /newroot/dev/console c 5 1
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"
995 [ "$DEBUGINITRD" ] || usleep 10000000
998 exec switch_root /newroot $init ${1:+"$@"}
1000 # FIXME: this code is never executed, as "exec" does not return!
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."
1006 exec chroot /newroot $init ${1:+"$@"}
1008 echo "Failed to chroot!"
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
1017 # find if $symbol exists in System.map $mapfile
1021 if [ ! -f $mapfile ]; then
1022 # missing mapfile (not a pld kernel?)
1026 awk -vc=1 -vsymbol="$symbol" '$2 == "T" && $3 == symbol {c = 0} END {exit c}' $mapfile
1029 # find best compressor (or forced one) for initrd
1032 # fastest initrd decompression speed is first
1033 local compressors='lzo gzip xz lzma bzip2'
1035 # a specified one, take it
1036 if ! is_yes "$mode"; then
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
1066 # any existing sym will work
1071 die "Unknown compressor $c"
1074 if sym_exists $map $sym && [ -x $prog ]; then
1080 verbose "using gzip for compressor (fallback)"
1084 # compresses kernel image image
1085 # in function so we could retry with other compressor on failure
1087 local compressor="$1" IMAGE="$2" target="$3" tmp
1088 tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1090 case "$compressor" in
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 $?
1096 xz --format=lzma -9 < "$IMAGE" > "$tmp" || return $?
1099 bzip2 -9 < "$IMAGE" > "$tmp" || return $?
1102 gzip -9 < "$IMAGE" > "$tmp" || return $?
1105 lzop -9 < "$IMAGE" > "$tmp" || return $?
1108 cat < "$IMAGE" > "$tmp" || return $?
1112 mv -f "$tmp" "$target"
1115 if [ -r /etc/sysconfig/geninitrd ]; then
1116 . /etc/sysconfig/geninitrd
1119 if [ ! -f /proc/mounts ]; then
1120 warn "/proc filesystem not mounted, may cause wrong results or failure."
1123 geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev tuxonice suspend fbsplash condecor bootsplash uvesafb nfs sata scsi usbkbd bcache
1125 while [ $# -gt 0 ]; do
1135 modulefile=${1#--modules-conf=}
1144 --without-bootsplash)
1156 --without-fbcondecor)
1165 --with-suspend2 | --with-tuxonice)
1168 --without-suspend2 | --without-tuxonice)
1172 LVMTOOLSVERSION=${1#--lvmversion=}
1174 --lvmtoolsversion=*)
1175 LVMTOOLSVERSION=${1#--lvmtoolsversion=}
1177 --lvmtoolsversion|--lvmversion)
1190 --without-multipath)
1194 USE_MULTIPATH=${1#--with-multipath=}
1203 BASICMODULES="$BASICMODULES ${1#--with=}"
1206 BASICMODULES="$BASICMODULES $2"
1210 echo "$PROGRAM: version $VERSION"
1214 if [ x"$verbose" = x"-v" ]; then
1225 COMPRESS="${1#--compress=}"
1234 STRIP="${1#--strip=}"
1247 PREMODS="$PREMODS ${1#--preload=}"
1250 PREMODS="$PREMODS $2"
1254 die "--fs option is obsoleted. Use --initrdfs instead"
1257 INITRDFS=${1#--initrdfs=}
1270 if [ -z "$target" ]; then
1272 elif [ -z "$kernel" ]; then
1284 if [ -z "$target" -o -z "$kernel" ]; then
1290 if [ "$(id -u)" != 0 ]; then
1291 die "You need to be root to generate initrd"
1294 if [ -d /lib64 -a -d /usr/lib64 ]; then
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)}')
1304 verbose "# geninitrd $VERSION"
1305 debug "Using _lib: $_lib"
1306 debug "Using initrd_dir: $initrd_dir"
1308 busybox=$(find_tool $initrd_dir/busybox $initrd_dir/initrd-busybox /bin/initrd-busybox) || die "Couldn't find busybox suitable for initrd"
1310 # we setup mods after parsing command line args
1311 geninitrd_setup_mods
1313 if [ ! -f /boot/vmlinuz-"$kernel" ]; then
1314 warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?"
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"
1324 if [ "$kernel_version" -ge "002005" ]; then
1325 INITRDFS="initramfs"
1333 [ -x /sbin/mke2fs ] || die "/sbin/mke2fs is missing"
1336 [ -x /sbin/genromfs ] || die "/sbin/genromfs is missing"
1339 [ -x /sbin/mkcramfs ] || die "/sbin/mkcramfs is missing"
1342 [ -x /bin/cpio ] || die "/bin/cpio is missing"
1343 [ -x /usr/bin/find ] || die "/usr/bin/find is missing"
1346 die "Filesystem $INITRDFS on initrd is not supported"
1350 if [ -L "$target" ]; then
1351 target=$(readlink -f "$target")
1354 if [ -n "$img_vers" ]; then
1355 target="$target-$kernel"
1358 if [ -z "$force" -a -f "$target" ]; then
1359 die "$target already exists."
1362 if [ ! -d "/lib/modules/$kernel" ]; then
1363 die "/lib/modules/$kernel is not a directory."
1366 if [ "$kernel_version" -ge "002005" ]; then
1372 for n in $PREMODS; do
1376 if [ "$FBMODULE" ]; then
1377 find_module "$FBMODULE"
1380 # autodetect USB keyboards
1383 # allow forcing loading SCSI and/or IDE modules
1384 # XXX: where ADDSCSI cames from? drop?
1385 if is_yes "$ADDSCSI"; then
1389 # autodetect SATA modules
1392 # XXX: where ADDIDE cames from? drop?
1393 if is_yes "$ADDIDE"; then
1397 if is_yes "$USE_SUSPEND"; then
1398 find_modules_suspend
1401 find_root "$fstab" || exit
1402 verbose "Using $rootdev as device for rootfs"
1404 find_modules_for_devpath "$rootdev"
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
1412 find_module "-$rootFs"
1414 for n in $BASICMODULES; do
1418 if is_yes "$USE_TUXONICE"; then
1423 find_modules_uvesafb
1424 find_modules_fbsplash
1426 if [ -n "$ifneeded" -a -z "$MODULES" ]; then
1427 verbose "No modules are needed -- not building initrd image."
1431 verbose "Building initrd..."
1432 DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
1433 RCFILE="$DESTDIR/linuxrc"
1435 chmod a+rx "$RCFILE"
1436 ln -s linuxrc $DESTDIR/init
1438 # create dirs that we really need
1439 inst_d /{lib,bin,etc,dev{,/pts,/shm},loopfs,var,proc,run,sys}
1441 modules_install "$MODULES"
1443 # mknod'ing the devices instead of copying them works both with and
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
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
1459 # initrd generated by geninitrd/$VERSION
1460 # on $(LC_ALL=C date)
1465 kmsg "geninitrd/$VERSION starting"
1468 # builtin defaults from geninitrd
1472 add_linuxrc <<-'EOF'
1473 read CMDLINE < /proc/cmdline
1475 for arg in $CMDLINE; do
1476 if [ "${arg}" = "debuginitrd" ] || [ "${arg}" = "debugrd" ]; then
1479 if [ "${arg##debuginitrd=}" != "${arg}" ] || [ "${arg##debugrd=}" != "${arg}" ]; then
1480 DEBUGINITRD=${arg##debug*rd=}
1482 if [ "${arg##root=}" != "${arg}" ]; then
1485 if [ "${arg##rootfsflags=}" != "${arg}" ]; then
1486 ROOTFSFLAGS=${arg##rootfsflags=}
1488 if [ "${arg##init=}" != "${arg}" ]; then
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
1499 # make debugshell() invoke subshell if $DEBUGINITRD=sh
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"
1507 add_linuxrc <<-'EOF'
1511 add_linuxrc <<-'EOF'
1519 if [ "$DEBUGINITRD" ]; then
1524 modules_add_linuxrc $MODULES
1526 # TODO: rewrite for busybox
1527 #if [ -n "$loopDev" ]; then
1528 # if [ ! -d /initrd ]; then
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"
1540 if is_yes "$USE_UDEV"; then
1549 initrd_gen_multipath
1552 if is_yes "$have_nfs"; then
1560 initrd_gen_setrootdev
1563 # additional devs always needed
1564 [ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev
1566 initrd_gen_stop_udevd
1567 initrd_gen_stop_mdev
1568 initrd_gen_stop_uvesafb
1570 # resume after killing local processes
1575 add_linuxrc <<-'EOF'
1576 if [ ! "$DEBUGINITRD" ]; then
1580 for i in $(export -p); do
1581 i=${i#declare -x } # ksh/bash
1582 i=${i#export } # busybox
1593 [ -z "$i" ] && continue
1596 ROOT|PATH|HOME|TERM)
1608 if [ "$INITRDFS" = "initramfs" ]; then
1609 initrd_gen_initramfs_switchroot
1615 initrd_gen_fbcondecor
1617 debug "Current /linuxrc:\n$(sed -e 's,^,| ,' $DESTDIR/linuxrc)"
1619 IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed"
1621 IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
1622 verbose "image size: $IMAGESIZE KiB ($DESTDIR)"
1624 verbose "Creating $INITRDFS image $IMAGE"
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
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
1638 debug "Copy recursively $DESTDIR -> $tmpmnt"
1639 cp -a $DESTDIR/* $tmpmnt
1645 genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD Linux/$kernel (geninitrd/$VERSION)"
1648 mkcramfs "$DESTDIR" "$IMAGE"
1651 (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
1654 die "Filesystem $INITRDFS not supported by $PROGRAM"
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"
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!"
1667 if ! is_no "$COMPRESS"; then
1668 compressor=$(find_compressor "$COMPRESS")
1669 verbose "Compressing $target with $compressor"
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" $?
1678 die "Could not compress image with $compressor"
1682 cp -a "$IMAGE" "$target"
1685 # XXX. check if bootsplash can output data to tmp dir not directly to initramfs image.
1686 initrd_gen_bootsplash "$target"
1688 rm -rf "$DESTDIR" "$IMAGE"
1690 # vim:ts=4:sw=4:noet:fdm=marker