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|zstd|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 warn "mounting multidevice btrfs volume requires rootfsflags=device=/dev/...,device=/dev/... kernel option"
436 find_depmod "-libcrc32c"
439 find_depmod "-libcrc32c"
442 find_depmod "-crct10dif-pclmul"
443 find_depmod "-crct10dif"
446 find_depmod "-crc32c-intel"
447 find_depmod "-crc32c"
449 virtio_blk|virtio_scsi)
450 find_depmod "-virtio_pci"
451 find_depmod "-virtio_mmio"
464 # no firmware support in 2.4 kernels
465 if [ "$kernel_version_long" -lt "002005048" ]; then
468 echo -n $(NEW_MODINFO=1 modinfo -k $kernel -F firmware $module 2>/dev/null | xargs)
473 local mod depmod module=$1
475 depmod=$(find_depmod $module) || exit 1
476 for mod in $depmod; do
477 mod=${mod#/lib/modules/$kernel/}
479 # add each module only once
481 for m in $MODULES; do
482 [ $m = $mod ] && have=1
484 if [ $have = 0 ]; then
485 MODULES="$MODULES $mod"
490 # install a file to temporary mount image.
491 # it will operate recursively (copying directories)
492 # and will symlink destinations if source is symlink.
494 if [ $# -lt 2 ]; then
495 die 'Usage: inst <file> [<file>] <destination>'
498 local src i=0 c=$(($# - 1))
499 while [ $i -lt $c ]; do
506 local parentDir=$(dirname $DESTDIR$dest)
507 if [ ! -d "$parentDir" ]; then
508 verbose "+ mkdir -p DESTDIR${parentDir#$DESTDIR}"
511 verbose "+ cp $* DESTDIR$dest"
512 cp -HRp "$@" "$DESTDIR$dest"
517 die 'Usage: inst_d <destination> <destination>'
521 install -d "$DESTDIR$dir"
525 # install executable and it's shared libraries
527 if [ $# -lt 2 ]; then
528 die "Invalid params ($@), Usage: inst_exec <file>[, <file>] <destination>"
530 local src i=0 c=$(($# - 1))
531 while [ $i -lt $c ]; do
541 local obj lib libs libdir
544 /lib/ld-linux.so.2 | /lib64/ld-linux-x86-64.so.2 | /libx32/ld-linux-x32.so.2)
548 libs=$(ldd "$obj" | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
550 libdir=$(cd $(dirname "$lib"); pwd)
551 if [ ! -f "$DESTDIR/$lib" ]; then
553 inst_exec $lib $libdir
558 # hack for uclibc linked binaries requiring this fixed path
559 # XXX: shouldn't rpath be used here instead so th
560 for _lib in $(get_libdir LIBDIR); do
561 if [ -f $DESTDIR/$_lib/libc.so.0 ]; then
562 lib=$DESTDIR/$_lib/libc.so.0
563 lib=$(ldd "$lib" | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
564 libdir=$(cd $(dirname "$lib"); pwd)
565 if [ ! -e $DESTDIR$libdir ]; then
566 libdir=$(dirname "$libdir")
568 verbose "+ ln -s /$_lib $DESTDIR$libdir"
569 ln -s /$_lib $DESTDIR$libdir
576 # output modules.conf / modprobe.conf
578 echo "$modprobe_conf_cache"
581 # return options for MODULE
582 # @param $1 module name
585 local options=$(modprobe_conf | awk -vmodule="$module" '{ if ($1 == "options" && $2 == module) { for(i=3;i<=NF;i++) printf("%s ",$i); }}')
590 # defaults to modprobe -c if not told otherwise, this means include statements
592 cache_modprobe_conf() {
593 if [ "$kernel_version" -lt "002005" ]; then
594 modulefile=/etc/modules.conf
595 if [ ! -f "$modulefile" -a -f /etc/conf.modules ]; then
596 modulefile=/etc/conf.modules
600 if [ -n "$modulefile" ]; then
601 debug "Using $modulefile for modules config"
602 modprobe_conf_cache=$(cat $modulefile | awk '!/^[\t ]*#/ { print }')
605 debug "Using modprobe -c to get modules config"
606 modprobe_conf_cache=$(modprobe -c --set-version $kernel | awk '!/^[\t ]*#/ { print }')
610 # find modules for $devpath
611 find_modules_for_devpath() {
613 if [ -z "$devpath" ]; then
614 die "No argument passed to find_modules_for_devpath() - is your /etc/fstab correct?"
617 if [[ "$devpath" = /dev/dm-* ]]; then
618 # /dev/dm-3 -> /dev/mapper/sil_ahbgadcbchfc3
619 devpath=$(dm_node "$devpath")
622 if [ -L "$devpath" ] && ! is_lvm "$devpath" && ! is_luks "$devpath"; then
623 # sanitize things like:
624 # /dev/block/104:2 -> /dev/cciss/c0d0p2
625 devpath=$(readlink -f "$devpath")
628 verbose "Finding modules for device path $devpath"
630 if is_luks "$devpath"; then
631 find_modules_luks "$devpath"
635 if is_nfs "$devpath"; then
636 find_modules_nfs "$devpath"
640 if is_md "$devpath"; then
641 find_modules_md "$devpath"
645 if is_multipath "$devpath"; then
646 if find_modules_multipath "$devpath"; then
653 if is_dmraid "$devpath"; then
654 if find_modules_dmraid "$devpath"; then
660 if is_scsi "$devpath"; then
661 find_modules_scsi "$devpath"
665 if is_ide "$devpath"; then
666 find_modules_ide "$devpath"
670 if [[ "$devpath" == /dev/bcache* ]]; then
671 find_modules_bcache "$devpath"
675 if [[ "$devpath" == /dev/rd/* ]]; then
681 if [[ "$devpath" == /dev/ida/* ]]; then
682 find_module "cpqarray"
683 rootdev_add=/dev/ida/
687 if [[ "$devpath" == /dev/cciss/* ]]; then
688 rootdev_add=/dev/cciss/
690 # load hpsa for future kernels, cciss for backwards compat
691 if [ "$kernel_version_long" -ge "003000000" ]; then
692 find_module "hpsa" "-cciss"
693 find_modules_scsi "$devpath"
701 if [[ "$devpath" == /dev/ataraid/* ]]; then
703 find_module "ataraid"
704 ataraidmodules=$(modprobe_conf | awk '/ataraid_hostadapter/ { print $3 }')
705 if [ -n "$ataraidmodules" ]; then
706 # FIXME: think about modules compiled in kernel
707 die "ataraid_hostadapter alias not defined in modprobe.conf! Please set it and run $PROGRAM again."
709 for n in $ataraidmodules; do
712 rootdev_add=/dev/ataraid/
716 # check to see if we need to set up a loopback filesystem
717 if [[ "$devpath" == /dev/loop* ]]; then
718 die "Sorry, root on loop device isn't supported."
719 # TODO: rewrite for bsp and make nfs ready
720 if [ ! -x /sbin/losetup ]; then
721 die "losetup is missing"
723 key="^# $(echo $devpath | awk -F/ '{print($3);}' | tr '[a-z]' '[A-Z]'):"
724 if ! is_yes "`awk '/'$key'/ { print( "yes"); }' $fstab`"; then
725 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"
728 line="`awk '/'$key'/ { print $0; }' $fstab`"
729 loopDev="$(echo $line | awk '{print $3}')"
730 loopFs="$(echo $line | awk '{print $4}')"
731 loopFile="$(echo $line | awk '{print $5}')"
733 BASICMODULES="$BASICMODULES -loop"
734 find_module "-$loopFs"
735 BASICMODULES="$BASICMODULES -${loopFs}"
739 if is_lvm "$devpath"; then
740 find_modules_lvm "$devpath"
745 firmware_install_module() {
747 local firmware_files="$2"
749 verbose "Adding Firmwares ($firmware_files) to initrd for module $module"
750 # firmware not yet installed
751 if [ ! -f "$DESTDIR/lib/firmware/firmware.sh" ]; then
753 cat << 'EOF' >> "$DESTDIR/lib/firmware/firmware.sh"
755 # handle only firmware add requests
756 if [ "$SUBSYSTEM" != "firmware" ]; then
759 if [ "$ACTION" != "add" ]; then
762 echo 1 > /sys$DEVPATH/loading
763 cat "/lib/firmware/$FIRMWARE" > /sys$DEVPATH/data
764 echo 0 > /sys$DEVPATH/loading
767 chmod 755 "$DESTDIR/lib/firmware/firmware.sh"
769 # setup firmware loader agent
770 echo "echo -n "/lib/firmware/firmware.sh" > /proc/sys/kernel/hotplug" | add_linuxrc
773 for firmware in $firmware_files; do
774 if [ -f "/lib/firmware/$kernel/$firmware" ]; then
775 FIRMWAREDIR=${firmware%/*}
776 [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
777 inst /lib/firmware/$kernel/$firmware /lib/firmware/$firmware
778 elif [ -f "/lib/firmware/$firmware" ]; then
779 FIRMWAREDIR=${firmware%/*}
780 [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
781 inst /lib/firmware/$firmware /lib/firmware/$firmware
783 warn "Possible missing firmware file /lib/firmware/$firmware or /lib/firmware/$kernel/$firmware for module $module."
794 for mod in $modules; do
796 inst_d "/lib/modules/$kernel/$MODULEDIR"
797 cp -a "/lib/modules/$kernel/$mod" "$DESTDIR/lib/modules/$kernel/$mod"
800 gunzip "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress gz"
804 xz -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress xz"
808 bzip2 -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress bz2"
812 if [ "$STRIP" ] && [ -x "$STRIP" ]; then
813 $STRIP -g --remove-section=.comment "$DESTDIR/lib/modules/$kernel/${mod}"
818 modules_add_linuxrc() {
822 # module path without optional compression
824 modpath=${modpath%.xz}
825 modpath=${modpath%.bz2}
828 local module=${modpath##*/}; module=${module%$modext}
829 local options=$(modprobe_options "$module")
830 local genericname=$(echo $module | tr - _)
831 local usleep=$(eval echo \$MODULE_${genericname}_USLEEP)
832 local firmware=$(eval echo \$MODULE_${genericname}_FIRMWARE)
834 if [ "$module" = "scsi_mod" -a "$kernel_version_long" -ge "002006030" ]; then
835 options="scan=sync $options"
838 if [ x"$verbose" = x"-v" ]; then
840 if [ "$options" ]; then
841 s="$s with options [$options]"
843 if [ "$usleep" ]; then
844 s="$s and $usleep usleep"
846 verbose "Loading module [$module]$s"
849 if [ -n "$firmware" ]; then
850 firmware_install_module "$module" "$firmware"
852 for file in $(find_firmware "$module"); do
853 firmware_install_module "$module" "$file"
857 echo "insmod /lib/modules/$kernel/$modpath $options" | add_linuxrc
858 if [ -n "$usleep" ]; then
859 echo "usleep $usleep" | add_linuxrc
861 if [ "$module" = "scsi_wait_scan" ]; then
862 if [ "$(busybox_applet rmmod 2>/dev/null; echo $?)" = 0 ]; then
863 echo "rmmod scsi_wait_scan" | add_linuxrc
870 # Generates /dev nodes based on /proc/partitions information.
871 # Needs /proc mounted.
872 # Can be called multiple times.
873 initrd_gen_devices() {
874 if is_yes "$proc_partitions"; then
881 : 'Making device nodes'
882 cat /proc/partitions | (
883 # ignore first two lines: header, empty line
886 while read major minor blocks dev rest; do
889 [ -e $node ] || mknod -m 660 $node b $major $minor
896 initrd_gen_setrootdev() {
897 verbose "Adding rootfs finding based on kernel cmdline root= option support."
899 debug "Current /proc/partitions:\n$(sed -e 's,^,| ,' /proc/partitions)"
901 if [ "${ROOT##/dev/}" != "${ROOT}" ]; then
902 rootnr="$(busybox awk -v rootnode="${ROOT##/dev/}" '$4 == rootnode { print 256 * $1 + $2 }' /proc/partitions)"
903 # fallback to ls, try two different formats
904 # http://lists.pld-linux.org/mailman/pipermail/pld-devel-en/2014-May/023915.html
905 if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
907 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $3 + $4; }}')"
909 if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
910 # busybox 1.22 and upwards
911 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $5 + $6; }}')"
913 if [ "${rootnr:-0}" -gt 0 ]; then
914 echo "$rootnr" > /proc/sys/kernel/real-root-dev
920 initrd_gen_initramfs_switchroot() {
922 if [ "$rootdev" = "/dev/nfs" ]; then
923 echo "rootfs on NFS root=/dev/nfs"
925 [ ! -e "$DESTDIR/$rootdev" ] && inst $rootdev $rootdev
928 # parse 'root=xxx' kernel commandline
929 # We support passing root as hda3 /dev/hda3 0303 0x0303 and 303
931 # from lilo-23.2/readme/README:
932 # root=<device> changes the root device. This overrides settings that may
933 # have been made in the boot image and on the LILO command line. <device> is
934 # either the hexadecimal device number or the full path name of the device,
937 # * The device names are hard-coded in the kernel. Therefore, only the
938 # "standard" names are supported and some less common devices may not be
939 # recognized. In those cases, only numbers can be used.
943 eval "$(busybox awk -v root="$ROOT" '
944 function h2d(str, hstr, res, num, n, digit, i) { # http://9fans.net/archive/2006/09/261
945 hstr = "0123456789abdcef"; res = 0;
946 n = split(tolower(str), digit, "");
948 for (i = 1; i <= n; i++) {
949 num = index(hstr, digit[i]) - 1;
950 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])+";
958 partition = ""; min = -1; maj = -1;
960 if (root ~ "^\/dev\/" dev_pattern "$" || root ~ "^" dev_pattern "$") { # see if we have /dev/hdX or hdX, we can just take partition name
961 partition = root; sub("^/dev/", "", partition);
962 } else { # unify values first
963 if (root ~ "^" num_pattern_short "$") { # change "303" => "0x0303"
965 } else if (root ~ "^" num_pattern "$") { # change "0303" => "0x0303"
968 maj = h2d(substr(root, 3, 2));
969 min = h2d(substr(root, 5, 2));
972 partition && $4 == partition { maj = $1; min = $2; }
973 $1 == maj && $2 == min { partition = $4; }
975 if (maj >= 0 && min >= 0) { printf("maj=%s; min=%s;\n", maj, min); }
976 if (partition) { printf("device=/dev/%s;\n", partition); }
977 }' /proc/partitions)"
979 if [ -z "$device" ]; then
980 if [ "$DEBUGINITRD" -a "$DEBUGINITRD" != 'sh' ]; then
986 if [ "$device" -a ! -b $device -a "$maj$min" ]; then
987 mknod -m 660 $device b $maj $min
990 # XXX hack, fallback to rootdev from geninitrd time
991 if [ ! -e "$device" ]; then
997 echo "DEVICE set to $device based on fstab entry from initrd gen time"
1000 # XXX hack, if no device, try to parse it from /proc/partitions using /proc/sys/kernel/real-root-dev
1001 if [ ! -e "$device" ]; then
1002 rrd=$(cat /proc/sys/kernel/real-root-dev)
1003 major=$(($rrd / 256))
1004 minor=$(($rrd % 256))
1006 while read pmajor pminor blocks dev rest; do
1007 # skip header and empty line
1008 [ -z "$pmajor" -o "$pmajor" = "major" ] && continue
1010 if [ $pmajor = $major -a $pminor = $minor ]; then
1012 echo "DEVICE set to $device based on real-root-dev"
1014 done < /proc/partitions
1017 [ -n "$ROOTFLAGS" ] && ROOTFLAGS="-o $ROOTFLAGS"
1019 mount -t $ROOTFS -r $device $ROOTFLAGS /newroot || echo "Mount of rootfs failed."
1021 if [ -z "$init" -o ! -x "/newroot$init" ]; then
1026 busybox_applet dmesg
1028 add_linuxrc <<-'EOF'
1029 if [ "$DEBUGINITRD" -a "$DEBUGINITRD" != 'sh' ]; then
1030 echo "Last 20 lines of dmesg:"
1036 kmsg "geninitrd/$VERSION switching root"
1039 busybox_applet switch_root usleep
1040 add_linuxrc <<-'EOF'
1041 [ ! -e /newroot/dev/console ] && mknod -m 660 /newroot/dev/console c 5 1
1043 # switch root to empty dir will make kernel panic, so sleep 10s before it
1044 # switch_root needs to be pid 1, so there's no other way to recover from here
1045 # if /dev is missing, switch root will likely fail, give debug shell before that
1046 if [ ! -d /newroot/dev ]; then
1047 echo "/dev is missing, switch_root will likely fail"
1048 echo "if you booted with debugrd=sh, then you be given shell and you might able to recover this situation"
1050 [ "$DEBUGINITRD" ] || usleep 10000000
1053 # systemd[1]: /usr appears to be on its own filesytem and is not
1054 # already mounted. This is not a supported setup. Some things will
1055 # probably break (sometimes even silently) in mysterious ways. Consult
1056 # http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken
1057 # for more information.
1058 echo trying to mount /usr
1059 chroot /newroot mount -n /usr
1061 exec switch_root /newroot $init ${1:+"$@"}
1063 # FIXME: this code is never executed, as "exec" does not return!
1065 echo "Error! initramfs should not reach this place."
1066 echo "It probably means you've got old version of busybox, with broken"
1067 echo "initramfs support. Trying to boot anyway, but won't promise anything."
1069 exec chroot /newroot $init ${1:+"$@"}
1071 echo "Failed to chroot!"
1074 # we need /init being real file, not symlink, otherwise the initramfs will
1075 # not be ran by pid 1 which is required for switch_root
1076 mv $DESTDIR/linuxrc $DESTDIR/init
1077 ln -s init $DESTDIR/linuxrc
1080 # find if $symbol exists in System.map $mapfile
1084 if [ ! -f $mapfile ]; then
1085 # missing mapfile (not a pld kernel?)
1089 awk -vc=1 -vsymbol="$symbol" '($2 == "T" || $2 == "t") && $3 == symbol {c = 0} END {exit c}' $mapfile
1092 # find best compressor (or forced one) for initrd
1095 local compressors='zstd xz lzma bzip2 gzip lzo'
1097 # a specified one, take it
1098 if ! is_yes "$mode"; then
1102 verbose "finding compressor: $compressors (via $mode)"
1103 # check for compressor validity
1104 local c prog map=/boot/System.map-$kernel
1105 for c in $compressors; do
1132 # any existing sym will work
1137 die "Unknown compressor $c"
1140 if sym_exists $map $sym && [ -x $prog ]; then
1146 verbose "using gzip for compressor (fallback)"
1150 # compresses kernel image image
1151 # in function so we could retry with other compressor on failure
1153 local compressor="$1" IMAGE="$2" target="$3" tmp
1154 tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1156 case "$compressor" in
1158 # don't use -9 here since kernel won't understand it
1159 xz --format=xz --check=crc32 --lzma2=preset=6e,dict=1MiB < "$IMAGE" > "$tmp" || return $?
1162 xz --format=lzma -9 < "$IMAGE" > "$tmp" || return $?
1165 bzip2 -9 < "$IMAGE" > "$tmp" || return $?
1168 gzip -9 < "$IMAGE" > "$tmp" || return $?
1171 lzop -9 < "$IMAGE" > "$tmp" || return $?
1174 zstd -9 < "$IMAGE" > "$tmp" || return $?
1177 cat < "$IMAGE" > "$tmp" || return $?
1181 mv -f "$tmp" "$target"
1184 if [ -r /etc/sysconfig/geninitrd ]; then
1185 . /etc/sysconfig/geninitrd
1188 if [ ! -f /proc/mounts ]; then
1189 warn "/proc filesystem not mounted, may cause wrong results or failure."
1192 geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev tuxonice suspend fbsplash condecor bootsplash uvesafb nfs sata scsi usbkbd bcache
1194 while [ $# -gt 0 ]; do
1204 modulefile=${1#--modules-conf=}
1213 --without-bootsplash)
1225 --without-fbcondecor)
1234 --with-suspend2 | --with-tuxonice)
1237 --without-suspend2 | --without-tuxonice)
1241 LVMTOOLSVERSION=${1#--lvmversion=}
1243 --lvmtoolsversion=*)
1244 LVMTOOLSVERSION=${1#--lvmtoolsversion=}
1246 --lvmtoolsversion|--lvmversion)
1259 --without-multipath)
1263 USE_MULTIPATH=${1#--with-multipath=}
1272 BASICMODULES="$BASICMODULES ${1#--with=}"
1275 BASICMODULES="$BASICMODULES $2"
1279 echo "$PROGRAM: version $VERSION"
1283 if [ x"$verbose" = x"-v" ]; then
1294 COMPRESS="${1#--compress=}"
1303 STRIP="${1#--strip=}"
1316 PREMODS="$PREMODS ${1#--preload=}"
1319 PREMODS="$PREMODS $2"
1323 die "--fs option is obsoleted. Use --initrdfs instead"
1326 INITRDFS=${1#--initrdfs=}
1339 if [ -z "$target" ]; then
1341 elif [ -z "$kernel" ]; then
1353 if [ -z "$target" -o -z "$kernel" ]; then
1359 if [ "$(id -u)" != 0 ]; then
1360 die "You need to be root to generate initrd"
1363 for dir in libx32 lib64 lib; do
1364 initrd_dir=/usr/$dir/initrd
1365 if [ -d "$initrd_dir" ]; then
1366 initrd_dirs="$initrd_dirs $initrd_dir"
1370 kernel_version=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d",$1,$2)}')
1371 kernel_version_long=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d%03d",$1,$2,$3)}')
1373 verbose "# geninitrd $VERSION"
1374 debug "Using initrd_dir: $initrd_dir"
1376 busybox=$(find_tool $initrd_dir/busybox $initrd_dir/initrd-busybox /bin/initrd-busybox) || die "Couldn't find busybox suitable for initrd"
1378 # we setup mods after parsing command line args
1379 geninitrd_setup_mods
1381 if [ ! -f /boot/vmlinuz-"$kernel" ]; then
1382 warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?"
1385 if [ -z "$INITRDFS" ]; then
1386 if [ -n "$FS" ]; then
1387 # FS= can came only via /etc/sysconfig/geninitrd likely?
1388 die "FS configuration option is obsoleted. Use INITRDFS instead"
1392 if [ "$kernel_version" -ge "002005" ]; then
1393 INITRDFS="initramfs"
1400 local s sfound sym p prog map=/boot/System.map-$kernel
1403 # TODO: symbols to check in case of ext2 used via ext3/4 subsystem
1416 sym=__initramfs_start
1417 prog="/bin/cpio /usr/bin/find"
1420 die "Filesystem $INITRDFS on initrd is not supported by geninitrd"
1424 # only one is needed (for cases like ext2 via ext2 or via ext3 or via ext4 subsysytem)
1427 sym_exists $map $s && sfound=1
1430 if [ "$sfound" -eq "0" ]; then
1431 die "Filesystem $INITRDFS on initrd is not supported by kernel"
1435 [ ! -x "$p" ] && die "$prog is missing"
1440 if [ -L "$target" ]; then
1441 target=$(readlink -f "$target")
1444 if [ -n "$img_vers" ]; then
1445 target="$target-$kernel"
1448 if [ -z "$force" -a -f "$target" ]; then
1449 die "$target already exists."
1452 if [ ! -d "/lib/modules/$kernel" ]; then
1453 die "/lib/modules/$kernel is not a directory."
1456 if [ "$kernel_version" -ge "002005" ]; then
1462 for n in $PREMODS; do
1466 if [ "$FBMODULE" ]; then
1467 find_module "$FBMODULE"
1470 # autodetect USB keyboards
1473 # allow forcing loading SCSI and/or IDE modules
1474 # XXX: where ADDSCSI cames from? drop?
1475 if is_yes "$ADDSCSI"; then
1479 # autodetect SATA modules
1482 # XXX: where ADDIDE cames from? drop?
1483 if is_yes "$ADDIDE"; then
1487 if is_yes "$USE_SUSPEND"; then
1488 find_modules_suspend
1491 find_root "$fstab" || exit
1492 verbose "Using $rootdev as device for rootfs"
1494 find_modules_for_devpath "$rootdev"
1496 # if USE_MULTIPATH is path to device, scan that too
1497 # this is to bootstrap multipath setup into initrd.
1498 if ! is_no "$USE_MULTIPATH" && ! is_yes "$USE_MULTIPATH"; then
1499 find_modules_multipath $USE_MULTIPATH
1502 find_module "-$rootFs"
1504 for n in $BASICMODULES; do
1508 if is_yes "$USE_TUXONICE"; then
1512 find_modules_uvesafb
1513 find_modules_fbsplash
1515 if [ -n "$ifneeded" -a -z "$MODULES" ]; then
1516 verbose "No modules are needed -- not building initrd image."
1520 verbose "Building initrd..."
1521 DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
1522 RCFILE="$DESTDIR/linuxrc"
1524 chmod a+rx "$RCFILE"
1525 ln -s linuxrc $DESTDIR/init
1527 # create dirs that we really need
1528 inst_d /{lib,bin,etc,dev{,/pts,/shm},loopfs,var,proc,run,sys}
1530 modules_install "$MODULES"
1532 # mknod'ing the devices instead of copying them works both with and
1534 mknod -m 600 "$DESTDIR/dev/console" c 5 1
1535 mknod -m 666 "$DESTDIR/dev/null" c 1 3
1536 mknod -m 666 "$DESTDIR/dev/zero" c 1 5
1537 mknod -m 666 "$DESTDIR/dev/random" c 1 8
1538 mknod -m 666 "$DESTDIR/dev/urandom" c 1 9
1539 mknod -m 644 "$DESTDIR/dev/kmsg" c 1 11
1541 inst_exec $busybox /bin/busybox
1542 ln -s busybox $DESTDIR/bin/sh
1543 # for older busyboxes who had /bin/initrd-busybox as EXEPATH
1544 ln -s busybox $DESTDIR/bin/initrd-busybox
1548 # initrd generated by geninitrd/$VERSION
1549 # on $(LC_ALL=C date)
1555 kmsg "geninitrd/$VERSION starting"
1558 # builtin defaults from geninitrd
1562 add_linuxrc <<-'EOF'
1563 read CMDLINE < /proc/cmdline
1565 for arg in $CMDLINE; do
1566 if [ "${arg}" = "debuginitrd" ] || [ "${arg}" = "debugrd" ]; then
1569 if [ "${arg##debuginitrd=}" != "${arg}" ] || [ "${arg##debugrd=}" != "${arg}" ]; then
1570 DEBUGINITRD=${arg##debug*rd=}
1572 if [ "${arg##root=}" != "${arg}" ]; then
1575 if [ "${arg##rootfs=}" != "${arg}" ]; then
1576 ROOTFS=${arg##rootfs=}
1578 if [ "${arg##rootflags=}" != "${arg}" ]; then
1579 ROOTFLAGS=${arg##rootflags=}
1581 if [ "${arg##rootfsflags=}" != "${arg}" ]; then
1582 ROOTFSFLAGS=${arg##rootfsflags=}
1584 if [ "${arg##init=}" != "${arg}" ]; then
1589 # handling of invalid, rootfsflags, option
1590 if [ -n "$ROOTFSFLAGS" ]; then
1591 if [ -n "$ROOTFLAGS" ]; then
1592 ROOTFLAGS="$ROOTFLAGS,$ROOTFSFLAGS"
1594 ROOTFLAGS="$ROOTFSFLAGS"
1598 if [ "$DEBUGINITRD" = "sh" ]; then
1599 # export some vars to subshell for debug to work
1600 export CMDLINE ROOT ROOTFS ROOTDEV ROOTFLAGS DEBUGINITRD INIT
1601 export LVM_ROOTVG LVM_SUSPENDVG LVM_VGVOLUMES
1602 export rootnr attrs majmin major minor device
1604 # make debugshell() invoke subshell if $DEBUGINITRD=sh
1607 if is_yes "$RUN_SULOGIN_ON_ERR"; then
1608 add_linuxrc <<-'EOF'
1609 echo "debug shell disabled by RUN_SULOGIN_ON_ERR=yes from /etc/sysconfig/system during initrd generation time"
1612 add_linuxrc <<-'EOF'
1616 add_linuxrc <<-'EOF'
1624 if [ "$DEBUGINITRD" ]; then
1629 modules_add_linuxrc $MODULES
1631 # TODO: rewrite for busybox
1632 #if [ -n "$loopDev" ]; then
1633 # if [ ! -d /initrd ]; then
1637 # cp -a "$loopDev" "$DESTDIR/dev"
1638 # cp -a "$rootdev" "$DESTDIR/dev"
1639 # echo "echo Mounting device containing loopback root filesystem" >> "$RCFILE"
1640 # echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE"
1641 # echo "echo Setting up loopback device $rootdev" >> $RCFILE
1642 # echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE"
1645 if is_yes "$USE_UDEV"; then
1654 initrd_gen_multipath
1657 if is_yes "$have_nfs"; then
1665 initrd_gen_setrootdev
1668 # additional devs always needed
1669 [ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev
1671 initrd_gen_stop_udevd
1672 initrd_gen_stop_mdev
1673 initrd_gen_stop_uvesafb
1675 # resume after killing local processes
1680 add_linuxrc <<-'EOF'
1681 if [ ! "$DEBUGINITRD" ]; then
1685 for i in $(export -p); do
1686 i=${i#declare -x } # ksh/bash
1687 i=${i#export } # busybox
1698 [ -z "$i" ] && continue
1701 ROOT|PATH|HOME|TERM)
1713 if [ "$INITRDFS" = "initramfs" ]; then
1714 initrd_gen_initramfs_switchroot
1720 initrd_gen_fbcondecor
1722 debug "Current /linuxrc:\n$(sed -e 's,^,| ,' $DESTDIR/linuxrc)"
1724 IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed"
1726 IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
1727 verbose "image size: $IMAGESIZE KiB ($DESTDIR)"
1729 verbose "Creating $INITRDFS image $IMAGE"
1732 dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null
1733 # NOTE: ext2 label is max 16 chars
1734 mke2fs -q -F -b 1024 -m 0 -L "PLD/$kernel" "$IMAGE" 2>/dev/null 1>&2
1735 tune2fs -i 0 "$IMAGE" >/dev/null 2>&1
1737 local tmpmnt=$(mktemp -d -t initrd.mnt-XXXXXX)
1738 debug "Mounting ext2 image $IMAGE to $tmpmnt"
1739 mount -o loop -t ext2 "$IMAGE" "$tmpmnt" || die "mount failed, check dmesg(1)"
1740 # We don't need this directory, so let's save space
1741 rm -rf "$tmpmnt"/lost+found
1743 debug "Copy recursively $DESTDIR -> $tmpmnt"
1744 cp -a $DESTDIR/* $tmpmnt
1750 genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD Linux/$kernel (geninitrd/$VERSION)"
1753 mkcramfs "$DESTDIR" "$IMAGE"
1756 (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
1759 die "Filesystem $INITRDFS not supported by $PROGRAM"
1762 CONFIG_BLK_DEV_RAM_SIZE=$(ikconfig | awk -F= '/^CONFIG_BLK_DEV_RAM_SIZE/{print $2}')
1763 if [ -z "$CONFIG_BLK_DEV_RAM_SIZE" ]; then
1764 CONFIG_BLK_DEV_RAM_SIZE=4096
1765 warn "No CONFIG_BLK_DEV_RAM_SIZE detected, fallback to $CONFIG_BLK_DEV_RAM_SIZE"
1768 if [ "$IMAGESIZE" -gt $CONFIG_BLK_DEV_RAM_SIZE ]; then
1769 warn "Your image size is larger than $CONFIG_BLK_DEV_RAM_SIZE, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!"
1772 if ! is_no "$COMPRESS"; then
1773 compressor=$(find_compressor "$COMPRESS")
1774 verbose "Compressing $target with $compressor"
1776 # TODO: the image name (specified from kernel.spec) already contains
1777 # extension, which is .gz most of the time.
1778 compress_image "$compressor" "$IMAGE" "$target" || {
1779 if [ $compressor != gzip ]; then
1780 warn "Could not compress with $compressor, retrying with gzip"
1781 compress_image gzip "$IMAGE" "$target" || die "compress failed with gzip" $?
1783 die "Could not compress image with $compressor"
1787 cp -a "$IMAGE" "$target"
1790 # XXX. check if bootsplash can output data to tmp dir not directly to initramfs image.
1791 initrd_gen_bootsplash "$target"
1793 rm -rf "$DESTDIR" "$IMAGE"
1795 # vim:ts=4:sw=4:noet:fdm=marker