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_dirs /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
208 [ ! -r /etc/sysconfig/console ] && return
209 . /etc/sysconfig/console
210 if [ -n "$CONSOLEFONT" ]; then
211 font=$(ls -1 /lib/kbd/consolefonts/${CONSOLEFONT}*.gz 2> /dev/null)
212 if [ -n "$font" ]; then
213 verbose "Loading font $font"
214 busybox_applet loadfont
215 inst_d "/lib/kbd/consolefonts"
216 cp -a "$font" "$DESTDIR/lib/kbd/consolefonts/"
217 gunzip ${DESTDIR}/lib/kbd/consolefonts/${CONSOLEFONT}*.gz
219 echo "loadfont < $font" | add_linuxrc
224 # generate code to mount /proc on initrd
225 # can be called multiple times
227 if is_yes "$proc_mounted"; then
232 if [ "$INITRDFS" = "initramfs" ]; then
233 # /proc is mounted with initramfs 2.6.22.14 kernel
234 # XXX: remove when it is clear why proc was already mounted
235 echo "[ -f /proc/cmdline ] || mount -t proc none /proc" | add_linuxrc
237 echo "mount -t proc none /proc" | add_linuxrc
241 # generate code to mount /sys on initrd
242 # can be called multiple times
244 if is_yes "$sys_mounted"; then
249 echo "mount -t sysfs none /sys" | add_linuxrc
252 # generate code to mount /tmp on initrd
253 # can be called multiple times
255 if [ "$INITRDFS" = "initramfs" ]; then
256 # initramfs is read-write filesystem, no need for tmpfs
260 if is_yes "$tmp_mounted"; then
265 echo "mount -t tmpfs none /tmp" | add_linuxrc
268 # generate code to mount /run on initrd
269 # can be called multiple times
271 if is_yes "$run_mounted"; then
276 echo "mount -t tmpfs run /run" | add_linuxrc
279 # unmount all mountpoints mounted by geninitrd
280 # try to move pseudo filesystems to newroot if possible
284 : Last shell before umounting all and giving control over to real init.
288 if is_yes "$run_mounted"; then
290 mount --bind /run /newroot/run
295 if is_yes "$dev_mounted"; then
297 mount --bind /dev /newroot/dev
302 if is_yes "$sys_mounted"; then
304 mount --bind /sys /newroot/sys
309 if is_yes "$proc_mounted"; then
311 mount --bind /proc /newroot/proc
316 if is_yes "$tmp_mounted"; then
317 echo 'umount /tmp' | add_linuxrc
322 # Checks if busybox has support for APPLET(s)
323 # Exits from geninitrd if the support is not present.
325 # NB! XXX do not output to STDOUT, it will appear in initrd images in some cases!
329 if [ -z "$busybox_functions" ]; then
330 local tmp=$($busybox 2>&1)
332 # BusyBox v1.1.3 says applet not found if it's not called 'busybox'.
333 if [[ "$tmp" = *applet\ not\ found* ]]; then
335 ln -s $busybox $t/busybox
336 local tmp=$($t/busybox 2>&1)
340 busybox_functions=$(echo "$tmp" | \
341 sed -ne '/Currently defined functions:/,$p' | \
342 xargs | sed -e 's,.*Currently defined functions: ,,'
348 eval have='$'busybox_have_$applet
349 if [ -z "$have" ]; then
350 have=$(echo "$busybox_functions" | grep -Ec "( |^)$applet(,|$)")
351 if [ "$have" = 0 ]; then
352 warn "This setup requires busybox-initrd compiled with applet '$applet' support"
355 eval busybox_have_$applet=$have
358 if [ $err = 1 ]; then
363 # Extract the .config file from a kernel image
364 # uses extract-ikconfig from kernel sources (scripts/extract-ikconfig)
366 local kofile=$(modinfo -k $kernel -n configs 2> /dev/null)
367 if [ -n "$kofile" ]; then
368 /lib/geninitrd/extract-ikconfig $kofile
372 # see if config available as separate file
373 if [ -f /boot/config-$kernel ]; then
374 cat /boot/config-$kernel
378 # finally try vmlinuz itself
379 /lib/geninitrd/extract-ikconfig /boot/vmlinuz-$kernel
387 module=${module%$modext*}
391 # Finds module dependencies
395 # Outputs full path to module and it's dependencies
400 # if module is prefixed with dash, we should ignore errors if the module
402 if [ ${module#-} != $module ]; then
407 # This works when user has module-init-tools installed even on 2.4 kernels
409 modprobe=$(modprobe --set-version $kernel --show-depends $module --ignore-install 2>&1)
412 if [ $skiperrors = 1 ]; then
417 if ! is_no "$EXIT_IF_MISSING"; then
418 die "$module: module not found for $kernel kernel"
421 warn "$module: module not found for $kernel kernel"
422 warn "If $module isn't compiled in kernel then this initrd may not start your system."
428 while read insmod modpath options; do
429 if [ "$insmod" = "insmod" ]; then
431 # XXX: find a away to autodetect
432 smodule=$(basename_module $modpath)
435 find_depmod "-libcrc32c"
438 find_depmod "-crct10dif-pclmul"
439 find_depmod "-crct10dif"
442 find_depmod "-crc32c-intel"
443 find_depmod "-crc32c"
445 virtio_blk|virtio_scsi)
446 find_depmod "-virtio_pci"
447 find_depmod "-virtio_mmio"
460 # no firmware support in 2.4 kernels
461 if [ "$kernel_version_long" -lt "002005048" ]; then
464 echo -n $(NEW_MODINFO=1 modinfo -k $kernel -F firmware $module 2>/dev/null | xargs)
469 local mod depmod module=$1
471 depmod=$(find_depmod $module) || exit 1
472 for mod in $depmod; do
473 mod=${mod#/lib/modules/$kernel/}
475 # add each module only once
477 for m in $MODULES; do
478 [ $m = $mod ] && have=1
480 if [ $have = 0 ]; then
481 MODULES="$MODULES $mod"
486 # install a file to temporary mount image.
487 # it will operate recursively (copying directories)
488 # and will symlink destinations if source is symlink.
490 if [ $# -lt 2 ]; then
491 die 'Usage: inst <file> [<file>] <destination>'
494 local src i=0 c=$(($# - 1))
495 while [ $i -lt $c ]; do
502 local parentDir=$(dirname $DESTDIR$dest)
503 if [ ! -d "$parentDir" ]; then
504 verbose "+ mkdir -p DESTDIR${parentDir#$DESTDIR}"
507 verbose "+ cp $* DESTDIR$dest"
508 cp -HRp "$@" "$DESTDIR$dest"
513 die 'Usage: inst_d <destination> <destination>'
517 install -d "$DESTDIR$dir"
521 # install executable and it's shared libraries
523 if [ $# -lt 2 ]; then
524 die "Invalid params ($@), Usage: inst_exec <file>[, <file>] <destination>"
526 local src i=0 c=$(($# - 1))
527 while [ $i -lt $c ]; do
537 local obj lib libs libdir
540 /lib/ld-linux.so.2 | /lib64/ld-linux-x86-64.so.2 | /libx32/ld-linux-x32.so.2)
544 libs=$(ldd "$obj" | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
546 libdir=$(cd $(dirname "$lib"); pwd)
547 if [ ! -f "$DESTDIR/$lib" ]; then
549 inst_exec $lib $libdir
554 # hack for uclibc linked binaries requiring this fixed path
555 # XXX: shouldn't rpath be used here instead so th
556 for _lib in $(get_libdir LIBDIR); do
557 if [ -f $DESTDIR/$_lib/libc.so.0 ]; then
558 lib=$DESTDIR/$_lib/libc.so.0
559 lib=$(ldd "$lib" | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
560 libdir=$(cd $(dirname "$lib"); pwd)
561 if [ ! -e $DESTDIR$libdir ]; then
562 libdir=$(dirname "$libdir")
564 verbose "+ ln -s /$_lib $DESTDIR$libdir"
565 ln -s /$_lib $DESTDIR$libdir
572 # output modules.conf / modprobe.conf
574 echo "$modprobe_conf_cache"
577 # return options for MODULE
578 # @param $1 module name
581 local options=$(modprobe_conf | awk -vmodule="$module" '{ if ($1 == "options" && $2 == module) { for(i=3;i<=NF;i++) printf("%s ",$i); }}')
586 # defaults to modprobe -c if not told otherwise, this means include statements
588 cache_modprobe_conf() {
589 if [ "$kernel_version" -lt "002005" ]; then
590 modulefile=/etc/modules.conf
591 if [ ! -f "$modulefile" -a -f /etc/conf.modules ]; then
592 modulefile=/etc/conf.modules
596 if [ -n "$modulefile" ]; then
597 debug "Using $modulefile for modules config"
598 modprobe_conf_cache=$(cat $modulefile | awk '!/^[\t ]*#/ { print }')
601 debug "Using modprobe -c to get modules config"
602 modprobe_conf_cache=$(modprobe -c --set-version $kernel | awk '!/^[\t ]*#/ { print }')
606 # find modules for $devpath
607 find_modules_for_devpath() {
609 if [ -z "$devpath" ]; then
610 die "No argument passed to find_modules_for_devpath() - is your /etc/fstab correct?"
613 if [[ "$devpath" = /dev/dm-* ]]; then
614 # /dev/dm-3 -> /dev/mapper/sil_ahbgadcbchfc3
615 devpath=$(dm_node "$devpath")
618 if [ -L "$devpath" ] && ! is_lvm "$devpath" && ! is_luks "$devpath"; then
619 # sanitize things like:
620 # /dev/block/104:2 -> /dev/cciss/c0d0p2
621 devpath=$(readlink -f "$devpath")
624 verbose "Finding modules for device path $devpath"
626 if is_luks "$devpath"; then
627 find_modules_luks "$devpath"
631 if is_nfs "$devpath"; then
632 find_modules_nfs "$devpath"
636 if is_md "$devpath"; then
637 find_modules_md "$devpath"
641 if is_multipath "$devpath"; then
642 if find_modules_multipath "$devpath"; then
649 if is_dmraid "$devpath"; then
650 if find_modules_dmraid "$devpath"; then
656 if is_scsi "$devpath"; then
657 find_modules_scsi "$devpath"
661 if is_ide "$devpath"; then
662 find_modules_ide "$devpath"
666 if [[ "$devpath" == /dev/bcache* ]]; then
667 find_modules_bcache "$devpath"
671 if [[ "$devpath" == /dev/rd/* ]]; then
677 if [[ "$devpath" == /dev/ida/* ]]; then
678 find_module "cpqarray"
679 rootdev_add=/dev/ida/
683 if [[ "$devpath" == /dev/cciss/* ]]; then
684 rootdev_add=/dev/cciss/
686 # load hpsa for future kernels, cciss for backwards compat
687 if [ "$kernel_version_long" -ge "003000000" ]; then
688 find_module "hpsa" "-cciss"
689 find_modules_scsi "$devpath"
697 if [[ "$devpath" == /dev/ataraid/* ]]; then
699 find_module "ataraid"
700 ataraidmodules=$(modprobe_conf | awk '/ataraid_hostadapter/ { print $3 }')
701 if [ -n "$ataraidmodules" ]; then
702 # FIXME: think about modules compiled in kernel
703 die "ataraid_hostadapter alias not defined in modprobe.conf! Please set it and run $PROGRAM again."
705 for n in $ataraidmodules; do
708 rootdev_add=/dev/ataraid/
712 # check to see if we need to set up a loopback filesystem
713 if [[ "$devpath" == /dev/loop* ]]; then
714 die "Sorry, root on loop device isn't supported."
715 # TODO: rewrite for bsp and make nfs ready
716 if [ ! -x /sbin/losetup ]; then
717 die "losetup is missing"
719 key="^# $(echo $devpath | awk -F/ '{print($3);}' | tr '[a-z]' '[A-Z]'):"
720 if ! is_yes "`awk '/'$key'/ { print( "yes"); }' $fstab`"; then
721 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"
724 line="`awk '/'$key'/ { print $0; }' $fstab`"
725 loopDev="$(echo $line | awk '{print $3}')"
726 loopFs="$(echo $line | awk '{print $4}')"
727 loopFile="$(echo $line | awk '{print $5}')"
729 BASICMODULES="$BASICMODULES -loop"
730 find_module "-$loopFs"
731 BASICMODULES="$BASICMODULES -${loopFs}"
735 if is_lvm "$devpath"; then
736 find_modules_lvm "$devpath"
741 firmware_install_module() {
743 local firmware_files="$2"
745 verbose "Adding Firmwares ($firmware_files) to initrd for module $module"
746 # firmware not yet installed
747 if [ ! -f "$DESTDIR/lib/firmware/firmware.sh" ]; then
749 cat << 'EOF' >> "$DESTDIR/lib/firmware/firmware.sh"
751 # handle only firmware add requests
752 if [ "$SUBSYSTEM" != "firmware" ]; then
755 if [ "$ACTION" != "add" ]; then
758 echo 1 > /sys$DEVPATH/loading
759 cat "/lib/firmware/$FIRMWARE" > /sys$DEVPATH/data
760 echo 0 > /sys$DEVPATH/loading
763 chmod 755 "$DESTDIR/lib/firmware/firmware.sh"
765 # setup firmware loader agent
766 echo "echo -n "/lib/firmware/firmware.sh" > /proc/sys/kernel/hotplug" | add_linuxrc
769 for firmware in $firmware_files; do
770 if [ -f "/lib/firmware/$kernel/$firmware" ]; then
771 FIRMWAREDIR=${firmware%/*}
772 [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
773 inst /lib/firmware/$kernel/$firmware /lib/firmware/$firmware
774 elif [ -f "/lib/firmware/$firmware" ]; then
775 FIRMWAREDIR=${firmware%/*}
776 [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
777 inst /lib/firmware/$firmware /lib/firmware/$firmware
779 warn "Possible missing firmware file /lib/firmware/$firmware or /lib/firmware/$kernel/$firmware for module $module."
790 for mod in $modules; do
792 inst_d "/lib/modules/$kernel/$MODULEDIR"
793 cp -a "/lib/modules/$kernel/$mod" "$DESTDIR/lib/modules/$kernel/$mod"
796 gunzip "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress gz"
800 xz -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress xz"
804 bzip2 -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress bz2"
808 if [ "$STRIP" ] && [ -x "$STRIP" ]; then
809 $STRIP -g --remove-section=.comment "$DESTDIR/lib/modules/$kernel/${mod}"
814 modules_add_linuxrc() {
818 # module path without optional compression
820 modpath=${modpath%.xz}
821 modpath=${modpath%.bz2}
824 local module=${modpath##*/}; module=${module%$modext}
825 local options=$(modprobe_options "$module")
826 local genericname=$(echo $module | tr - _)
827 local usleep=$(eval echo \$MODULE_${genericname}_USLEEP)
828 local firmware=$(eval echo \$MODULE_${genericname}_FIRMWARE)
830 if [ "$module" = "scsi_mod" -a "$kernel_version_long" -ge "002006030" ]; then
831 options="scan=sync $options"
834 if [ x"$verbose" = x"-v" ]; then
836 if [ "$options" ]; then
837 s="$s with options [$options]"
839 if [ "$usleep" ]; then
840 s="$s and $usleep usleep"
842 verbose "Loading module [$module]$s"
845 if [ -n "$firmware" ]; then
846 firmware_install_module "$module" "$firmware"
848 for file in $(find_firmware "$module"); do
849 firmware_install_module "$module" "$file"
853 echo "insmod /lib/modules/$kernel/$modpath $options" | add_linuxrc
854 if [ -n "$usleep" ]; then
855 echo "usleep $usleep" | add_linuxrc
857 if [ "$module" = "scsi_wait_scan" ]; then
858 if [ "$(busybox_applet rmmod 2>/dev/null; echo $?)" = 0 ]; then
859 echo "rmmod scsi_wait_scan" | add_linuxrc
866 # Generates /dev nodes based on /proc/partitions information.
867 # Needs /proc mounted.
868 # Can be called multiple times.
869 initrd_gen_devices() {
870 if is_yes "$proc_partitions"; then
877 : 'Making device nodes'
878 cat /proc/partitions | (
879 # ignore first two lines: header, empty line
882 while read major minor blocks dev rest; do
885 [ -e $node ] || mknod -m 660 $node b $major $minor
892 initrd_gen_setrootdev() {
893 verbose "Adding rootfs finding based on kernel cmdline root= option support."
895 debug "Current /proc/partitions:\n$(sed -e 's,^,| ,' /proc/partitions)"
897 if [ "${ROOT##/dev/}" != "${ROOT}" ]; then
898 rootnr="$(busybox awk -v rootnode="${ROOT##/dev/}" '$4 == rootnode { print 256 * $1 + $2 }' /proc/partitions)"
899 # fallback to ls, try two different formats
900 # http://lists.pld-linux.org/mailman/pipermail/pld-devel-en/2014-May/023915.html
901 if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
903 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $3 + $4; }}')"
905 if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
906 # busybox 1.22 and upwards
907 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $5 + $6; }}')"
909 if [ "${rootnr:-0}" -gt 0 ]; then
910 echo "$rootnr" > /proc/sys/kernel/real-root-dev
916 initrd_gen_initramfs_switchroot() {
918 if [ "$rootdev" = "/dev/nfs" ]; then
919 echo "rootfs on NFS root=/dev/nfs"
921 [ ! -e "$DESTDIR/$rootdev" ] && inst $rootdev $rootdev
924 # parse 'root=xxx' kernel commandline
925 # We support passing root as hda3 /dev/hda3 0303 0x0303 and 303
927 # from lilo-23.2/readme/README:
928 # root=<device> changes the root device. This overrides settings that may
929 # have been made in the boot image and on the LILO command line. <device> is
930 # either the hexadecimal device number or the full path name of the device,
933 # * The device names are hard-coded in the kernel. Therefore, only the
934 # "standard" names are supported and some less common devices may not be
935 # recognized. In those cases, only numbers can be used.
939 eval "$(busybox awk -v root="$ROOT" '
940 # http://9fans.net/archive/2006/09/261
941 function h2d(str, hstr, res, num, n, digit, i) {
942 hstr = "0123456789abdcef";
944 n = split(tolower(str), digit, "");
946 for (i = 1; i <= n; i++) {
947 num = index(hstr, digit[i]) - 1;
948 res = res + (num * 16 ^ (n - i));
955 num_pattern_short = "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]";
956 num_pattern = "[0-9a-fA-F]" num_pattern_short;
957 dev_pattern = "[hms][a-z][a-z]([0-9])+";
961 # see if we have /dev/hdX or hdX, we can just take partition name
962 if (root ~ "^\/dev\/" dev_pattern "$" || root ~ "^" dev_pattern "$") {
964 sub("^/dev/", "", partition);
968 if (root ~ "^" num_pattern_short "$") {
969 # change "303" => "0x0303"
971 } else if (root ~ "^" num_pattern "$") {
972 # change "0303" => "0x0303"
976 maj = h2d(substr(root, 3, 2));
977 min = h2d(substr(root, 5, 2));
981 partition && $4 == partition { maj = $1; min = $2; }
982 $1 == maj && $2 == min { partition = $4; }
985 if (maj >= 0 && min >= 0) {
986 printf("maj=%s; min=%s;\n", maj, min);
989 printf("device=/dev/%s;\n", partition);
994 if [ -z "$device" ]; then
995 if [ "$DEBUGINITRD" ]; then
1001 if [ "$device" -a ! -b $device -a "$maj$min" ]; then
1002 mknod -m 660 $device b $maj $min
1005 # XXX hack, fallback to rootdev from geninitrd time
1006 if [ ! -e "$device" ]; then
1008 echo "DEVICE set to $device based on fstab entry from initrd gen time"
1011 # XXX hack, if no device, try to parse it from /proc/partitions using /proc/sys/kernel/real-root-dev
1012 if [ ! -e "$device" ]; then
1013 rrd=$(cat /proc/sys/kernel/real-root-dev)
1014 major=$(($rrd / 256))
1015 minor=$(($rrd % 256))
1017 while read pmajor pminor blocks dev rest; do
1018 # skip header and empty line
1019 [ -z "$pmajor" -o "$pmajor" = "major" ] && continue
1021 if [ $pmajor = $major -a $pminor = $minor ]; then
1023 echo "DEVICE set to $device based on real-root-dev"
1025 done < /proc/partitions
1028 [ -n "$ROOTFLAGS" ] && ROOTFLAGS="-o $ROOTFLAGS"
1030 mount -t $ROOTFS -r $device $ROOTFLAGS /newroot || echo "Mount of rootfs failed."
1032 if [ -z "$init" -o ! -x "/newroot$init" ]; then
1037 busybox_applet dmesg
1039 add_linuxrc <<-'EOF'
1040 if [ "$DEBUGINITRD" ]; then
1041 echo "Last 20 lines of dmesg:"
1047 kmsg "geninitrd/$VERSION switching root"
1050 busybox_applet switch_root usleep
1051 add_linuxrc <<-'EOF'
1052 [ ! -e /newroot/dev/console ] && mknod -m 660 /newroot/dev/console c 5 1
1054 # switch root to empty dir will make kernel panic, so sleep 10s before it
1055 # switch_root needs to be pid 1, so there's no other way to recover from here
1056 # if /dev is missing, switch root will likely fail, give debug shell before that
1057 if [ ! -d /newroot/dev ]; then
1058 echo "/dev is missing, switch_root will likely fail"
1059 echo "if you booted with debugrd=sh, then you be given shell and you might able to recover this situation"
1061 [ "$DEBUGINITRD" ] || usleep 10000000
1064 # systemd[1]: /usr appears to be on its own filesytem and is not
1065 # already mounted. This is not a supported setup. Some things will
1066 # probably break (sometimes even silently) in mysterious ways. Consult
1067 # http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken
1068 # for more information.
1069 echo trying to mount /usr
1070 chroot /newroot mount -n /usr
1072 exec switch_root /newroot $init ${1:+"$@"}
1074 # FIXME: this code is never executed, as "exec" does not return!
1076 echo "Error! initramfs should not reach this place."
1077 echo "It probably means you've got old version of busybox, with broken"
1078 echo "initramfs support. Trying to boot anyway, but won't promise anything."
1080 exec chroot /newroot $init ${1:+"$@"}
1082 echo "Failed to chroot!"
1085 # we need /init being real file, not symlink, otherwise the initramfs will
1086 # not be ran by pid 1 which is required for switch_root
1087 mv $DESTDIR/linuxrc $DESTDIR/init
1088 ln -s init $DESTDIR/linuxrc
1091 # find if $symbol exists in System.map $mapfile
1095 if [ ! -f $mapfile ]; then
1096 # missing mapfile (not a pld kernel?)
1100 awk -vc=1 -vsymbol="$symbol" '$2 == "T" && $3 == symbol {c = 0} END {exit c}' $mapfile
1103 # find best compressor (or forced one) for initrd
1106 # fastest initrd decompression speed is first
1107 local compressors='lzo gzip xz lzma bzip2'
1109 # a specified one, take it
1110 if ! is_yes "$mode"; then
1114 verbose "finding compressor: $compressors (via $mode)"
1115 # check for compressor validity
1116 local c prog map=/boot/System.map-$kernel
1117 for c in $compressors; do
1140 # any existing sym will work
1145 die "Unknown compressor $c"
1148 if sym_exists $map $sym && [ -x $prog ]; then
1154 verbose "using gzip for compressor (fallback)"
1158 # compresses kernel image image
1159 # in function so we could retry with other compressor on failure
1161 local compressor="$1" IMAGE="$2" target="$3" tmp
1162 tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1164 case "$compressor" in
1166 # don't use -9 here since kernel won't understand it
1167 xz --format=xz --check=crc32 --lzma2=preset=6e,dict=1MiB < "$IMAGE" > "$tmp" || return $?
1170 xz --format=lzma -9 < "$IMAGE" > "$tmp" || return $?
1173 bzip2 -9 < "$IMAGE" > "$tmp" || return $?
1176 gzip -9 < "$IMAGE" > "$tmp" || return $?
1179 lzop -9 < "$IMAGE" > "$tmp" || return $?
1182 cat < "$IMAGE" > "$tmp" || return $?
1186 mv -f "$tmp" "$target"
1189 if [ -r /etc/sysconfig/geninitrd ]; then
1190 . /etc/sysconfig/geninitrd
1193 if [ ! -f /proc/mounts ]; then
1194 warn "/proc filesystem not mounted, may cause wrong results or failure."
1197 geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev tuxonice suspend fbsplash condecor bootsplash uvesafb nfs sata scsi usbkbd bcache
1199 while [ $# -gt 0 ]; do
1209 modulefile=${1#--modules-conf=}
1218 --without-bootsplash)
1230 --without-fbcondecor)
1239 --with-suspend2 | --with-tuxonice)
1242 --without-suspend2 | --without-tuxonice)
1246 LVMTOOLSVERSION=${1#--lvmversion=}
1248 --lvmtoolsversion=*)
1249 LVMTOOLSVERSION=${1#--lvmtoolsversion=}
1251 --lvmtoolsversion|--lvmversion)
1264 --without-multipath)
1268 USE_MULTIPATH=${1#--with-multipath=}
1277 BASICMODULES="$BASICMODULES ${1#--with=}"
1280 BASICMODULES="$BASICMODULES $2"
1284 echo "$PROGRAM: version $VERSION"
1288 if [ x"$verbose" = x"-v" ]; then
1299 COMPRESS="${1#--compress=}"
1308 STRIP="${1#--strip=}"
1321 PREMODS="$PREMODS ${1#--preload=}"
1324 PREMODS="$PREMODS $2"
1328 die "--fs option is obsoleted. Use --initrdfs instead"
1331 INITRDFS=${1#--initrdfs=}
1344 if [ -z "$target" ]; then
1346 elif [ -z "$kernel" ]; then
1358 if [ -z "$target" -o -z "$kernel" ]; then
1364 if [ "$(id -u)" != 0 ]; then
1365 die "You need to be root to generate initrd"
1368 for dir in libx32 lib64 lib; do
1369 initrd_dir=/usr/$dir/initrd
1370 if [ -d "$initrd_dir" ]; then
1371 initrd_dirs="$initrd_dirs $initrd_dir"
1375 kernel_version=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d",$1,$2)}')
1376 kernel_version_long=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d%03d",$1,$2,$3)}')
1378 verbose "# geninitrd $VERSION"
1379 debug "Using initrd_dir: $initrd_dir"
1381 busybox=$(find_tool $initrd_dir/busybox $initrd_dir/initrd-busybox /bin/initrd-busybox) || die "Couldn't find busybox suitable for initrd"
1383 # we setup mods after parsing command line args
1384 geninitrd_setup_mods
1386 if [ ! -f /boot/vmlinuz-"$kernel" ]; then
1387 warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?"
1390 if [ -z "$INITRDFS" ]; then
1391 if [ -n "$FS" ]; then
1392 # FS= can came only via /etc/sysconfig/geninitrd likely?
1393 die "FS configuration option is obsoleted. Use INITRDFS instead"
1397 if [ "$kernel_version" -ge "002005" ]; then
1398 INITRDFS="initramfs"
1406 [ -x /sbin/mke2fs ] || die "/sbin/mke2fs is missing"
1409 [ -x /sbin/genromfs ] || die "/sbin/genromfs is missing"
1412 [ -x /sbin/mkcramfs ] || die "/sbin/mkcramfs is missing"
1415 [ -x /bin/cpio ] || die "/bin/cpio is missing"
1416 [ -x /usr/bin/find ] || die "/usr/bin/find is missing"
1419 die "Filesystem $INITRDFS on initrd is not supported"
1423 if [ -L "$target" ]; then
1424 target=$(readlink -f "$target")
1427 if [ -n "$img_vers" ]; then
1428 target="$target-$kernel"
1431 if [ -z "$force" -a -f "$target" ]; then
1432 die "$target already exists."
1435 if [ ! -d "/lib/modules/$kernel" ]; then
1436 die "/lib/modules/$kernel is not a directory."
1439 if [ "$kernel_version" -ge "002005" ]; then
1445 for n in $PREMODS; do
1449 if [ "$FBMODULE" ]; then
1450 find_module "$FBMODULE"
1453 # autodetect USB keyboards
1456 # allow forcing loading SCSI and/or IDE modules
1457 # XXX: where ADDSCSI cames from? drop?
1458 if is_yes "$ADDSCSI"; then
1462 # autodetect SATA modules
1465 # XXX: where ADDIDE cames from? drop?
1466 if is_yes "$ADDIDE"; then
1470 if is_yes "$USE_SUSPEND"; then
1471 find_modules_suspend
1474 find_root "$fstab" || exit
1475 verbose "Using $rootdev as device for rootfs"
1477 find_modules_for_devpath "$rootdev"
1479 # if USE_MULTIPATH is path to device, scan that too
1480 # this is to bootstrap multipath setup into initrd.
1481 if ! is_no "$USE_MULTIPATH" && ! is_yes "$USE_MULTIPATH"; then
1482 find_modules_multipath $USE_MULTIPATH
1485 find_module "-$rootFs"
1487 for n in $BASICMODULES; do
1491 if is_yes "$USE_TUXONICE"; then
1495 find_modules_uvesafb
1496 find_modules_fbsplash
1498 if [ -n "$ifneeded" -a -z "$MODULES" ]; then
1499 verbose "No modules are needed -- not building initrd image."
1503 verbose "Building initrd..."
1504 DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
1505 RCFILE="$DESTDIR/linuxrc"
1507 chmod a+rx "$RCFILE"
1508 ln -s linuxrc $DESTDIR/init
1510 # create dirs that we really need
1511 inst_d /{lib,bin,etc,dev{,/pts,/shm},loopfs,var,proc,run,sys}
1513 modules_install "$MODULES"
1515 # mknod'ing the devices instead of copying them works both with and
1517 mknod -m 600 "$DESTDIR/dev/console" c 5 1
1518 mknod -m 666 "$DESTDIR/dev/null" c 1 3
1519 mknod -m 666 "$DESTDIR/dev/zero" c 1 5
1520 mknod -m 666 "$DESTDIR/dev/random" c 1 8
1521 mknod -m 666 "$DESTDIR/dev/urandom" c 1 9
1522 mknod -m 644 "$DESTDIR/dev/kmsg" c 1 11
1524 inst_exec $busybox /bin/busybox
1525 ln -s busybox $DESTDIR/bin/sh
1526 # for older busyboxes who had /bin/initrd-busybox as EXEPATH
1527 ln -s busybox $DESTDIR/bin/initrd-busybox
1531 # initrd generated by geninitrd/$VERSION
1532 # on $(LC_ALL=C date)
1538 kmsg "geninitrd/$VERSION starting"
1541 # builtin defaults from geninitrd
1545 add_linuxrc <<-'EOF'
1546 read CMDLINE < /proc/cmdline
1548 for arg in $CMDLINE; do
1549 if [ "${arg}" = "debuginitrd" ] || [ "${arg}" = "debugrd" ]; then
1552 if [ "${arg##debuginitrd=}" != "${arg}" ] || [ "${arg##debugrd=}" != "${arg}" ]; then
1553 DEBUGINITRD=${arg##debug*rd=}
1555 if [ "${arg##root=}" != "${arg}" ]; then
1558 if [ "${arg##rootflags=}" != "${arg}" ]; then
1559 ROOTFLAGS=${arg##rootflags=}
1561 if [ "${arg##rootfsflags=}" != "${arg}" ]; then
1562 ROOTFSFLAGS=${arg##rootfsflags=}
1564 if [ "${arg##init=}" != "${arg}" ]; then
1569 # handling of invalid, rootfsflags, option
1570 if [ -n "$ROOTFSFLAGS" ]; then
1571 if [ -n "$ROOTFLAGS" ]; then
1572 ROOTFLAGS="$ROOTFLAGS,$ROOTFSFLAGS"
1574 ROOTFLAGS="$ROOTFSFLAGS"
1578 if [ "$DEBUGINITRD" = "sh" ]; then
1579 # export some vars to subshell for debug to work
1580 export CMDLINE ROOT ROOTFS ROOTDEV ROOTFLAGS DEBUGINITRD INIT
1581 export LVM_ROOTVG LVM_SUSPENDVG LVM_VGVOLUMES
1582 export rootnr attrs majmin major minor device
1584 # make debugshell() invoke subshell if $DEBUGINITRD=sh
1587 if is_yes "$RUN_SULOGIN_ON_ERR"; then
1588 add_linuxrc <<-'EOF'
1589 echo "debug shell disabled by RUN_SULOGIN_ON_ERR=yes from /etc/sysconfig/system during initrd generation time"
1592 add_linuxrc <<-'EOF'
1596 add_linuxrc <<-'EOF'
1604 if [ "$DEBUGINITRD" ]; then
1609 modules_add_linuxrc $MODULES
1611 # TODO: rewrite for busybox
1612 #if [ -n "$loopDev" ]; then
1613 # if [ ! -d /initrd ]; then
1617 # cp -a "$loopDev" "$DESTDIR/dev"
1618 # cp -a "$rootdev" "$DESTDIR/dev"
1619 # echo "echo Mounting device containing loopback root filesystem" >> "$RCFILE"
1620 # echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE"
1621 # echo "echo Setting up loopback device $rootdev" >> $RCFILE
1622 # echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE"
1625 if is_yes "$USE_UDEV"; then
1634 initrd_gen_multipath
1637 if is_yes "$have_nfs"; then
1645 initrd_gen_setrootdev
1648 # additional devs always needed
1649 [ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev
1651 initrd_gen_stop_udevd
1652 initrd_gen_stop_mdev
1653 initrd_gen_stop_uvesafb
1655 # resume after killing local processes
1660 add_linuxrc <<-'EOF'
1661 if [ ! "$DEBUGINITRD" ]; then
1665 for i in $(export -p); do
1666 i=${i#declare -x } # ksh/bash
1667 i=${i#export } # busybox
1678 [ -z "$i" ] && continue
1681 ROOT|PATH|HOME|TERM)
1693 if [ "$INITRDFS" = "initramfs" ]; then
1694 initrd_gen_initramfs_switchroot
1700 initrd_gen_fbcondecor
1702 debug "Current /linuxrc:\n$(sed -e 's,^,| ,' $DESTDIR/linuxrc)"
1704 IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed"
1706 IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
1707 verbose "image size: $IMAGESIZE KiB ($DESTDIR)"
1709 verbose "Creating $INITRDFS image $IMAGE"
1712 dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null
1713 # NOTE: ext2 label is max 16 chars
1714 mke2fs -q -F -b 1024 -m 0 -L "PLD/$kernel" "$IMAGE" 2>/dev/null 1>&2
1715 tune2fs -i 0 "$IMAGE" >/dev/null 2>&1
1717 local tmpmnt=$(mktemp -d -t initrd.mnt-XXXXXX)
1718 debug "Mounting ext2 image $IMAGE to $tmpmnt"
1719 mount -o loop -t ext2 "$IMAGE" "$tmpmnt" || die "mount failed, check dmesg(1)"
1720 # We don't need this directory, so let's save space
1721 rm -rf "$tmpmnt"/lost+found
1723 debug "Copy recursively $DESTDIR -> $tmpmnt"
1724 cp -a $DESTDIR/* $tmpmnt
1730 genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD Linux/$kernel (geninitrd/$VERSION)"
1733 mkcramfs "$DESTDIR" "$IMAGE"
1736 (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
1739 die "Filesystem $INITRDFS not supported by $PROGRAM"
1742 CONFIG_BLK_DEV_RAM_SIZE=$(ikconfig | awk -F= '/^CONFIG_BLK_DEV_RAM_SIZE/{print $2}')
1743 if [ -z "$CONFIG_BLK_DEV_RAM_SIZE" ]; then
1744 CONFIG_BLK_DEV_RAM_SIZE=4096
1745 warn "No CONFIG_BLK_DEV_RAM_SIZE detected, fallback to $CONFIG_BLK_DEV_RAM_SIZE"
1748 if [ "$IMAGESIZE" -gt $CONFIG_BLK_DEV_RAM_SIZE ]; then
1749 warn "Your image size is larger than $CONFIG_BLK_DEV_RAM_SIZE, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!"
1752 if ! is_no "$COMPRESS"; then
1753 compressor=$(find_compressor "$COMPRESS")
1754 verbose "Compressing $target with $compressor"
1756 # TODO: the image name (specified from kernel.spec) already contains
1757 # extension, which is .gz most of the time.
1758 compress_image "$compressor" "$IMAGE" "$target" || {
1759 if [ $compressor != gzip ]; then
1760 warn "Could not compress with $compressor, retrying with gzip"
1761 compress_image gzip "$IMAGE" "$target" || die "compress failed with gzip" $?
1763 die "Could not compress image with $compressor"
1767 cp -a "$IMAGE" "$target"
1770 # XXX. check if bootsplash can output data to tmp dir not directly to initramfs image.
1771 initrd_gen_bootsplash "$target"
1773 rm -rf "$DESTDIR" "$IMAGE"
1775 # vim:ts=4:sw=4:noet:fdm=marker