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 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" | 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" | 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/bcache* ]]; then
676 find_modules_bcache "$devpath"
680 if [[ "$devpath" == /dev/rd/* ]]; then
686 if [[ "$devpath" == /dev/ida/* ]]; then
687 find_module "cpqarray"
688 rootdev_add=/dev/ida/
692 if [[ "$devpath" == /dev/cciss/* ]]; then
693 rootdev_add=/dev/cciss/
695 # load hpsa for future kernels, cciss for backwards compat
696 if [ "$kernel_version_long" -ge "003000000" ]; then
697 find_module "hpsa" "-cciss"
698 find_modules_scsi "$devpath"
706 if [[ "$devpath" == /dev/ataraid/* ]]; then
708 find_module "ataraid"
709 ataraidmodules=$(modprobe_conf | awk '/ataraid_hostadapter/ { print $3 }')
710 if [ -n "$ataraidmodules" ]; then
711 # FIXME: think about modules compiled in kernel
712 die "ataraid_hostadapter alias not defined in modprobe.conf! Please set it and run $PROGRAM again."
714 for n in $ataraidmodules; do
717 rootdev_add=/dev/ataraid/
721 # check to see if we need to set up a loopback filesystem
722 if [[ "$devpath" == /dev/loop* ]]; then
723 die "Sorry, root on loop device isn't supported."
724 # TODO: rewrite for bsp and make nfs ready
725 if [ ! -x /sbin/losetup ]; then
726 die "losetup is missing"
728 key="^# $(echo $devpath | awk -F/ '{print($3);}' | tr '[a-z]' '[A-Z]'):"
729 if ! is_yes "`awk '/'$key'/ { print( "yes"); }' $fstab`"; then
730 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"
733 line="`awk '/'$key'/ { print $0; }' $fstab`"
734 loopDev="$(echo $line | awk '{print $3}')"
735 loopFs="$(echo $line | awk '{print $4}')"
736 loopFile="$(echo $line | awk '{print $5}')"
738 BASICMODULES="$BASICMODULES -loop"
739 find_module "-$loopFs"
740 BASICMODULES="$BASICMODULES -${loopFs}"
744 if is_lvm "$devpath"; then
745 find_modules_lvm "$devpath"
750 firmware_install_module() {
752 local firmware_files="$2"
754 verbose "Adding Firmwares ($firmware_files) to initrd for module $module"
755 # firmware not yet installed
756 if [ ! -f "$DESTDIR/lib/firmware/firmware.sh" ]; then
758 cat << 'EOF' >> "$DESTDIR/lib/firmware/firmware.sh"
760 # handle only firmware add requests
761 if [ "$SUBSYSTEM" != "firmware" ]; then
764 if [ "$ACTION" != "add" ]; then
767 echo 1 > /sys$DEVPATH/loading
768 cat "/lib/firmware/$FIRMWARE" > /sys$DEVPATH/data
769 echo 0 > /sys$DEVPATH/loading
772 chmod 755 "$DESTDIR/lib/firmware/firmware.sh"
774 # setup firmware loader agent
775 echo "echo -n "/lib/firmware/firmware.sh" > /proc/sys/kernel/hotplug" | add_linuxrc
778 for firmware in $firmware_files; do
779 if [ -f "/lib/firmware/$kernel/$firmware" ]; then
780 FIRMWAREDIR=${firmware%/*}
781 [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
782 inst /lib/firmware/$kernel/$firmware /lib/firmware/$firmware
783 elif [ -f "/lib/firmware/$firmware" ]; then
784 FIRMWAREDIR=${firmware%/*}
785 [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
786 inst /lib/firmware/$firmware /lib/firmware/$firmware
788 warn "Possible missing firmware file /lib/firmware/$firmware or /lib/firmware/$kernel/$firmware for module $module."
799 for mod in $modules; do
801 inst_d "/lib/modules/$kernel/$MODULEDIR"
802 cp -a "/lib/modules/$kernel/$mod" "$DESTDIR/lib/modules/$kernel/$mod"
805 gunzip "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress gz"
809 xz -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress xz"
813 bzip2 -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress bz2"
817 if [ "$STRIP" ] && [ -x "$STRIP" ]; then
818 $STRIP -g --remove-section=.comment "$DESTDIR/lib/modules/$kernel/${mod}"
823 modules_add_linuxrc() {
827 # module path without optional compression
829 modpath=${modpath%.xz}
830 modpath=${modpath%.bz2}
833 local module=${modpath##*/}; module=${module%$modext}
834 local options=$(modprobe_options "$module")
835 local genericname=$(echo $module | tr - _)
836 local usleep=$(eval echo \$MODULE_${genericname}_USLEEP)
837 local firmware=$(eval echo \$MODULE_${genericname}_FIRMWARE)
839 if [ "$module" = "scsi_mod" -a "$kernel_version_long" -ge "002006030" ]; then
840 options="scan=sync $options"
843 if [ x"$verbose" = x"-v" ]; then
845 if [ "$options" ]; then
846 s="$s with options [$options]"
848 if [ "$usleep" ]; then
849 s="$s and $usleep usleep"
851 verbose "Loading module [$module]$s"
854 if [ -n "$firmware" ]; then
855 firmware_install_module "$module" "$firmware"
857 for file in $(find_firmware "$module"); do
858 firmware_install_module "$module" "$file"
862 echo "insmod /lib/modules/$kernel/$modpath $options" | add_linuxrc
863 if [ -n "$usleep" ]; then
864 echo "usleep $usleep" | add_linuxrc
866 if [ "$module" = "scsi_wait_scan" ]; then
867 if [ "$(busybox_applet rmmod 2>/dev/null; echo $?)" = 0 ]; then
868 echo "rmmod scsi_wait_scan" | add_linuxrc
875 # Generates /dev nodes based on /proc/partitions information.
876 # Needs /proc mounted.
877 # Can be called multiple times.
878 initrd_gen_devices() {
879 if is_yes "$proc_partitions"; then
886 : 'Making device nodes'
887 cat /proc/partitions | (
888 # ignore first two lines: header, empty line
891 while read major minor blocks dev rest; do
894 [ -e $node ] || mknod -m 660 $node b $major $minor
901 initrd_gen_setrootdev() {
902 verbose "Adding rootfs finding based on kernel cmdline root= option support."
904 debug "Current /proc/partitions:\n$(sed -e 's,^,| ,' /proc/partitions)"
906 if [ "${ROOT##/dev/}" != "${ROOT}" ]; then
907 rootnr="$(busybox awk -v rootnode="${ROOT##/dev/}" '$4 == rootnode { print 256 * $1 + $2 }' /proc/partitions)"
908 # fallback to ls, try two different formats
909 # http://lists.pld-linux.org/mailman/pipermail/pld-devel-en/2014-May/023915.html
910 if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
912 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $3 + $4; }}')"
914 if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
915 # busybox 1.22 and upwards
916 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $5 + $6; }}')"
918 if [ "${rootnr:-0}" -gt 0 ]; then
919 echo "$rootnr" > /proc/sys/kernel/real-root-dev
925 initrd_gen_initramfs_switchroot() {
927 if [ "$rootdev" = "/dev/nfs" ]; then
928 echo "rootfs on NFS root=/dev/nfs"
930 [ ! -e "$DESTDIR/$rootdev" ] && inst $rootdev $rootdev
933 # parse 'root=xxx' kernel commandline
934 # We support passing root as hda3 /dev/hda3 0303 0x0303 and 303
936 # from lilo-23.2/readme/README:
937 # root=<device> changes the root device. This overrides settings that may
938 # have been made in the boot image and on the LILO command line. <device> is
939 # either the hexadecimal device number or the full path name of the device,
942 # * The device names are hard-coded in the kernel. Therefore, only the
943 # "standard" names are supported and some less common devices may not be
944 # recognized. In those cases, only numbers can be used.
948 eval "$(busybox awk -v root="$ROOT" '
949 function h2d(str, hstr, res, num, n, digit, i) { # http://9fans.net/archive/2006/09/261
950 hstr = "0123456789abdcef"; res = 0;
951 n = split(tolower(str), digit, "");
953 for (i = 1; i <= n; i++) {
954 num = index(hstr, digit[i]) - 1;
955 res = res + (num * 16 ^ (n - i));
960 num_pattern_short = "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]";
961 num_pattern = "[0-9a-fA-F]" num_pattern_short;
962 dev_pattern = "[hms][a-z][a-z]([0-9])+";
963 partition = ""; min = -1; maj = -1;
965 if (root ~ "^\/dev\/" dev_pattern "$" || root ~ "^" dev_pattern "$") { # see if we have /dev/hdX or hdX, we can just take partition name
966 partition = root; sub("^/dev/", "", partition);
967 } else { # unify values first
968 if (root ~ "^" num_pattern_short "$") { # change "303" => "0x0303"
970 } else if (root ~ "^" num_pattern "$") { # change "0303" => "0x0303"
973 maj = h2d(substr(root, 3, 2));
974 min = h2d(substr(root, 5, 2));
977 partition && $4 == partition { maj = $1; min = $2; }
978 $1 == maj && $2 == min { partition = $4; }
980 if (maj >= 0 && min >= 0) { printf("maj=%s; min=%s;\n", maj, min); }
981 if (partition) { printf("device=/dev/%s;\n", partition); }
982 }' /proc/partitions)"
984 if [ -z "$device" ]; then
985 if [ "$DEBUGINITRD" -a "$DEBUGINITRD" != 'sh' ]; then
991 if [ "$device" -a ! -b $device -a "$maj$min" ]; then
992 mknod -m 660 $device b $maj $min
995 # XXX hack, fallback to rootdev from geninitrd time
996 if [ ! -e "$device" ]; then
1001 add_linuxrc <<-'EOF'
1002 echo "DEVICE set to $device based on fstab entry from initrd gen time"
1005 # XXX hack, if no device, try to parse it from /proc/partitions using /proc/sys/kernel/real-root-dev
1006 if [ ! -e "$device" ]; then
1007 rrd=$(cat /proc/sys/kernel/real-root-dev)
1008 major=$(($rrd / 256))
1009 minor=$(($rrd % 256))
1011 while read pmajor pminor blocks dev rest; do
1012 # skip header and empty line
1013 [ -z "$pmajor" -o "$pmajor" = "major" ] && continue
1015 if [ $pmajor = $major -a $pminor = $minor ]; then
1017 echo "DEVICE set to $device based on real-root-dev"
1019 done < /proc/partitions
1022 [ -n "$ROOTFLAGS" ] && ROOTFLAGS="-o $ROOTFLAGS"
1024 mount -t $ROOTFS -r $device $ROOTFLAGS /newroot || echo "Mount of rootfs failed."
1026 if [ -z "$init" -o ! -x "/newroot$init" ]; then
1031 busybox_applet dmesg
1033 add_linuxrc <<-'EOF'
1034 if [ "$DEBUGINITRD" -a "$DEBUGINITRD" != 'sh' ]; then
1035 echo "Last 20 lines of dmesg:"
1041 kmsg "geninitrd/$VERSION switching root"
1044 busybox_applet switch_root usleep
1045 add_linuxrc <<-'EOF'
1046 [ ! -e /newroot/dev/console ] && mknod -m 660 /newroot/dev/console c 5 1
1048 # switch root to empty dir will make kernel panic, so sleep 10s before it
1049 # switch_root needs to be pid 1, so there's no other way to recover from here
1050 # if /dev is missing, switch root will likely fail, give debug shell before that
1051 if [ ! -d /newroot/dev ]; then
1052 echo "/dev is missing, switch_root will likely fail"
1053 echo "if you booted with debugrd=sh, then you be given shell and you might able to recover this situation"
1055 [ "$DEBUGINITRD" ] || usleep 10000000
1058 # systemd[1]: /usr appears to be on its own filesytem and is not
1059 # already mounted. This is not a supported setup. Some things will
1060 # probably break (sometimes even silently) in mysterious ways. Consult
1061 # http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken
1062 # for more information.
1063 echo trying to mount /usr
1064 chroot /newroot mount -n /usr
1066 exec switch_root /newroot $init ${1:+"$@"}
1068 # FIXME: this code is never executed, as "exec" does not return!
1070 echo "Error! initramfs should not reach this place."
1071 echo "It probably means you've got old version of busybox, with broken"
1072 echo "initramfs support. Trying to boot anyway, but won't promise anything."
1074 exec chroot /newroot $init ${1:+"$@"}
1076 echo "Failed to chroot!"
1079 # we need /init being real file, not symlink, otherwise the initramfs will
1080 # not be ran by pid 1 which is required for switch_root
1081 mv $DESTDIR/linuxrc $DESTDIR/init
1082 ln -s init $DESTDIR/linuxrc
1085 # find if $symbol exists in System.map $mapfile
1089 if [ ! -f $mapfile ]; then
1090 # missing mapfile (not a pld kernel?)
1094 awk -vc=1 -vsymbol="$symbol" '($2 == "T" || $2 == "t") && $3 == symbol {c = 0} END {exit c}' $mapfile
1097 # find best compressor (or forced one) for initrd
1100 local compressors='zstd xz lzma bzip2 gzip lzo'
1102 # a specified one, take it
1103 if ! is_yes "$mode"; then
1107 verbose "finding compressor: $compressors (via $mode)"
1108 # check for compressor validity
1109 local c prog map=/boot/System.map-$kernel
1110 for c in $compressors; do
1137 # any existing sym will work
1142 die "Unknown compressor $c"
1145 if sym_exists $map $sym && [ -x $prog ]; then
1151 verbose "using gzip for compressor (fallback)"
1155 # compresses kernel image image
1156 # in function so we could retry with other compressor on failure
1158 local compressor="$1" IMAGE="$2" target="$3" tmp
1159 tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1161 case "$compressor" in
1163 # don't use -9 here since kernel won't understand it
1164 xz --format=xz --check=crc32 --lzma2=preset=6e,dict=1MiB < "$IMAGE" > "$tmp" || return $?
1167 xz --format=lzma -9 < "$IMAGE" > "$tmp" || return $?
1170 bzip2 -9 < "$IMAGE" > "$tmp" || return $?
1173 gzip -9 < "$IMAGE" > "$tmp" || return $?
1176 lzop -9 < "$IMAGE" > "$tmp" || return $?
1179 zstd -9 < "$IMAGE" > "$tmp" || return $?
1182 cat < "$IMAGE" > "$tmp" || return $?
1186 mv -f "$tmp" "$target"
1189 if [ -r /etc/sysconfig/geninitrd ]; then
1190 . /etc/sysconfig/geninitrd
1193 if [ ! -f /proc/mounts ]; then
1194 warn "/proc filesystem not mounted, may cause wrong results or failure."
1197 geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev tuxonice suspend fbsplash condecor bootsplash uvesafb nfs sata scsi usbkbd bcache
1199 while [ $# -gt 0 ]; do
1209 modulefile=${1#--modules-conf=}
1218 --without-bootsplash)
1230 --without-fbcondecor)
1239 --with-suspend2 | --with-tuxonice)
1242 --without-suspend2 | --without-tuxonice)
1246 LVMTOOLSVERSION=${1#--lvmversion=}
1248 --lvmtoolsversion=*)
1249 LVMTOOLSVERSION=${1#--lvmtoolsversion=}
1251 --lvmtoolsversion|--lvmversion)
1264 --without-multipath)
1268 USE_MULTIPATH=${1#--with-multipath=}
1277 BASICMODULES="$BASICMODULES ${1#--with=}"
1280 BASICMODULES="$BASICMODULES $2"
1284 echo "$PROGRAM: version $VERSION"
1288 if [ x"$verbose" = x"-v" ]; then
1299 COMPRESS="${1#--compress=}"
1308 STRIP="${1#--strip=}"
1321 PREMODS="$PREMODS ${1#--preload=}"
1324 PREMODS="$PREMODS $2"
1328 die "--fs option is obsoleted. Use --initrdfs instead"
1331 INITRDFS=${1#--initrdfs=}
1344 if [ -z "$target" ]; then
1346 elif [ -z "$kernel" ]; then
1358 if [ -z "$target" -o -z "$kernel" ]; then
1364 if [ "$(id -u)" != 0 ]; then
1365 die "You need to be root to generate initrd"
1368 for dir in libx32 lib64 lib; do
1369 initrd_dir=/usr/$dir/initrd
1370 if [ -d "$initrd_dir" ]; then
1371 initrd_dirs="$initrd_dirs $initrd_dir"
1375 kernel_version=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d",$1,$2)}')
1376 kernel_version_long=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d%03d",$1,$2,$3)}')
1378 verbose "# geninitrd $VERSION"
1379 debug "Using initrd_dir: $initrd_dir"
1381 busybox=$(find_tool $initrd_dir/busybox $initrd_dir/initrd-busybox /bin/initrd-busybox) || die "Couldn't find busybox suitable for initrd"
1383 # we setup mods after parsing command line args
1384 geninitrd_setup_mods
1386 if [ ! -f /boot/vmlinuz-"$kernel" ]; then
1387 warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?"
1390 if [ -z "$INITRDFS" ]; then
1391 if [ -n "$FS" ]; then
1392 # FS= can came only via /etc/sysconfig/geninitrd likely?
1393 die "FS configuration option is obsoleted. Use INITRDFS instead"
1397 if [ "$kernel_version" -ge "002005" ]; then
1398 INITRDFS="initramfs"
1405 local s sfound sym p prog map=/boot/System.map-$kernel
1408 # TODO: symbols to check in case of ext2 used via ext3/4 subsystem
1421 sym=__initramfs_start
1422 prog="/bin/cpio /usr/bin/find"
1425 die "Filesystem $INITRDFS on initrd is not supported by geninitrd"
1429 # only one is needed (for cases like ext2 via ext2 or via ext3 or via ext4 subsysytem)
1432 sym_exists $map $s && sfound=1
1435 if [ "$sfound" -eq "0" ]; then
1436 die "Filesystem $INITRDFS on initrd is not supported by kernel"
1440 [ ! -x "$p" ] && die "$prog is missing"
1445 if [ -L "$target" ]; then
1446 target=$(readlink -f "$target")
1449 if [ -n "$img_vers" ]; then
1450 target="$target-$kernel"
1453 if [ -z "$force" -a -f "$target" ]; then
1454 die "$target already exists."
1457 if [ ! -d "/lib/modules/$kernel" ]; then
1458 die "/lib/modules/$kernel is not a directory."
1461 if [ "$kernel_version" -ge "002005" ]; then
1467 for n in $PREMODS; do
1471 if [ "$FBMODULE" ]; then
1472 find_module "$FBMODULE"
1475 # autodetect USB keyboards
1478 # allow forcing loading SCSI and/or IDE modules
1479 # XXX: where ADDSCSI cames from? drop?
1480 if is_yes "$ADDSCSI"; then
1484 # autodetect SATA modules
1487 # XXX: where ADDIDE cames from? drop?
1488 if is_yes "$ADDIDE"; then
1492 if is_yes "$USE_SUSPEND"; then
1493 find_modules_suspend
1496 find_root "$fstab" || exit
1497 verbose "Using $rootdev as device for rootfs"
1499 find_modules_for_devpath "$rootdev"
1501 # if USE_MULTIPATH is path to device, scan that too
1502 # this is to bootstrap multipath setup into initrd.
1503 if ! is_no "$USE_MULTIPATH" && ! is_yes "$USE_MULTIPATH"; then
1504 find_modules_multipath $USE_MULTIPATH
1507 find_module "-$rootFs"
1509 for n in $BASICMODULES; do
1513 if is_yes "$USE_TUXONICE"; then
1517 find_modules_uvesafb
1518 find_modules_fbsplash
1520 if [ -n "$ifneeded" -a -z "$MODULES" ]; then
1521 verbose "No modules are needed -- not building initrd image."
1525 verbose "Building initrd..."
1526 DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
1527 RCFILE="$DESTDIR/linuxrc"
1529 chmod a+rx "$RCFILE"
1530 ln -s linuxrc $DESTDIR/init
1532 # create dirs that we really need
1533 inst_d /{lib,bin,sbin,etc,dev{,/pts,/shm},loopfs,var,proc,run,sys,tmp}
1535 modules_install "$MODULES"
1537 # mknod'ing the devices instead of copying them works both with and
1539 mknod -m 600 "$DESTDIR/dev/console" c 5 1
1540 mknod -m 666 "$DESTDIR/dev/null" c 1 3
1541 mknod -m 666 "$DESTDIR/dev/zero" c 1 5
1542 mknod -m 666 "$DESTDIR/dev/random" c 1 8
1543 mknod -m 666 "$DESTDIR/dev/urandom" c 1 9
1544 mknod -m 644 "$DESTDIR/dev/kmsg" c 1 11
1546 inst_exec $busybox /bin/busybox
1547 ln -s busybox $DESTDIR/bin/sh
1548 # for older busyboxes who had /bin/initrd-busybox as EXEPATH
1549 ln -s busybox $DESTDIR/bin/initrd-busybox
1553 # initrd generated by geninitrd/$VERSION
1554 # on $(LC_ALL=C date)
1560 kmsg "geninitrd/$VERSION starting"
1562 inst_d /lib/geninitrd/
1563 inst /lib/geninitrd/functions.initrd /lib/geninitrd/functions.initrd
1566 . /lib/geninitrd/functions.initrd
1567 # builtin defaults from geninitrd
1571 add_linuxrc <<-'EOF'
1572 read CMDLINE < /proc/cmdline
1574 for arg in $CMDLINE; do
1575 if [ "${arg}" = "debuginitrd" ] || [ "${arg}" = "debugrd" ]; then
1578 if [ "${arg##debuginitrd=}" != "${arg}" ] || [ "${arg##debugrd=}" != "${arg}" ]; then
1579 DEBUGINITRD=${arg##debug*rd=}
1581 if [ "${arg##root=}" != "${arg}" ]; then
1584 if [ "${arg##rootfs=}" != "${arg}" ]; then
1585 ROOTFS=${arg##rootfs=}
1587 if [ "${arg##rootflags=}" != "${arg}" ]; then
1588 ROOTFLAGS=${arg##rootflags=}
1590 if [ "${arg##rootfsflags=}" != "${arg}" ]; then
1591 ROOTFSFLAGS=${arg##rootfsflags=}
1593 if [ "${arg##init=}" != "${arg}" ]; then
1598 # handling of invalid, rootfsflags, option
1599 if [ -n "$ROOTFSFLAGS" ]; then
1600 if [ -n "$ROOTFLAGS" ]; then
1601 ROOTFLAGS="$ROOTFLAGS,$ROOTFSFLAGS"
1603 ROOTFLAGS="$ROOTFSFLAGS"
1607 if [ "$DEBUGINITRD" = "sh" ]; then
1608 # export some vars to subshell for debug to work
1609 export CMDLINE ROOT ROOTFS ROOTDEV ROOTFLAGS DEBUGINITRD INIT
1610 export LVM_ROOTVG LVM_SUSPENDVG LVM_VGVOLUMES
1611 export rootnr attrs majmin major minor device
1613 # make debugshell() invoke subshell if $DEBUGINITRD=sh
1616 if is_yes "$RUN_SULOGIN_ON_ERR"; then
1617 add_linuxrc <<-'EOF'
1618 echo "debug shell disabled by RUN_SULOGIN_ON_ERR=yes from /etc/sysconfig/system during initrd generation time"
1621 add_linuxrc <<-'EOF'
1625 add_linuxrc <<-'EOF'
1633 if [ "$DEBUGINITRD" ]; then
1641 modules_add_linuxrc $MODULES
1643 # TODO: rewrite for busybox
1644 #if [ -n "$loopDev" ]; then
1645 # if [ ! -d /initrd ]; then
1649 # cp -a "$loopDev" "$DESTDIR/dev"
1650 # cp -a "$rootdev" "$DESTDIR/dev"
1651 # echo "echo Mounting device containing loopback root filesystem" >> "$RCFILE"
1652 # echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE"
1653 # echo "echo Setting up loopback device $rootdev" >> $RCFILE
1654 # echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE"
1657 if is_yes "$USE_UDEV"; then
1666 initrd_gen_multipath
1669 if is_yes "$have_nfs"; then
1677 initrd_gen_setrootdev
1680 # additional devs always needed
1681 [ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev
1683 initrd_gen_stop_udevd
1684 initrd_gen_stop_mdev
1685 initrd_gen_stop_uvesafb
1687 # resume after killing local processes
1692 add_linuxrc <<-'EOF'
1693 if [ ! "$DEBUGINITRD" ]; then
1697 for i in $(export -p); do
1698 i=${i#declare -x } # ksh/bash
1699 i=${i#export } # busybox
1710 [ -z "$i" ] && continue
1713 ROOT|PATH|HOME|TERM)
1725 if [ "$INITRDFS" = "initramfs" ]; then
1726 initrd_gen_initramfs_switchroot
1732 initrd_gen_fbcondecor
1734 debug "Current /linuxrc:\n$(sed -e 's,^,| ,' $DESTDIR/linuxrc)"
1736 IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed"
1738 IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
1739 verbose "image size: $IMAGESIZE KiB ($DESTDIR)"
1741 verbose "Creating $INITRDFS image $IMAGE"
1744 dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null
1745 # NOTE: ext2 label is max 16 chars
1746 mke2fs -q -F -b 1024 -m 0 -L "PLD/$kernel" "$IMAGE" 2>/dev/null 1>&2
1747 tune2fs -i 0 "$IMAGE" >/dev/null 2>&1
1749 local tmpmnt=$(mktemp -d -t initrd.mnt-XXXXXX)
1750 debug "Mounting ext2 image $IMAGE to $tmpmnt"
1751 mount -o loop -t ext2 "$IMAGE" "$tmpmnt" || die "mount failed, check dmesg(1)"
1752 # We don't need this directory, so let's save space
1753 rm -rf "$tmpmnt"/lost+found
1755 debug "Copy recursively $DESTDIR -> $tmpmnt"
1756 cp -a $DESTDIR/* $tmpmnt
1762 genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD Linux/$kernel (geninitrd/$VERSION)"
1765 mkcramfs "$DESTDIR" "$IMAGE"
1768 (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
1771 die "Filesystem $INITRDFS not supported by $PROGRAM"
1774 if [ "$INITRDFS" != "initramfs" ]; then
1775 CONFIG_BLK_DEV_RAM_SIZE=$(ikconfig | awk -F= '/^CONFIG_BLK_DEV_RAM_SIZE/{print $2}')
1776 if [ -z "$CONFIG_BLK_DEV_RAM_SIZE" ]; then
1777 CONFIG_BLK_DEV_RAM_SIZE=4096
1778 warn "No CONFIG_BLK_DEV_RAM_SIZE detected, fallback to $CONFIG_BLK_DEV_RAM_SIZE"
1781 if [ "$IMAGESIZE" -gt $CONFIG_BLK_DEV_RAM_SIZE ]; then
1782 warn "Your image size is larger than $CONFIG_BLK_DEV_RAM_SIZE, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!"
1786 if ! is_no "$COMPRESS"; then
1787 compressor=$(find_compressor "$COMPRESS")
1788 verbose "Compressing $target with $compressor"
1790 # TODO: the image name (specified from kernel.spec) already contains
1791 # extension, which is .gz most of the time.
1792 compress_image "$compressor" "$IMAGE" "$target" || {
1793 if [ $compressor != gzip ]; then
1794 warn "Could not compress with $compressor, retrying with gzip"
1795 compress_image gzip "$IMAGE" "$target" || die "compress failed with gzip" $?
1797 die "Could not compress image with $compressor"
1801 cp -a "$IMAGE" "$target"
1804 # XXX. check if bootsplash can output data to tmp dir not directly to initramfs image.
1805 initrd_gen_bootsplash "$target"
1807 rm -rf "$DESTDIR" "$IMAGE"
1809 # vim:ts=4:sw=4:noet:fdm=marker