#!/bin/sh # geninitrd # # by Jacek Konieczny # # based on mkinitrd from RedHat RCSID='$Id$' PATH=/sbin:$PATH export PATH VERSION="`echo "$RCSID"|awk '{print $3}'`" . /etc/rc.d/init.d/functions COMPRESS="yes" # INITRDFS is set later (catch obsoleted FS option) #INITRDFS="rom" USERAIDSTART="yes" USEMDADMSTATIC="no" USEINSMODSTATIC="no" USESUSPEND="yes" uselvm="no" usenfs="no" # it should be safe to remove scsi_mod from here, but I'm not sure... PRESCSIMODS="-scsi_mod unknown -sd_mod" PREIDEMODS="-ide-core unknown -ide-detect -ide-disk" PREIDEMODSOLD="-ide-probe -ide-probe-mod -ide-disk" SUSPEND2MODS="-suspend2_core -suspend2_lzf -suspend2_block_io -suspend2_swap -suspend_core -suspend_text -suspend_lzf -suspend_block_io -suspend_swap" target="" kernel="" force="" verbose="" MODULES="" img_vers="" modulefile="" fstab="/etc/fstab" insmod="insmod" modext=".o" rootdev_nr=0 # default bootsplash is off, if it have to be on, install bootsplash package BOOT_SPLASH=no if [ -f /etc/udev/udev.conf -a -x /sbin/initrd-udev ]; then USE_UDEV="yes" UDEV_TMPFS="yes" . /etc/udev/udev.conf fi if [ -x /sbin/dmraid-initrd ]; then USE_DMRAID="yes" fi usage () { echo "usage: `basename $0` [--version] [-v] [-f] [--ifneeded] [--preload ]" echo " [--with=] [--image-version] [--fstab=] [--nocompress]" echo " [--initrdfs=rom|ext2|cram] [--modules-conf=]" echo " [--with-raidstart] [--without-raidstart] [--with-insmod-static]" echo " [--without-bootsplash] [--lvmtoolsversion=1|2] [--without-udev]" echo " [--without-suspend2] [--without-dmraid]" echo " " echo " (ex: `basename $0` /boot/initrd-2.2.5-15.img 2.2.5-15)" exit 1 } my_dirname() { echo $1|awk -F/ '{print substr($0, 0, length($0) - length($NF));}' } find_depmod () { typeset mods module f level depfile first depfile=/lib/modules/$kernel/modules.dep if [ -f $depfile ] ; then : ok else echo "Error: no $depfile ! Run depmod and rerun geninitrd." 1>&2 exit 1 fi # prepend / if no path given, append $modext.gz if not given, # quote / origmodule="$2" module=$(echo "$2" | \ awk '/\// {print;next} {print "/" $0}' | \ awk '/\./ {print;next} {print $0 "'$modext'.gz"}' | awk '{gsub("/","\\/");print}') mods=$(awk ' BEGIN { here = 0 } /'"$module"':(.*)/ { gsub(/:/," "); gsub(/\\/," "); print; here = 1; next } /:/ { here = 0 } /(.*)/ { gsub(/\\/," "); if (here) print } ' $depfile | xargs) # fallback to $modext if [ "$mods" = "" ] ; then module=$(echo "$module" | \ awk '{gsub("\'$modext'\.gz$","\'$modext'",$0);print}') fi mods=$(awk ' BEGIN { here = 0 } /'"$module"':(.*)/ { gsub(/:/," "); gsub(/\\/," "); print; here = 1; next } /:/ { here = 0 } /(.*)/ { gsub(/\\/," "); if (here) print } ' $depfile | xargs) if [ "$mods" = "" ] ; then if [ "$1" != silent ] ; then echo "$origmodule: module not found in $depfile" 1>&2 fi if ! is_no "$EXIT_IF_MISSING" ; then exit 1 else echo "If $origmodule isn't compiled in kernel then this initrd may not start your system". 1>&2 fi fi level=$3 if [ "$level" = "" ] ; then level=0 fi level=$(awk "BEGIN{print $level + 1}") if [ $level -gt 20 ] ; then echo "$origmodule: cycle in $depfile" 1>&2 exit 1 fi first= for f in $mods ; do if [ "$first" = "" ] ; then first=$f else find_depmod $1 $f $level fi done echo $first } addmodule() { fmPath=$1 skiperrors=$2 if [ ! -f "/lib/modules/$kernel/$fmPath" ]; then if [ -n "$skiperrors" ]; then return fi echo "module $fmPath present in modules.dep, but not in filesystem (kernel = $kernel)" 1>&2 exit 1 fi # only need to add each module once # quote / tmpFmPath=$(echo $fmPath | awk '{gsub(/\//,"\\/");print}') if echo "$MODULES" | awk '/'"$tmpFmPath"'/ {exit 1}' ; then MODULES="$MODULES $fmPath" fi } findmodule() { skiperrors="" modName=$1 if [ "$(echo $modName | awk '{print(substr($0,1,1));}')" = "-" ]; then skiperrors=1 modName="$(echo $modName | awk '{print(substr($0,2));}')" fi # what's that? if [ "$modName" = "pluto" ]; then findmodule fc4 findmodule soc fi if [ "$modName" = "fcal" ]; then findmodule fc4 findmodule socal fi if [ -n "$skiperrors" ]; then allModulesToFind=`find_depmod silent $modName` else allModulesToFind=`find_depmod normal $modName` if [ $? != 0 ] ; then exit 1 fi fi for mod in $allModulesToFind ; do mod=$(echo $mod | \ awk '{sub(/^\/lib\/modules\/[^\/]*\//,"");print}') addmodule $mod "$skiperrors" done } inst() { if [ "$#" != "2" ];then echo "usage: inst " return fi [ -n "$verbose" ] && echo "$1 -> $2" cp "$1" "$2" } get_label_ext2 () { /sbin/e2label $1 2> /dev/null } get_uuid_ext2 () { /sbin/tune2fs -l $1 2> /dev/null | awk -F: '/UUID:/ {gsub(" ",""); print $2}' } get_label_xfs () { /usr/sbin/xfs_db -x -p xfs_admin -c label -r "$1"|awk -F= '{sub("^\"","", $2); sub("\"$", "", $2); print $2}' } get_uuid_xfs () { /usr/sbin/xfs_db -x -p xfs_admin -c uuid -r "$1"|awk -F= '{print $2}' } find_root() { eval `awk '/^[\t ]*#/ {next} {if ( $2 == "/" ) {print "rootdev=\"" $1 "\"\nrootFs=\"" $3 "\""}}' $fstab` case $rootdev in LABEL=*) if [ -x /sbin/findfs -a \( "$rootFs." = "ext2." -o "$rootFs." = "ext3." \) ] ; then rootdev2="`/sbin/findfs $rootdev 2>/dev/null`" if [ -n "$rootdev2" ] ; then rootdev=$rootdev2 rootdev_found=1 fi fi if [ "$rootdev_found." != "1." ] ; then case $rootFs in ext2|ext3) if [ ! -x /sbin/e2label ] ; then echo "/sbin/e2label is missing" 1>&2 exit 1 fi get_label="get_label_ext2" ;; xfs) if [ ! -x /usr/sbin/xfs_db ] ; then echo "/usr/sbin/xfs_db is missing" 1>&2 exit 1 fi get_label="get_label_xfs" ;; *) echo "LABEL on $rootFs in not supported by geninitrd" 1>&2 exit 1 ;; esac if [ ! -r /proc/partitions ] ; then echo '/proc/partitions is not readable'; 1>&2 exit 1 fi label=${rootdev#"LABEL="} for dev in `awk 'BEGIN {getline;getline} {print "/dev/" $4}' /proc/partitions` ; do if [ -r $dev ] && [ "$label" = "`$get_label $dev`" ] ; then if [ -n "$verbose" ] ; then echo "Using $dev as device for rootfs" fi rootdev=$dev rootdev_found=1 break fi done if [ "$rootdev_found." != "1." ] ; then echo "geninitrd can't find real device for LABEL=$label" 1>&2 exit 1 fi fi ;; UUID=*) if [ -x /sbin/findfs -a \( "$rootFs." = "ext2." -o "$rootFs." = "ext3." \) ] ; then rootdev2="`/sbin/findfs $rootdev 2>/dev/null`" if [ -n "$rootdev2" ] ; then rootdev=$rootdev2 rootdev_found=1 fi fi if [ "$rootdev_found." != "1." ] ; then case $rootFs in ext2|ext3) if [ ! -x /sbin/tune2fs ] ; then echo "/sbin/tune2fs is missing" 1>&2 exit 1 fi get_uuid="get_uuid_ext2" ;; xfs) if [ ! -x /usr/sbin/xfs_db ] ; then echo "/usr/sbin/xfs_db is missing" 1>&2 exit 1 fi get_label="get_uuid_xfs" ;; *) echo "UUID on $rootFs in not supported by geninitrd" 1>&2 exit 1 ;; esac if [ ! -r /proc/partitions ] ; then echo '/proc/partitions is not readable'; 1>&2 exit 1 fi uuid=${rootdev#"UUID="} for dev in `awk 'BEGIN {getline;getline} {print "/dev/" $4}' /proc/partitions` ; do if [ -r $dev ] && [ "$uuid" = "`$get_uuid $dev`" ] ; then if [ -n "$verbose" ] ; then echo "Using $dev as device for rootfs" fi rootdev=$dev rootdev_found=1 break fi done if [ "$rootdev_found" != 1 ] ; then echo "geninitrd can't find real device for UUID=$uuid" 1>&2 exit 1 fi fi ;; esac rootdev1=${rootdev} } find_modules_softraid() { if [ -f /etc/mdadm.conf ] ; then [ -n "$verbose" ] && echo "Finding RAID details using mdadm for rootdev=$1" eval `/sbin/mdadm -v --examine --scan --config=/etc/mdadm.conf | \ awk -v rootdev="$1" ' BEGIN { found = "no"; dev_list = ""; raidlevel = "" rootdev_devfs = rootdev; if (rootdev ~ /\/dev\/md\/[0-9]/) { gsub(/\/dev\/md\//,"/dev/md",rootdev_devfs); } } /^ARRAY/ { if (($2 == rootdev) || ($2 == rootdev_devfs)) { raidlevel=$3; gsub(/level=/,NUL,raidlevel); if (raidlevel ~ /^raid([0-6]|10)/) { gsub(/raid/,NUL,raidlevel); }; found="yes"; getline x; if (x ~ /devices=/) { dev_list = x; gsub(".*devices=", NUL, dev_list); gsub(",", " ", dev_list); } } } END { print "raidfound=" found; print "raidlevel=" raidlevel; print "dev_list=\"" dev_list "\""; }'` fi if [ "$raidfound" != "yes" -a -f /etc/raidtab ]; then echo "ERROR: raidtools are not longer supported. Please migrate to mdadm setup!" 1>&2 exit 1 fi if is_yes "$raidfound" ; then case "$raidlevel" in [01456]|10) findmodule "raid$raidlevel" ;; linear) findmodule "linear" ;; *) echo "raid level $number (in mdadm config) not recognized" 1>&2 ;; esac else echo "ERROR: RAID devices not found for \"$1\", check your configuration!" 1>&2 exit 1 fi rootdev_nr=$(( $rootdev_nr + 1 )) eval "rootdev${rootdev_nr}=\"$1\"" eval "dev_list${rootdev_nr}=\"${dev_list}\"" for device in $dev_list; do find_modules_for $device done } find_modules_scsi() { for n in $PRESCSIMODS; do if [ "X$n" = "Xunknown" ] ; then if [ -f "$modulefile" ]; then scsimodules="`awk '/scsi_hostadapter/ && ! /^[\t ]*#/ { print $3; }' $modulefile`" for n in $scsimodules; do # for now allow scsi modules to come from anywhere. There are some # RAID controllers with drivers in block findmodule "$n" done fi else findmodule "$n" fi done } find_modules_ide() { typeset rootdev rootdev="$(echo "$1" | awk ' { gsub(/\/dev\//,NUL); gsub(/[0-9].*/, NUL); print $0 } ')" if [ "$pack_version_long" -lt "002004021" ]; then [ -n "$verbose" ] && echo "Finding IDE modules for kernels <= 2.4.20" for n in $PREIDEMODSOLD; do findmodule "$n" done else tryauto=1 for n in $PREIDEMODS; do if [ "X$n" = "Xunknown" ] ; then if [ -f "$modulefile" ]; then [ -n "$verbose" ] && echo "Finding IDE modules using ide_hostadapter" idemodules="`awk '/ide_hostadapter/ && ! /^[\t ]*#/ { print $3; }' $modulefile`" for na in $idemodules; do tryauto=0; findmodule "$na" done fi if [ "$tryauto" -eq 1 ]; then if [ -r /usr/share/pci-database/ide.pci -a -r /proc/bus/pci/devices ]; then [ -n "$verbose" ] && echo "Finding IDE modules using PCI ID database" if is_yes "${ide_only_root}"; then if [ -f /sys/block/${rootdev}/device/../../vendor -a -f /sys/block/${rootdev}/device/../../device ] ; then vendorid="$(awk ' { gsub(/0x/,NUL); print $0 } ' /sys/block/${rootdev}/device/../../vendor)" deviceid="$(awk ' { gsub(/0x/,NUL); print $0 } ' /sys/block/${rootdev}/device/../../device)" searchpciid="${vendorid}${deviceid}" elif [ -f /proc/ide/${rootdev}/../config ]; then searchpciid="$(awk ' /pci bus/ { print $7$9 } ' /proc/ide/${rootdev}/../config)" fi fi if [ -z "${searchpciid}" ]; then searchpciid="$(awk ' { print $2 } ' /proc/bus/pci/devices)" fi idemodules="" for nb in $searchpciid; do eval `awk -v pciid="$nb" 'BEGIN { } { gsub("\t"," "); gsub(" +", " "); gsub("^ ",""); if (/^[\t ]*#/) next; compmod = $1 ""; # make sure comparison type will be string # cause pci IDs are hexadecimal numeric if (compmod == pciid) { module=$2; # min_kernel=$3; # now in ide.pci $3,$4 = vendor and device name # max_kernel=$4; # exit 0; } } END { print "module=" module "\nmin_kernel=" min_kernel "\nmax_kernel=\"" max_kernel "\"\n"; }' /usr/share/pci-database/ide.pci` [ -n "$module" ] && idemodules="$idemodules $module" done if is_yes "$(awk ' /ide=reverse/ { print "yes" } ' /proc/cmdline)"; then new_idemodules="" for nc in idemodules; do new_idemodules="$nc $new_idemodules" done idemodules="${new_idemodules}" fi if [ -z "$idemodules" ]; then echo "WARNING: rootfs on IDE device but no related modules found, loading ide-generic." idemodules="ide-generic" fi for nd in $idemodules; do findmodule "-$nd" done else [ -r /usr/share/pci-database/ide.pci ] || echo "WARNING: /usr/share/pci-database/ide.pci missing." [ -r /proc/bus/pci/devices ] || echo "WARNING: /proc/bus/pci/devices missing." echo "Automatic IDE modules finding not available." fi fi else findmodule "$n" fi done fi } find_modules_for() { if [ -z "$1" ]; then echo "ERROR: no argument passed to find_modules_for() - is your /etc/fstab correct?" >&2 exit elif is_yes "`echo "$1" | awk '/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:|\/dev\/nfs)/ { print "yes"; }'`"; then if [ ! -x /usr/bin/pcidev -a -z "$NFS_ETH_MODULES" ] ; then echo "ERROR: root on NFS but /usr/bin/pcidev not found." >&2 echo "Please install correct pci-database package and rerun $0." >&2 exit 1 fi [ -z "$NFS_ETH_MODULES" ] && NFS_ETH_MODULES=$(/usr/bin/pcidev /m net | xargs) for m in $NFS_ETH_MODULES; do findmodule "$m" done findmodule "-ipv4" findmodule "nfs" usenfs="yes" echo "Remember to use \`root=/dev/ram0 init=/linuxrc' when starting kernel" >&2 echo "or you will have problems like init(xx) being child process of swapper(1)." >&2 elif is_yes "`echo "$1" | awk '/^\/dev\/md/ { print "yes"; }'`"; then find_modules_softraid "$1" elif is_yes "$(echo "$1" | awk '/^\/dev\/(sd|scsi)/ { print "yes"; }')" ; then find_modules_scsi elif is_yes "`echo "$1" | awk '/^\/dev\/(hd|ide)/ { print "yes"; }'`" ; then find_modules_ide "$1" elif is_yes "`echo "$1" | awk '/\/dev\/rd\// { print "yes"; }'`" ; then findmodule "DAC960" elif is_yes "`echo "$1" | awk '/\/dev\/ida\// { print "yes"; }'`" ; then findmodule "cpqarray" elif is_yes "`echo "$1" | awk '/\/dev\/cciss\// { print "yes"; }'`" ; then findmodule "cciss" elif is_yes "`echo "$1" | awk '/\/dev\/ataraid\// { print "yes"; }'`"; then find_modules_ide findmodule "ataraid" ataraidmodules="`awk '/ataraid_hostadapter/ && ! /^[\t ]*#/ { print $3; }' $modulefile`" if -n "$ataraidmodules" ; then # FIXME: think about modules compiled in kernel echo "ERROR: ataraid_hostadapter alias not defined in $modulefile !" echo "Please set it and run $0 again." exit 1 fi for n in $ataraidmodules; do findmodule "$n" done # check to see if we need to set up a loopback filesystem elif is_yes "`echo "$1" | awk -F/ '{print($3);}' | awk '/loop/ { print "yes"; }'`" ; then echo "Sorry, root on loop device isn't supported." 1>&2 exit 1 # TODO: rewrite for bsp and make nfs ready if [ ! -x /sbin/losetup ]; then echo "losetup is missing" exit 1 fi key="^# $(echo $1 | awk -F/ '{print($3);}' | tr '[a-z]' '[A-Z]'):" if ! is_yes "`awk '/'$key'/ { print( "yes"); }' $fstab`" ; then echo "The root filesystem is on a $1, but there is no magic entry in $fstab" 1>&2 echo "for this device. Consult the geninitrd man page for more information" 1>&2 exit 1 fi line="`awk '/'$key'/ { print $0; }' $fstab`" loopDev="$(echo $line | awk '{print $3}')" loopFs="$(echo $line | awk '{print $4}')" loopFile="$(echo $line | awk '{print $5}')" BASICMODULES="$BASICMODULES -loop" findmodule "-$loopFs" BASICMODULES="$BASICMODULES -${loopFs}" # don't have any clue, how is this supposed to work elif [ -e "$1" ] && ls -l "$1" 2> /dev/null | awk '{if (/^b/) { if ($5 == "58,") { exit 0; } else { exit 1; } } else { exit 1; }}' || /sbin/lvm lvdisplay "$1" > /dev/null 2>&1 ; then if [ ! -f /sbin/initrd-lvm -o ! -x /sbin/lvdisplay -o ! -x /sbin/pvdisplay ] ; then echo "ERROR: root on LVM but /sbin/initrd-lvm, /sbin/lvdisplay and /sbin/pvdisplay not found." >&2 echo "Please install lvm(2) and lvm(2)-initrd package and rerun $0." >&2 exit 1 fi if [ -z "$LVMTOOLSVERSION" ] ; then LVMTOOLSVERSION=$(/sbin/initrd-lvm vgchange --version 2>/dev/null|head -n 1|awk '{gsub("vgchange: Logical Volume Manager ",NIL); gsub("LVM version: ",NIL); gsub(/\..*/,NIL); print $1}') if [ -z "$LVMTOOLSVERSION" ] ; then echo "ERROR: Can't determine LVM tools version. Please set LVMTOOLSVERSION" >&2 echo "and rerun $0." >&2 exit 1 fi fi if [ -z "$PVDEVICES" ] ; then VGVOLUME=$(/sbin/lvdisplay -c "$1" 2> /dev/null | awk -F":" ' { print $2 } ') PVDEVICES=$(/sbin/pvdisplay -c | awk -F":" -v vg="$VGVOLUME" ' BEGIN { devices="" } { if ($2 == vg) { devices = devices " " $1 } } END { print devices } ') fi if [ -n "$PVDEVICES" ] ; then for device in $PVDEVICES; do find_modules_for $device done else echo "ERROR: I wasn't able to find PV (via lvdisplay and pvdisplay)." >&2 echo "You can try to set PVDEVICES in /etc/sysconfig/geninitrd." >&2 exit 1 fi if [ "$LVMTOOLSVERSION" = "2" ]; then findmodule "-dm-mod" elif [ "$LVMTOOLSVERSION" = "1" ]; then findmodule "-lvm" findmodule "-lvm-mod" else echo "ERROR: LVM version $LVMTOOLSVERSION is not supported yet." >&2 exit 1 fi uselvm="yes" fi } modules_install() { modules="$1" for mod in $modules; do MODULEDIR="`my_dirname "$mod"`" mkdir -p "$MNTIMAGE/lib/modules/$kernel/$MODULEDIR" cp $verbose -a "/lib/modules/$kernel/$mod" "$MNTIMAGE/lib/modules/$kernel/$mod" gunzip "$MNTIMAGE/lib/modules/$kernel/$mod" 2> /dev/null done } modules_add_linuxrc() { modules="$1" linuxrc="$2" for mod in $modules; do MODULE2="`my_dirname "$mod"`" NAME2=`basename "$mod" .gz` MODULE2=$MODULE2/$NAME2 module="`echo $mod | awk -F/ '{ $0=$NF } /'$modext'.*$/ { gsub(/'$modext'.*/, NIL, $0); } { print $0; }'`" options="`awk '{ if($1 == "options" && $2 == "'${module}'") { for(i=3;i<=NF;i++) printf("%s ",$i); }}' "$modulefile"`" sleep_module=$(echo "${module}" | awk ' { gsub("-", "_", $0) } { print $0; } ') sleep_var="$(eval echo \$MODULE_${sleep_module}_USLEEP)" if [ -n "$verbose" ]; then echo -n "Loading module [$module] " if [ -n "$options" ] ; then echo -n "with options [$options]" else echo -n "without options" fi if [ -n "$sleep_var" ]; then echo " and $sleep_var usleep." else echo "." fi fi echo "$insmod /lib/modules/$kernel/$MODULE2 $options" >> "$linuxrc" if [ -n "${sleep_var}" ]; then echo "usleep $sleep_var" >> "$linuxrc" fi done } if [ -r /etc/sysconfig/geninitrd ] ; then . /etc/sysconfig/geninitrd fi if [ -r /etc/sysconfig/bootsplash ] ; then . /etc/sysconfig/bootsplash fi if [ ! -x /bin/initrd-busybox ] ; then echo "/bin/initrd-busybox is missing !" exit 1 fi case "$(uname -m)" in ia64|amd64|x86_64|sparc64) IMAGESIZE=3000 ;; *) IMAGESIZE=1500 ;; esac while [ $# -gt 0 ]; do case $1 in --fstab=*) fstab="`echo $1 | awk -F= '{print $2;}'`" ;; --fstab) fstab="$2" shift ;; --modules-conf=*) modulefile="`echo $1 | awk -F= '{print $2;}'`" ;; --modules-conf) modulefile="$2" shift ;; --use-raidstart|--with-raidstart) USERAIDSTART="yes" ;; --without-raidstart) USERAIDSTART="no" ;; --use-insmod-static|--with-insmod-static) USEINSMODSTATIC="yes" ;; --without-insmod-static) USEINSMODSTATIC="no" ;; --without-bootsplash) BOOT_SPLASH="no" ;; --without-suspend2) USESUSPEND2="no"; ;; --lvmtoolsversion=|--lvmversion=) LVMTOOLSVERSION="`echo $1 | awk -F= '{print $2;}'`" ;; --lvmtoolsversion|--lvmversion) LVMTOOLSVERSION="$2" shift ;; --without-udev) USE_UDEV= ;; --without-dmraid) USE_DMRAID= ;; --with=*) BASICMODULES="$BASICMODULES `echo $1 | awk -F= '{print $2;}'`" ;; --with) BASICMODULES="$BASICMODULES $2" shift ;; --version) echo "geninitrd: version $VERSION" exit 0 ;; -v) verbose=-v ;; --nocompress) COMPRESS="no" ;; --ifneeded) ifneeded=1 ;; -f) force=1 ;; --preload=*) PREMODS="$PREMODS `echo $1 | awk -F= '{print $2;}'`" ;; --preload) PREMODS="$PREMODS $2" shift ;; --fs=*) echo "Warning: --fs option is obsoleted. Use --initrdfs instead" 1>&2 INITRDFS="`echo $1 | awk -F= '{print $2;}'`" ;; --fs) echo "Warning: --fs option is obsoleted. Use --initrdfs instead" 1>&2 INITRDFS="$2" shift ;; --initrdfs=*) INITRDFS="`echo $1 | awk -F= '{print $2;}'`" ;; --initrdfs) INITRDFS="$2" shift ;; --image-version) img_vers=yes ;; --ide-only-root) ide_only_root="yes" ;; *) if [ -z "$target" ]; then target="$1" elif [ -z "$kernel" ]; then kernel="$1" else usage fi ;; esac shift done if [ -z "$target" -o -z "$kernel" ]; then usage fi pack_version="`echo "$kernel"|awk -F. '{print sprintf("%03d%03d",$1,$2)}'`" pack_version_long="`echo "$kernel"|awk -F. '{print sprintf("%03d%03d%03d",$1,$2,$3)}'`" if [ "x" = "x$INITRDFS" ] ; then if [ "x" = "x$FS" ] ; then # default value # XXX: initramfs blocked for now if [ "1" = " 0" -a "$pack_version" -ge "002005" ] ; then INITRDFS="initramfs" else INITRDFS="rom" fi else echo "Warning: FS configuration options is obsoleted. Use INITRDFS instead" 1>&2 INITRDFS="$FS" fi fi if [ "$pack_version" -lt "002006" ] ; then USE_UDEV= USE_DMRAID= fi [ -z "$USE_UDEV" ] && UDEV_TMPFS= if [ "$pack_version" -ge "002005" ] ; then modext=".ko" insmod="insmod" fi if is_yes "$USEINSMODSTATIC" ; then insmod="insmod.static" INSMOD="/sbin/insmod.static" if [ "$pack_version" -lt "002005" -a -f /sbin/insmod.static.modutils ] ; then INSMOD="/sbin/insmod.static.modutils" fi if [ ! -f "$INSMOD" ] ; then echo "insmod.static requested but /sbin/insmod.static not found !" >&2 exit 1 fi fi case "$INITRDFS" in ext2) if [ ! -x /sbin/mke2fs ]; then echo "/sbin/mke2fs is missing" 1>&2 exit 1 fi ;; rom) if [ ! -x /sbin/genromfs ]; then echo "/sbin/genromfs is missing" 1>&2 exit 1 fi ;; cram) if [ ! -x /sbin/mkcramfs ]; then echo "/sbin/mkcramfs is missing" 1>&2 exit 1 fi ;; initramfs) if [ ! -x /bin/cpio ]; then echo "/bin/cpio is missing" 1>&2 exit 1 fi if [ ! -x /usr/bin/find ]; then echo "/usr/bin/find is missing" 1>&2 exit 1 fi ;; *) echo "Filesystem $INITRDFS on initrd is not supported" 1>&2 exit 1 ;; esac if [ -n "$img_vers" ]; then target="$target-$kernel" fi if [ -z "$force" -a -f "$target" ]; then echo "$target already exists." 1>&2 exit 1 fi if [ ! -d "/lib/modules/$kernel" ]; then echo "/lib/modules/$kernel is not a directory." 1>&2 exit 1 fi if [ ! -f /proc/mounts ]; then echo "WARNING: /proc filesystem not mounted, may cause wrong results or failure." 1>&2 fi if [ "$pack_version" -lt "002005" ]; then modulefile=/etc/modules.conf if [ ! -f "$modulefile" -a -f /etc/conf.modules ]; then modulefile=/etc/conf.modules fi else modulefile=/etc/modprobe.conf fi for n in $PREMODS; do findmodule "$n" done # allow forcing loading SCSI and/or IDE modules if is_yes "$ADDSCSI" ; then find_modules_scsi fi if is_yes "$ADDIDE" ; then find_modules_ide fi find_root org_rootdev="$rootdev1" find_modules_for "$rootdev1" findmodule "-$rootFs" for n in $BASICMODULES; do findmodule "$n" done if [ -n "$ifneeded" -a -z "$MODULES" ]; then if [ -n "$verbose" ]; then echo "No modules are needed -- not building initrd image." fi exit 0 fi if [ -n "$verbose" ]; then echo "Using modules: $MODULES" fi MNTIMAGE="`mktemp -d /tmp/initrd.XXXXXX`" IMAGE="`mktemp -u /tmp/initrd.img-XXXXXX`" MNTPOINT="`mktemp -d /tmp/initrd.mnt-XXXXXX`" RCFILE="$MNTIMAGE/linuxrc" if [ -f "$MNTIMAGE" ]; then echo "$MNTIMAGE already exists. Remove it and try again" 1>&2 exit 1 fi if [ -f "$IMAGE" ]; then echo "$IMAGE already exists. Remove it and try again" 1>&2 exit 1 fi if [ "$INITRDFS" = "ext2" ] ; then dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null # We have to "echo y |" so that it doesn't complain about $IMAGE not # being a block device echo y | mke2fs -F "$IMAGE" "$IMAGESIZE" >/dev/null 2>/dev/null mkdir -p "$MNTPOINT" mount -o loop -t ext2 "$IMAGE" "$MNTPOINT" else mkdir -p "$MNTPOINT" fi mkdir -p "$MNTIMAGE"/{lib,bin,etc,dev,loopfs,var} # We don't need this directory, so let's save space rm -rf "$MNTPOINT"/lost+found modules_install "$MODULES" # mknod'ing the devices instead of copying them works both with and # without devfs... mknod "$MNTIMAGE/dev/console" c 5 1 mknod "$MNTIMAGE/dev/null" c 1 3 mknod "$MNTIMAGE/dev/zero" c 1 5 s="$RCFILE" ln -s /linuxrc $MNTIMAGE/init inst /bin/initrd-busybox "$MNTIMAGE/bin/sh" ln -s sh "$MNTIMAGE/bin/busybox" if is_yes "$USEINSMODSTATIC" ; then inst "$INSMOD" $MNTIMAGE/bin/insmod.static fi cat > "$s" <> "$RCFILE" # echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE" # echo "echo Setting up loopback device $rootdev1" >> $RCFILE # echo "losetup $rootdev1 /loopfs$loopFile" >> "$RCFILE" #fi initrd_gen_suspend2() { MODULES="" for mod in $SUSPEND2MODS; do is_yes "$BOOT_SPLASH" && [ "$mod" = "-suspend-text" ] && mod="-suspend_bootsplash" findmodule "$mod" done modules_install "$MODULES" mkdir -p $MNTIMAGE/sys mkdir -p $MNTIMAGE/proc cat << EOF >> "$s" mount -t proc none /proc if [ "\$(awk ' /resume2=/ { print "yes"; } ' /proc/cmdline)" = "yes" ]; then EOF modules_add_linuxrc "$MODULES" "$s" cat << EOF >> "$s" echo > /proc/software_suspend/activate fi umount /proc EOF } initrd_gen_udev() { [ -n "$verbose" ] && echo "Setting up udev..." mkdir -p $MNTIMAGE/sbin mkdir -p $MNTIMAGE/proc mkdir -p $MNTIMAGE/etc/udev inst /sbin/initrd-udev $MNTIMAGE/sbin/udev ln -s udev $MNTIMAGE/sbin/udevstart inst /etc/udev/udev.conf $MNTIMAGE/etc/udev/udev.conf ln -s udev $MNTIMAGE/sbin/hotplug if is_yes "$USE_UDEV"; then if is_yes "$UDEV_TMPFS"; then cat >> "$s" <<-EOF echo Creating /dev mount -o mode=0755 -t tmpfs none /dev mknod /dev/console c 5 1 mknod /dev/null c 1 3 mknod /dev/zero c 1 5 mkdir /dev/pts mkdir /dev/shm EOF fi cat >> "$s" <<-EOF mount -t proc none /proc echo Starting udev /sbin/udevstart echo -n "/sbin/hotplug" > /proc/sys/kernel/hotplug umount /proc EOF fi } initrd_gen_dmraid() { if [ ! -x /sbin/dmraid-initrd ] ; then echo "/sbin/dmraid-initrd is missing missing !" exit 1 fi if [ ! -x $MNTIMAGE/sbin/udev ]; then echo "udev is needed on target initrd for dmraid to work!" exit 1 fi mkdir -p "$MNTIMAGE/sbin" inst /sbin/dmraid-initrd $MNTIMAGE/sbin/dmraid cat <<-EOF >> "$s" mount -t proc none /proc mount -t sysfs none /sys # 2 secs was enough for my system to initialize. but really this is udev issue? usleep 2000000 /sbin/dmraid -ay -i umount /sys umount /proc EOF } initrd_gen_softraid() { [ -n "$verbose" ] && echo "Setting up mdadm..." if [ ! -x /sbin/mdadm -o ! -x /sbin/initrd-mdassemble ] ; then echo "/sbin/mdadm or /sbin/initrd-mdassemble is missing !" exit 1 fi inst /sbin/initrd-mdassemble "$MNTIMAGE/bin/mdassemble" # LVM on RAID case dev_list_extra=$(awk '/^DEVICE / { for (i=2; i<=NF; i++) { printf "%s ", $i; }; } ' /etc/mdadm.conf) for ex_dev in $dev_list_extra; do echo "DEVICE $ex_dev" >> "$MNTIMAGE/etc/mdadm.conf" done do_md0=1 for nr in `seq 1 $rootdev_nr`; do eval cr_rootdev="\$rootdev${nr}" eval cr_dev_list="\$dev_list${nr}" [ -n "$verbose" ] && echo "Setting up array ($cr_rootdev = $cr_dev_list)" [ "$cr_rootdev" = "/dev/md0" ] && do_md0=0 echo "DEVICE $cr_dev_list" >> "$MNTIMAGE/etc/mdadm.conf" cr_dev_list_md="$(echo "$cr_dev_list" | xargs | awk ' { gsub(/ +/,",",$0); print $0; }')" cr_md_conf=$(/sbin/mdadm --detail --brief --config=/etc/mdadm.conf $cr_rootdev) if [ -n "$cr_md_conf" ]; then echo "$cr_md_conf" >> "$MNTIMAGE/etc/mdadm.conf" else echo "ARRAY $cr_rootdev devices=$cr_dev_list_md" >> "$MNTIMAGE/etc/mdadm.conf" fi for f in $cr_dev_list $cr_rootdev $dev_list_extra; do # mkdir in case of devfs name mkdir -p $MNTIMAGE/`my_dirname $f` [ -e "$MNTIMAGE/$f" ] && continue [ -n "$verbose" ] && echo "copying $f" # this works fine with and without devfs cp -HR $f $MNTIMAGE/$f done done echo "mdassemble" >> "$s" # needed to determine md-version if [ "$do_md0" -eq 1 ] ; then mknod $MNTIMAGE/dev/md0 b 9 0 fi } initrd_gen_nfs() { # use root=/dev/ram0 init=/linuxrc when starting kernel or you will # have problems like init(XX) being child process of swapper(1). [ -n "$verbose" ] && echo "Adding rootfs on NFS support to initrd (dhcp)" mknod "$MNTIMAGE/dev/urandom" c 1 8 mkdir "$MNTIMAGE/newroot" echo "ifconfig lo 127.0.0.1 up" >> "$s" echo "route add -net 127.0.0.0 netmask 255.0.0.0 lo" >> "$s" echo "ifconfig eth0 0.0.0.0 up" >> "$s" echo "udhcpc -i eth0 -f -q -s /bin/setdhcp" >> "$s" cat << EOF > "$MNTIMAGE/bin/setdhcp" #!/bin/sh [ "\$1" != "bound" ] && exit [ -n "\$broadcast" ] && BROADCAST="broadcast \$broadcast" [ -n "\$subnet" ] && NETMASK="netmask \$subnet" set -x ifconfig \$interface \$ip \$BROADCAST \$NETMASK up set +x if [ -n "\$router" ]; then for r in \$router; do set -x route add default gw \$r dev \$interface set +x done fi if [ -n "\$rootpath" ]; then set -x mount -n -t nfs -o ro,nolock,posix,tcp,wsize=8192,rsize=8192 \$rootpath /newroot set +x else set +x echo "Missing rootpath in what DHCP server sent to us. Failing..." echo "All seen variables are listed below:" set set -x fi EOF chmod 755 "$MNTIMAGE/bin/setdhcp" echo "cd /newroot" >> "$s" echo "pivot_root . initrd" >> "$s" echo "[ -x /sbin/chroot ] && exec /sbin/chroot . /sbin/init -i < dev/console > dev/console 2>&1" >> "$s" echo "exec /usr/sbin/chroot . /sbin/init -i < dev/console > dev/console 2>&1" >> "$s" } initrd_gen_lvm() { [ -n "$verbose" ] && echo "Adding LVM support to initrd" inst /sbin/initrd-lvm $MNTIMAGE/bin/lvm mkdir -p $MNTIMAGE/etc mkdir -p $MNTIMAGE/tmp mkdir -p $MNTIMAGE/proc mkdir -p $MNTIMAGE/newroot if ! is_yes "$USE_UDEV"; then mkdir -p $MNTIMAGE/dev/mapper mknod $MNTIMAGE/dev/mapper/control c 10 63 for device in $PVDEVICES; do # if LVM on RAID then device might be copied already in gen_softraid [ -e "$MNTIMAGE/dev/$(basename $device)" ] && continue cp -HR $device $MNTIMAGE/dev/ done fi echo "mount -t proc none /proc" >> "$s" echo "mount -t tmpfs none /tmp" >> "$s" if [ "$LVMTOOLSVERSION" = "1" ] ; then echo "lvm vgscan -T" >> "$s" echo "lvm vgchange -T -a y $VGVOLUME" >> "$s" echo "umount /tmp" >> "$s" # fail to umount echo "umount /dev" >> "$s" echo "umount /proc" >> "$s" else echo "cat /etc/lvm.conf > /tmp/lvm.conf" >> "$s" echo "global {" > "$MNTIMAGE/etc/lvm.conf" echo " locking_type = 0" >> "$MNTIMAGE/etc/lvm.conf" echo " locking_dir = \"/tmp\"" >> "$MNTIMAGE/etc/lvm.conf" echo "}" >> "$MNTIMAGE/etc/lvm.conf" echo "devices {" >> "$MNTIMAGE/etc/lvm.conf" echo " sysfs_scan=0" >> "$MNTIMAGE/etc/lvm.conf" if is_yes "$raidfound"; then echo " md_component_detection = 1" >> "$MNTIMAGE/etc/lvm.conf" fi lvm dumpconfig | awk '/filter=/' >> "$MNTIMAGE/etc/lvm.conf" echo "}" >> "$MNTIMAGE/etc/lvm.conf" echo "LVM_SYSTEM_DIR=/tmp lvm vgscan --ignorelockingfailure" >> "$s" echo "LVM_SYSTEM_DIR=/tmp lvm vgchange --ignorelockingfailure -a y $VGVOLUME" >> "$s" echo "LVM_SYSTEM_DIR=/tmp lvm vgscan --ignorelockingfailure --mknodes" >> "$s" # Find out major/minor echo "majmin=\"\`LVM_SYSTEM_DIR=/tmp lvm lvdisplay --ignorelockingfailure -c $org_rootdev\`\"" >> "$s" echo "majmin=\"\${majmin#*/}\"" >> "$s" echo "majmin=\"\${majmin#*:*:*:*:*:*:*:*:*:*:*:*}\"" >> "$s" echo "major=\"\${majmin%:*}\"" >> "$s" echo "minor=\"\${majmin#*:}\"" >> "$s" # Pass it to kernel echo "val=\$((256 * \$major + \$minor))" >> "$s" echo "echo \$val > /proc/sys/kernel/real-root-dev" >> "$s" echo "umount /tmp" >> "$s" echo "umount /proc" >> "$s" fi } initrd_gen_procdata() { [ -n "$verbose" ] && echo "Adding rootfs finding based on root= option support." mkdir -p $MNTIMAGE/proc cat << EOF >> "$s" set +x mount -t proc none /proc root="\$(busybox awk ' /root=\/dev\// { gsub(/.*root=\/dev\//,NIL,\$0); gsub(/ .*/,NIL,\$0); print \$0; } ' /proc/cmdline)" if [ -n "\$root" ]; then rootnr="\$(busybox awk -v root="\$root" ' { if (\$4 == root) { print 256*\$1+\$2; } } ' /proc/partitions)" if [ -n "\$rootnr" ]; then echo "\$rootnr" > /proc/sys/kernel/real-root-dev fi fi umount /proc set -x EOF } # main generation if is_yes "$USE_UDEV"; then initrd_gen_udev fi if is_yes "$USESUSPEND2"; then initrd_gen_suspend2 fi if is_yes "$USE_DMRAID"; then initrd_gen_dmraid fi if is_yes "$usenfs" ; then initrd_gen_nfs elif is_yes "$USERAIDSTART" && is_yes "$raidfound" ; then initrd_gen_softraid if is_yes "$uselvm" ; then initrd_gen_lvm else initrd_gen_procdata fi elif is_yes "$uselvm" ; then initrd_gen_lvm else initrd_gen_procdata fi if [ "$INITRDFS" = "initramfs" ]; then mkdir -p $MNTIMAGE/newroot cp -HR $org_rootdev $MNTIMAGE/dev echo "mount -t $rootFs $org_rootdev /newroot" >> "$s" echo "switch_root /newroot /sbin/init" >> "$s" # we need real file, not symlink rm -f $MNTIMAGE/init cp -a $MNTIMAGE/linuxrc $MNTIMAGE/init fi chmod +x "$RCFILE" (cd "$MNTIMAGE"; tar cf - .) | (cd "$MNTPOINT"; tar xf -) case "$INITRDFS" in ext2) umount "$IMAGE" ;; rom) genromfs -f "$IMAGE" -d "$MNTPOINT" -V "PLD initrd for kernel $kernel" ;; cram) mkcramfs "$MNTPOINT" "$IMAGE" ;; initramfs) (cd $MNTPOINT ; find . | cpio -H newc -o > "$IMAGE") ;; *) echo "Filesystem $INITRDFS not supported by $0"; esac if is_yes "$COMPRESS" ; then gzip -9 < "$IMAGE" > "$target" else cp -a "$IMAGE" "$target" fi if is_yes "$BOOT_SPLASH"; then if [ ! -x /bin/splash.bin ]; then echo "Failed to execute /bin/splash.bin. Is bootsplash package installed?" 1>&2 elif [ -z "$THEME" ]; then echo "Please configure your /etc/sysconfig/bootsplash first." 1>&2 echo "Generating bootsplashes skipped." 1>&2 else if [ -n "$BOOT_SPLASH_RESOLUTIONS" ]; then for res in $BOOT_SPLASH_RESOLUTIONS; do if [ -f "/etc/bootsplash/themes/$THEME/config/bootsplash-$res.cfg" ]; then /bin/splash.bin -s -f "/etc/bootsplash/themes/$THEME/config/bootsplash-$res.cfg" >> "$target" && \ [ -n "$verbose" ] && echo "Added $res $THEME theme to initrd." else echo "/etc/bootsplash/themes/$THEME/config/bootsplash-$res.cfg doesn't exist, skipped" 1>&2 fi done else echo "No BOOT_SPLASH_RESOLUTIONS specified in /etc/sysconfig/bootsplash." 1>&2 echo "Not adding bootsplash to initrd." 1>&2 fi fi fi rm -rf "$MNTIMAGE" "$MNTPOINT" "$IMAGE"