#!/bin/sh # geninitrd # # by Jacek Konieczny # # based on geninitrd written by Erik Troan # and contributors: # Elliot Lee # Miguel de Icaza # Christian 'Dr. Disk' Hechelmann # Michael K. Johnson # Pierre Habraken # Jakub Jelinek # Carlo Arenas Belon (carenas@chasqui.lared.net.pe> # PATH=/sbin:$PATH export PATH VERSION=%VERSIONTAG% . /etc/rc.d/init.d/functions COMPRESS="yes" FS="rom" PROBESCSI="yes" PROBEIDE="yes" PROBERAID="yes" if [ -f /etc/sysconfig/initrd ] ; then . /etc/sysconfig/initrd fi target="" kernel="" force="" verbose="" MODULES="" img_vers="" modulefile=/etc/modules.conf if [ `uname -m` = "ia64" ]; then IMAGESIZE=3000 else IMAGESIZE=1500 fi PRESCSIMODS="scsi_mod sd_mod unknown" PREIDEMODS="ide-mod ide-probe-mod ide-disk" fstab="/etc/fstab" usage () { echo "usage: `basename $0` [--version] [-v] [-f] [--ifneeded] [--preload ]" >&2 echo " [--omit-scsi-modules] [--omit-raid-modules] [--omit-ide-modules] [--with=]" >&2 echo " [--image-version] [--fstab=] [--nocompress] [--fs=rom|ext2|cram]" >&2 echo " " >&2 echo " (ex: `basename $0` /boot/initrd-2.2.5-15.img 2.2.5-15)" >&2 exit 1 } findmodule() { skiperrors="" modName=$2 if [ $(echo $modName | cut -b1) = "-" ]; then skiperrors=1 modName=$(echo $modName | cut -b2-) fi if [ "$modName" = "pluto" ]; then findmodule "" fc4 findmodule "" soc fi if [ "$modName" = "fcal" ]; then findmodule "" fc4 findmodule "" socal fi if [ -n "$1" ]; then fmPath="$1"/"$modName".o else fmPath=`(cd /lib/modules/$kernel; echo */$modName.o)` fi if [ "$1" = "fs" ] && [ ! -f /lib/modules/$kernel/$fmPath ]; then fmPath="$1"/"${modName}fs".o fi 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" >&2 exit 1 fi # only need to add each module once if echo $MODULES | grep $fmPath >/dev/null 2>&1 ; then : ; else MODULES="$MODULES $fmPath" fi } inst() { if [ "$#" != "2" ];then echo "usage: inst " return fi [ -n "$verbose" ] && echo "$1 -> $2" cp $1 $2 } while [ $# -gt 0 ]; do case $1 in --fstab*) if echo $1 | grep '=' >/dev/null ; then fstab=`echo $1 | sed 's/^--with=//'` else fstab=$2 shift fi ;; --with*) if echo $1 | grep '=' >/dev/null ; then modname=`echo $1 | sed 's/^--with=//'` 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 echo $1 | grep '=' >/dev/null ; then modname=`echo $1 | sed 's/^--preload=//'` else modname=$2 shift fi PREMODS="$PREMODS $modname" ;; --omit-scsi-modules) PRESCSIMODS="" PROBESCSI="no"; ;; --omit-raid-modules) PROBERAID="no"; ;; --omit-ide-modules) PROBEIDE="no"; ;; --with-fs) if echo $1 | grep '=' >/dev/null ; then FS=`echo $1 | sed 's/^--fs=//'` else FS=$2 shift fi ;; --image-version) img_vers=yes ;; *) if [ -z "$target" ]; then target=$1 elif [ -z "$kernel" ]; then kernel=$1 else usage fi ;; esac shift done case "$FS" in ext2) if [ ! -x /sbin/losetup ]; then echo "losetup is missing" exit 1 fi ;; rom) if [ ! -x /sbin/genromfs ]; then echo "genromfs is missing" exit 1 fi ;; cram) if [ ! -x /sbin/mkcramfs ]; then echo "mkcramfs is missing" exit 1 fi ;; *) echo "Filesystem $FS not supported" exit 1 ;; esac if [ -z "$target" -o -z "$kernel" ]; then usage fi if [ -n "$img_vers" ]; then target="$target-$kernel" fi if [ -z "$force" -a -f $target ]; then echo "$target already exists." >&2 exit 1 fi if [ ! -d /lib/modules/$kernel ]; then echo "/lib/modules/$kernel is not a directory." >&2 exit 1 fi for n in $PREMODS; do findmodule "" $n done rootdev=$(awk '{ if ($2 == "/") { print $1; }}' $fstab) if is_yes "$PROBESCSI" && echo "$rootdev" | grep -q "^/dev/sd" ; then for n in $PRESCSIMODS; do findmodule scsi $n done if [ ! -f $modulefile ]; then modulefile=/etc/conf.modules fi if [ -f $modulefile ]; then scsimodules=`grep scsi_hostadapter $modulefile | grep -v '^[ ]*#' | LC_ALL=C sort -u | awk '{ print $3 }'` 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 fi if is_yes "$PROBEIDE" && echo "$rootdev" | grep -q "^/dev/hd" ; then for n in $PREIDEMODS; do findmodule block $n done fi if is_yes "$PROBERAID" ; then # load appropriate raid devices if necessary if grep '^/dev/md' $fstab | grep -v noauto >/dev/null 2>&1 ; then for number in $(grep '^[ ]*raid-level' /etc/raidtab | awk '{print $2}' | LC_ALL=C sort -u) ; do case $number in [0145]) findmodule "" raid$number ;; *) echo "raid level $number (in /etc/raidtab) not recognized" >&2 ;; esac done fi fi # check to see if we need to set up a loopback filesystem if echo $rootdev | cut -d/ -f3 | grep loop >/dev/null; then key="^# $(echo $rootdev | cut -d/ -f3 | tr '[a-z]' '[A-Z]'):" if ! grep "$key" $fstab > /dev/null; 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" 2>&2 exit 1 fi line=$(grep "$key" $fstab) loopDev=$(echo $line | awk '{print $3}') loopFs=$(echo $line | awk '{print $4}') loopFile=$(echo $line | awk '{print $5}') BASICMODULES="$BASICMODULES -loop" findmodule fs "-$loopFs" BASICMODULES="$BASICMODULES -${loopFs}" else # Check for other filesystems rootFs=`awk '{if ($2 == "/") {print $3}}' $fstab` findmodule fs "-$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=/tmp/initrd.$$ IMAGE=/tmp/initrd.img-$$ MNTPOINT=/tmp/initrd.mnt-$$ RCFILE=$MNTIMAGE/linuxrc if [ -f $MNTIMAGE ]; then echo "$MNTIMAGE already exists. Remove it and try again" >&2 exit 1 fi if [ -f $IMAGE ]; then echo "$IMAGE already exists. Remove it and try again" >&2 exit 1 fi if [ "$FS" = "ext2" ] ; then dd if=/dev/zero of=$IMAGE bs=1k count=$IMAGESIZE 2> /dev/null if [ -e /dev/.devfsd ]; then LOOPDEV=/dev/loop/ else LOOPDEV=/dev/loop fi for devnum in 0 1 2 3 4 5 6 7 8; do if losetup ${LOOPDEV}${devnum} $IMAGE 2>/dev/null ; then break; fi done if [ "$devnum" = "8" ]; then rm -rf $MNTPOINT $IMAGE echo "All of your loopback devices are in use!" >&2 exit 1 fi LODEV=${LOOPDEV}${devnum} # We have to "echo y |" so that it doesn't complain about $IMAGE not # being a block device echo y | mke2fs $LODEV $IMAGESIZE >/dev/null 2>/dev/null if [ -n "$verbose" ]; then echo "Using loopback device $LODEV" fi mkdir -p $MNTPOINT mount -t ext2 $LODEV $MNTPOINT || { echo "Can't get a loopback device" exit 1 } 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 inst /bin/ash.static "$MNTIMAGE/bin/sh" inst /sbin/insmod.static "$MNTIMAGE/bin/insmod" for MODULE in $MODULES; do cp $verbose -a /lib/modules/$kernel/$MODULE $MNTIMAGE/lib done # 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/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 echo "#!/bin/sh" > $RCFILE echo "" >> $RCFILE for MODULE in $MODULES; do module=`echo $MODULE | sed "s|.*/||" | sed "s/.o$//"` options=`sed -n -e "s/^options[ ][ ]*$module[ ][ ]*//p" $modulefile` if [ -n "$verbose" ]; then echo "Loading module $module with options $options" fi echo "echo \"Loading $module module\"" >> $RCFILE echo "insmod /lib/$module.o $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 chmod +x $RCFILE (cd $MNTIMAGE; tar cf - .) | (cd $MNTPOINT; tar xf -) case "$FS" in ext2) mount $MNTPOINT losetup -d $LODEV ;; rom) genromfs -f "$IMAGE" -d "$MNTPOINT" -V "PLD initrd for kernel $kernel" ;; cram) mkcramfs "$MNTPOINT" "$IMAGE" COMPRESS=no ;; *) 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