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
31 # device node for rootfs from fstab
41 # is /tmp mounted on tmpfs
44 # are /dev nodes already created from /proc/devices info?
48 echo "Usage: $PROGRAM [--version] [-v] [-f] [--ifneeded] [--preload <module>]"
49 echo " [--with=<module>] [--image-version] [--fstab=<fstab>] [--nocompress]"
50 echo " [--compress=yes|zstd|xz|lzma|bzip2|gzip|lzo]"
51 echo " [--nostrip ] [--strip PATH/strip] [--strip=PATH/strip]"
52 echo " [--initrdfs=rom|initramfs|ext2|cram] [--modules-conf=<modules.conf>]"
53 echo " [--with-bootsplash] [--without-bootsplash]"
54 echo " [--with-fbsplash] [--without-fbsplash]"
55 echo " [--with-fbcondecor] [--without-fbcondecor]"
56 echo " [--lvmtoolsversion=1|2] [--with-udev] [--without-udev]"
57 echo " [--with-suspend] [--without-suspend]"
58 echo " [--with-tuxonice] [--without-tuxonice]"
59 echo " [--without-dmraid]"
60 echo " [--with-multipath=DEVPATH] [--without-multipath]"
61 echo " [--without-blkid] [--without-luks]"
62 echo " <initrd-image> <kernel-version>"
66 local kdir kver dir=${target:-/boot}
67 for kdir in /lib/modules/*; do
68 [ -d $kdir ] || continue
70 echo " $0 -f --initrdfs=initramfs $dir/initrd-$kver.gz $kver $verbose"
83 [ -n "$verbose" ] && msg "$*" >&3
87 [ x"$verbose" = x"-v -v" ] && msg "$*" >&3
90 # add initrd code to print to kmsg
91 # @param string message
92 # @param int loglevel. defaults to "6" (info)
95 # KERN_EMERG "0" Emergency messages, system is about to crash or is unstable
96 # KERN_ALERT "1" Something bad happened and action must be taken immediately
97 # KERN_CRIT "2" A critical condition occurred like a serious hardware/software failure
98 # KERN_ERR "3" An error condition, often used by drivers to indicate difficulties with the hardware
99 # KERN_WARNING "4" A warning, meaning nothing serious by itself but might indicate problems
100 # KERN_NOTICE "5" Nothing serious, but notably nevertheless. Often used to report security events.
101 # KERN_INFO "6" Informational message e.g. startup information at driver initialization
102 # KERN_DEBUG "7" Debug messages
103 # KERN_CONT "c" "continued" line of log printout (only done after a line that had no enclosing \n)
105 local msg="$1" level=${2:-6}
106 echo "echo '<$level>$msg' > /dev/kmsg" | add_linuxrc
109 # aborts program abnormally
116 # find program from specified paths
119 local paths="$initrd_dirs /bin /sbin /usr/bin /usr/sbin"
121 debug "find_tool: checking $x"
124 verbose "find_tool: found $x"
130 debug "find_tool: checking $p/$b"
131 if [ -x "$p/$b" ]; then
133 verbose "find_tool: found $p/$b"
139 debug "find_tool: did not find any of: $n"
143 # loads geninitrd modules
144 geninitrd_load_mods() {
147 if [ ! -f /lib/geninitrd/mod-$mod.sh ]; then
148 die "$mod geninitrd module can't be loaded"
150 . /lib/geninitrd/mod-$mod.sh
152 GENINITRD_MODS="$GENINITRD_MODS $mod"
156 # setup geninitrd modules
157 geninitrd_setup_mods() {
160 for mod in $GENINITRD_MODS; do
163 # some mods want init
164 if type setup_mod_$mod > /dev/null; then
170 # append text to /linuxrc
171 # takes STDIN as input
176 # generate code to mount /dev on tmpfs and create initial nodes
177 # can be called multiple times. /dev is cleaned up (umounted) automatically at
180 # we already generated tmpfs code; return
181 if is_yes "$dev_mounted"; then
187 busybox_applet mount mknod mkdir
190 if ! mount -t devtmpfs -o mode=0755,nosuid devtmpfs /dev > /dev/null 2>&1; then
191 mount -o mode=0755,nosuid -t tmpfs tmpfs /dev
192 mknod -m 600 /dev/console c 5 1
193 mknod -m 666 /dev/null c 1 3
194 mknod -m 666 /dev/zero c 1 5
195 mknod -m 666 /dev/random c 1 8
196 mknod -m 600 /dev/snapshot c 10 231
197 mknod -m 666 /dev/urandom c 1 9
198 mknod -m 666 /dev/ptmx c 5 2
199 mknod -m 644 /dev/kmsg c 1 11
209 [ ! -r /etc/sysconfig/console ] && return
210 . /etc/sysconfig/console
211 if [ -n "$CONSOLEFONT" ]; then
212 font=$(ls -1 /lib/kbd/consolefonts/${CONSOLEFONT}*.gz 2> /dev/null)
213 if [ -n "$font" ]; then
214 verbose "Loading font $font"
215 busybox_applet loadfont
216 inst_d "/lib/kbd/consolefonts"
217 cp -a "$font" "$DESTDIR/lib/kbd/consolefonts/"
218 gunzip ${DESTDIR}/lib/kbd/consolefonts/${CONSOLEFONT}*.gz
220 echo "loadfont < $font" | add_linuxrc
225 # generate code to mount /proc on initrd
226 # can be called multiple times
228 if is_yes "$proc_mounted"; then
233 if [ "$INITRDFS" = "initramfs" ]; then
234 # /proc is mounted with initramfs 2.6.22.14 kernel
235 # XXX: remove when it is clear why proc was already mounted
236 echo "[ -f /proc/cmdline ] || mount -t proc none /proc" | add_linuxrc
238 echo "mount -t proc none /proc" | add_linuxrc
242 # generate code to mount /sys on initrd
243 # can be called multiple times
245 if is_yes "$sys_mounted"; then
250 echo "mount -t sysfs none /sys" | add_linuxrc
253 # generate code to mount /tmp on initrd
254 # can be called multiple times
256 if [ "$INITRDFS" = "initramfs" ]; then
257 # initramfs is read-write filesystem, no need for tmpfs
261 if is_yes "$tmp_mounted"; then
266 echo "mount -t tmpfs none /tmp" | add_linuxrc
269 # generate code to mount /run on initrd
270 # can be called multiple times
272 if is_yes "$run_mounted"; then
277 echo "mount -t tmpfs run /run -o mode=0755,noexec,nosuid,nodev" | add_linuxrc
280 # unmount all mountpoints mounted by geninitrd
281 # try to move pseudo filesystems to newroot if possible
285 : Last shell before umounting all and giving control over to real init.
289 if is_yes "$run_mounted"; then
291 mount --bind /run /newroot/run
296 if is_yes "$dev_mounted"; then
298 mount --bind /dev /newroot/dev
303 if is_yes "$sys_mounted"; then
305 mount --bind /sys /newroot/sys
310 if is_yes "$proc_mounted"; then
312 mount --bind /proc /newroot/proc
317 if is_yes "$tmp_mounted"; then
318 echo 'umount /tmp' | add_linuxrc
323 # Checks if busybox has support for APPLET(s)
324 # Exits from geninitrd if the support is not present.
326 # NB! XXX do not output to STDOUT, it will appear in initrd images in some cases!
330 if [ -z "$busybox_functions" ]; then
331 local tmp=$($busybox 2>&1)
333 # BusyBox v1.1.3 says applet not found if it's not called 'busybox'.
334 if [[ "$tmp" = *applet\ not\ found* ]]; then
336 ln -s $busybox $t/busybox
337 local tmp=$($t/busybox 2>&1)
341 busybox_functions=$(echo "$tmp" | \
342 sed -ne '/Currently defined functions:/,$p' | \
343 xargs | sed -e 's,.*Currently defined functions: ,,'
349 eval have='$'busybox_have_$applet
350 if [ -z "$have" ]; then
351 have=$(echo "$busybox_functions" | grep -Ec "( |^)$applet(,|$)")
352 if [ "$have" = 0 ]; then
353 warn "This setup requires busybox-initrd compiled with applet '$applet' support"
356 eval busybox_have_$applet=$have
359 if [ $err = 1 ]; then
364 # Extract the .config file from a kernel image
365 # uses extract-ikconfig from kernel sources (scripts/extract-ikconfig)
367 local kofile=$(modinfo -k $kernel -n configs 2> /dev/null)
368 if [ -n "$kofile" ]; then
369 /lib/geninitrd/extract-ikconfig $kofile
373 # see if config available as separate file
374 if [ -f /boot/config-$kernel ]; then
375 cat /boot/config-$kernel
379 # finally try vmlinuz itself
380 /lib/geninitrd/extract-ikconfig /boot/vmlinuz-$kernel
388 module=${module%$modext*}
392 # Finds module dependencies
396 # Outputs full path to module and it's dependencies
401 # if module is prefixed with dash, we should ignore errors if the module
403 if [ ${module#-} != $module ]; then
408 # This works when user has module-init-tools installed even on 2.4 kernels
410 modprobe=$(modprobe --set-version $kernel --show-depends $module --ignore-install 2>&1)
413 if [ $skiperrors = 1 ]; then
418 if ! is_no "$EXIT_IF_MISSING"; then
419 die "$module: module not found for $kernel kernel"
422 warn "$module: module not found for $kernel kernel"
423 warn "If $module isn't compiled in kernel then this initrd may not start your system."
429 while read insmod modpath options; do
430 if [ "$insmod" = "insmod" ]; then
432 # XXX: find a away to autodetect
433 smodule=$(basename_module $modpath)
436 warn "mounting multidevice btrfs volume requires rootfsflags=device=/dev/...,device=/dev/... kernel option"
437 find_depmod "-libcrc32c"
440 find_depmod "-libcrc32c"
443 find_depmod "-crct10dif-pclmul"
444 find_depmod "-crct10dif"
447 find_depmod "-crc32c-intel"
448 find_depmod "-crc32c"
450 virtio_blk|virtio_scsi)
451 find_depmod "-virtio_pci"
452 find_depmod "-virtio_mmio"
465 # no firmware support in 2.4 kernels
466 if [ "$kernel_version_long" -lt "002005048" ]; then
469 echo -n $(NEW_MODINFO=1 modinfo -k $kernel -F firmware $module 2>/dev/null | xargs)
474 local mod depmod module=$1
476 depmod=$(find_depmod $module) || exit 1
477 for mod in $depmod; do
478 mod=${mod#/lib/modules/$kernel/}
480 # add each module only once
482 for m in $MODULES; do
483 [ $m = $mod ] && have=1
485 if [ $have = 0 ]; then
486 MODULES="$MODULES $mod"
491 # install a file to temporary mount image.
492 # it will operate recursively (copying directories)
493 # and will symlink destinations if source is symlink.
495 if [ $# -lt 2 ]; then
496 die 'Usage: inst <file> [<file>] <destination>'
499 local src i=0 c=$(($# - 1))
500 while [ $i -lt $c ]; do
507 local parentDir=$(dirname $DESTDIR$dest)
508 if [ ! -d "$parentDir" ]; then
509 verbose "+ mkdir -p DESTDIR${parentDir#$DESTDIR}"
512 verbose "+ cp $* DESTDIR$dest"
513 cp -HRp "$@" "$DESTDIR$dest"
518 die 'Usage: inst_d <destination> <destination>'
522 install -d "$DESTDIR$dir"
526 # install executable and it's shared libraries
528 if [ $# -lt 2 ]; then
529 die "Invalid params ($@), Usage: inst_exec <file>[, <file>] <destination>"
531 local src i=0 c=$(($# - 1))
532 while [ $i -lt $c ]; do
542 local obj lib libs libs_additional libdir
545 /lib/ld-linux.so.2 | /lib64/ld-linux-x86-64.so.2 | /libx32/ld-linux-x32.so.2)
548 /lib/libpthread.so* | /lib64/libpthread.so* | /libx32/libpthread.so*)
549 libs_additional="${obj%/libpthread*}/libgcc_s.so.1"
554 libs=$(ldd "$obj" | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
555 for lib in $libs $libs_additional; do
556 libdir=$(cd $(dirname "$lib"); pwd)
557 if [ ! -f "$DESTDIR/$lib" ]; then
559 inst_exec $lib $libdir
564 # hack for uclibc linked binaries requiring this fixed path
565 # XXX: shouldn't rpath be used here instead so th
566 for _lib in $(get_libdir LIBDIR); do
567 if [ -f $DESTDIR/$_lib/libc.so.0 ]; then
568 lib=$DESTDIR/$_lib/libc.so.0
569 lib=$(ldd "$lib" | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
570 libdir=$(cd $(dirname "$lib"); pwd)
571 if [ ! -e $DESTDIR$libdir ]; then
572 libdir=$(dirname "$libdir")
574 verbose "+ ln -s /$_lib $DESTDIR$libdir"
575 ln -s /$_lib $DESTDIR$libdir
582 # output modules.conf / modprobe.conf
584 echo "$modprobe_conf_cache"
587 # return options for MODULE
588 # @param $1 module name
591 local options=$(modprobe_conf | awk -vmodule="$module" '{ if ($1 == "options" && $2 == module) { for(i=3;i<=NF;i++) printf("%s ",$i); }}')
596 # defaults to modprobe -c if not told otherwise, this means include statements
598 cache_modprobe_conf() {
599 if [ "$kernel_version" -lt "002005" ]; then
600 modulefile=/etc/modules.conf
601 if [ ! -f "$modulefile" -a -f /etc/conf.modules ]; then
602 modulefile=/etc/conf.modules
606 if [ -n "$modulefile" ]; then
607 debug "Using $modulefile for modules config"
608 modprobe_conf_cache=$(cat $modulefile | awk '!/^[\t ]*#/ { print }')
611 debug "Using modprobe -c to get modules config"
612 modprobe_conf_cache=$(modprobe -c --set-version $kernel | awk '!/^[\t ]*#/ { print }')
616 # find modules for $devpath
617 find_modules_for_devpath() {
619 if [ -z "$devpath" ]; then
620 die "No argument passed to find_modules_for_devpath() - is your /etc/fstab correct?"
623 if [[ "$devpath" = /dev/dm-* ]]; then
624 # /dev/dm-3 -> /dev/mapper/sil_ahbgadcbchfc3
625 devpath=$(dm_node "$devpath")
628 if [ -L "$devpath" ] && ! is_lvm "$devpath" && ! is_luks "$devpath"; then
629 # sanitize things like:
630 # /dev/block/104:2 -> /dev/cciss/c0d0p2
631 devpath=$(readlink -f "$devpath")
634 verbose "Finding modules for device path $devpath"
636 if is_luks "$devpath"; then
637 find_modules_luks "$devpath"
641 if is_nfs "$devpath"; then
642 find_modules_nfs "$devpath"
646 if is_md "$devpath"; then
647 find_modules_md "$devpath"
651 if is_multipath "$devpath"; then
652 if find_modules_multipath "$devpath"; then
659 if is_dmraid "$devpath"; then
660 if find_modules_dmraid "$devpath"; then
666 if is_scsi "$devpath"; then
667 find_modules_scsi "$devpath"
671 if is_ide "$devpath"; then
672 find_modules_ide "$devpath"
676 if [[ "$devpath" == /dev/nvme* ]]; then
681 if [[ "$devpath" == /dev/bcache* ]]; then
682 find_modules_bcache "$devpath"
686 if [[ "$devpath" == /dev/rd/* ]]; then
692 if [[ "$devpath" == /dev/ida/* ]]; then
693 find_module "cpqarray"
694 rootdev_add=/dev/ida/
698 if [[ "$devpath" == /dev/cciss/* ]]; then
699 rootdev_add=/dev/cciss/
701 # load hpsa for future kernels, cciss for backwards compat
702 if [ "$kernel_version_long" -ge "003000000" ]; then
703 find_module "hpsa" "-cciss"
704 find_modules_scsi "$devpath"
712 if [[ "$devpath" == /dev/ataraid/* ]]; then
714 find_module "ataraid"
715 ataraidmodules=$(modprobe_conf | awk '/ataraid_hostadapter/ { print $3 }')
716 if [ -n "$ataraidmodules" ]; then
717 # FIXME: think about modules compiled in kernel
718 die "ataraid_hostadapter alias not defined in modprobe.conf! Please set it and run $PROGRAM again."
720 for n in $ataraidmodules; do
723 rootdev_add=/dev/ataraid/
727 # check to see if we need to set up a loopback filesystem
728 if [[ "$devpath" == /dev/loop* ]]; then
729 die "Sorry, root on loop device isn't supported."
730 # TODO: rewrite for bsp and make nfs ready
731 if [ ! -x /sbin/losetup ]; then
732 die "losetup is missing"
734 key="^# $(echo $devpath | awk -F/ '{print($3);}' | tr '[a-z]' '[A-Z]'):"
735 if ! is_yes "`awk '/'$key'/ { print( "yes"); }' $fstab`"; then
736 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"
739 line="`awk '/'$key'/ { print $0; }' $fstab`"
740 loopDev="$(echo $line | awk '{print $3}')"
741 loopFs="$(echo $line | awk '{print $4}')"
742 loopFile="$(echo $line | awk '{print $5}')"
744 BASICMODULES="$BASICMODULES -loop"
745 find_module "-$loopFs"
746 BASICMODULES="$BASICMODULES -${loopFs}"
750 if is_lvm "$devpath"; then
751 find_modules_lvm "$devpath"
756 firmware_install_module() {
758 local firmware_files="$2"
760 verbose "Adding Firmwares ($firmware_files) to initrd for module $module"
761 # firmware not yet installed
762 if [ ! -f "$DESTDIR/lib/firmware/firmware.sh" ]; then
764 cat << 'EOF' >> "$DESTDIR/lib/firmware/firmware.sh"
766 # handle only firmware add requests
767 if [ "$SUBSYSTEM" != "firmware" ]; then
770 if [ "$ACTION" != "add" ]; then
773 echo 1 > /sys$DEVPATH/loading
774 cat "/lib/firmware/$FIRMWARE" > /sys$DEVPATH/data
775 echo 0 > /sys$DEVPATH/loading
778 chmod 755 "$DESTDIR/lib/firmware/firmware.sh"
780 # setup firmware loader agent
781 echo "echo -n "/lib/firmware/firmware.sh" > /proc/sys/kernel/hotplug" | add_linuxrc
784 for firmware in $firmware_files; do
785 if [ -f "/lib/firmware/$kernel/$firmware" ]; then
786 FIRMWAREDIR=${firmware%/*}
787 [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
788 inst /lib/firmware/$kernel/$firmware /lib/firmware/$firmware
789 elif [ -f "/lib/firmware/$firmware" ]; then
790 FIRMWAREDIR=${firmware%/*}
791 [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
792 inst /lib/firmware/$firmware /lib/firmware/$firmware
794 warn "Possible missing firmware file /lib/firmware/$firmware or /lib/firmware/$kernel/$firmware for module $module."
805 for mod in $modules; do
807 inst_d "/lib/modules/$kernel/$MODULEDIR"
808 cp -a "/lib/modules/$kernel/$mod" "$DESTDIR/lib/modules/$kernel/$mod"
811 gunzip "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress gz"
815 xz -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress xz"
819 bzip2 -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress bz2"
823 if [ "$STRIP" ] && [ -x "$STRIP" ]; then
824 $STRIP -g --remove-section=.comment "$DESTDIR/lib/modules/$kernel/${mod}"
829 modules_add_linuxrc() {
833 # module path without optional compression
835 modpath=${modpath%.xz}
836 modpath=${modpath%.bz2}
839 local module=${modpath##*/}; module=${module%$modext}
840 local options=$(modprobe_options "$module")
841 local genericname=$(echo $module | tr - _)
842 local usleep=$(eval echo \$MODULE_${genericname}_USLEEP)
843 local firmware=$(eval echo \$MODULE_${genericname}_FIRMWARE)
845 if [ "$module" = "scsi_mod" -a "$kernel_version_long" -ge "002006030" ]; then
846 options="scan=sync $options"
849 if [ x"$verbose" = x"-v" ]; then
851 if [ "$options" ]; then
852 s="$s with options [$options]"
854 if [ "$usleep" ]; then
855 s="$s and $usleep usleep"
857 verbose "Loading module [$module]$s"
860 if [ -n "$firmware" ]; then
861 firmware_install_module "$module" "$firmware"
863 for file in $(find_firmware "$module"); do
864 firmware_install_module "$module" "$file"
868 echo "insmod /lib/modules/$kernel/$modpath $options" | add_linuxrc
869 if [ -n "$usleep" ]; then
870 echo "usleep $usleep" | add_linuxrc
872 if [ "$module" = "scsi_wait_scan" ]; then
873 if [ "$(busybox_applet rmmod 2>/dev/null; echo $?)" = 0 ]; then
874 echo "rmmod scsi_wait_scan" | add_linuxrc
881 # Generates /dev nodes based on /proc/partitions information.
882 # Needs /proc mounted.
883 # Can be called multiple times.
884 initrd_gen_devices() {
885 if is_yes "$proc_partitions"; then
892 : 'Making device nodes'
893 cat /proc/partitions | (
894 # ignore first two lines: header, empty line
897 while read major minor blocks dev rest; do
900 [ -e $node ] || mknod -m 660 $node b $major $minor
907 initrd_gen_setrootdev() {
908 verbose "Adding rootfs finding based on kernel cmdline root= option support."
910 debug "Current /proc/partitions:\n$(sed -e 's,^,| ,' /proc/partitions)"
912 if [ "${ROOT##/dev/}" != "${ROOT}" ]; then
913 rootnr="$(busybox awk -v rootnode="${ROOT##/dev/}" '$4 == rootnode { print 256 * $1 + $2 }' /proc/partitions)"
914 # fallback to ls, try two different formats
915 # http://lists.pld-linux.org/mailman/pipermail/pld-devel-en/2014-May/023915.html
916 if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
918 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $3 + $4; }}')"
920 if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
921 # busybox 1.22 and upwards
922 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $5 + $6; }}')"
924 if [ "${rootnr:-0}" -gt 0 ]; then
925 echo "$rootnr" > /proc/sys/kernel/real-root-dev
931 initrd_gen_initramfs_switchroot() {
933 if [ "$rootdev" = "/dev/nfs" ]; then
934 echo "rootfs on NFS root=/dev/nfs"
936 [ ! -e "$DESTDIR/$rootdev" ] && inst $rootdev $rootdev
939 # parse 'root=xxx' kernel commandline
940 # We support passing root as hda3 /dev/hda3 0303 0x0303 and 303
942 # from lilo-23.2/readme/README:
943 # root=<device> changes the root device. This overrides settings that may
944 # have been made in the boot image and on the LILO command line. <device> is
945 # either the hexadecimal device number or the full path name of the device,
948 # * The device names are hard-coded in the kernel. Therefore, only the
949 # "standard" names are supported and some less common devices may not be
950 # recognized. In those cases, only numbers can be used.
954 eval "$(busybox awk -v root="$ROOT" '
955 function h2d(str, hstr, res, num, n, digit, i) { # http://9fans.net/archive/2006/09/261
956 hstr = "0123456789abdcef"; res = 0;
957 n = split(tolower(str), digit, "");
959 for (i = 1; i <= n; i++) {
960 num = index(hstr, digit[i]) - 1;
961 res = res + (num * 16 ^ (n - i));
966 num_pattern_short = "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]";
967 num_pattern = "[0-9a-fA-F]" num_pattern_short;
968 dev_pattern = "[hms][a-z][a-z]([0-9])+";
969 partition = ""; min = -1; maj = -1;
971 if (root ~ "^\/dev\/" dev_pattern "$" || root ~ "^" dev_pattern "$") { # see if we have /dev/hdX or hdX, we can just take partition name
972 partition = root; sub("^/dev/", "", partition);
973 } else { # unify values first
974 if (root ~ "^" num_pattern_short "$") { # change "303" => "0x0303"
976 } else if (root ~ "^" num_pattern "$") { # change "0303" => "0x0303"
979 maj = h2d(substr(root, 3, 2));
980 min = h2d(substr(root, 5, 2));
983 partition && $4 == partition { maj = $1; min = $2; }
984 $1 == maj && $2 == min { partition = $4; }
986 if (maj >= 0 && min >= 0) { printf("maj=%s; min=%s;\n", maj, min); }
987 if (partition) { printf("device=/dev/%s;\n", partition); }
988 }' /proc/partitions)"
990 if [ -z "$device" ]; then
991 if [ "$DEBUGINITRD" -a "$DEBUGINITRD" != 'sh' ]; then
997 if [ "$device" -a ! -b $device -a "$maj$min" ]; then
998 mknod -m 660 $device b $maj $min
1001 # XXX hack, fallback to rootdev from geninitrd time
1002 if [ ! -e "$device" ]; then
1007 add_linuxrc <<-'EOF'
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" -a "$DEBUGINITRD" != 'sh' ]; 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" || $2 == "t") && $3 == symbol {c = 0} END {exit c}' $mapfile
1103 # find best compressor (or forced one) for initrd
1106 local compressors='zstd xz lzma bzip2 gzip lzo'
1108 # a specified one, take it
1109 if ! is_yes "$mode"; then
1113 verbose "finding compressor: $compressors (via $mode)"
1114 # check for compressor validity
1115 local c prog map=/boot/System.map-$kernel
1116 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 zstd -9 < "$IMAGE" > "$tmp" || return $?
1188 cat < "$IMAGE" > "$tmp" || return $?
1192 mv -f "$tmp" "$target"
1195 # prepend file to image
1196 prepend_file_to_image() {
1197 local file="$1" target="$2" tmp
1198 tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1200 cat "$file" "$target" > "$tmp" || return $?
1202 mv -f "$tmp" "$target"
1205 if [ -r /etc/sysconfig/geninitrd ]; then
1206 . /etc/sysconfig/geninitrd
1209 if [ ! -f /proc/mounts ]; then
1210 warn "/proc filesystem not mounted, may cause wrong results or failure."
1213 geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev tuxonice suspend fbsplash condecor bootsplash uvesafb nfs sata scsi usbkbd bcache
1215 while [ $# -gt 0 ]; do
1225 modulefile=${1#--modules-conf=}
1234 --without-bootsplash)
1246 --without-fbcondecor)
1255 --with-suspend2 | --with-tuxonice)
1258 --without-suspend2 | --without-tuxonice)
1262 LVMTOOLSVERSION=${1#--lvmversion=}
1264 --lvmtoolsversion=*)
1265 LVMTOOLSVERSION=${1#--lvmtoolsversion=}
1267 --lvmtoolsversion|--lvmversion)
1280 --without-multipath)
1284 USE_MULTIPATH=${1#--with-multipath=}
1293 BASICMODULES="$BASICMODULES ${1#--with=}"
1296 BASICMODULES="$BASICMODULES $2"
1300 echo "$PROGRAM: version $VERSION"
1304 if [ x"$verbose" = x"-v" ]; then
1315 COMPRESS="${1#--compress=}"
1324 STRIP="${1#--strip=}"
1337 PREMODS="$PREMODS ${1#--preload=}"
1340 PREMODS="$PREMODS $2"
1344 die "--fs option is obsoleted. Use --initrdfs instead"
1347 INITRDFS=${1#--initrdfs=}
1360 if [ -z "$target" ]; then
1362 elif [ -z "$kernel" ]; then
1374 if [ -z "$target" -o -z "$kernel" ]; then
1380 if [ "$(id -u)" != 0 ]; then
1381 die "You need to be root to generate initrd"
1384 for dir in libx32 lib64 lib; do
1385 initrd_dir=/usr/$dir/initrd
1386 if [ -d "$initrd_dir" ]; then
1387 initrd_dirs="$initrd_dirs $initrd_dir"
1391 kernel_version=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d",$1,$2)}')
1392 kernel_version_long=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d%03d",$1,$2,$3)}')
1394 verbose "# geninitrd $VERSION"
1395 debug "Using initrd_dir: $initrd_dir"
1397 busybox=$(find_tool $initrd_dir/busybox $initrd_dir/initrd-busybox /bin/initrd-busybox) || die "Couldn't find busybox suitable for initrd"
1399 # we setup mods after parsing command line args
1400 geninitrd_setup_mods
1402 if [ ! -f /boot/vmlinuz-"$kernel" ]; then
1403 warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?"
1406 if [ -z "$INITRDFS" ]; then
1407 if [ -n "$FS" ]; then
1408 # FS= can came only via /etc/sysconfig/geninitrd likely?
1409 die "FS configuration option is obsoleted. Use INITRDFS instead"
1413 if [ "$kernel_version" -ge "002005" ]; then
1414 INITRDFS="initramfs"
1421 local s sfound sym p prog map=/boot/System.map-$kernel
1424 # TODO: symbols to check in case of ext2 used via ext3/4 subsystem
1437 sym=__initramfs_start
1438 prog="/bin/cpio /usr/bin/find"
1441 die "Filesystem $INITRDFS on initrd is not supported by geninitrd"
1445 # only one is needed (for cases like ext2 via ext2 or via ext3 or via ext4 subsysytem)
1448 sym_exists $map $s && sfound=1
1451 if [ "$sfound" -eq "0" ]; then
1452 die "Filesystem $INITRDFS on initrd is not supported by kernel"
1456 [ ! -x "$p" ] && die "$prog is missing"
1461 if [ -L "$target" ]; then
1462 target=$(readlink -f "$target")
1465 if [ -n "$img_vers" ]; then
1466 target="$target-$kernel"
1469 if [ -z "$force" -a -f "$target" ]; then
1470 die "$target already exists."
1473 if [ ! -d "/lib/modules/$kernel" ]; then
1474 die "/lib/modules/$kernel is not a directory."
1477 if [ "$kernel_version" -ge "002005" ]; then
1483 for n in $PREMODS; do
1487 if [ "$FBMODULE" ]; then
1488 find_module "$FBMODULE"
1491 # autodetect USB keyboards
1494 # allow forcing loading SCSI and/or IDE modules
1495 # XXX: where ADDSCSI cames from? drop?
1496 if is_yes "$ADDSCSI"; then
1500 # autodetect SATA modules
1503 # XXX: where ADDIDE cames from? drop?
1504 if is_yes "$ADDIDE"; then
1508 if is_yes "$USE_SUSPEND"; then
1509 find_modules_suspend
1512 find_root "$fstab" || exit
1513 verbose "Using $rootdev as device for rootfs"
1515 find_modules_for_devpath "$rootdev"
1517 # if USE_MULTIPATH is path to device, scan that too
1518 # this is to bootstrap multipath setup into initrd.
1519 if ! is_no "$USE_MULTIPATH" && ! is_yes "$USE_MULTIPATH"; then
1520 find_modules_multipath $USE_MULTIPATH
1523 find_module "-$rootFs"
1525 for n in $BASICMODULES; do
1529 if is_yes "$USE_TUXONICE"; then
1533 find_modules_uvesafb
1534 find_modules_fbsplash
1536 if [ -n "$ifneeded" -a -z "$MODULES" ]; then
1537 verbose "No modules are needed -- not building initrd image."
1541 verbose "Building initrd..."
1542 DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
1543 RCFILE="$DESTDIR/linuxrc"
1545 chmod a+rx "$RCFILE"
1546 ln -s linuxrc $DESTDIR/init
1548 # create dirs that we really need
1549 inst_d /{lib,bin,sbin,etc,dev{,/pts,/shm},loopfs,var,proc,run,sys,tmp}
1551 modules_install "$MODULES"
1553 # mknod'ing the devices instead of copying them works both with and
1555 mknod -m 600 "$DESTDIR/dev/console" c 5 1
1556 mknod -m 666 "$DESTDIR/dev/null" c 1 3
1557 mknod -m 666 "$DESTDIR/dev/zero" c 1 5
1558 mknod -m 666 "$DESTDIR/dev/random" c 1 8
1559 mknod -m 666 "$DESTDIR/dev/urandom" c 1 9
1560 mknod -m 644 "$DESTDIR/dev/kmsg" c 1 11
1562 inst_exec $busybox /bin/busybox
1563 ln -s busybox $DESTDIR/bin/sh
1564 # for older busyboxes who had /bin/initrd-busybox as EXEPATH
1565 ln -s busybox $DESTDIR/bin/initrd-busybox
1569 # initrd generated by geninitrd/$VERSION
1570 # on $(LC_ALL=C date)
1576 kmsg "geninitrd/$VERSION starting"
1578 inst_d /lib/geninitrd/
1579 inst /lib/geninitrd/functions.initrd /lib/geninitrd/functions.initrd
1582 . /lib/geninitrd/functions.initrd
1583 # builtin defaults from geninitrd
1587 add_linuxrc <<-'EOF'
1588 read CMDLINE < /proc/cmdline
1590 for arg in $CMDLINE; do
1591 if [ "${arg}" = "debuginitrd" ] || [ "${arg}" = "debugrd" ]; then
1594 if [ "${arg##debuginitrd=}" != "${arg}" ] || [ "${arg##debugrd=}" != "${arg}" ]; then
1595 DEBUGINITRD=${arg##debug*rd=}
1597 if [ "${arg##root=}" != "${arg}" ]; then
1600 if [ "${arg##rootfs=}" != "${arg}" ]; then
1601 ROOTFS=${arg##rootfs=}
1603 if [ "${arg##rootflags=}" != "${arg}" ]; then
1604 ROOTFLAGS=${arg##rootflags=}
1606 if [ "${arg##rootfsflags=}" != "${arg}" ]; then
1607 ROOTFSFLAGS=${arg##rootfsflags=}
1609 if [ "${arg##init=}" != "${arg}" ]; then
1614 # handling of invalid, rootfsflags, option
1615 if [ -n "$ROOTFSFLAGS" ]; then
1616 if [ -n "$ROOTFLAGS" ]; then
1617 ROOTFLAGS="$ROOTFLAGS,$ROOTFSFLAGS"
1619 ROOTFLAGS="$ROOTFSFLAGS"
1623 if [ "$DEBUGINITRD" = "sh" ]; then
1624 # export some vars to subshell for debug to work
1625 export CMDLINE ROOT ROOTFS ROOTDEV ROOTFLAGS DEBUGINITRD INIT
1626 export LVM_ROOTVG LVM_SUSPENDVG LVM_VGVOLUMES
1627 export rootnr attrs majmin major minor device
1629 # make debugshell() invoke subshell if $DEBUGINITRD=sh
1632 if is_yes "$RUN_SULOGIN_ON_ERR"; then
1633 add_linuxrc <<-'EOF'
1634 echo "debug shell disabled by RUN_SULOGIN_ON_ERR=yes from /etc/sysconfig/system during initrd generation time"
1637 add_linuxrc <<-'EOF'
1641 add_linuxrc <<-'EOF'
1649 if [ "$DEBUGINITRD" ]; then
1657 modules_add_linuxrc $MODULES
1659 # TODO: rewrite for busybox
1660 #if [ -n "$loopDev" ]; then
1661 # if [ ! -d /initrd ]; then
1665 # cp -a "$loopDev" "$DESTDIR/dev"
1666 # cp -a "$rootdev" "$DESTDIR/dev"
1667 # echo "echo Mounting device containing loopback root filesystem" >> "$RCFILE"
1668 # echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE"
1669 # echo "echo Setting up loopback device $rootdev" >> $RCFILE
1670 # echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE"
1673 if is_yes "$USE_UDEV"; then
1682 initrd_gen_multipath
1685 if is_yes "$have_nfs"; then
1693 initrd_gen_setrootdev
1696 # additional devs always needed
1697 [ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev
1699 initrd_gen_stop_udevd
1700 initrd_gen_stop_mdev
1701 initrd_gen_stop_uvesafb
1703 # resume after killing local processes
1708 add_linuxrc <<-'EOF'
1709 if [ ! "$DEBUGINITRD" ]; then
1713 for i in $(export -p); do
1714 i=${i#declare -x } # ksh/bash
1715 i=${i#export } # busybox
1726 [ -z "$i" ] && continue
1729 ROOT|PATH|HOME|TERM)
1741 if [ "$INITRDFS" = "initramfs" ]; then
1742 initrd_gen_initramfs_switchroot
1748 initrd_gen_fbcondecor
1750 debug "Current /linuxrc:\n$(sed -e 's,^,| ,' $DESTDIR/linuxrc)"
1752 IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed"
1754 IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
1755 verbose "image size: $IMAGESIZE KiB ($DESTDIR)"
1757 verbose "Creating $INITRDFS image $IMAGE"
1760 dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null
1761 # NOTE: ext2 label is max 16 chars
1762 mke2fs -q -F -b 1024 -m 0 -L "PLD/$kernel" "$IMAGE" 2>/dev/null 1>&2
1763 tune2fs -i 0 "$IMAGE" >/dev/null 2>&1
1765 local tmpmnt=$(mktemp -d -t initrd.mnt-XXXXXX)
1766 debug "Mounting ext2 image $IMAGE to $tmpmnt"
1767 mount -o loop -t ext2 "$IMAGE" "$tmpmnt" || die "mount failed, check dmesg(1)"
1768 # We don't need this directory, so let's save space
1769 rm -rf "$tmpmnt"/lost+found
1771 debug "Copy recursively $DESTDIR -> $tmpmnt"
1772 cp -a $DESTDIR/* $tmpmnt
1778 genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD Linux/$kernel (geninitrd/$VERSION)"
1781 mkcramfs "$DESTDIR" "$IMAGE"
1784 (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
1787 die "Filesystem $INITRDFS not supported by $PROGRAM"
1790 if [ "$INITRDFS" != "initramfs" ]; then
1791 CONFIG_BLK_DEV_RAM_SIZE=$(ikconfig | awk -F= '/^CONFIG_BLK_DEV_RAM_SIZE/{print $2}')
1792 if [ -z "$CONFIG_BLK_DEV_RAM_SIZE" ]; then
1793 CONFIG_BLK_DEV_RAM_SIZE=4096
1794 warn "No CONFIG_BLK_DEV_RAM_SIZE detected, fallback to $CONFIG_BLK_DEV_RAM_SIZE"
1797 if [ "$IMAGESIZE" -gt $CONFIG_BLK_DEV_RAM_SIZE ]; then
1798 warn "Your image size is larger than $CONFIG_BLK_DEV_RAM_SIZE, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!"
1802 if ! is_no "$COMPRESS"; then
1803 compressor=$(find_compressor "$COMPRESS")
1804 verbose "Compressing $target with $compressor"
1806 # TODO: the image name (specified from kernel.spec) already contains
1807 # extension, which is .gz most of the time.
1808 compress_image "$compressor" "$IMAGE" "$target" || {
1809 if [ $compressor != gzip ]; then
1810 warn "Could not compress with $compressor, retrying with gzip"
1811 compress_image gzip "$IMAGE" "$target" || die "compress failed with gzip" $?
1813 die "Could not compress image with $compressor"
1817 cp -a "$IMAGE" "$target"
1820 # microcode support for lilo
1821 if ! is_no "$LILO_MICROCODE"; then
1822 if [ -x /sbin/lilo -a -f "/boot/intel-ucode.img" ]; then
1823 verbose "Prepending $target with microcode image /boot/intel-ucode.img for LILO"
1824 prepend_file_to_image "/boot/intel-ucode.img" "$target"
1828 # XXX. check if bootsplash can output data to tmp dir not directly to initramfs image.
1829 initrd_gen_bootsplash "$target"
1831 rm -rf "$DESTDIR" "$IMAGE"
1833 # vim:ts=4:sw=4:noet:fdm=marker