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
32 # device node for rootfs from fstab
42 # is /tmp mounted on tmpfs
45 # are /dev nodes already created from /proc/devices info?
49 echo "Usage: $PROGRAM [--version] [-v] [-f] [--ifneeded] [--preload <module>]"
50 echo " [--with=<module>] [--image-version] [--fstab=<fstab>] [--nocompress]"
51 echo " [--compress=yes|zstd|xz|lzma|bzip2|gzip|lzo|lz4]"
52 echo " [--nostrip ] [--strip PATH/strip] [--strip=PATH/strip]"
53 echo " [--initrdfs=rom|initramfs|ext2|cram] [--modules-conf=<modules.conf>]"
54 echo " [--with-bootsplash] [--without-bootsplash]"
55 echo " [--with-fbsplash] [--without-fbsplash]"
56 echo " [--with-fbcondecor] [--without-fbcondecor]"
57 echo " [--lvmtoolsversion=1|2] [--with-udev] [--without-udev]"
58 echo " [--with-suspend] [--without-suspend]"
59 echo " [--with-tuxonice] [--without-tuxonice]"
60 echo " [--without-dmraid]"
61 echo " [--with-multipath=DEVPATH] [--without-multipath]"
62 echo " [--without-blkid] [--without-luks]"
63 echo " <initrd-image> <kernel-version>"
67 local kdir kver dir=${target:-/boot}
68 for kdir in /lib/modules/*; do
69 [ -d $kdir ] || continue
71 echo " $0 -f --initrdfs=initramfs $dir/initrd-$kver.gz $kver $verbose"
84 [ -n "$verbose" ] && msg "$*" >&3
88 [ x"$verbose" = x"-v -v" ] && msg "$*" >&3
91 # add initrd code to print to kmsg
92 # @param string message
93 # @param int loglevel. defaults to "6" (info)
96 # KERN_EMERG "0" Emergency messages, system is about to crash or is unstable
97 # KERN_ALERT "1" Something bad happened and action must be taken immediately
98 # KERN_CRIT "2" A critical condition occurred like a serious hardware/software failure
99 # KERN_ERR "3" An error condition, often used by drivers to indicate difficulties with the hardware
100 # KERN_WARNING "4" A warning, meaning nothing serious by itself but might indicate problems
101 # KERN_NOTICE "5" Nothing serious, but notably nevertheless. Often used to report security events.
102 # KERN_INFO "6" Informational message e.g. startup information at driver initialization
103 # KERN_DEBUG "7" Debug messages
104 # KERN_CONT "c" "continued" line of log printout (only done after a line that had no enclosing \n)
106 local msg="$1" level=${2:-6}
107 echo "echo '<$level>$msg' > /dev/kmsg" | add_linuxrc
110 # aborts program abnormally
117 # find program from specified paths
120 local paths="$initrd_dirs /bin /sbin /usr/bin /usr/sbin"
122 debug "find_tool: checking $x"
125 verbose "find_tool: found $x"
131 debug "find_tool: checking $p/$b"
132 if [ -x "$p/$b" ]; then
134 verbose "find_tool: found $p/$b"
140 debug "find_tool: did not find any of: $n"
144 # loads geninitrd modules
145 geninitrd_load_mods() {
148 if [ ! -f /lib/geninitrd/mod-$mod.sh ]; then
149 die "$mod geninitrd module can't be loaded"
151 . /lib/geninitrd/mod-$mod.sh
153 GENINITRD_MODS="$GENINITRD_MODS $mod"
157 # setup geninitrd modules
158 geninitrd_setup_mods() {
161 for mod in $GENINITRD_MODS; do
164 # some mods want init
165 if type setup_mod_$mod > /dev/null; then
171 # append text to /linuxrc
172 # takes STDIN as input
177 # generate code to mount /dev on tmpfs and create initial nodes
178 # can be called multiple times. /dev is cleaned up (umounted) automatically at
181 # we already generated tmpfs code; return
182 if is_yes "$dev_mounted"; then
188 busybox_applet mount mknod mkdir
191 if ! mount -t devtmpfs -o mode=0755,nosuid devtmpfs /dev > /dev/null 2>&1; then
192 mount -o mode=0755,nosuid -t tmpfs tmpfs /dev
193 mknod -m 600 /dev/console c 5 1
194 mknod -m 666 /dev/null c 1 3
195 mknod -m 666 /dev/zero c 1 5
196 mknod -m 666 /dev/random c 1 8
197 mknod -m 600 /dev/snapshot c 10 231
198 mknod -m 666 /dev/urandom c 1 9
199 mknod -m 666 /dev/ptmx c 5 2
200 mknod -m 644 /dev/kmsg c 1 11
210 [ ! -r /etc/sysconfig/console ] && return
211 . /etc/sysconfig/console
212 if [ -n "$CONSOLEFONT" ]; then
213 font=$(ls -1 /lib/kbd/consolefonts/${CONSOLEFONT}*.gz 2> /dev/null)
214 if [ -n "$font" ]; then
215 verbose "Loading font $font"
216 busybox_applet loadfont
217 inst_d "/lib/kbd/consolefonts"
218 cp -a "$font" "$DESTDIR/lib/kbd/consolefonts/"
219 gunzip ${DESTDIR}/lib/kbd/consolefonts/${CONSOLEFONT}*.gz
221 echo "loadfont < $font" | add_linuxrc
226 # generate code to mount /proc on initrd
227 # can be called multiple times
229 if is_yes "$proc_mounted"; then
234 if [ "$INITRDFS" = "initramfs" ]; then
235 # /proc is mounted with initramfs 2.6.22.14 kernel
236 # XXX: remove when it is clear why proc was already mounted
237 echo "[ -f /proc/cmdline ] || mount -t proc none /proc" | add_linuxrc
239 echo "mount -t proc none /proc" | add_linuxrc
243 # generate code to mount /sys on initrd
244 # can be called multiple times
246 if is_yes "$sys_mounted"; then
251 echo "mount -t sysfs none /sys" | add_linuxrc
254 # generate code to mount /tmp on initrd
255 # can be called multiple times
257 if [ "$INITRDFS" = "initramfs" ]; then
258 # initramfs is read-write filesystem, no need for tmpfs
262 if is_yes "$tmp_mounted"; then
267 echo "mount -t tmpfs none /tmp" | add_linuxrc
270 # generate code to mount /run on initrd
271 # can be called multiple times
273 if is_yes "$run_mounted"; then
278 echo "mount -t tmpfs run /run -o mode=0755,noexec,nosuid,nodev" | add_linuxrc
281 # unmount all mountpoints mounted by geninitrd
282 # try to move pseudo filesystems to newroot if possible
286 : Last shell before umounting all and giving control over to real init.
290 if is_yes "$run_mounted"; then
292 mount -n --move /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_TO_INSTALL; do
483 [ $m = $mod ] && have=1
485 if [ $have = 0 ]; then
486 MODULES_TO_INSTALL="$MODULES_TO_INSTALL $mod"
487 if ! is_yes "$USE_MODPROBE"; then
488 MODULES_TO_LOAD="$MODULES_TO_LOAD $mod"
492 if is_yes "$USE_MODPROBE" && [ -n "$mod" ]; then
493 MODULES_TO_LOAD="$MODULES_TO_LOAD $mod"
497 # install a file to temporary mount image.
498 # it will operate recursively (copying directories)
499 # and will symlink destinations if source is symlink.
501 if [ $# -lt 2 ]; then
502 die 'Usage: inst <file> [<file>] <destination>'
505 local src i=0 c=$(($# - 1))
506 while [ $i -lt $c ]; do
513 local parentDir=$(dirname $DESTDIR$dest)
514 if [ ! -d "$parentDir" ]; then
515 verbose "+ mkdir -p DESTDIR${parentDir#$DESTDIR}"
518 verbose "+ cp $* DESTDIR$dest"
519 cp -HRp "$@" "$DESTDIR$dest"
524 die 'Usage: inst_d <destination> <destination>'
528 install -d "$DESTDIR$dir"
532 # install executable and it's shared libraries
534 if [ $# -lt 2 ]; then
535 die "Invalid params ($@), Usage: inst_exec <file>[, <file>] <destination>"
537 local src i=0 c=$(($# - 1))
538 while [ $i -lt $c ]; do
548 local obj lib libs libs_additional libdir
551 /lib/ld-linux.so.2 | /lib64/ld-linux-x86-64.so.2 | /libx32/ld-linux-x32.so.2)
554 /lib/libpthread.so* | /lib64/libpthread.so* | /libx32/libpthread.so*)
555 libs_additional="${obj%/libpthread*}/libgcc_s.so.1"
560 libs=$(ldd "$obj" 2> /dev/null | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
561 for lib in $libs $libs_additional; do
562 libdir=$(cd $(dirname "$lib"); pwd)
563 if [ ! -f "$DESTDIR/$lib" ]; then
565 inst_exec $lib $libdir
570 # hack for uclibc linked binaries requiring this fixed path
571 # XXX: shouldn't rpath be used here instead so th
572 for _lib in $(get_libdir LIBDIR); do
573 if [ -f $DESTDIR/$_lib/libc.so.0 ]; then
574 lib=$DESTDIR/$_lib/libc.so.0
575 lib=$(ldd "$lib" 2> /dev/null | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
576 libdir=$(cd $(dirname "$lib"); pwd)
577 if [ ! -e $DESTDIR$libdir ]; then
578 libdir=$(dirname "$libdir")
580 verbose "+ ln -s /$_lib $DESTDIR$libdir"
581 ln -s /$_lib $DESTDIR$libdir
589 local start_point="$1" pattern="$2"
591 test -n "$(find "$start_point" -mindepth 1 -maxdepth 1 -name "$pattern" -print -quit)"
594 # output modules.conf / modprobe.conf
596 echo "$modprobe_conf_cache"
599 # return options for MODULE
600 # @param $1 module name
603 local options=$(modprobe_conf | awk -vmodule="$module" '{ if ($1 == "options" && $2 == module) { for(i=3;i<=NF;i++) printf("%s ",$i); }}')
608 # defaults to modprobe -c if not told otherwise, this means include statements
610 cache_modprobe_conf() {
611 if [ "$kernel_version" -lt "002005" ]; then
612 modulefile=/etc/modules.conf
613 if [ ! -f "$modulefile" -a -f /etc/conf.modules ]; then
614 modulefile=/etc/conf.modules
618 if [ -n "$modulefile" ]; then
619 debug "Using $modulefile for modules config"
620 modprobe_conf_cache=$(cat $modulefile | awk '!/^[\t ]*#/ { print }')
623 debug "Using modprobe -c to get modules config"
624 modprobe_conf_cache=$(modprobe -c --set-version $kernel | awk '!/^[\t ]*#/ { print }')
628 # find modules for $devpath
629 find_modules_for_devpath() {
631 if [ -z "$devpath" ]; then
632 die "No argument passed to find_modules_for_devpath() - is your /etc/fstab correct?"
635 if [[ "$devpath" = /dev/dm-* ]]; then
636 # /dev/dm-3 -> /dev/mapper/sil_ahbgadcbchfc3
637 devpath=$(dm_node "$devpath")
640 if [ -L "$devpath" ] && ! is_lvm "$devpath" && ! is_luks "$devpath"; then
641 # sanitize things like:
642 # /dev/block/104:2 -> /dev/cciss/c0d0p2
643 devpath=$(readlink -f "$devpath")
646 verbose "Finding modules for device path $devpath"
648 if is_luks "$devpath"; then
649 find_modules_luks "$devpath"
653 if is_nfs "$devpath"; then
654 find_modules_nfs "$devpath"
658 if is_md "$devpath"; then
659 find_modules_md "$devpath"
663 if is_multipath "$devpath"; then
664 if find_modules_multipath "$devpath"; then
671 if is_dmraid "$devpath"; then
672 if find_modules_dmraid "$devpath"; then
678 if is_scsi "$devpath"; then
679 find_modules_scsi "$devpath"
683 if is_ide "$devpath"; then
684 find_modules_ide "$devpath"
688 if [[ "$devpath" == /dev/nvme* ]]; then
693 if [[ "$devpath" == /dev/bcache* ]]; then
694 find_modules_bcache "$devpath"
698 if [[ "$devpath" == /dev/rd/* ]]; then
704 if [[ "$devpath" == /dev/ida/* ]]; then
705 find_module "cpqarray"
706 rootdev_add=/dev/ida/
710 if [[ "$devpath" == /dev/cciss/* ]]; then
711 rootdev_add=/dev/cciss/
713 # load hpsa for future kernels, cciss for backwards compat
714 if [ "$kernel_version_long" -ge "003000000" ]; then
715 find_module "hpsa" "-cciss"
716 find_modules_scsi "$devpath"
724 if [[ "$devpath" == /dev/ataraid/* ]]; then
726 find_module "ataraid"
727 ataraidmodules=$(modprobe_conf | awk '/ataraid_hostadapter/ { print $3 }')
728 if [ -n "$ataraidmodules" ]; then
729 # FIXME: think about modules compiled in kernel
730 die "ataraid_hostadapter alias not defined in modprobe.conf! Please set it and run $PROGRAM again."
732 for n in $ataraidmodules; do
735 rootdev_add=/dev/ataraid/
739 # check to see if we need to set up a loopback filesystem
740 if [[ "$devpath" == /dev/loop* ]]; then
741 die "Sorry, root on loop device isn't supported."
742 # TODO: rewrite for bsp and make nfs ready
743 if [ ! -x /sbin/losetup ]; then
744 die "losetup is missing"
746 key="^# $(echo $devpath | awk -F/ '{print($3);}' | tr '[a-z]' '[A-Z]'):"
747 if ! is_yes "`awk '/'$key'/ { print( "yes"); }' $fstab`"; then
748 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"
751 line="`awk '/'$key'/ { print $0; }' $fstab`"
752 loopDev="$(echo $line | awk '{print $3}')"
753 loopFs="$(echo $line | awk '{print $4}')"
754 loopFile="$(echo $line | awk '{print $5}')"
756 BASICMODULES="$BASICMODULES -loop"
757 find_module "-$loopFs"
758 BASICMODULES="$BASICMODULES -${loopFs}"
762 if is_lvm "$devpath"; then
763 find_modules_lvm "$devpath"
768 firmware_install_module() {
770 local firmware_files="$2"
772 verbose "Adding Firmwares ($firmware_files) to initrd for module $module"
773 # firmware not yet installed
774 if [ ! -f "$DESTDIR/lib/firmware/firmware.sh" ]; then
776 cat << 'EOF' >> "$DESTDIR/lib/firmware/firmware.sh"
778 # handle only firmware add requests
779 if [ "$SUBSYSTEM" != "firmware" ]; then
782 if [ "$ACTION" != "add" ]; then
785 echo 1 > /sys$DEVPATH/loading
786 cat "/lib/firmware/$FIRMWARE" > /sys$DEVPATH/data
787 echo 0 > /sys$DEVPATH/loading
790 chmod 755 "$DESTDIR/lib/firmware/firmware.sh"
792 # setup firmware loader agent
793 echo "echo -n "/lib/firmware/firmware.sh" > /proc/sys/kernel/hotplug" | add_linuxrc
796 for firmware in $firmware_files; do
797 if [ -f "/lib/firmware/$kernel/$firmware" ]; then
798 FIRMWAREDIR=${firmware%/*}
799 [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
800 inst /lib/firmware/$kernel/$firmware /lib/firmware/$firmware
801 elif [ -f "/lib/firmware/$firmware" ]; then
802 FIRMWAREDIR=${firmware%/*}
803 [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
804 inst /lib/firmware/$firmware /lib/firmware/$firmware
806 warn "Possible missing firmware file /lib/firmware/$firmware or /lib/firmware/$kernel/$firmware for module $module."
817 for mod in $modules; do
819 inst_d "/lib/modules/$kernel/$MODULEDIR"
820 cp -a "/lib/modules/$kernel/$mod" "$DESTDIR/lib/modules/$kernel/$mod"
823 gunzip "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress gz"
827 xz -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress xz"
831 bzip2 -d "$DESTDIR/lib/modules/$kernel/$mod" || die "Can't uncompress bz2"
835 if [ "$STRIP" ] && [ -x "$STRIP" ]; then
836 $STRIP -g --remove-section=.comment "$DESTDIR/lib/modules/$kernel/${mod}"
841 modules_add_linuxrc() {
845 # module path without optional compression
847 modpath=${modpath%.xz}
848 modpath=${modpath%.bz2}
851 local module=${modpath##*/}; module=${module%$modext}
853 if ! is_yes "$USE_MODPROBE"; then
854 options=$(modprobe_options "$module")
856 local genericname=$(echo $module | tr - _)
857 local usleep=$(eval echo \$MODULE_${genericname}_USLEEP)
858 local firmware=$(eval echo \$MODULE_${genericname}_FIRMWARE)
860 if [ "$module" = "scsi_mod" -a "$kernel_version_long" -ge "002006030" ]; then
861 options="scan=sync $options"
864 if [ x"$verbose" = x"-v" ]; then
866 if [ "$options" ]; then
867 s="$s with options [$options]"
869 if [ "$usleep" ]; then
870 s="$s and $usleep usleep"
872 verbose "Loading module [$module]$s"
875 if [ -n "$firmware" ]; then
876 firmware_install_module "$module" "$firmware"
878 for file in $(find_firmware "$module"); do
879 firmware_install_module "$module" "$file"
883 if is_yes "$USE_MODPROBE"; then
884 echo "/sbin/modprobe $module $options" | add_linuxrc
886 echo "insmod /lib/modules/$kernel/$modpath $options" | add_linuxrc
888 if [ -n "$usleep" ]; then
889 echo "usleep $usleep" | add_linuxrc
891 if [ "$module" = "scsi_wait_scan" ]; then
892 if [ "$(busybox_applet rmmod 2>/dev/null; echo $?)" = 0 ]; then
893 echo "rmmod scsi_wait_scan" | add_linuxrc
900 # Generates /dev nodes based on /proc/partitions information.
901 # Needs /proc mounted.
902 # Can be called multiple times.
903 initrd_gen_devices() {
904 if is_yes "$proc_partitions"; then
911 : 'Making device nodes'
912 cat /proc/partitions | (
913 # ignore first two lines: header, empty line
916 while read major minor blocks dev rest; do
919 [ -e $node ] || mknod -m 660 $node b $major $minor
926 initrd_gen_setrootdev() {
927 verbose "Adding rootfs finding based on kernel cmdline root= option support."
929 debug "Current /proc/partitions:\n$(sed -e 's,^,| ,' /proc/partitions)"
931 if [ "${ROOT##/dev/}" != "${ROOT}" ]; then
932 rootnr="$(busybox awk -v rootnode="${ROOT##/dev/}" '$4 == rootnode { print 256 * $1 + $2 }' /proc/partitions)"
933 # fallback to ls, try two different formats
934 # http://lists.pld-linux.org/mailman/pipermail/pld-devel-en/2014-May/023915.html
935 if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
937 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $3 + $4; }}')"
939 if [ "${rootnr:-0}" = 0 -a -e "$ROOT" ]; then
940 # busybox 1.22 and upwards
941 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $5 + $6; }}')"
943 if [ "${rootnr:-0}" -gt 0 ]; then
944 echo "$rootnr" > /proc/sys/kernel/real-root-dev
950 initrd_gen_initramfs_switchroot() {
952 if [ "$rootdev" = "/dev/nfs" ]; then
953 echo "rootfs on NFS root=/dev/nfs"
955 [ -e $rootdev ] && [ ! -e "$DESTDIR/$rootdev" ] && inst $rootdev $rootdev
958 # parse 'root=xxx' kernel commandline
959 # We support passing root as hda3 /dev/hda3 0303 0x0303 and 303
961 # from lilo-23.2/readme/README:
962 # root=<device> changes the root device. This overrides settings that may
963 # have been made in the boot image and on the LILO command line. <device> is
964 # either the hexadecimal device number or the full path name of the device,
967 # * The device names are hard-coded in the kernel. Therefore, only the
968 # "standard" names are supported and some less common devices may not be
969 # recognized. In those cases, only numbers can be used.
973 eval "$(busybox awk -v root="$ROOT" '
974 function h2d(str, hstr, res, num, n, digit, i) { # http://9fans.net/archive/2006/09/261
975 hstr = "0123456789abdcef"; res = 0;
976 n = split(tolower(str), digit, "");
978 for (i = 1; i <= n; i++) {
979 num = index(hstr, digit[i]) - 1;
980 res = res + (num * 16 ^ (n - i));
985 num_pattern_short = "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]";
986 num_pattern = "[0-9a-fA-F]" num_pattern_short;
987 dev_pattern = "[hms][a-z][a-z]([0-9])+";
988 partition = ""; min = -1; maj = -1;
990 if (root ~ "^\/dev\/" dev_pattern "$" || root ~ "^" dev_pattern "$") { # see if we have /dev/hdX or hdX, we can just take partition name
991 partition = root; sub("^/dev/", "", partition);
992 } else { # unify values first
993 if (root ~ "^" num_pattern_short "$") { # change "303" => "0x0303"
995 } else if (root ~ "^" num_pattern "$") { # change "0303" => "0x0303"
998 maj = h2d(substr(root, 3, 2));
999 min = h2d(substr(root, 5, 2));
1002 partition && $4 == partition { maj = $1; min = $2; }
1003 $1 == maj && $2 == min { partition = $4; }
1005 if (maj >= 0 && min >= 0) { printf("maj=%s; min=%s;\n", maj, min); }
1006 if (partition) { printf("device=/dev/%s;\n", partition); }
1007 }' /proc/partitions)"
1009 if [ -z "$device" ]; then
1010 if [ "$DEBUGINITRD" -a "$DEBUGINITRD" != 'sh' ]; then
1011 cat /proc/partitions
1016 if [ "$device" -a ! -b $device -a "$maj$min" ]; then
1017 mknod -m 660 $device b $maj $min
1020 # XXX hack, fallback to rootdev from geninitrd time
1021 if [ ! -e "$device" ]; then
1026 add_linuxrc <<-'EOF'
1027 echo "DEVICE set to $device based on fstab entry from initrd gen time"
1030 # XXX hack, if no device, try to parse it from /proc/partitions using /proc/sys/kernel/real-root-dev
1031 if [ ! -e "$device" ]; then
1032 rrd=$(cat /proc/sys/kernel/real-root-dev)
1033 major=$(($rrd / 256))
1034 minor=$(($rrd % 256))
1036 while read pmajor pminor blocks dev rest; do
1037 # skip header and empty line
1038 [ -z "$pmajor" -o "$pmajor" = "major" ] && continue
1040 if [ $pmajor = $major -a $pminor = $minor ]; then
1042 echo "DEVICE set to $device based on real-root-dev"
1044 done < /proc/partitions
1047 [ -n "$ROOTFLAGS" ] && ROOTFLAGS="-o $ROOTFLAGS"
1049 mount -t $ROOTFS -r $device $ROOTFLAGS /newroot || echo "Mount of rootfs failed."
1051 if [ -z "$init" -o ! -x "/newroot$init" ]; then
1056 busybox_applet dmesg
1058 add_linuxrc <<-'EOF'
1059 if [ "$DEBUGINITRD" -a "$DEBUGINITRD" != 'sh' ]; then
1060 echo "Last 20 lines of dmesg:"
1066 kmsg "geninitrd/$VERSION switching root"
1069 busybox_applet switch_root usleep mountpoint
1070 add_linuxrc <<-'EOF'
1071 [ ! -e /newroot/dev/console ] && mountpoint -q /newroot/dev && mknod -m 660 /newroot/dev/console c 5 1
1073 # switch root to empty dir will make kernel panic, so sleep 10s before it
1074 # switch_root needs to be pid 1, so there's no other way to recover from here
1075 # if /dev is missing, switch root will likely fail, give debug shell before that
1076 if [ ! -d /newroot/dev ]; then
1077 echo "/dev is missing, switch_root will likely fail"
1078 echo "if you booted with debugrd=sh, then you be given shell and you might able to recover this situation"
1080 [ "$DEBUGINITRD" ] || usleep 10000000
1083 # systemd[1]: /usr appears to be on its own filesytem and is not
1084 # already mounted. This is not a supported setup. Some things will
1085 # probably break (sometimes even silently) in mysterious ways. Consult
1086 # http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken
1087 # for more information.
1088 if chroot /newroot findmnt -s -n /usr > /dev/null 2> /dev/null; then
1089 echo trying to mount /usr
1090 chroot /newroot mount -n /usr
1093 exec switch_root /newroot $init ${1:+"$@"}
1095 # FIXME: this code is never executed, as "exec" does not return!
1097 echo "Error! initramfs should not reach this place."
1098 echo "It probably means you've got old version of busybox, with broken"
1099 echo "initramfs support. Trying to boot anyway, but won't promise anything."
1101 exec chroot /newroot $init ${1:+"$@"}
1103 echo "Failed to chroot!"
1106 # we need /init being real file, not symlink, otherwise the initramfs will
1107 # not be ran by pid 1 which is required for switch_root
1108 mv $DESTDIR/linuxrc $DESTDIR/init
1109 ln -s init $DESTDIR/linuxrc
1112 # find if $symbol exists in System.map $mapfile
1116 if [ ! -f $mapfile ]; then
1117 # missing mapfile (not a pld kernel?)
1121 awk -vc=1 -vsymbol="$symbol" '(tolower($2) == "t" || tolower($2) == "d") && $3 == symbol {c = 0} END {exit c}' $mapfile
1124 # find best compressor (or forced one) for initrd
1127 local compressors='zstd xz lzma bzip2 gzip lzo lz4'
1129 # a specified one, take it
1130 if ! is_yes "$mode"; then
1134 verbose "finding compressor: $compressors (via $mode)"
1135 # check for compressor validity
1136 local c prog map=/boot/System.map-$kernel
1137 for c in $compressors; do
1168 # any existing sym will work
1173 die "Unknown compressor $c"
1176 if sym_exists $map $sym && [ -x $prog ]; then
1182 verbose "using gzip for compressor (fallback)"
1186 # compresses kernel image image
1187 # in function so we could retry with other compressor on failure
1189 local compressor="$1" IMAGE="$2" target="$3" tmp
1190 tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1192 case "$compressor" in
1194 # don't use -9 here since kernel won't understand it
1195 xz --format=xz --check=crc32 --lzma2=preset=6e,dict=1MiB < "$IMAGE" > "$tmp" || return $?
1198 xz --format=lzma -9 < "$IMAGE" > "$tmp" || return $?
1201 bzip2 -9 < "$IMAGE" > "$tmp" || return $?
1204 gzip -9 < "$IMAGE" > "$tmp" || return $?
1207 lzop -9 < "$IMAGE" > "$tmp" || return $?
1210 zstd -9 < "$IMAGE" > "$tmp" || return $?
1213 lz4 -9 -l < "$IMAGE" > "$tmp" || return $?
1216 cat < "$IMAGE" > "$tmp" || return $?
1220 mv -f "$tmp" "$target"
1223 # prepend file to image
1224 prepend_file_to_image() {
1225 local file="$1" target="$2" tmp
1226 tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1228 cat "$file" "$target" > "$tmp" || return $?
1230 mv -f "$tmp" "$target"
1233 if [ -r /etc/sysconfig/geninitrd ]; then
1234 . /etc/sysconfig/geninitrd
1237 if [ ! -f /proc/mounts ]; then
1238 warn "/proc filesystem not mounted, may cause wrong results or failure."
1241 geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev swsusp tuxonice suspend fbsplash condecor bootsplash uvesafb nfs sata scsi usbkbd bcache
1243 while [ $# -gt 0 ]; do
1253 modulefile=${1#--modules-conf=}
1262 --without-bootsplash)
1274 --without-fbcondecor)
1292 --with-suspend2 | --with-tuxonice)
1295 --without-suspend2 | --without-tuxonice)
1299 LVMTOOLSVERSION=${1#--lvmversion=}
1301 --lvmtoolsversion=*)
1302 LVMTOOLSVERSION=${1#--lvmtoolsversion=}
1304 --lvmtoolsversion|--lvmversion)
1317 --without-multipath)
1321 USE_MULTIPATH=${1#--with-multipath=}
1330 BASICMODULES="$BASICMODULES ${1#--with=}"
1333 BASICMODULES="$BASICMODULES $2"
1337 echo "$PROGRAM: version $VERSION"
1341 if [ x"$verbose" = x"-v" ]; then
1352 COMPRESS="${1#--compress=}"
1361 STRIP="${1#--strip=}"
1374 PREMODS="$PREMODS ${1#--preload=}"
1377 PREMODS="$PREMODS $2"
1381 die "--fs option is obsoleted. Use --initrdfs instead"
1384 INITRDFS=${1#--initrdfs=}
1397 if [ -z "$target" ]; then
1399 elif [ -z "$kernel" ]; then
1411 if [ -z "$target" -o -z "$kernel" ]; then
1417 if [ "$(id -u)" != 0 ]; then
1418 die "You need to be root to generate initrd"
1421 for dir in libx32 lib64 lib; do
1422 initrd_dir=/usr/$dir/initrd
1423 if [ -d "$initrd_dir" ]; then
1424 initrd_dirs="$initrd_dirs $initrd_dir"
1428 kernel_version=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d",$1,$2)}')
1429 kernel_version_long=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d%03d",$1,$2,$3)}')
1431 verbose "# geninitrd $VERSION"
1432 debug "Using initrd_dir: $initrd_dir"
1434 busybox=$(find_tool $initrd_dir/busybox $initrd_dir/initrd-busybox /bin/initrd-busybox) || die "Couldn't find busybox suitable for initrd"
1436 # we setup mods after parsing command line args
1437 geninitrd_setup_mods
1439 if [ ! -f /boot/vmlinuz-"$kernel" ]; then
1440 warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?"
1443 if [ -z "$INITRDFS" ]; then
1444 if [ -n "$FS" ]; then
1445 # FS= can came only via /etc/sysconfig/geninitrd likely?
1446 die "FS configuration option is obsoleted. Use INITRDFS instead"
1450 if [ "$kernel_version" -ge "002005" ]; then
1451 INITRDFS="initramfs"
1458 local s sfound sym p prog map=/boot/System.map-$kernel
1461 # TODO: symbols to check in case of ext2 used via ext3/4 subsystem
1474 sym=__initramfs_start
1475 prog="/bin/cpio /usr/bin/find"
1478 die "Filesystem $INITRDFS on initrd is not supported by geninitrd"
1482 # only one is needed (for cases like ext2 via ext2 or via ext3 or via ext4 subsysytem)
1485 sym_exists $map $s && sfound=1
1488 if [ "$sfound" -eq "0" ]; then
1489 die "Filesystem $INITRDFS on initrd is not supported by kernel"
1493 [ ! -x "$p" ] && die "$prog is missing"
1498 if [ -L "$target" ]; then
1499 target=$(readlink -f "$target")
1502 if [ -n "$img_vers" ]; then
1503 target="$target-$kernel"
1506 if [ -z "$force" -a -f "$target" ]; then
1507 die "$target already exists."
1510 if [ ! -d "/lib/modules/$kernel" ]; then
1511 die "/lib/modules/$kernel is not a directory."
1514 if [ "$kernel_version" -ge "002005" ]; then
1520 for n in $PREMODS; do
1524 if [ "$FBMODULE" ]; then
1525 find_module "$FBMODULE"
1528 # autodetect USB keyboards
1531 # allow forcing loading SCSI and/or IDE modules
1532 # XXX: where ADDSCSI cames from? drop?
1533 if is_yes "$ADDSCSI"; then
1537 # autodetect SATA modules
1540 # XXX: where ADDIDE cames from? drop?
1541 if is_yes "$ADDIDE"; then
1545 if is_yes "$USE_SUSPEND"; then
1546 find_modules_suspend
1549 if is_yes "$USE_SWSUSP"; then
1553 find_root "$fstab" || exit
1554 verbose "Using $rootdev as device for rootfs"
1556 find_modules_for_devpath "$rootdev"
1558 # if USE_MULTIPATH is path to device, scan that too
1559 # this is to bootstrap multipath setup into initrd.
1560 if ! is_no "$USE_MULTIPATH" && ! is_yes "$USE_MULTIPATH"; then
1561 find_modules_multipath $USE_MULTIPATH
1564 find_module "-$rootFs"
1566 for n in $BASICMODULES; do
1570 if is_yes "$USE_TUXONICE"; then
1574 find_modules_uvesafb
1575 find_modules_fbsplash
1577 if [ -n "$ifneeded" -a -z "$MODULES_TO_LOAD" ]; then
1578 verbose "No modules are needed -- not building initrd image."
1582 verbose "Building initrd..."
1583 DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
1584 RCFILE="$DESTDIR/linuxrc"
1586 chmod a+rx "$RCFILE"
1587 ln -s linuxrc $DESTDIR/init
1589 # create dirs that we really need
1590 inst_d /{lib,bin,sbin,etc,dev{,/pts,/shm},loopfs,var,proc,run,sys,tmp}
1592 modules_install "$MODULES_TO_INSTALL"
1594 if is_yes "$USE_MODPROBE"; then
1595 inst /lib/modules/$kernel/modules.{builtin,order} /lib/modules/$kernel
1596 depmod -b "$DESTDIR" $kernel
1599 # mknod'ing the devices instead of copying them works both with and
1601 mknod -m 600 "$DESTDIR/dev/console" c 5 1
1602 mknod -m 666 "$DESTDIR/dev/null" c 1 3
1603 mknod -m 666 "$DESTDIR/dev/zero" c 1 5
1604 mknod -m 666 "$DESTDIR/dev/random" c 1 8
1605 mknod -m 666 "$DESTDIR/dev/urandom" c 1 9
1606 mknod -m 644 "$DESTDIR/dev/kmsg" c 1 11
1608 inst_exec $busybox /bin/busybox
1609 ln -s busybox $DESTDIR/bin/sh
1610 # for older busyboxes who had /bin/initrd-busybox as EXEPATH
1611 ln -s busybox $DESTDIR/bin/initrd-busybox
1615 # initrd generated by geninitrd/$VERSION
1616 # on $(LC_ALL=C date)
1622 kmsg "geninitrd/$VERSION starting"
1624 inst_d /lib/geninitrd/
1625 inst /lib/geninitrd/functions.initrd /lib/geninitrd/functions.initrd
1628 . /lib/geninitrd/functions.initrd
1629 # builtin defaults from geninitrd
1633 add_linuxrc <<-'EOF'
1634 read CMDLINE < /proc/cmdline
1636 for arg in $CMDLINE; do
1637 if [ "${arg}" = "debuginitrd" ] || [ "${arg}" = "debugrd" ]; then
1640 if [ "${arg##debuginitrd=}" != "${arg}" ] || [ "${arg##debugrd=}" != "${arg}" ]; then
1641 DEBUGINITRD=${arg##debug*rd=}
1643 if [ "${arg##root=}" != "${arg}" ]; then
1646 if [ "${arg##rootfs=}" != "${arg}" ]; then
1647 ROOTFS=${arg##rootfs=}
1649 if [ "${arg##rootflags=}" != "${arg}" ]; then
1650 ROOTFLAGS=${arg##rootflags=}
1652 if [ "${arg##rootfsflags=}" != "${arg}" ]; then
1653 ROOTFSFLAGS=${arg##rootfsflags=}
1655 if [ "${arg##init=}" != "${arg}" ]; then
1660 # handling of invalid, rootfsflags, option
1661 if [ -n "$ROOTFSFLAGS" ]; then
1662 if [ -n "$ROOTFLAGS" ]; then
1663 ROOTFLAGS="$ROOTFLAGS,$ROOTFSFLAGS"
1665 ROOTFLAGS="$ROOTFSFLAGS"
1669 if [ "$DEBUGINITRD" = "sh" ]; then
1670 # export some vars to subshell for debug to work
1671 export CMDLINE ROOT ROOTFS ROOTDEV ROOTFLAGS DEBUGINITRD INIT
1672 export LVM_ROOTVG LVM_SUSPENDVG LVM_VGVOLUMES
1673 export rootnr attrs majmin major minor device
1675 # make debugshell() invoke subshell if $DEBUGINITRD=sh
1678 if is_yes "$RUN_SULOGIN_ON_ERR"; then
1679 add_linuxrc <<-'EOF'
1680 echo "debug shell disabled by RUN_SULOGIN_ON_ERR=yes from /etc/sysconfig/system during initrd generation time"
1683 add_linuxrc <<-'EOF'
1687 add_linuxrc <<-'EOF'
1695 if [ "$DEBUGINITRD" ]; then
1704 if is_yes "$USE_MODPROBE"; then
1705 if files_exist /lib/modprobe.d '*.conf'; then
1706 inst_d /lib/modprobe.d
1707 inst /lib/modprobe.d/*.conf /lib/modprobe.d
1709 if files_exist /etc/modprobe.d '*.conf'; then
1710 inst_d /etc/modprobe.d
1711 inst /etc/modprobe.d/*.conf /etc/modprobe.d
1713 if files_exist /etc/modprobe.d/$kernel '*.conf'; then
1714 inst_d /etc/modprobe.d/$kernel
1715 inst /etc/modprobe.d/$kernel/*.conf /etc/modprobe.d/$kernel
1717 inst_exec /sbin/modprobe /sbin
1720 modules_add_linuxrc $MODULES_TO_LOAD
1722 # TODO: rewrite for busybox
1723 #if [ -n "$loopDev" ]; then
1724 # if [ ! -d /initrd ]; then
1728 # cp -a "$loopDev" "$DESTDIR/dev"
1729 # cp -a "$rootdev" "$DESTDIR/dev"
1730 # echo "echo Mounting device containing loopback root filesystem" >> "$RCFILE"
1731 # echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE"
1732 # echo "echo Setting up loopback device $rootdev" >> $RCFILE
1733 # echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE"
1736 if is_yes "$USE_UDEV"; then
1745 initrd_gen_multipath
1748 if is_yes "$have_nfs"; then
1756 initrd_gen_setrootdev
1759 # additional devs always needed
1760 [ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev
1762 initrd_gen_stop_udevd
1763 initrd_gen_stop_mdev
1764 initrd_gen_stop_uvesafb
1766 # resume after killing local processes
1772 add_linuxrc <<-'EOF'
1773 if [ ! "$DEBUGINITRD" ]; then
1777 for i in $(export -p); do
1778 i=${i#declare -x } # ksh/bash
1779 i=${i#export } # busybox
1790 [ -z "$i" ] && continue
1793 ROOT|PATH|HOME|TERM)
1805 if [ "$INITRDFS" = "initramfs" ]; then
1806 initrd_gen_initramfs_switchroot
1812 initrd_gen_fbcondecor
1814 debug "Current /linuxrc:\n$(sed -e 's,^,| ,' $DESTDIR/linuxrc)"
1816 IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed"
1818 IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
1819 verbose "image size: $IMAGESIZE KiB ($DESTDIR)"
1821 verbose "Creating $INITRDFS image $IMAGE"
1824 dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null
1825 # NOTE: ext2 label is max 16 chars
1826 mke2fs -q -F -b 1024 -m 0 -L "PLD/$kernel" "$IMAGE" 2>/dev/null 1>&2
1827 tune2fs -i 0 "$IMAGE" >/dev/null 2>&1
1829 local tmpmnt=$(mktemp -d -t initrd.mnt-XXXXXX)
1830 debug "Mounting ext2 image $IMAGE to $tmpmnt"
1831 mount -o loop -t ext2 "$IMAGE" "$tmpmnt" || die "mount failed, check dmesg(1)"
1832 # We don't need this directory, so let's save space
1833 rm -rf "$tmpmnt"/lost+found
1835 debug "Copy recursively $DESTDIR -> $tmpmnt"
1836 cp -a $DESTDIR/* $tmpmnt
1842 genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD Linux/$kernel (geninitrd/$VERSION)"
1845 mkcramfs "$DESTDIR" "$IMAGE"
1848 (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
1851 die "Filesystem $INITRDFS not supported by $PROGRAM"
1854 if [ "$INITRDFS" != "initramfs" ]; then
1855 CONFIG_BLK_DEV_RAM_SIZE=$(ikconfig | awk -F= '/^CONFIG_BLK_DEV_RAM_SIZE/{print $2}')
1856 if [ -z "$CONFIG_BLK_DEV_RAM_SIZE" ]; then
1857 CONFIG_BLK_DEV_RAM_SIZE=4096
1858 warn "No CONFIG_BLK_DEV_RAM_SIZE detected, fallback to $CONFIG_BLK_DEV_RAM_SIZE"
1861 if [ "$IMAGESIZE" -gt $CONFIG_BLK_DEV_RAM_SIZE ]; then
1862 warn "Your image size is larger than $CONFIG_BLK_DEV_RAM_SIZE, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!"
1866 if ! is_no "$COMPRESS"; then
1867 compressor=$(find_compressor "$COMPRESS")
1868 verbose "Compressing $target with $compressor"
1870 # TODO: the image name (specified from kernel.spec) already contains
1871 # extension, which is .gz most of the time.
1872 compress_image "$compressor" "$IMAGE" "$target" || {
1873 if [ $compressor != gzip ]; then
1874 warn "Could not compress with $compressor, retrying with gzip"
1875 compress_image gzip "$IMAGE" "$target" || die "compress failed with gzip" $?
1877 die "Could not compress image with $compressor"
1881 cp -a "$IMAGE" "$target"
1884 # microcode support for lilo
1885 if ! is_no "$LILO_MICROCODE"; then
1886 if [ -x /sbin/lilo -a -f "/boot/intel-ucode.img" ]; then
1887 verbose "Prepending $target with microcode image /boot/intel-ucode.img for LILO"
1888 prepend_file_to_image "/boot/intel-ucode.img" "$target"
1892 # XXX. check if bootsplash can output data to tmp dir not directly to initramfs image.
1893 initrd_gen_bootsplash "$target"
1895 rm -rf "$DESTDIR" "$IMAGE"
1897 # vim:ts=4:sw=4:noet:fdm=marker