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 -o mode=0755,noexec,nosuid,nodev" | 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
1011 add_linuxrc <<-'EOF'
1012 echo "DEVICE set to $device based on fstab entry from initrd gen time"
1015 # XXX hack, if no device, try to parse it from /proc/partitions using /proc/sys/kernel/real-root-dev
1016 if [ ! -e "$device" ]; then
1017 rrd=$(cat /proc/sys/kernel/real-root-dev)
1018 major=$(($rrd / 256))
1019 minor=$(($rrd % 256))
1021 while read pmajor pminor blocks dev rest; do
1022 # skip header and empty line
1023 [ -z "$pmajor" -o "$pmajor" = "major" ] && continue
1025 if [ $pmajor = $major -a $pminor = $minor ]; then
1027 echo "DEVICE set to $device based on real-root-dev"
1029 done < /proc/partitions
1032 [ -n "$ROOTFLAGS" ] && ROOTFLAGS="-o $ROOTFLAGS"
1034 mount -t $ROOTFS -r $device $ROOTFLAGS /newroot || echo "Mount of rootfs failed."
1036 if [ -z "$init" -o ! -x "/newroot$init" ]; then
1041 busybox_applet dmesg
1043 add_linuxrc <<-'EOF'
1044 if [ "$DEBUGINITRD" ]; then
1045 echo "Last 20 lines of dmesg:"
1051 kmsg "geninitrd/$VERSION switching root"
1054 busybox_applet switch_root usleep
1055 add_linuxrc <<-'EOF'
1056 [ ! -e /newroot/dev/console ] && mknod -m 660 /newroot/dev/console c 5 1
1058 # switch root to empty dir will make kernel panic, so sleep 10s before it
1059 # switch_root needs to be pid 1, so there's no other way to recover from here
1060 # if /dev is missing, switch root will likely fail, give debug shell before that
1061 if [ ! -d /newroot/dev ]; then
1062 echo "/dev is missing, switch_root will likely fail"
1063 echo "if you booted with debugrd=sh, then you be given shell and you might able to recover this situation"
1065 [ "$DEBUGINITRD" ] || usleep 10000000
1068 # systemd[1]: /usr appears to be on its own filesytem and is not
1069 # already mounted. This is not a supported setup. Some things will
1070 # probably break (sometimes even silently) in mysterious ways. Consult
1071 # http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken
1072 # for more information.
1073 echo trying to mount /usr
1074 chroot /newroot mount -n /usr
1076 exec switch_root /newroot $init ${1:+"$@"}
1078 # FIXME: this code is never executed, as "exec" does not return!
1080 echo "Error! initramfs should not reach this place."
1081 echo "It probably means you've got old version of busybox, with broken"
1082 echo "initramfs support. Trying to boot anyway, but won't promise anything."
1084 exec chroot /newroot $init ${1:+"$@"}
1086 echo "Failed to chroot!"
1089 # we need /init being real file, not symlink, otherwise the initramfs will
1090 # not be ran by pid 1 which is required for switch_root
1091 mv $DESTDIR/linuxrc $DESTDIR/init
1092 ln -s init $DESTDIR/linuxrc
1095 # find if $symbol exists in System.map $mapfile
1099 if [ ! -f $mapfile ]; then
1100 # missing mapfile (not a pld kernel?)
1104 awk -vc=1 -vsymbol="$symbol" '($2 == "T" || $2 == "t") && $3 == symbol {c = 0} END {exit c}' $mapfile
1107 # find best compressor (or forced one) for initrd
1110 local compressors='xz lzma bzip2 gzip lzo'
1112 # a specified one, take it
1113 if ! is_yes "$mode"; then
1117 verbose "finding compressor: $compressors (via $mode)"
1118 # check for compressor validity
1119 local c prog map=/boot/System.map-$kernel
1120 for c in $compressors; do
1143 # any existing sym will work
1148 die "Unknown compressor $c"
1151 if sym_exists $map $sym && [ -x $prog ]; then
1157 verbose "using gzip for compressor (fallback)"
1161 # compresses kernel image image
1162 # in function so we could retry with other compressor on failure
1164 local compressor="$1" IMAGE="$2" target="$3" tmp
1165 tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1167 case "$compressor" in
1169 # don't use -9 here since kernel won't understand it
1170 xz --format=xz --check=crc32 --lzma2=preset=6e,dict=1MiB < "$IMAGE" > "$tmp" || return $?
1173 xz --format=lzma -9 < "$IMAGE" > "$tmp" || return $?
1176 bzip2 -9 < "$IMAGE" > "$tmp" || return $?
1179 gzip -9 < "$IMAGE" > "$tmp" || return $?
1182 lzop -9 < "$IMAGE" > "$tmp" || return $?
1185 cat < "$IMAGE" > "$tmp" || return $?
1189 mv -f "$tmp" "$target"
1192 if [ -r /etc/sysconfig/geninitrd ]; then
1193 . /etc/sysconfig/geninitrd
1196 if [ ! -f /proc/mounts ]; then
1197 warn "/proc filesystem not mounted, may cause wrong results or failure."
1200 geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev tuxonice suspend fbsplash condecor bootsplash uvesafb nfs sata scsi usbkbd bcache
1202 while [ $# -gt 0 ]; do
1212 modulefile=${1#--modules-conf=}
1221 --without-bootsplash)
1233 --without-fbcondecor)
1242 --with-suspend2 | --with-tuxonice)
1245 --without-suspend2 | --without-tuxonice)
1249 LVMTOOLSVERSION=${1#--lvmversion=}
1251 --lvmtoolsversion=*)
1252 LVMTOOLSVERSION=${1#--lvmtoolsversion=}
1254 --lvmtoolsversion|--lvmversion)
1267 --without-multipath)
1271 USE_MULTIPATH=${1#--with-multipath=}
1280 BASICMODULES="$BASICMODULES ${1#--with=}"
1283 BASICMODULES="$BASICMODULES $2"
1287 echo "$PROGRAM: version $VERSION"
1291 if [ x"$verbose" = x"-v" ]; then
1302 COMPRESS="${1#--compress=}"
1311 STRIP="${1#--strip=}"
1324 PREMODS="$PREMODS ${1#--preload=}"
1327 PREMODS="$PREMODS $2"
1331 die "--fs option is obsoleted. Use --initrdfs instead"
1334 INITRDFS=${1#--initrdfs=}
1347 if [ -z "$target" ]; then
1349 elif [ -z "$kernel" ]; then
1361 if [ -z "$target" -o -z "$kernel" ]; then
1367 if [ "$(id -u)" != 0 ]; then
1368 die "You need to be root to generate initrd"
1371 for dir in libx32 lib64 lib; do
1372 initrd_dir=/usr/$dir/initrd
1373 if [ -d "$initrd_dir" ]; then
1374 initrd_dirs="$initrd_dirs $initrd_dir"
1378 kernel_version=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d",$1,$2)}')
1379 kernel_version_long=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d%03d",$1,$2,$3)}')
1381 verbose "# geninitrd $VERSION"
1382 debug "Using initrd_dir: $initrd_dir"
1384 busybox=$(find_tool $initrd_dir/busybox $initrd_dir/initrd-busybox /bin/initrd-busybox) || die "Couldn't find busybox suitable for initrd"
1386 # we setup mods after parsing command line args
1387 geninitrd_setup_mods
1389 if [ ! -f /boot/vmlinuz-"$kernel" ]; then
1390 warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?"
1393 if [ -z "$INITRDFS" ]; then
1394 if [ -n "$FS" ]; then
1395 # FS= can came only via /etc/sysconfig/geninitrd likely?
1396 die "FS configuration option is obsoleted. Use INITRDFS instead"
1400 if [ "$kernel_version" -ge "002005" ]; then
1401 INITRDFS="initramfs"
1408 local s sfound sym p prog map=/boot/System.map-$kernel
1411 # TODO: symbols to check in case of ext2 used via ext3/4 subsystem
1424 sym=__initramfs_start
1425 prog="/bin/cpio /usr/bin/find"
1428 die "Filesystem $INITRDFS on initrd is not supported by geninitrd"
1432 # only one is needed (for cases like ext2 via ext2 or via ext3 or via ext4 subsysytem)
1435 sym_exists $map $s && sfound=1
1438 if [ "$sfound" -eq "0" ]; then
1439 die "Filesystem $INITRDFS on initrd is not supported by kernel"
1443 [ ! -x "$p" ] && die "$prog is missing"
1448 if [ -L "$target" ]; then
1449 target=$(readlink -f "$target")
1452 if [ -n "$img_vers" ]; then
1453 target="$target-$kernel"
1456 if [ -z "$force" -a -f "$target" ]; then
1457 die "$target already exists."
1460 if [ ! -d "/lib/modules/$kernel" ]; then
1461 die "/lib/modules/$kernel is not a directory."
1464 if [ "$kernel_version" -ge "002005" ]; then
1470 for n in $PREMODS; do
1474 if [ "$FBMODULE" ]; then
1475 find_module "$FBMODULE"
1478 # autodetect USB keyboards
1481 # allow forcing loading SCSI and/or IDE modules
1482 # XXX: where ADDSCSI cames from? drop?
1483 if is_yes "$ADDSCSI"; then
1487 # autodetect SATA modules
1490 # XXX: where ADDIDE cames from? drop?
1491 if is_yes "$ADDIDE"; then
1495 if is_yes "$USE_SUSPEND"; then
1496 find_modules_suspend
1499 find_root "$fstab" || exit
1500 verbose "Using $rootdev as device for rootfs"
1502 find_modules_for_devpath "$rootdev"
1504 # if USE_MULTIPATH is path to device, scan that too
1505 # this is to bootstrap multipath setup into initrd.
1506 if ! is_no "$USE_MULTIPATH" && ! is_yes "$USE_MULTIPATH"; then
1507 find_modules_multipath $USE_MULTIPATH
1510 find_module "-$rootFs"
1512 for n in $BASICMODULES; do
1516 if is_yes "$USE_TUXONICE"; then
1520 find_modules_uvesafb
1521 find_modules_fbsplash
1523 if [ -n "$ifneeded" -a -z "$MODULES" ]; then
1524 verbose "No modules are needed -- not building initrd image."
1528 verbose "Building initrd..."
1529 DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
1530 RCFILE="$DESTDIR/linuxrc"
1532 chmod a+rx "$RCFILE"
1533 ln -s linuxrc $DESTDIR/init
1535 # create dirs that we really need
1536 inst_d /{lib,bin,etc,dev{,/pts,/shm},loopfs,var,proc,run,sys}
1538 modules_install "$MODULES"
1540 # mknod'ing the devices instead of copying them works both with and
1542 mknod -m 600 "$DESTDIR/dev/console" c 5 1
1543 mknod -m 666 "$DESTDIR/dev/null" c 1 3
1544 mknod -m 666 "$DESTDIR/dev/zero" c 1 5
1545 mknod -m 666 "$DESTDIR/dev/random" c 1 8
1546 mknod -m 666 "$DESTDIR/dev/urandom" c 1 9
1547 mknod -m 644 "$DESTDIR/dev/kmsg" c 1 11
1549 inst_exec $busybox /bin/busybox
1550 ln -s busybox $DESTDIR/bin/sh
1551 # for older busyboxes who had /bin/initrd-busybox as EXEPATH
1552 ln -s busybox $DESTDIR/bin/initrd-busybox
1556 # initrd generated by geninitrd/$VERSION
1557 # on $(LC_ALL=C date)
1563 kmsg "geninitrd/$VERSION starting"
1566 # builtin defaults from geninitrd
1570 add_linuxrc <<-'EOF'
1571 read CMDLINE < /proc/cmdline
1573 for arg in $CMDLINE; do
1574 if [ "${arg}" = "debuginitrd" ] || [ "${arg}" = "debugrd" ]; then
1577 if [ "${arg##debuginitrd=}" != "${arg}" ] || [ "${arg##debugrd=}" != "${arg}" ]; then
1578 DEBUGINITRD=${arg##debug*rd=}
1580 if [ "${arg##root=}" != "${arg}" ]; then
1583 if [ "${arg##rootfs=}" != "${arg}" ]; then
1584 ROOTFS=${arg##rootfs=}
1586 if [ "${arg##rootflags=}" != "${arg}" ]; then
1587 ROOTFLAGS=${arg##rootflags=}
1589 if [ "${arg##rootfsflags=}" != "${arg}" ]; then
1590 ROOTFSFLAGS=${arg##rootfsflags=}
1592 if [ "${arg##init=}" != "${arg}" ]; then
1597 # handling of invalid, rootfsflags, option
1598 if [ -n "$ROOTFSFLAGS" ]; then
1599 if [ -n "$ROOTFLAGS" ]; then
1600 ROOTFLAGS="$ROOTFLAGS,$ROOTFSFLAGS"
1602 ROOTFLAGS="$ROOTFSFLAGS"
1606 if [ "$DEBUGINITRD" = "sh" ]; then
1607 # export some vars to subshell for debug to work
1608 export CMDLINE ROOT ROOTFS ROOTDEV ROOTFLAGS DEBUGINITRD INIT
1609 export LVM_ROOTVG LVM_SUSPENDVG LVM_VGVOLUMES
1610 export rootnr attrs majmin major minor device
1612 # make debugshell() invoke subshell if $DEBUGINITRD=sh
1615 if is_yes "$RUN_SULOGIN_ON_ERR"; then
1616 add_linuxrc <<-'EOF'
1617 echo "debug shell disabled by RUN_SULOGIN_ON_ERR=yes from /etc/sysconfig/system during initrd generation time"
1620 add_linuxrc <<-'EOF'
1624 add_linuxrc <<-'EOF'
1632 if [ "$DEBUGINITRD" ]; then
1637 modules_add_linuxrc $MODULES
1639 # TODO: rewrite for busybox
1640 #if [ -n "$loopDev" ]; then
1641 # if [ ! -d /initrd ]; then
1645 # cp -a "$loopDev" "$DESTDIR/dev"
1646 # cp -a "$rootdev" "$DESTDIR/dev"
1647 # echo "echo Mounting device containing loopback root filesystem" >> "$RCFILE"
1648 # echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE"
1649 # echo "echo Setting up loopback device $rootdev" >> $RCFILE
1650 # echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE"
1653 if is_yes "$USE_UDEV"; then
1662 initrd_gen_multipath
1665 if is_yes "$have_nfs"; then
1673 initrd_gen_setrootdev
1676 # additional devs always needed
1677 [ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev
1679 initrd_gen_stop_udevd
1680 initrd_gen_stop_mdev
1681 initrd_gen_stop_uvesafb
1683 # resume after killing local processes
1688 add_linuxrc <<-'EOF'
1689 if [ ! "$DEBUGINITRD" ]; then
1693 for i in $(export -p); do
1694 i=${i#declare -x } # ksh/bash
1695 i=${i#export } # busybox
1706 [ -z "$i" ] && continue
1709 ROOT|PATH|HOME|TERM)
1721 if [ "$INITRDFS" = "initramfs" ]; then
1722 initrd_gen_initramfs_switchroot
1728 initrd_gen_fbcondecor
1730 debug "Current /linuxrc:\n$(sed -e 's,^,| ,' $DESTDIR/linuxrc)"
1732 IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed"
1734 IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
1735 verbose "image size: $IMAGESIZE KiB ($DESTDIR)"
1737 verbose "Creating $INITRDFS image $IMAGE"
1740 dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null
1741 # NOTE: ext2 label is max 16 chars
1742 mke2fs -q -F -b 1024 -m 0 -L "PLD/$kernel" "$IMAGE" 2>/dev/null 1>&2
1743 tune2fs -i 0 "$IMAGE" >/dev/null 2>&1
1745 local tmpmnt=$(mktemp -d -t initrd.mnt-XXXXXX)
1746 debug "Mounting ext2 image $IMAGE to $tmpmnt"
1747 mount -o loop -t ext2 "$IMAGE" "$tmpmnt" || die "mount failed, check dmesg(1)"
1748 # We don't need this directory, so let's save space
1749 rm -rf "$tmpmnt"/lost+found
1751 debug "Copy recursively $DESTDIR -> $tmpmnt"
1752 cp -a $DESTDIR/* $tmpmnt
1758 genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD Linux/$kernel (geninitrd/$VERSION)"
1761 mkcramfs "$DESTDIR" "$IMAGE"
1764 (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
1767 die "Filesystem $INITRDFS not supported by $PROGRAM"
1770 CONFIG_BLK_DEV_RAM_SIZE=$(ikconfig | awk -F= '/^CONFIG_BLK_DEV_RAM_SIZE/{print $2}')
1771 if [ -z "$CONFIG_BLK_DEV_RAM_SIZE" ]; then
1772 CONFIG_BLK_DEV_RAM_SIZE=4096
1773 warn "No CONFIG_BLK_DEV_RAM_SIZE detected, fallback to $CONFIG_BLK_DEV_RAM_SIZE"
1776 if [ "$IMAGESIZE" -gt $CONFIG_BLK_DEV_RAM_SIZE ]; then
1777 warn "Your image size is larger than $CONFIG_BLK_DEV_RAM_SIZE, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!"
1780 if ! is_no "$COMPRESS"; then
1781 compressor=$(find_compressor "$COMPRESS")
1782 verbose "Compressing $target with $compressor"
1784 # TODO: the image name (specified from kernel.spec) already contains
1785 # extension, which is .gz most of the time.
1786 compress_image "$compressor" "$IMAGE" "$target" || {
1787 if [ $compressor != gzip ]; then
1788 warn "Could not compress with $compressor, retrying with gzip"
1789 compress_image gzip "$IMAGE" "$target" || die "compress failed with gzip" $?
1791 die "Could not compress image with $compressor"
1795 cp -a "$IMAGE" "$target"
1798 # XXX. check if bootsplash can output data to tmp dir not directly to initramfs image.
1799 initrd_gen_bootsplash "$target"
1801 rm -rf "$DESTDIR" "$IMAGE"
1803 # vim:ts=4:sw=4:noet:fdm=marker