7 # based on mkinitrd from RedHat Linux
10 GENINITRD_RCSID='$Revision$ $Date:: $'
11 R=${GENINITRD_RCSID#* *}; VERSION=${R%% *}
14 . /etc/rc.d/init.d/functions
15 . /lib/geninitrd/functions
16 . /etc/sysconfig/system
18 # 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|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 # aborts program abnormally
97 # find program from specified paths
100 local paths="$initrd_dir /bin /sbin /usr/bin /usr/sbin"
102 debug "find_tool: checking $x"
105 verbose "find_tool: found $x"
111 debug "find_tool: checking $p/$b"
112 if [ -x "$p/$b" ]; then
114 verbose "find_tool: found $p/$b"
120 debug "find_tool: did not find any of: $n"
124 # loads geninitrd modules
125 geninitrd_load_mods() {
128 if [ ! -f /lib/geninitrd/mod-$mod.sh ]; then
129 die "$mod geninitrd module can't be loaded"
131 . /lib/geninitrd/mod-$mod.sh
133 GENINITRD_MODS="$GENINITRD_MODS $mod"
137 # setup geninitrd modules
138 geninitrd_setup_mods() {
141 for mod in $GENINITRD_MODS; do
142 eval rcsid=$(echo \$$mod | LC_ALL=C tr '[a-z]' '[A-Z]')_RCSID
143 debug "# $rcsid (mod-$mod)"
145 # some mods want init
146 if type setup_mod_$mod > /dev/null; then
152 # append text to /linuxrc
153 # takes STDIN as input
158 # generate code to mount /dev on tmpfs and create initial nodes
159 # can be called multiple times. /dev is cleaned up (umounted) automatically at
162 # we already generated tmpfs code; return
163 if is_yes "$dev_mounted"; then
169 busybox_applet mount mknod mkdir
172 if ! mount -t devtmpfs -o mode=0755,nosuid devtmpfs /dev > /dev/null 2>&1; then
173 mount -o mode=0755,nosuid -t tmpfs tmpfs /dev
174 mknod -m 600 /dev/console c 5 1
175 mknod -m 666 /dev/null c 1 3
176 mknod -m 666 /dev/zero c 1 5
177 mknod -m 666 /dev/random c 1 8
178 mknod -m 600 /dev/snapshot c 10 231
179 mknod -m 666 /dev/urandom c 1 9
180 mknod -m 666 /dev/ptmx c 5 2
181 mknod -m 644 /dev/kmsg c 1 11
188 # generate code to mount /proc on initrd
189 # can be called multiple times
191 if is_yes "$proc_mounted"; then
196 if [ "$INITRDFS" = "initramfs" ]; then
197 # /proc is mounted with initramfs 2.6.22.14 kernel
198 # XXX: remove when it is clear why proc was already mounted
199 echo "[ -f /proc/cmdline ] || mount -t proc none /proc" | add_linuxrc
201 echo "mount -t proc none /proc" | add_linuxrc
205 # generate code to mount /sys on initrd
206 # can be called multiple times
208 if is_yes "$sys_mounted"; then
213 echo "mount -t sysfs none /sys" | add_linuxrc
216 # generate code to mount /tmp on initrd
217 # can be called multiple times
219 if [ "$INITRDFS" = "initramfs" ]; then
220 # initramfs is read-write filesystem, no need for tmpfs
224 if is_yes "$tmp_mounted"; then
229 echo "mount -t tmpfs none /tmp" | add_linuxrc
232 # generate code to mount /run on initrd
233 # can be called multiple times
235 if is_yes "$run_mounted"; then
240 echo "mount -t tmpfs run /run" | add_linuxrc
243 # unmount all mountpoints mounted by geninitrd
244 # try to move pseudo filesystems to newroot if possible
248 : Last shell before umounting all and giving control over to real init.
252 if is_yes "$run_mounted"; then
254 mount --bind /run /newroot/run
259 if is_yes "$dev_mounted"; then
261 mount --bind /dev /newroot/dev
266 if is_yes "$sys_mounted"; then
268 mount --bind /sys /newroot/sys
273 if is_yes "$proc_mounted"; then
275 mount --bind /proc /newroot/proc
280 if is_yes "$tmp_mounted"; then
281 echo 'umount /tmp' | add_linuxrc
286 # Checks if busybox has support for APPLET(s)
287 # Exits from geninitrd if the support is not present.
289 # NB! XXX do not output to STDOUT, it will appear in initrd images in some cases!
293 if [ -z "$busybox_functions" ]; then
294 local tmp=$($busybox 2>&1)
296 # BusyBox v1.1.3 says applet not found if it's not called 'busybox'.
297 if [[ "$tmp" = *applet\ not\ found* ]]; then
299 ln -s $busybox $t/busybox
300 local tmp=$($t/busybox 2>&1)
304 busybox_functions=$(echo "$tmp" | \
305 sed -ne '/Currently defined functions:/,$p' | \
306 xargs | sed -e 's,.*Currently defined functions: ,,'
312 eval have='$'busybox_have_$applet
313 if [ -z "$have" ]; then
314 have=$(echo "$busybox_functions" | grep -Ec "( |^)$applet(,|$)")
315 if [ "$have" = 0 ]; then
316 warn "This setup requires busybox-initrd compiled with applet '$applet' support"
319 eval busybox_have_$applet=$have
322 if [ $err = 1 ]; then
327 # Extract the .config file from a kernel image
328 # uses extract-ikconfig from kernel sources (scripts/extract-ikconfig)
330 local kofile=$(modinfo -k $kernel -n configs 2> /dev/null)
331 if [ -n "$kofile" ]; then
332 /lib/geninitrd/extract-ikconfig $kofile
336 # see if config available as separate file
337 if [ -f /boot/config-$kernel ]; then
338 cat /boot/config-$kernel
342 # finally try vmlinuz itself
343 /lib/geninitrd/extract-ikconfig /boot/vmlinuz-$kernel
351 module=${module%$modext*}
355 # Finds module dependencies
359 # Outputs full path to module and it's dependencies
364 # if module is prefixed with dash, we should ignore errors if the module
366 if [ ${module#-} != $module ]; then
371 # This works when user has module-init-tools installed even on 2.4 kernels
373 modprobe=$(modprobe --set-version $kernel --show-depends $module --ignore-install 2>&1)
376 if [ $skiperrors = 1 ]; then
381 if ! is_no "$EXIT_IF_MISSING"; then
382 die "$module: module not found for $kernel kernel"
385 warn "$module: module not found for $kernel kernel"
386 warn "If $module isn't compiled in kernel then this initrd may not start your system."
392 while read insmod modpath options; do
393 if [ "$insmod" = "insmod" ]; then
395 # XXX: find a away to autodetect
396 smodule=$(basename_module $modpath)
399 find_depmod "-crct10dif-pclmul"
400 find_depmod "-crct10dif"
403 find_depmod "-crc32c-intel"
404 find_depmod "-crc32c"
406 virtio_blk|virtio_scsi)
407 find_depmod "-virtio_pci"
408 find_depmod "-virtio_mmio"
421 # no firmware support in 2.4 kernels
422 if [ "$kernel_version_long" -lt "002005048" ]; then
425 echo -n $(NEW_MODINFO=1 modinfo -k $kernel -F firmware $module 2>/dev/null | xargs)
430 local mod depmod module=$1
432 depmod=$(find_depmod $module) || exit 1
433 for mod in $depmod; do
434 mod=${mod#/lib/modules/$kernel/}
436 # add each module only once
438 for m in $MODULES; do
439 [ $m = $mod ] && have=1
441 if [ $have = 0 ]; then
442 MODULES="$MODULES $mod"
447 # install a file to temporary mount image.
448 # it will operate recursively (copying directories)
449 # and will symlink destinations if source is symlink.
451 if [ $# -lt 2 ]; then
452 die 'Usage: inst <file> [<file>] <destination>'
455 local src i=0 c=$(($# - 1))
456 while [ $i -lt $c ]; do
463 local parentDir=$(dirname $DESTDIR$dest)
464 if [ ! -d "$parentDir" ]; then
465 verbose "+ mkdir -p $parentDir"
468 verbose "+ cp $* $DESTDIR$dest"
469 cp -HR "$@" "$DESTDIR$dest"
474 die 'Usage: inst_d <destination> <destination>'
477 install -d "$DESTDIR$dir"
481 # install executable and it's shared libraries
483 if [ $# -lt 2 ]; then
484 die "Invalid params ($@), Usage: inst_exec <file>[, <file>] <destination>"
486 local src i=0 c=$(($# - 1))
487 while [ $i -lt $c ]; do
500 /lib/ld-linux.so.2 | /lib64/ld-linux-x86-64.so.2)
504 libs=$(ldd "$obj" | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
506 if [ ! -f "$DESTDIR/$_lib/${lib##*/}" ]; then
508 inst_exec $lib /$_lib
513 # hack for uclibc linked binaries requiring this fixed path
514 # XXX: shouldn't rpath be used here instead so th
515 if [ -f $DESTDIR/$_lib/libc.so.0 ]; then
516 local lib=$DESTDIR/$_lib/libc.so.0
517 lib=$(ldd "$lib" | awk '/statically|linux-(gate|vdso)\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u)
518 local libdir=$(cd $(dirname "$lib"); pwd)
519 if [ ! -e $DESTDIR$libdir ]; then
520 libdir=$(dirname "$libdir")
522 verbose "+ ln -s /$_lib $DESTDIR$libdir"
523 ln -s /$_lib $DESTDIR$libdir
528 # output modules.conf / modprobe.conf
530 echo "$modprobe_conf_cache"
533 # return options for MODULE
534 # @param $1 module name
537 local options=$(modprobe_conf | awk -vmodule="$module" '{ if ($1 == "options" && $2 == module) { for(i=3;i<=NF;i++) printf("%s ",$i); }}')
542 # defaults to modprobe -c if not told otherwise, this means include statements
544 cache_modprobe_conf() {
545 if [ "$kernel_version" -lt "002005" ]; then
546 modulefile=/etc/modules.conf
547 if [ ! -f "$modulefile" -a -f /etc/conf.modules ]; then
548 modulefile=/etc/conf.modules
552 if [ -n "$modulefile" ]; then
553 debug "Using $modulefile for modules config"
554 modprobe_conf_cache=$(cat $modulefile | awk '!/^[\t ]*#/ { print }')
557 debug "Using modprobe -c to get modules config"
558 modprobe_conf_cache=$(modprobe -c --set-version $kernel | awk '!/^[\t ]*#/ { print }')
562 # find modules for $devpath
563 find_modules_for_devpath() {
565 if [ -z "$devpath" ]; then
566 die "No argument passed to find_modules_for_devpath() - is your /etc/fstab correct?"
569 if [[ "$devpath" = /dev/dm-* ]]; then
570 # /dev/dm-3 -> /dev/mapper/sil_ahbgadcbchfc3
571 devpath=$(dm_node "$devpath")
574 if [ -L "$devpath" ] && ! is_lvm "$devpath" && ! is_luks "$devpath"; then
575 # sanitize things like:
576 # /dev/block/104:2 -> /dev/cciss/c0d0p2
577 devpath=$(readlink -f "$devpath")
580 verbose "Finding modules for device path $devpath"
582 if is_luks "$devpath"; then
583 find_modules_luks "$devpath"
587 if is_nfs "$devpath"; then
588 find_modules_nfs "$devpath"
592 if is_md "$devpath"; then
593 find_modules_md "$devpath"
597 if is_multipath "$devpath"; then
598 if find_modules_multipath "$devpath"; then
605 if is_dmraid "$devpath"; then
606 if find_modules_dmraid "$devpath"; then
612 if is_scsi "$devpath"; then
613 find_modules_scsi "$devpath"
617 if is_ide "$devpath"; then
618 find_modules_ide "$devpath"
622 if [[ "$devpath" == /dev/rd/* ]]; then
628 if [[ "$devpath" == /dev/ida/* ]]; then
629 find_module "cpqarray"
630 rootdev_add=/dev/ida/
634 if [[ "$devpath" == /dev/cciss/* ]]; then
635 rootdev_add=/dev/cciss/
637 # load hpsa for future kernels, cciss for backwards compat
638 if [ "$kernel_version_long" -ge "003000000" ]; then
639 find_module "hpsa" "-cciss"
640 find_modules_scsi "$devpath"
648 if [[ "$devpath" == /dev/ataraid/* ]]; then
650 find_module "ataraid"
651 ataraidmodules=$(modprobe_conf | awk '/ataraid_hostadapter/ { print $3 }')
652 if [ -n "$ataraidmodules" ]; then
653 # FIXME: think about modules compiled in kernel
654 die "ataraid_hostadapter alias not defined in modprobe.conf! Please set it and run $PROGRAM again."
656 for n in $ataraidmodules; do
659 rootdev_add=/dev/ataraid/
663 # check to see if we need to set up a loopback filesystem
664 if [[ "$devpath" == /dev/loop* ]]; then
665 die "Sorry, root on loop device isn't supported."
666 # TODO: rewrite for bsp and make nfs ready
667 if [ ! -x /sbin/losetup ]; then
668 die "losetup is missing"
670 key="^# $(echo $devpath | awk -F/ '{print($3);}' | tr '[a-z]' '[A-Z]'):"
671 if ! is_yes "`awk '/'$key'/ { print( "yes"); }' $fstab`"; then
672 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"
675 line="`awk '/'$key'/ { print $0; }' $fstab`"
676 loopDev="$(echo $line | awk '{print $3}')"
677 loopFs="$(echo $line | awk '{print $4}')"
678 loopFile="$(echo $line | awk '{print $5}')"
680 BASICMODULES="$BASICMODULES -loop"
681 find_module "-$loopFs"
682 BASICMODULES="$BASICMODULES -${loopFs}"
686 if is_lvm "$devpath"; then
687 find_modules_lvm "$devpath"
692 firmware_install_module() {
694 local firmware_files="$2"
696 verbose "Adding Firmwares ($firmware_files) to initrd for module $module"
697 # firmware not yet installed
698 if [ ! -f "$DESTDIR/lib/firmware/firmware.sh" ]; then
700 cat << 'EOF' >> "$DESTDIR/lib/firmware/firmware.sh"
702 echo 1 > /sys$DEVPATH/loading
703 cat "/lib/firmware/$FIRMWARE" > /sys$DEVPATH/data
704 echo 0 > /sys$DEVPATH/loading
707 chmod 755 "$DESTDIR/lib/firmware/firmware.sh"
709 # setup firmware loader agent
710 echo "echo -n "/lib/firmware/firmware.sh" > /proc/sys/kernel/hotplug" | add_linuxrc
713 for firmware in $firmware_files; do
714 if [ -f "/lib/firmware/$kernel/$firmware" ]; then
715 FIRMWAREDIR=${firmware%/*}
716 [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
717 inst /lib/firmware/$kernel/$firmware /lib/firmware/$firmware
718 elif [ -f "/lib/firmware/$firmware" ]; then
719 FIRMWAREDIR=${firmware%/*}
720 [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
721 inst /lib/firmware/$firmware /lib/firmware/$firmware
723 warn "Possible missing firmware file /lib/firmware/$firmware or /lib/firmware/$kernel/$firmware for module $module."
734 for mod in $modules; do
736 inst_d "/lib/modules/$kernel/$MODULEDIR"
737 cp -a "/lib/modules/$kernel/$mod" "$DESTDIR/lib/modules/$kernel/$mod"
738 gunzip "$DESTDIR/lib/modules/$kernel/$mod" 2> /dev/null
739 if [ "$STRIP" ] && [ -x "$STRIP" ]; then
740 $STRIP -g --remove-section=.comment "$DESTDIR/lib/modules/$kernel/${mod%.gz}"
745 modules_add_linuxrc() {
749 # module path without optional compression
753 local module=${modpath##*/}; module=${module%$modext}
754 local options=$(modprobe_options "$module")
755 local genericname=$(echo $module | tr - _)
756 local usleep=$(eval echo \$MODULE_${genericname}_USLEEP)
757 local firmware=$(eval echo \$MODULE_${genericname}_FIRMWARE)
759 if [ "$module" = "scsi_mod" -a "$kernel_version_long" -ge "002006030" ]; then
760 options="scan=sync $options"
763 if [ x"$verbose" = x"-v" ]; then
765 if [ "$options" ]; then
766 s="$s with options [$options]"
768 if [ "$usleep" ]; then
769 s="$s and $usleep usleep"
771 verbose "Loading module [$module]$s"
774 if [ -n "$firmware" ]; then
775 firmware_install_module "$module" "$firmware"
777 for file in $(find_firmware "$module"); do
778 firmware_install_module "$module" "$file"
782 echo "insmod /lib/modules/$kernel/$modpath $options" | add_linuxrc
783 if [ -n "$usleep" ]; then
784 echo "usleep $usleep" | add_linuxrc
786 if [ "$module" = "scsi_wait_scan" ]; then
787 if [ "$(busybox_applet rmmod 2>/dev/null; echo $?)" = 0 ]; then
788 echo "rmmod scsi_wait_scan" | add_linuxrc
795 # Generates /dev nodes based on /proc/partitions information.
796 # Needs /proc mounted.
797 # Can be called multiple times.
798 initrd_gen_devices() {
799 if is_yes "$proc_partitions"; then
806 : 'Making device nodes'
807 cat /proc/partitions | (
808 # ignore first two lines: header, empty line
811 while read major minor blocks dev rest; do
814 [ -e $node ] || mknod -m 660 $node b $major $minor
821 initrd_gen_setrootdev() {
822 verbose "Adding rootfs finding based on kernel cmdline root= option support."
824 debug "Current /proc/partitions:\n$(sed -e 's,^,> ,' /proc/partitions)"
826 if [ "${ROOT##/dev/}" != "${ROOT}" ]; then
827 rootnr="$(busybox awk -v rootnode="${ROOT##/dev/}" '$4 == rootnode { print 256 * $1 + $2 }' /proc/partitions)"
829 if [ -z "$rootnr" -a -e "$ROOT" ]; then
830 rootnr="$(busybox ls -lL ${ROOT} | busybox awk '{if (/^b/) { print 256 * $3 + $4; }}')"
832 if [ -n "$rootnr" ]; then
833 echo "$rootnr" > /proc/sys/kernel/real-root-dev
839 initrd_gen_initramfs_switchroot() {
841 if [ "$rootdev" = "/dev/nfs" ]; then
842 echo "rootfs on NFS root=/dev/nfs"
844 [ ! -e "$DESTDIR/$rootdev" ] && inst $rootdev $rootdev
847 # parse 'root=xxx' kernel commandline
848 # We support passing root as hda3 /dev/hda3 0303 0x0303 and 303
850 # from lilo-23.2/readme/README:
851 # root=<device> changes the root device. This overrides settings that may
852 # have been made in the boot image and on the LILO command line. <device> is
853 # either the hexadecimal device number or the full path name of the device,
856 # * The device names are hard-coded in the kernel. Therefore, only the
857 # "standard" names are supported and some less common devices may not be
858 # recognized. In those cases, only numbers can be used.
862 eval "$(busybox awk -v root="$ROOT" '
863 # http://9fans.net/archive/2006/09/261
864 function h2d(str, hstr, res, num, n, digit, i) {
865 hstr = "0123456789abdcef";
867 n = split(tolower(str), digit, "");
869 for (i = 1; i <= n; i++) {
870 num = index(hstr, digit[i]) - 1;
871 res = res + (num * 16 ^ (n - i));
878 num_pattern_short = "[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]";
879 num_pattern = "[0-9a-fA-F]" num_pattern_short;
880 dev_pattern = "[hms][a-z][a-z]([0-9])+";
884 # see if we have /dev/hdX or hdX, we can just take partition name
885 if (root ~ "^\/dev\/" dev_pattern "$" || root ~ "^" dev_pattern "$") {
887 sub("^/dev/", "", partition);
891 if (root ~ "^" num_pattern_short "$") {
892 # change "303" => "0x0303"
894 } else if (root ~ "^" num_pattern "$") {
895 # change "0303" => "0x0303"
899 maj = h2d(substr(root, 3, 2));
900 min = h2d(substr(root, 5, 2));
904 partition && $4 == partition { maj = $1; min = $2; }
905 $1 == maj && $2 == min { partition = $4; }
908 if (maj >= 0 && min >= 0) {
909 printf("maj=%s; min=%s;\n", maj, min);
912 printf("device=/dev/%s;\n", partition);
917 if [ -z "$device" ]; then
918 if [ "$DEBUGINITRD" ]; then
924 if [ "$device" -a ! -b $device -a "$maj$min" ]; then
925 mknod -m 660 $device b $maj $min
928 # XXX hack, if no device, try to parse it from /proc/partitions using /proc/sys/kernel/real-root-dev
929 if [ ! -e "$device" ]; then
930 rrd=$(cat /proc/sys/kernel/real-root-dev)
931 major=$(($rrd / 256))
932 minor=$(($rrd % 256))
934 while read pmajor pminor blocks dev rest; do
935 # skip header and empty line
936 [ -z "$pmajor" -o "$pmajor" = "major" ] && continue
938 if [ $pmajor = $major -a $pminor = $minor ]; then
940 echo "DEVICE set to $device based on real-root-dev"
942 done < /proc/partitions
945 [ -n "$ROOTFSFLAGS" ] && ROOTFSFLAGS="-o $ROOTFSFLAGS"
947 mount -t $ROOTFS -r $device $ROOTFSFLAGS /newroot || echo "Mount of rootfs failed."
949 if [ -z "$init" -o ! -x "/newroot$init" ]; then
957 if [ "$DEBUGINITRD" ]; then
958 echo "Last 20 lines of dmesg:"
964 busybox_applet switch_root usleep
966 [ ! -e /newroot/dev/console ] && mknod -m 660 /newroot/dev/console c 5 1
968 # switch root to empty dir will make kernel panic, so sleep 10s before it
969 # switch_root needs to be pid 1, so there's no other way to recover from here
970 # if /dev is missing, switch root will likely fail, give debug shell before that
971 if [ ! -d /newroot/dev ]; then
972 echo "/dev is missing, switch_root will likely fail"
973 echo "if you booted with debugrd=sh, then you be given shell and you might able to recover this situation"
975 [ "$DEBUGINITRD" ] || usleep 10000000
978 exec switch_root /newroot $init ${1:+"$@"}
980 # FIXME: this code is never executed, as "exec" does not return!
982 echo "Error! initramfs should not reach this place."
983 echo "It probably means you've got old version of busybox, with broken"
984 echo "initramfs support. Trying to boot anyway, but won't promise anything."
986 exec chroot /newroot $init ${1:+"$@"}
988 echo "Failed to chroot!"
991 # we need /init being real file, not symlink, otherwise the initramfs will
992 # not be ran by pid 1 which is required for switch_root
993 mv $DESTDIR/linuxrc $DESTDIR/init
994 ln -s init $DESTDIR/linuxrc
997 # find if $symbol exists in System.map $mapfile
1001 if [ ! -f $mapfile ]; then
1002 # missing mapfile (not a pld kernel?)
1006 awk -vc=1 -vsymbol="$symbol" '$2 == "T" && $3 == symbol {c = 0} END {exit c}' $mapfile
1009 # find best compressor (or forced one) for initrd
1012 # fastest initrd decompression speed is first
1013 local compressors='lzo gzip xz lzma bzip2'
1015 # a specified one, take it
1016 if ! is_yes "$mode"; then
1020 verbose "finding compressor: $compressors (via $mode)"
1021 # check for compressor validity
1022 local c prog map=/boot/System.map-$kernel
1023 for c in $compressors; do
1046 # any existing sym will work
1051 die "Unknown compressor $c"
1054 if sym_exists $map $sym && [ -x $prog ]; then
1060 verbose "using gzip for compressor (fallback)"
1064 # compresses kernel image image
1065 # in function so we could retry with other compressor on failure
1067 local compressor="$1" IMAGE="$2" target="$3" tmp
1068 tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
1070 case "$compressor" in
1072 # don't use -9 here since kernel won't understand it
1073 xz --format=xz --check=crc32 --lzma2=preset=6e,dict=1MiB < "$IMAGE" > "$tmp" || return $?
1076 xz --format=lzma -9 < "$IMAGE" > "$tmp" || return $?
1079 bzip2 -9 < "$IMAGE" > "$tmp" || return $?
1082 gzip -9 < "$IMAGE" > "$tmp" || return $?
1085 lzop -9 < "$IMAGE" > "$tmp" || return $?
1088 cat < "$IMAGE" > "$tmp" || return $?
1092 mv -f "$tmp" "$target"
1095 if [ -r /etc/sysconfig/geninitrd ]; then
1096 . /etc/sysconfig/geninitrd
1099 if [ ! -f /proc/mounts ]; then
1100 warn "/proc filesystem not mounted, may cause wrong results or failure."
1103 geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev tuxonice suspend fbsplash condecor bootsplash uvesafb nfs sata scsi usbkbd
1105 while [ $# -gt 0 ]; do
1115 modulefile=${1#--modules-conf=}
1124 --without-bootsplash)
1136 --without-fbcondecor)
1145 --with-suspend2 | --with-tuxonice)
1148 --without-suspend2 | --without-tuxonice)
1152 LVMTOOLSVERSION=${1#--lvmversion=}
1154 --lvmtoolsversion=*)
1155 LVMTOOLSVERSION=${1#--lvmtoolsversion=}
1157 --lvmtoolsversion|--lvmversion)
1170 --without-multipath)
1174 USE_MULTIPATH=${1#--with-multipath=}
1183 BASICMODULES="$BASICMODULES ${1#--with=}"
1186 BASICMODULES="$BASICMODULES $2"
1190 echo "$PROGRAM: version $VERSION"
1194 if [ x"$verbose" = x"-v" ]; then
1205 COMPRESS="${1#--compress=}"
1214 STRIP="${1#--strip=}"
1227 PREMODS="$PREMODS ${1#--preload=}"
1230 PREMODS="$PREMODS $2"
1234 die "--fs option is obsoleted. Use --initrdfs instead"
1237 INITRDFS=${1#--initrdfs=}
1250 if [ -z "$target" ]; then
1252 elif [ -z "$kernel" ]; then
1264 if [ -z "$target" -o -z "$kernel" ]; then
1270 if [ "$(id -u)" != 0 ]; then
1271 die "You need to be root to generate initrd"
1274 if [ -d /lib64 -a -d /usr/lib64 ]; then
1280 initrd_dir=/usr/$_lib/initrd
1281 kernel_version=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d",$1,$2)}')
1282 kernel_version_long=$(echo "$kernel" | awk -F. '{gsub(/[_-].*/, "", $0); print sprintf("%03d%03d%03d",$1,$2,$3)}')
1284 verbose "# $GENINITRD_RCSID (geninitrd)"
1285 debug "Using _lib: $_lib"
1286 debug "Using initrd_dir: $initrd_dir"
1288 busybox=$(find_tool $initrd_dir/busybox $initrd_dir/initrd-busybox /bin/initrd-busybox) || die "Couldn't find busybox suitable for initrd"
1290 # we setup mods after parsing command line args
1291 geninitrd_setup_mods
1293 if [ ! -f /boot/vmlinuz-"$kernel" ]; then
1294 warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?"
1297 if [ -z "$INITRDFS" ]; then
1298 if [ -n "$FS" ]; then
1299 # FS= can came only via /etc/sysconfig/geninitrd likely?
1300 die "FS configuration option is obsoleted. Use INITRDFS instead"
1304 if [ "$kernel_version" -ge "002005" ]; then
1305 INITRDFS="initramfs"
1313 [ -x /sbin/mke2fs ] || die "/sbin/mke2fs is missing"
1316 [ -x /sbin/genromfs ] || die "/sbin/genromfs is missing"
1319 [ -x /sbin/mkcramfs ] || die "/sbin/mkcramfs is missing"
1322 [ -x /bin/cpio ] || die "/bin/cpio is missing"
1323 [ -x /usr/bin/find ] || die "/usr/bin/find is missing"
1326 die "Filesystem $INITRDFS on initrd is not supported"
1330 if [ -L "$target" ]; then
1331 target=$(readlink -f "$target")
1334 if [ -n "$img_vers" ]; then
1335 target="$target-$kernel"
1338 if [ -z "$force" -a -f "$target" ]; then
1339 die "$target already exists."
1342 if [ ! -d "/lib/modules/$kernel" ]; then
1343 die "/lib/modules/$kernel is not a directory."
1346 if [ "$kernel_version" -ge "002005" ]; then
1352 for n in $PREMODS; do
1356 if [ "$FBMODULE" ]; then
1357 find_module "$FBMODULE"
1360 # autodetect USB keyboards
1363 # allow forcing loading SCSI and/or IDE modules
1364 # XXX: where ADDSCSI cames from? drop?
1365 if is_yes "$ADDSCSI"; then
1369 # autodetect SATA modules
1372 # XXX: where ADDIDE cames from? drop?
1373 if is_yes "$ADDIDE"; then
1377 if is_yes "$USE_SUSPEND"; then
1378 find_modules_suspend
1381 find_root "$fstab" || exit
1382 verbose "Using $rootdev as device for rootfs"
1384 find_modules_for_devpath "$rootdev"
1386 # if USE_MULTIPATH is path to device, scan that too
1387 # this is to bootstrap multipath setup into initrd.
1388 if ! is_no "$USE_MULTIPATH" && ! is_yes "$USE_MULTIPATH"; then
1389 find_modules_multipath $USE_MULTIPATH
1392 find_module "-$rootFs"
1394 for n in $BASICMODULES; do
1398 if is_yes "$USE_TUXONICE"; then
1402 find_modules_fbsplash
1404 if [ -n "$ifneeded" -a -z "$MODULES" ]; then
1405 verbose "No modules are needed -- not building initrd image."
1409 verbose "Building initrd..."
1410 DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
1411 RCFILE="$DESTDIR/linuxrc"
1413 chmod a+rx "$RCFILE"
1414 ln -s linuxrc $DESTDIR/init
1416 # create dirs that we really need
1417 inst_d /{lib,bin,etc,dev{,/pts,/shm},loopfs,var,proc,run,sys}
1419 modules_install "$MODULES"
1421 # mknod'ing the devices instead of copying them works both with and
1423 mknod -m 600 "$DESTDIR/dev/console" c 5 1
1424 mknod -m 666 "$DESTDIR/dev/null" c 1 3
1425 mknod -m 666 "$DESTDIR/dev/zero" c 1 5
1426 mknod -m 666 "$DESTDIR/dev/random" c 1 8
1427 mknod -m 666 "$DESTDIR/dev/urandom" c 1 9
1429 inst_exec $busybox /bin/busybox
1430 ln -s busybox $DESTDIR/bin/sh
1431 # for older busyboxes who had /bin/initrd-busybox as EXEPATH
1432 ln -s busybox $DESTDIR/bin/initrd-busybox
1437 # on $(LC_ALL=C date)
1438 # by $GENINITRD_RCSID
1443 # builtin defaults from geninitrd
1447 add_linuxrc <<-'EOF'
1448 read CMDLINE < /proc/cmdline
1450 for arg in $CMDLINE; do
1451 if [ "${arg}" = "debuginitrd" ] || [ "${arg}" = "debugrd" ]; then
1454 if [ "${arg##debuginitrd=}" != "${arg}" ] || [ "${arg##debugrd=}" != "${arg}" ]; then
1455 DEBUGINITRD=${arg##debug*rd=}
1457 if [ "${arg##root=}" != "${arg}" ]; then
1460 if [ "${arg##rootfsflags=}" != "${arg}" ]; then
1461 ROOTFSFLAGS=${arg##rootfsflags=}
1463 if [ "${arg##init=}" != "${arg}" ]; then
1468 if [ "$DEBUGINITRD" = "sh" ]; then
1469 # export some vars to subshell for debug to work
1470 export CMDLINE ROOT ROOTFS ROOTDEV ROOTFSFLAGS DEBUGINITRD INIT
1471 export LVM_ROOTVG LVM_SUSPENDVG LVM_VGVOLUMES
1472 export rootnr attrs majmin major minor device
1474 # make debugshell() invoke subshell if $DEBUGINITRD=sh
1477 if is_yes "$RUN_SULOGIN_ON_ERR"; then
1478 add_linuxrc <<-'EOF'
1479 echo "debug shell disabled by RUN_SULOGIN_ON_ERR=yes from /etc/sysconfig/system during initrd generation time"
1482 add_linuxrc <<-'EOF'
1486 add_linuxrc <<-'EOF'
1494 if [ "$DEBUGINITRD" ]; then
1499 modules_add_linuxrc $MODULES
1501 # TODO: rewrite for busybox
1502 #if [ -n "$loopDev" ]; then
1503 # if [ ! -d /initrd ]; then
1507 # cp -a "$loopDev" "$DESTDIR/dev"
1508 # cp -a "$rootdev" "$DESTDIR/dev"
1509 # echo "echo Mounting device containing loopback root filesystem" >> "$RCFILE"
1510 # echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE"
1511 # echo "echo Setting up loopback device $rootdev" >> $RCFILE
1512 # echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE"
1515 if is_yes "$USE_UDEV"; then
1521 find_modules_uvesafb
1526 initrd_gen_multipath
1529 if is_yes "$have_nfs"; then
1536 initrd_gen_setrootdev
1539 # additional devs always needed
1540 [ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev
1542 initrd_gen_stop_udevd
1543 initrd_gen_stop_mdev
1544 initrd_gen_stop_uvesafb
1546 # resume after killing local processes
1551 add_linuxrc <<-'EOF'
1552 if [ ! "$DEBUGINITRD" ]; then
1556 for i in $(export -p); do
1557 i=${i#declare -x } # ksh/bash
1558 i=${i#export } # busybox
1569 [ -z "$i" ] && continue
1572 ROOT|PATH|HOME|TERM)
1584 if [ "$INITRDFS" = "initramfs" ]; then
1585 initrd_gen_initramfs_switchroot
1591 initrd_gen_fbcondecor
1593 debug "Current /linuxrc:\n$(sed -e 's,^,> ,' $DESTDIR/linuxrc)"
1595 IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed"
1597 IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
1598 verbose "image size: $IMAGESIZE KiB ($DESTDIR)"
1600 verbose "Creating $INITRDFS image $IMAGE"
1603 dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null
1604 # NOTE: ext2 label is max 16 chars
1605 mke2fs -q -F -b 1024 -m 0 -L "PLD/$kernel" "$IMAGE" 2>/dev/null 1>&2
1606 tune2fs -i 0 "$IMAGE" >/dev/null 2>&1
1608 local tmpmnt=$(mktemp -d -t initrd.mnt-XXXXXX)
1609 debug "Mounting ext2 image $IMAGE to $tmpmnt"
1610 mount -o loop -t ext2 "$IMAGE" "$tmpmnt" || die "mount failed, check dmesg(1)"
1611 # We don't need this directory, so let's save space
1612 rm -rf "$tmpmnt"/lost+found
1614 debug "Copy recursively $DESTDIR -> $tmpmnt"
1615 cp -a $DESTDIR/* $tmpmnt
1621 genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD Linux/$kernel (geninitrd/$VERSION)"
1624 mkcramfs "$DESTDIR" "$IMAGE"
1627 (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
1630 die "Filesystem $INITRDFS not supported by $PROGRAM"
1633 CONFIG_BLK_DEV_RAM_SIZE=$(ikconfig | awk -F= '/^CONFIG_BLK_DEV_RAM_SIZE/{print $2}')
1634 if [ -z "$CONFIG_BLK_DEV_RAM_SIZE" ]; then
1635 CONFIG_BLK_DEV_RAM_SIZE=4096
1636 warn "No CONFIG_BLK_DEV_RAM_SIZE detected, fallback to $CONFIG_BLK_DEV_RAM_SIZE"
1639 if [ "$IMAGESIZE" -gt $CONFIG_BLK_DEV_RAM_SIZE ]; then
1640 warn "Your image size is larger than $CONFIG_BLK_DEV_RAM_SIZE, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!"
1643 if ! is_no "$COMPRESS"; then
1644 compressor=$(find_compressor "$COMPRESS")
1645 verbose "Compressing $target with $compressor"
1647 # TODO: the image name (specified from kernel.spec) already contains
1648 # extension, which is .gz most of the time.
1649 compress_image "$compressor" "$IMAGE" "$target" || {
1650 if [ $compressor != gzip ]; then
1651 warn "Could not compress with $compressor, retrying with gzip"
1652 compress_image gzip "$IMAGE" "$target" || die "compress failed with gzip" $?
1654 die "Could not compress image with $compressor"
1658 cp -a "$IMAGE" "$target"
1661 # XXX. check if bootsplash can output data to tmp dir not directly to initramfs image.
1662 initrd_gen_bootsplash "$target"
1664 rm -rf "$DESTDIR" "$IMAGE"
1666 # vim:ts=4:sw=4:noet:fdm=marker