#!/bin/sh # geninitrd # # by Jacek Konieczny # # based on mkinitrd from RedHat # # $Id: geninitrd,v 2.7 2001/09/07 17:56:33 kloczek Exp $ PATH=/sbin:$PATH export PATH VERSION="2.6" . /etc/rc.d/init.d/functions COMPRESS="yes" FS="rom" USEBSP="yes" USERAIDSTART="no" PRESCSIMODS="scsi_mod unknown sd_mod" PREIDEMODS="ide-mod ide-probe ide-probe-mod ide-disk" target="" kernel="" force="" verbose="" MODULES="" img_vers="" modulefile=/etc/modules.conf raidtab=/etc/raidtab fstab="/etc/fstab" usage () { echo "usage: `basename $0` [--version] [-v] [-f] [--ifneeded] [--preload ]" 1>&2 echo " [--with=] [--image-version] [--fstab=] [--nocompress]" 1>&2 echo " [--fs=rom|ext2|cram] [--no-bsp] [--modules-conf=" 1>&2 echo " " 1>&2 echo " (ex: `basename $0` /boot/initrd-2.2.5-15.img 2.2.5-15)" 1>&2 exit 1 } my_find() { for name in `ls` do if [ -d $name ]; then if [ "$name" != "build" ]; then (cd $name;my_find $1/$name $2) fi else if [ -f $name -a "$name" = "$2" ]; then echo $1/$name fi fi done } my_dirname() { echo $1|awk -F/ '{print substr($0, 0, length($0) - length($NF));}' } 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 if [ "$modName" = "pluto" ]; then findmodule fc4 findmodule soc fi if [ "$modName" = "fcal" ]; then findmodule fc4 findmodule socal fi fmPath="`(cd /lib/modules/$kernel; my_find . "$modName.o")`" if [ ! -f "/lib/modules/$kernel/$fmPath" ]; then if [ -n "$skiperrors" ]; then return fi # ignore the absence of the scsi modules for n in $PRESCSIMODS; do if [ "$n" = "$modName" ]; then return; fi done; # ignore the absence of the ide modules for n in $PREIDEMODS; do if [ "$n" = "$modName" ]; then return; fi done; echo "No module $modName found for kernel $kernel" 1>&2 exit 1 fi # only need to add each module once tmpFmPath="`echo "$fmPath"|awk -F/ '{for(i=1;i " 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=*) case $rootFs in ext2) 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 ;; UUID=*) case $rootFs in ext2) 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 ;; esac } if [ -r /etc/sysconfig/geninitrd ] ; then . /etc/sysconfig/geninitrd fi if is_yes $USEBSP ; then [ ! -x /sbin/bsp ] && USEBSP="no" fi if [ "`uname -m`" = "ia64" ]; then IMAGESIZE=3000 else IMAGESIZE=1500 fi while [ $# -gt 0 ]; do case $1 in --no-bsp) USEBSP="no" ;; --fstab*) if is_yes "`echo $1 | awk '/=/ { print "yes"; }'`" ; then fstab="`echo $1 | awk -F= '{print $2;}'`" else fstab="$2" shift fi ;; --modules-conf=*) modulefile="`echo $1 | awk -F= '{print $2;}'`" ;; --modukes-conf) modulefile="$2" shift ;; --raidtab=*) raidtab="`echo $1 | awk -F= '{print $2;}'`" ;; --raidtab) raidtab="$2" shift ;; --with*) if is_yes "`echo $1 | awk '/=/ { print "yes"; }'`" ; then modname="`echo $1 | awk -F= '{print $2;}'`" else modname="$2" shift fi BASICMODULES="$BASICMODULES $modname" ;; --version) echo "geninitrd: version $VERSION" exit 0 ;; -v) verbose=-v ;; --nocompress) COMPRESS="no" ;; --ifneeded) ifneeded=1 ;; -f) force=1 ;; --preload*) if is_yes "`echo $1 | awk '/=/ { print "yes"; }'`" ; then modname="`echo $1 | awk -F= '{print $2;}'`" else modname="$2" shift fi PREMODS="$PREMODS $modname" ;; --fs=*) FS="`echo $1 | awk -F= '{print $2;}'`" ;; --fs) FS="$2" shift ;; --image-version) img_vers=yes ;; --use-raidstart) USERAIDSTART=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 case "$FS" 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 ;; *) echo "Filesystem $FS 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 for n in $PREMODS; do findmodule "$n" done find_root if is_yes "`echo "$rootdev" | awk '/^\/dev\/md/ { print "yes"; }'`"; then eval `awk -v rootdev=$rootdev 'BEGIN { addide="no"; addscsi="no"; found="no"; } { gsub("\t"," "); gsub(" +", " "); gsub("^ ",""); if (/^[\t ]*#/) next; if (/^raiddev/) { if ($2 == rootdev) { found="yes"; } else { if (found == "yes") { exit 0; }; }; }; if (found == "yes") { if ($1 == "device") { if ($2 ~ /\/dev\/(sd|scsi)/) { addscsi="yes"; }; if ($2 ~ /\/dev\/(hd|ide)/) { addide="yes"; }; }; if ($1 == "raid-level") { raidlevel=$2; } }; } END { print "raidfound=" found "\nADDSCSI=" addscsi "\nADDIDE=" addide "\nraidlevel=" raidlevel "\n"; }' $raidtab ` if is_yes "$raidfound" ; then case "$raidlevel" in [0145]) findmodule "raid$raidlevel" ;; linear) findmodule "linear" ;; *) echo "raid level $number (in $raidtab) not recognized" 1>&2 ;; esac fi else USERAIDSTART="no" fi if is_yes "$ADDSCSI" || is_yes "$(echo "$rootdev" | awk '/^\/dev\/(sd|scsi)/ { print "yes"; }')" ; then for n in $PRESCSIMODS; do if [ "$n" = "unknown" ] ; then if [ ! -f "$modulefile" ]; then modulefile=/etc/conf.modules fi if [ -f "$modulefile" ]; then scsimodules="`awk '/scsi_hostadapter/ && ! /^[\t ]*#/ { print $3; }' $modulefile| LC_ALL=C sort -u`" 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 fi if is_yes "$ADDIDE" || is_yes "`echo "$rootdev" | awk '/^\/dev\/(hd|ide)/ { print "yes"; }'`" ; then for n in $PREIDEMODS; do findmodule "$n" done fi if is_yes "`echo "$rootdev" | awk '/\/dev\/rd\// { print "yes"; }'`" ; then findmodule "DAC960" fi if is_yes "`echo "$rootdev" | awk '/\/dev\/ida\// { print "yes"; }'`" ; then findmodule "cpqarray" fi if is_yes "`echo "$rootdev" | awk '/\/dev\/cciss\// { print "yes"; }'`" ; then findmodule "cciss" fi # check to see if we need to set up a loopback filesystem if is_yes "`echo "$rootdev" | awk -F/ '{print($3);}' | awk '/loop/ { print "yes"; }'`" ; then if [ ! -x /sbin/losetup ]; then echo "losetup is missing" exit 1 fi key="^# $(echo $rootdev | 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 $rootdev, 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, # anyway no bsp USEBSP="no" else # Check for other filesystems findmodule "-$rootFs" fi 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 [ "$FS" = "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} # We don't need this directory, so let's save space rm -rf "$MNTPOINT"/lost+found for MODULE in $MODULES; do MODULEDIR="`my_dirname "$MODULE"`" mkdir -p "$MNTIMAGE/lib/modules/$kernel/$MODULEDIR" cp $verbose -a "/lib/modules/$kernel/$MODULE" "$MNTIMAGE/lib/modules/$kernel/$MODULE" done # mknod'ing the devices instead of copying them works both with and # without devfs... mknod "$MNTIMAGE/dev/console" c 5 1 if is_yes "$USEBSP" ; then s="$MNTIMAGE/etc/startup" inst /sbin/bsp "$RCFILE" echo "# autogenerated startup" > "$s" echo "" >> "$s" for MODULE in $MODULES; do module="`echo $MODULE | awk -F/ '{ $0=$NF } /.o$/ { $0=substr($0,1,length($0)-2); } { print $0; }'`" options="`awk '{ if($1 == "options" && $2 == "'${module}'") { for(i=3;i<=NF;i++) printf("%s ",$i); }}' "$modulefile"`" if [ -n "$verbose" ]; then /bin/echo -n "Loading module $module " if [ -n "$options" ] ; then echo "with options $options." else echo "without options." fi fi echo "insmod /lib/modules/$kernel/$MODULE $options" >> "$s" done else inst /bin/trash "$MNTIMAGE/bin/sh" inst /sbin/insmod.static "$MNTIMAGE/bin/insmod" mknod "$MNTIMAGE/dev/null" c 1 3 mknod "$MNTIMAGE/dev/ram" b 1 1 mknod "$MNTIMAGE/dev/systty" c 4 0 for i in 1 2 3 4; do mknod "$MNTIMAGE/dev/tty$i" c 4 1 done mknod "$MNTIMAGE/dev/zero" c 1 5 echo "#!/bin/sh" > "$RCFILE" echo "" >> "$RCFILE" for MODULE in $MODULES; do module="`echo $MODULE | awk -F/ '{ $0=$NF } /.o$/ { $0=substr($0,1,length($0)-2); } { print $0; }'`" if [ -f "$modulefile" ] ; then options="`awk '{ if($1 == "options" && $2 == "'${module}'") { for(i=3;i<=NF;i++) printf("%s ",$i); }}' "$modulefile"`" else options= fi if [ -n "$verbose" ]; then echo "Loading module $module with options $options" fi echo "Add module $module to initrd." echo "echo \"Loading $module module\"" >> "$RCFILE" echo "insmod -k /lib/modules/$kernel/$MODULE $options" >> "$RCFILE" done if [ -n "$loopDev" ]; then if [ ! -d /initrd ]; then mkdir /initrd fi cp -a "$loopDev" "$MNTIMAGE/dev" cp -a "$rootdev" "$MNTIMAGE/dev" echo "echo Mounting device containing loopback root filesystem" >> "$RCFILE" echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE" echo "echo Setting up loopback device $rootdev" >> $RCFILE echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE" fi fi if is_yes "$USERAIDSTART" ; then if [ -x /sbin/raidstart.static ] ; then [ -n "$verbose" ] && echo "Add raidstart to initrd" mkdir -p "$MNTIMAGE/etc" || true inst /sbin/raidstart.static "$MNTIMAGE/bin/raidstart" inst "$raidtab" "$MNTIMAGE/etc/raidtab" echo "echo \"Starting RAID\"" >> "$RCFILE" echo "/bin/raidstart $rootdev" >> "$RCFILE" else echo "/sbin/raidstart.static is missing" 1>&2 exit 1 fi fi chmod +x "$RCFILE" (cd "$MNTIMAGE"; tar cf - .) | (cd "$MNTPOINT"; tar xf -) case "$FS" in ext2) umount "$IMAGE" ;; rom) genromfs -f "$IMAGE" -d "$MNTPOINT" -V "PLD initrd for kernel $kernel" ;; cram) mkcramfs "$MNTPOINT" "$IMAGE" ;; *) echo "Filesystem $FS not supported by $0"; esac if is_yes "$COMPRESS" ; then gzip -9 < "$IMAGE" > "$target" else cp -a "$IMAGE" "$target" fi rm -rf "$MNTIMAGE" "$MNTPOINT" "$IMAGE"