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 -n --move /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 libs_additional libdir
544 /lib/ld-linux.so.2 | /lib64/ld-linux-x86-64.so.2 | /libx32/ld-linux-x32.so.2)
547 /lib/libpthread.so* | /lib64/libpthread.so* | /libx32/libpthread.so*)
548 libs_additional="${obj%/libpthread*}/libgcc_s.so.1"
553 libs=$(ldd "$obj" 2> /dev/null | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
554 for lib in $libs $libs_additional; do
555 libdir=$(cd $(dirname "$lib"); pwd)
556 if [ ! -f "$DESTDIR/$lib" ]; then
558 inst_exec $lib $libdir
563 # hack for uclibc linked binaries requiring this fixed path
564 # XXX: shouldn't rpath be used here instead so th
565 for _lib in $(get_libdir LIBDIR); do
566 if [ -f $DESTDIR/$_lib/libc.so.0 ]; then
567 lib=$DESTDIR/$_lib/libc.so.0
568 lib=$(ldd "$lib" 2> /dev/null | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
569 libdir=$(cd $(dirname "$lib"); pwd)
570 if [ ! -e $DESTDIR$libdir ]; then
571 libdir=$(dirname "$libdir")
573 verbose "+ ln -s /$_lib $DESTDIR$libdir"
574 ln -s /$_lib $DESTDIR$libdir
581 # output modules.conf / modprobe.conf
583 echo "$modprobe_conf_cache"
586 # return options for MODULE
587 # @param $1 module name
590 local options=$(modprobe_conf | awk -vmodule="$module" '{ if ($1 == "options" && $2 == module) { for(i=3;i<=NF;i++) printf("%s ",$i); }}')
595 # defaults to modprobe -c if not told otherwise, this means include statements
597 cache_modprobe_conf() {
598 if [ "$kernel_version" -lt "002005" ]; then
599 modulefile=/etc/modules.conf
600 if [ ! -f "$modulefile" -a -f /etc/conf.modules ]; then
601 modulefile=/etc/conf.modules
605 if [ -n "$modulefile" ]; then
606 debug "Using $modulefile for modules config"
607 modprobe_conf_cache=$(cat $modulefile | awk '!/^[\t ]*#/ { print }')
610 debug "Using modprobe -c to get modules config"
611 modprobe_conf_cache=$(modprobe -c --set-version $kernel | awk '!/^[\t ]*#/ { print }')
615 # find modules for $devpath
616 find_modules_for_devpath() {
618 if [ -z "$devpath" ]; then
619 die "No argument passed to find_modules_for_devpath() - is your /etc/fstab correct?"
622 if [[ "$devpath" = /dev/dm-* ]]; then
623 # /dev/dm-3 -> /dev/mapper/sil_ahbgadcbchfc3
624 devpath=$(dm_node "$devpath")
627 if [ -L "$devpath" ] && ! is_lvm "$devpath" && ! is_luks "$devpath"; then
628 # sanitize things like:
629 # /dev/block/104:2 -> /dev/cciss/c0d0p2
630 devpath=$(readlink -f "$devpath")
633 verbose "Finding modules for device path $devpath"
635 if is_luks "$devpath"; then
636 find_modules_luks "$devpath"
640 if is_nfs "$devpath"; then
641 find_modules_nfs "$devpath"
645 if is_md "$devpath"; then
646 find_modules_md "$devpath"
650 if is_multipath "$devpath"; then
651 if find_modules_multipath "$devpath"; then
658 if is_dmraid "$devpath"; then
659 if find_modules_dmraid "$devpath"; then
665 if is_scsi "$devpath"; then
666 find_modules_scsi "$devpath"
670 if is_ide "$devpath"; then
671 find_modules_ide "$devpath"
675 if [[ "$devpath" == /dev/nvme* ]]; then
680 if [[ "$devpath" == /dev/bcache* ]]; then
681 find_modules_bcache "$devpath"
685 if [[ "$devpath" == /dev/rd/* ]]; then
691 if [[ "$devpath" == /dev/ida/* ]]; then
692 find_module "cpqarray"
693 rootdev_add=/dev/ida/
697 if [[ "$devpath" == /dev/cciss/* ]]; then
698 rootdev_add=/dev/cciss/
700 # load hpsa for future kernels, cciss for backwards compat
701 if [ "$kernel_version_long" -ge "003000000" ]; then
702 find_module "hpsa" "-cciss"
703 find_modules_scsi "$devpath"
711 if [[ "$devpath" == /dev/ataraid/* ]]; then
713 find_module "ataraid"
714 ataraidmodules=$(modprobe_conf | awk '/ataraid_hostadapter/ { print $3 }')
715 if [ -n "$ataraidmodules" ]; then
716 # FIXME: think about modules compiled in kernel
717 die "ataraid_hostadapter alias not defined in modprobe.conf! Please set it and run $PROGRAM again."
719 for n in $ataraidmodules; do
722 rootdev_add=/dev/ataraid/
726 # check to see if we need to set up a loopback filesystem
727 if [[ "$devpath" == /dev/loop* ]]; then
728 die "Sorry, root on loop device isn't supported."
729 # TODO: rewrite for bsp and make nfs ready
730 if [ ! -x /sbin/losetup ]; then
731 die "losetup is missing"
733 key="^# $(echo $devpath | awk -F/ '{print($3);}' | tr '[a-z]' '[A-Z]'):"
734 if ! is_yes "`awk '/'$key'/ { print( "yes"); }' $fstab`"; then
735 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"
738 line="`awk '/'$key'/ { print $0; }' $fstab`"
739 loopDev="$(echo $line | awk '{print $3}')"
740 loopFs="$(echo $line | awk '{print $4}')"
741 loopFile="$(echo $line | awk '{print $5}')"
743 BASICMODULES="$BASICMODULES -loop"
744 find_module "-$loopFs"
745 BASICMODULES="$BASICMODULES -${loopFs}"
749 if is_lvm "$devpath"; then
750 find_modules_lvm "$devpath"
755 firmware_install_module() {
757 local firmware_files="$2"
759 verbose "Adding Firmwares ($firmware_files) to initrd for module $module"
760 # firmware not yet installed
761 if [ ! -f "$DESTDIR/lib/firmware/firmware.sh" ]; then
763 cat << 'EOF' >> "$DESTDIR/lib/firmware/firmware.sh"
765 # handle only firmware add requests
766 if [ "$SUBSYSTEM" != "firmware" ]; then
769 if [ "$ACTION" != "add" ]; then
772 echo 1 > /sys$DEVPATH/loading
773 cat "/lib/firmware/$FIRMWARE" > /sys$DEVPATH/data
774 echo 0 > /sys$DEVPATH/loading
777 chmod 755 "$DESTDIR/lib/firmware/firmware.sh"
779 # setup firmware loader agent
780 echo "echo -n "/lib/firmware/firmware.sh" > /proc/sys/kernel/hotplug" | add_linuxrc
783 for firmware in $firmware_files; do
784 if [ -f "/lib/firmware/$kernel/$firmware" ]; then
785 FIRMWAREDIR=${firmware%/*}
786 [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
787 inst /lib/firmware/$kernel/$firmware /lib/firmware/$firmware
788 elif [ -f "/lib/firmware/$firmware" ]; then
789 FIRMWAREDIR=${firmware%/*}
790 [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
791 inst /lib/firmware/$firmware /lib/firmware/$firmware
793 warn "Possible missing firmware file /lib/firmware/$firmware or /lib/firmware/$kernel/$firmware for module $module."
804 for mod in $modules; do
806 inst_d "/lib/modules/$kernel/$MODULEDIR"
807 cp -a "/lib/modules/$kernel/$mod" "$DESTDIR/lib/modules/$kernel/$mod"
810 gunzip "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress gz"
814 xz -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress xz"
818 bzip2 -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress bz2"
822 if [ "$STRIP" ] && [ -x "$STRIP" ]; then
823 $STRIP -g --remove-section=.comment "$DESTDIR/lib/modules/$kernel/${mod}"
828 modules_add_linuxrc() {
832 # module path without optional compression
834 modpath=${modpath%.xz}
835 modpath=${modpath%.bz2}
838 local module=${modpath##*/}; module=${module%$modext}
839 local options=$(modprobe_options "$module")
840 local genericname=$(echo $module | tr - _)
841 local usleep=$(eval echo \$MODULE_${genericname}_USLEEP)
842 local firmware=$(eval echo \$MODULE_${genericname}_FIRMWARE)
844 if [ "$module" = "scsi_mod" -a "$kernel_version_long" -ge "002006030" ]; then
845 options="scan=sync $options"
848 if [ x"$verbose" = x"-v" ]; then
850 if [ "$options" ]; then
851 s="$s with options [$options]"
853 if [ "$usleep" ]; then
854 s="$s and $usleep usleep"
856 verbose "Loading module [$module]$s"
859 if [ -n "$firmware" ]; then
860 firmware_install_module "$module" "$firmware"
862 for file in $(find_firmware "$module"); do
863 firmware_install_module "$module" "$file"
867 echo "insmod /lib/modules/$kernel/$modpath $options" | add_linuxrc
868 if [ -n "$usleep" ]; then
869 echo "usleep $usleep" | add_linuxrc
871 if [ "$module" = "scsi_wait_scan" ]; then
872 if [ "$(busybox_applet rmmod 2>/dev/null; echo $?)" = 0 ]; then
873 echo "rmmod scsi_wait_scan" | add_linuxrc
880 # Generates /dev nodes based on /proc/partitions information.
881 # Needs /proc mounted.
882 # Can be called multiple times.
883 initrd_gen_devices() {
884 if is_yes "$proc_partitions"; then
891 : 'Making device nodes'
892 cat /proc/partitions | (
893 # ignore first two lines: header, empty line
896 while read major minor blocks dev rest; do
899 [ -e $node ] || mknod -m 660 $node b $major $minor
906 initrd_gen_setrootdev() {
907 verbose "Adding rootfs finding based on kernel cmdline root= option support."
909 debug "Current /proc/partitions:\n$(sed -e 's,^,| ,' /proc/partitions)"
911 if [ "${ROOT##/dev/}" != "${ROOT}" ]; then
912 rootnr="$(busybox awk -v rootnode="${ROOT##/dev/}" '$4 == rootnode { print 256 * $1 + $2 }' /proc/partitions)"
913 # fallback to ls, try two different formats
914 # http://lists.pld-linux.org/mailman/pipermail/pld-devel-en/2014-May/023915.html
915 if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
917 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $3 + $4; }}')"
919 if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
920 # busybox 1.22 and upwards
921 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $5 + $6; }}')"
923 if [ "${rootnr:-0}" -gt 0 ]; then
924 echo "$rootnr" > /proc/sys/kernel/real-root-dev
930 initrd_gen_initramfs_switchroot() {
932 if [ "$rootdev" = "/dev/nfs" ]; then
933 echo "rootfs on NFS root=/dev/nfs"
935 [ ! -e "$DESTDIR/$rootdev" ] && inst $rootdev $rootdev
938 # parse 'root=xxx' kernel commandline
939 # We support passing root as hda3 /dev/hda3 0303 0x0303 and 303
941 # from lilo-23.2/readme/README:
942 # root=<device> changes the root device. This overrides settings that may
943 # have been made in the boot image and on the LILO command line. <device> is
944 # either the hexadecimal device number or the full path name of the device,
947 # * The device names are hard-coded in the kernel. Therefore, only the
948 # "standard" names are supported and some less common devices may not be
949 # recognized. In those cases, only numbers can be used.
953 eval "$(busybox awk -v root="$ROOT" '
954 function h2d(str, hstr, res, num, n, digit, i) { # http://9fans.net/archive/2006/09/261
955 hstr = "0123456789abdcef"; res = 0;
956 n = split(tolower(str), digit, "");
958 for (i = 1; i <= n; i++) {
959 num = index(hstr, digit[i]) - 1;
960 res = res + (num * 16 ^ (n - i));
965 num_pattern_short = "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]";
966 num_pattern = "[0-9a-fA-F]" num_pattern_short;
967 dev_pattern = "[hms][a-z][a-z]([0-9])+";
968 partition = ""; min = -1; maj = -1;
970 if (root ~ "^\/dev\/" dev_pattern "$" || root ~ "^" dev_pattern "$") { # see if we have /dev/hdX or hdX, we can just take partition name
971 partition = root; sub("^/dev/", "", partition);
972 } else { # unify values first
973 if (root ~ "^" num_pattern_short "$") { # change "303" => "0x0303"
975 } else if (root ~ "^" num_pattern "$") { # change "0303" => "0x0303"
978 maj = h2d(substr(root, 3, 2));
979 min = h2d(substr(root, 5, 2));
982 partition && $4 == partition { maj = $1; min = $2; }
983 $1 == maj && $2 == min { partition = $4; }
985 if (maj >= 0 && min >= 0) { printf("maj=%s; min=%s;\n", maj, min); }
986 if (partition) { printf("device=/dev/%s;\n", partition); }
987 }' /proc/partitions)"
989 if [ -z "$device" ]; then
990 if [ "$DEBUGINITRD" -a "$DEBUGINITRD" != 'sh' ]; then
996 if [ "$device" -a ! -b $device -a "$maj$min" ]; then
997 mknod -m 660 $device b $maj $min
1000 # XXX hack, fallback to rootdev from geninitrd time
1001 if [ ! -e "$device" ]; then
1006 add_linuxrc <<-'EOF'
1007 echo "DEVICE set to $device based on fstab entry from initrd gen time"
1010 # XXX hack, if no device, try to parse it from /proc/partitions using /proc/sys/kernel/real-root-dev
1011 if [ ! -e "$device" ]; then
1012 rrd=$(cat /proc/sys/kernel/real-root-dev)
1013 major=$(($rrd / 256))
1014 minor=$(($rrd % 256))
1016 while read pmajor pminor blocks dev rest; do
1017 # skip header and empty line
1018 [ -z "$pmajor" -o "$pmajor" = "major" ] && continue
1020 if [ $pmajor = $major -a $pminor = $minor ]; then
1022 echo "DEVICE set to $device based on real-root-dev"
1024 done < /proc/partitions
1027 [ -n "$ROOTFLAGS" ] && ROOTFLAGS="-o $ROOTFLAGS"
1029 mount -t $ROOTFS -r $device $ROOTFLAGS /newroot || echo "Mount of rootfs failed."
1031 if [ -z "$init" -o ! -x "/newroot$init" ]; then
1036 busybox_applet dmesg
1038 add_linuxrc <<-'EOF'
1039 if [ "$DEBUGINITRD" -a "$DEBUGINITRD" != 'sh' ]; then
1040 echo "Last 20 lines of dmesg:"
1046 kmsg "geninitrd/$VERSION switching root"
1049 busybox_applet switch_root usleep
1050 add_linuxrc <<-'EOF'
1051 [ ! -e /newroot/dev/console ] && mknod -m 660 /newroot/dev/console c 5 1
1053 # switch root to empty dir will make kernel panic, so sleep 10s before it
1054 # switch_root needs to be pid 1, so there's no other way to recover from here
1055 # if /dev is missing, switch root will likely fail, give debug shell before that
1056 if [ ! -d /newroot/dev ]; then
1057 echo "/dev is missing, switch_root will likely fail"
1058 echo "if you booted with debugrd=sh, then you be given shell and you might able to recover this situation"
1060 [ "$DEBUGINITRD" ] || usleep 10000000
1063 # systemd[1]: /usr appears to be on its own filesytem and is not
1064 # already mounted. This is not a supported setup. Some things will
1065 # probably break (sometimes even silently) in mysterious ways. Consult
1066 # http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken
1067 # for more information.
1068 echo trying to mount /usr
1069 chroot /newroot mount -n /usr
1071 exec switch_root /newroot $init ${1:+"$@"}
1073 # FIXME: this code is never executed, as "exec" does not return!
1075 echo "Error! initramfs should not reach this place."
1076 echo "It probably means you've got old version of busybox, with broken"
1077 echo "initramfs support. Trying to boot anyway, but won't promise anything."
1079 exec chroot /newroot $init ${1:+"$@"}
1081 echo "Failed to chroot!"
1084 # we need /init being real file, not symlink, otherwise the initramfs will
1085 # not be ran by pid 1 which is required for switch_root
1086 mv $DESTDIR/linuxrc $DESTDIR/init
1087 ln -s init $DESTDIR/linuxrc
1090 # find if $symbol exists in System.map $mapfile
1094 if [ ! -f $mapfile ]; then
1095 # missing mapfile (not a pld kernel?)
1099 awk -vc=1 -vsymbol="$symbol" '(tolower($2) == "t" || tolower($2) == "d") && $3 == symbol {c = 0} END {exit c}' $mapfile
1102 # find best compressor (or forced one) for initrd
1105 local compressors='zstd xz lzma bzip2 gzip lzo'
1107 # a specified one, take it
1108 if ! is_yes "$mode"; then
1112 verbose "finding compressor: $compressors (via $mode)"
1113 # check for compressor validity
1114 local c prog map=/boot/System.map-$kernel
1115 for c in $compressors; do
1142 # any existing sym will work
1147 die "Unknown compressor $c"
1150 if sym_exists $map $sym && [ -x $prog ]; then
1156 verbose "using gzip for compressor (fallback)"
1160 # compresses kernel image image
1161 # in function so we could retry with other compressor on failure
1163 local compressor="$1" IMAGE="$2" target="$3" tmp
1164 tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1166 case "$compressor" in
1168 # don't use -9 here since kernel won't understand it
1169 xz --format=xz --check=crc32 --lzma2=preset=6e,dict=1MiB < "$IMAGE" > "$tmp" || return $?
1172 xz --format=lzma -9 < "$IMAGE" > "$tmp" || return $?
1175 bzip2 -9 < "$IMAGE" > "$tmp" || return $?
1178 gzip -9 < "$IMAGE" > "$tmp" || return $?
1181 lzop -9 < "$IMAGE" > "$tmp" || return $?
1184 zstd -9 < "$IMAGE" > "$tmp" || return $?
1187 cat < "$IMAGE" > "$tmp" || return $?
1191 mv -f "$tmp" "$target"
1194 # prepend file to image
1195 prepend_file_to_image() {
1196 local file="$1" target="$2" tmp
1197 tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1199 cat "$file" "$target" > "$tmp" || return $?
1201 mv -f "$tmp" "$target"
1204 if [ -r /etc/sysconfig/geninitrd ]; then
1205 . /etc/sysconfig/geninitrd
1208 if [ ! -f /proc/mounts ]; then
1209 warn "/proc filesystem not mounted, may cause wrong results or failure."
1212 geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev tuxonice suspend fbsplash condecor bootsplash uvesafb nfs sata scsi usbkbd bcache
1214 while [ $# -gt 0 ]; do
1224 modulefile=${1#--modules-conf=}
1233 --without-bootsplash)
1245 --without-fbcondecor)
1254 --with-suspend2 | --with-tuxonice)
1257 --without-suspend2 | --without-tuxonice)
1261 LVMTOOLSVERSION=${1#--lvmversion=}
1263 --lvmtoolsversion=*)
1264 LVMTOOLSVERSION=${1#--lvmtoolsversion=}
1266 --lvmtoolsversion|--lvmversion)
1279 --without-multipath)
1283 USE_MULTIPATH=${1#--with-multipath=}
1292 BASICMODULES="$BASICMODULES ${1#--with=}"
1295 BASICMODULES="$BASICMODULES $2"
1299 echo "$PROGRAM: version $VERSION"
1303 if [ x"$verbose" = x"-v" ]; then
1314 COMPRESS="${1#--compress=}"
1323 STRIP="${1#--strip=}"
1336 PREMODS="$PREMODS ${1#--preload=}"
1339 PREMODS="$PREMODS $2"
1343 die "--fs option is obsoleted. Use --initrdfs instead"
1346 INITRDFS=${1#--initrdfs=}
1359 if [ -z "$target" ]; then
1361 elif [ -z "$kernel" ]; then
1373 if [ -z "$target" -o -z "$kernel" ]; then
1379 if [ "$(id -u)" != 0 ]; then
1380 die "You need to be root to generate initrd"
1383 for dir in libx32 lib64 lib; do
1384 initrd_dir=/usr/$dir/initrd
1385 if [ -d "$initrd_dir" ]; then
1386 initrd_dirs="$initrd_dirs $initrd_dir"
1390 kernel_version=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d",$1,$2)}')
1391 kernel_version_long=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d%03d",$1,$2,$3)}')
1393 verbose "# geninitrd $VERSION"
1394 debug "Using initrd_dir: $initrd_dir"
1396 busybox=$(find_tool $initrd_dir/busybox $initrd_dir/initrd-busybox /bin/initrd-busybox) || die "Couldn't find busybox suitable for initrd"
1398 # we setup mods after parsing command line args
1399 geninitrd_setup_mods
1401 if [ ! -f /boot/vmlinuz-"$kernel" ]; then
1402 warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?"
1405 if [ -z "$INITRDFS" ]; then
1406 if [ -n "$FS" ]; then
1407 # FS= can came only via /etc/sysconfig/geninitrd likely?
1408 die "FS configuration option is obsoleted. Use INITRDFS instead"
1412 if [ "$kernel_version" -ge "002005" ]; then
1413 INITRDFS="initramfs"
1420 local s sfound sym p prog map=/boot/System.map-$kernel
1423 # TODO: symbols to check in case of ext2 used via ext3/4 subsystem
1436 sym=__initramfs_start
1437 prog="/bin/cpio /usr/bin/find"
1440 die "Filesystem $INITRDFS on initrd is not supported by geninitrd"
1444 # only one is needed (for cases like ext2 via ext2 or via ext3 or via ext4 subsysytem)
1447 sym_exists $map $s && sfound=1
1450 if [ "$sfound" -eq "0" ]; then
1451 die "Filesystem $INITRDFS on initrd is not supported by kernel"
1455 [ ! -x "$p" ] && die "$prog is missing"
1460 if [ -L "$target" ]; then
1461 target=$(readlink -f "$target")
1464 if [ -n "$img_vers" ]; then
1465 target="$target-$kernel"
1468 if [ -z "$force" -a -f "$target" ]; then
1469 die "$target already exists."
1472 if [ ! -d "/lib/modules/$kernel" ]; then
1473 die "/lib/modules/$kernel is not a directory."
1476 if [ "$kernel_version" -ge "002005" ]; then
1482 for n in $PREMODS; do
1486 if [ "$FBMODULE" ]; then
1487 find_module "$FBMODULE"
1490 # autodetect USB keyboards
1493 # allow forcing loading SCSI and/or IDE modules
1494 # XXX: where ADDSCSI cames from? drop?
1495 if is_yes "$ADDSCSI"; then
1499 # autodetect SATA modules
1502 # XXX: where ADDIDE cames from? drop?
1503 if is_yes "$ADDIDE"; then
1507 if is_yes "$USE_SUSPEND"; then
1508 find_modules_suspend
1511 find_root "$fstab" || exit
1512 verbose "Using $rootdev as device for rootfs"
1514 find_modules_for_devpath "$rootdev"
1516 # if USE_MULTIPATH is path to device, scan that too
1517 # this is to bootstrap multipath setup into initrd.
1518 if ! is_no "$USE_MULTIPATH" && ! is_yes "$USE_MULTIPATH"; then
1519 find_modules_multipath $USE_MULTIPATH
1522 find_module "-$rootFs"
1524 for n in $BASICMODULES; do
1528 if is_yes "$USE_TUXONICE"; then
1532 find_modules_uvesafb
1533 find_modules_fbsplash
1535 if [ -n "$ifneeded" -a -z "$MODULES" ]; then
1536 verbose "No modules are needed -- not building initrd image."
1540 verbose "Building initrd..."
1541 DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
1542 RCFILE="$DESTDIR/linuxrc"
1544 chmod a+rx "$RCFILE"
1545 ln -s linuxrc $DESTDIR/init
1547 # create dirs that we really need
1548 inst_d /{lib,bin,sbin,etc,dev{,/pts,/shm},loopfs,var,proc,run,sys,tmp}
1550 modules_install "$MODULES"
1552 # mknod'ing the devices instead of copying them works both with and
1554 mknod -m 600 "$DESTDIR/dev/console" c 5 1
1555 mknod -m 666 "$DESTDIR/dev/null" c 1 3
1556 mknod -m 666 "$DESTDIR/dev/zero" c 1 5
1557 mknod -m 666 "$DESTDIR/dev/random" c 1 8
1558 mknod -m 666 "$DESTDIR/dev/urandom" c 1 9
1559 mknod -m 644 "$DESTDIR/dev/kmsg" c 1 11
1561 inst_exec $busybox /bin/busybox
1562 ln -s busybox $DESTDIR/bin/sh
1563 # for older busyboxes who had /bin/initrd-busybox as EXEPATH
1564 ln -s busybox $DESTDIR/bin/initrd-busybox
1568 # initrd generated by geninitrd/$VERSION
1569 # on $(LC_ALL=C date)
1575 kmsg "geninitrd/$VERSION starting"
1577 inst_d /lib/geninitrd/
1578 inst /lib/geninitrd/functions.initrd /lib/geninitrd/functions.initrd
1581 . /lib/geninitrd/functions.initrd
1582 # builtin defaults from geninitrd
1586 add_linuxrc <<-'EOF'
1587 read CMDLINE < /proc/cmdline
1589 for arg in $CMDLINE; do
1590 if [ "${arg}" = "debuginitrd" ] || [ "${arg}" = "debugrd" ]; then
1593 if [ "${arg##debuginitrd=}" != "${arg}" ] || [ "${arg##debugrd=}" != "${arg}" ]; then
1594 DEBUGINITRD=${arg##debug*rd=}
1596 if [ "${arg##root=}" != "${arg}" ]; then
1599 if [ "${arg##rootfs=}" != "${arg}" ]; then
1600 ROOTFS=${arg##rootfs=}
1602 if [ "${arg##rootflags=}" != "${arg}" ]; then
1603 ROOTFLAGS=${arg##rootflags=}
1605 if [ "${arg##rootfsflags=}" != "${arg}" ]; then
1606 ROOTFSFLAGS=${arg##rootfsflags=}
1608 if [ "${arg##init=}" != "${arg}" ]; then
1613 # handling of invalid, rootfsflags, option
1614 if [ -n "$ROOTFSFLAGS" ]; then
1615 if [ -n "$ROOTFLAGS" ]; then
1616 ROOTFLAGS="$ROOTFLAGS,$ROOTFSFLAGS"
1618 ROOTFLAGS="$ROOTFSFLAGS"
1622 if [ "$DEBUGINITRD" = "sh" ]; then
1623 # export some vars to subshell for debug to work
1624 export CMDLINE ROOT ROOTFS ROOTDEV ROOTFLAGS DEBUGINITRD INIT
1625 export LVM_ROOTVG LVM_SUSPENDVG LVM_VGVOLUMES
1626 export rootnr attrs majmin major minor device
1628 # make debugshell() invoke subshell if $DEBUGINITRD=sh
1631 if is_yes "$RUN_SULOGIN_ON_ERR"; then
1632 add_linuxrc <<-'EOF'
1633 echo "debug shell disabled by RUN_SULOGIN_ON_ERR=yes from /etc/sysconfig/system during initrd generation time"
1636 add_linuxrc <<-'EOF'
1640 add_linuxrc <<-'EOF'
1648 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