#!/bin/bash # mkinitrd # # Written by Erik Troan # # 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> # Keith Owens # Bernhard Rosenkraenzer # Matt Wilson # # Patched for Mandrake by Guillaume Cottenceau # PATH=/sbin:$PATH export PATH VERSION=3.1.6-mdk compress=1 target="" kernel="" force="" verbose="" MODULES="" img_vers="" modulefile=/etc/modules.conf tmpdir= splash_script=/usr/share/bootsplash/scripts/ splash=auto IMAGESIZE=100 PRESCSIMODS="scsi_mod sd_mod unknown" fstab="/etc/fstab" IGNOREMODS="$IGNOREMODS ppa imm ide-scsi ext2 usb-storage" [[ -f /etc/sysconfig/installkernel ]] && source /etc/sysconfig/installkernel [[ -n $SPLASH ]] && splash=$SPLASH usage () { echo "usage: `basename $0` [--version] [-v] [-f] [--ifneeded] [--preload ]" >&2 echo " [--omit-scsi-modules] [--omit-raid-modules] [--splash=[auto|resolution] [--with=]" >&2 echo " [--image-version] [--fstab=] [--nocompress] [--tmpdir=]" >&2 echo " " >&2 echo " (ex: `basename $0` /boot/initrd-$(uname -r).img $(uname -r))" >&2 exit 1 } findmodule() { skiperrors="" modName=$1 if [ $(echo $modName | cut -b1) = "-" ]; then skiperrors=1 modName=$(echo $modName | cut -b2-) fi if [ "$modName" = "i2o_block" ]; then findmodule i2o_pci findmodule i2o_core modName="i2o_block" fi if [ "$modName" = "pluto" ]; then findmodule fc4 findmodule soc modName="pluto" fi if [ "$modName" = "fcal" ]; then findmodule fc4 findmodule socal modName="fcal" fi if [ "$modName" = "xfs" ]; then if [ -n "$skiperrors" ]; then findmodule -pagebuf else findmodule pagebuf fi findmodule xfs_support if [ -n "$skiperrors" ]; then findmodule -xfs_dmapi else findmodule xfs_dmapi fi modName="xfs" fi if [ "$modName" = "ext3" ]; then if [ -n "$skiperrors" ]; then findmodule -jbd else findmodule jbd fi modName="ext3" fi for i in $IGNOREMODS; do [ "$i" = "$modName" ] && return done fmPath=`(cd /lib/modules/$kernel; find -type f -name $modName.o | grep -v build)` if [ -n "$fmPath" ]; then # only need to add each module once if echo $MODULES | grep $fmPath >/dev/null 2>&1 ; then : ; else MODULES="$MODULES $fmPath" fi else fmPath=`(cd /lib/modules/$kernel; find -type f -name $modName.o.gz | grep -v build)` if [ -n "$fmPath" ]; then # only need to add each module once if echo $MODULES | grep $fmPath >/dev/null 2>&1 ; then : ; else zfmPath=`echo $fmPath | sed s/\.gz//` MODULES="$MODULES $zfmPath" fi fi fi if [ -z "$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; echo "No module $modName found for kernel $kernel" >&2 exit 1 fi } is_good_fs() { local parttype= tmpname= local dir=$1 [[ -d $dir ]] || return 1 [[ -w $dir ]] || return 1 [[ $dir == */ ]] && dir=${dir%/} parttype=$(awk "{if (\$2 == \""$dir"\") print \$3 }" /proc/mounts) while tmpname=${dir%/*} && [[ -z $parttype ]];do [[ -z $tmpname ]] && tmpname=/ parttype=$(awk "{if (\$2 == \""$tmpname"\") print \$3 }" /proc/mounts) dir=$tmpname done case $parttype in nfs|tmpfs) return 1;; *) return 0; esac } inst() { if [ "$#" != "2" ];then echo "usage: inst " return fi [ -n "$verbose" ] && echo "$1 -> $2" cp $1 $2 } is_ix86() { if [ -n "`uname -m | grep i.86`" ]; then return 0; fi return 1 } is_ppc() { if [ -n "`uname -m | grep ppc`" ]; then return 0; fi return 1 } while [ $# -gt 0 ]; do case $1 in --fstab*) if echo $1 | grep '=' >/dev/null ; then fstab=`echo $1 | sed 's/^--fstab=//'` else fstab=$2 shift fi ;; --tmpdir*) if echo $1 | grep '=' >/dev/null ; then tmpdir=`echo $1 | sed 's/^--tmpdir=//'` else tmpdir=$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 "mkinitrd: version $VERSION" exit 0 ;; -v) verbose=-v ;; --nocompress) compress="" ;; --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="" noscsi=1; ;; --omit-raid-modules) noraid=1; ;; --image-version) img_vers=yes ;; --splash) if echo $1 | grep '=' >/dev/null ; then splash=`echo $1 | sed 's/^--splash=//'` else splash=$2 shift fi [[ $splash == no ]] && splash= ;; *) if [ -z "$target" ]; then target=$1 elif [ -z "$kernel" ]; then kernel=$1 else usage fi ;; esac shift done if [[ $splash == auto && -f $splash_script/detect-resolution ]];then splash=$( $splash_script/detect-resolution ) fi 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 if [ -z "$noscsi" ]; then if [ ! -f $modulefile ]; then modulefile=/etc/conf.modules fi if [ -f $modulefile ]; then scsimodules=`grep -E "alias[ ]+scsi_hostadapter" $modulefile | grep -v '^[ ]*#' | LC_ALL=C sort -u | awk '{ print $3 }'` # support probeall form as found with Mandrake 8.1 and superior scsimodules="$scsimodules `sed -n 's/^ *probeall *scsi_hostadapter//p' $modulefile`" if [ -n "$scsimodules" ]; then SAVEMODULES=$MODULES for n in $PRESCSIMODS; do findmodule $n done SAVEMODULESCMP=$MODULES for n in $(for m in $scsimodules; do echo $m; done | awk 'a[$1]=="" {print;a[$1]=1}'); do # for now allow scsi modules to come from anywhere. There are some # RAID controllers with drivers in block/ findmodule $n done [ "$SAVEMODULESCMP" = "$MODULES" ] && MODULES=$SAVEMODULES fi fi fi # If we have ide devices and module ide, do the right thing ide=/proc/ide/ide* if [ -n "$ide" ]; then findmodule -ide-mod findmodule -ide-probe-mod findmodule -ide-disk fi if [ -z "$noraid" ]; then # load appropriate raid devices if necessary, this means that the # /etc/raidtab *must* be up to date for raided root to work. #if grep '^/dev/md' $fstab | grep -v noauto >/dev/null 2>&1 ; then for number in $(grep '^[ ]*raid-level' /etc/raidtab 2>/dev/null | awk '{print $2}' | LC_ALL=C sort -u) ; do case $number in [014]) findmodule raid$number startraid=1 ;; 5) findmodule -xor findmodule raid$number startraid=1 ;; *) 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 fullloopfile=$(awk '$2 == "/" && $4 ~ "loop" { print $1 }' /etc/fstab) if [ -n "$fullloopfile" ]; then dir=$fullloopfile while [ -n "$dir" -a -z "$line" ]; do dir=$(dirname $dir) line=$(awk -v dir=$dir '$2 == dir { print $0 }' /etc/fstab) done if [ -z "$line" -o "$dir" = "/" ]; then echo "bad fstab, loopback file doesn't belong to any device" exit 1 fi loopDev=$(echo $line | awk '{ print $1 }') loopFs=$(echo $line | awk '{print $3 }') loopFile=$(echo $fullloopfile | sed "s|$dir||") basicmodules="$basicmodules -loop" if [ "$loopFs" = "vfat" -o "$loopFs" = "msdos" ]; then basicmodules="$basicmodules -fat" fi basicmodules="$basicmodules -${loopFs}" fi rootfs=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $3; }}' $fstab) rootfsopts=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/" && $6) { print $4; }}' $fstab | sed "s|defaults||;s|auto||;s|loop||;s|,,|,|;s|,$||;s|^,||") # in case the root filesystem is modular findmodule -${rootfs} if [ "$rootfs" = "ext3" ] && echo $kernel | grep -q "^2\.2"; then echo "Mandrake 2.2 kernels don't have ext3 compiled in, falling back to ext2 for you." rootfs=ext2 fi for n in $basicmodules; do findmodule $n done [[ -d $splash_script ]] || splash= if [ "$rootfs" != "ext3" -a -z "$rootfsopts" -a -n "$ifneeded" -a -z "$MODULES" -a -z "$splash" ]; then if [ -n "$verbose" ]; then echo "Rootfs is not ext3, there is no rootfs special options, and" echo "no modules are needed -- not building initrd image." fi exit 0 fi if [ -n "$verbose" ]; then echo "Using modules: $MODULES" fi [[ -n $tmpdir ]] && { is_good_fs $tmpdir || tmpdir= ;} #command-line [[ -z $tmpdir && -n $TMPDIR ]] && { is_good_fs $TMPDIR || tmpdir= && tmpdir=$TMPDIR ;} #environement if [[ -z $tmpdir ]];then if is_good_fs /tmp;then tmpdir=/tmp elif is_good_fs /var/tmp;then tmpdir=/var/tmp elif is_good_fs /root/tmp;then tmpdir=/root/tmp else echo "Cannot use a tmp directory" >&2 exit 1 fi fi [[ -n $verbose ]] && echo "Using $tmpdir as temporary directory." MNTIMAGE=`mktemp -d ${tmpdir}/initrd.XXXXXX` IMAGE=`mktemp ${tmpdir}/initrd.img.XXXXXX` MNTPOINT=`mktemp -d ${tmpdir}/initrd.mnt.XXXXXX` RCFILE=$MNTIMAGE/linuxrc # cleanup on exit, hangup, interrupt, quit, termination trap 'rm -rf $MNTIMAGE $MNTPOINT $IMAGE' 0 1 2 3 15 if [ -z "$MNTIMAGE" -o -z "$IMAGE" -o -z "$MNTPOINT" ]; then echo "Error creating temporaries. Try again" >&2 exit 1 fi mkdir -p $MNTIMAGE mkdir -p $MNTIMAGE/lib mkdir -p $MNTIMAGE/bin mkdir -p $MNTIMAGE/etc mkdir -p $MNTIMAGE/dev mkdir -p $MNTIMAGE/loopfs mkdir -p $MNTIMAGE/proc mkdir -p $MNTIMAGE/sysroot ln -s bin $MNTIMAGE/sbin # devfs will shadow some of my dev entries, I'll put them here mkdir -p $MNTIMAGE/safedev # We don't need this directory, so let's save space rm -rf $MNTPOINT/lost+found inst /sbin/nash "$MNTIMAGE/bin/nash" if is_ix86; then inst /sbin/insmod-DIET "$MNTIMAGE/bin/insmod" else inst /sbin/insmod.static "$MNTIMAGE/bin/insmod" fi ln -s ../bin/nash $MNTIMAGE/sbin/modprobe for MODULE in $MODULES; do f="/lib/modules/$kernel/$MODULE" if [ -e $f ]; then cp $verbose -a $f $MNTIMAGE/lib else gunzip -c $f.gz > $MNTIMAGE/lib/`basename $MODULE` fi 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 $i done echo "#!/bin/nash" > $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 2>/dev/null` 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 echo "echo Mounting /proc filesystem" >> $RCFILE echo "mount -t proc /proc /proc" >> $RCFILE if [ -n "$loopDev" ]; then [ -d /initrd ] || mkdir /initrd # our dear friend devfsd will create links for us if devfs in use cp -aL $loopDev $MNTIMAGE/safedev cp -aL /dev/loop7 $MNTIMAGE/safedev loopDev=`echo $loopDev | sed "s|/dev/|/safedev/|"` echo "echo Mounting device containing loopback root filesystem" >> $RCFILE echo "mount -t $loopFs $loopDev /loopfs" >> $RCFILE echo "echo Setting up loopback device on $loopFile" >> $RCFILE echo "losetup /safedev/loop7 /loopfs$loopFile" >> $RCFILE rootdev=/safedev/loop7 else echo "echo Creating root device" >> $RCFILE echo "mkrootdev /dev/root" >> $RCFILE rootdev=/dev/root fi if [ -n "$startraid" ]; then cp -aL /dev/md0 $MNTIMAGE/safedev echo "raidautorun /safedev/md0" >> $RCFILE fi if echo $kernel | grep -q "^2\.2"; then if is_ppc; then [ -n "$loopDev" ] && echo "echo 0x07070000 > /proc/sys/kernel/real-root-dev" >> $RCFILE else [ -n "$loopDev" ] && echo "echo 0x0707 > /proc/sys/kernel/real-root-dev" >> $RCFILE fi echo "umount /proc" >> $RCFILE else # Linux-2.4 if [[ -n "$splash" ]];then if [[ $LOGO_CONSOLE != yes ]] && [[ $LOGO_CONSOLE != YES ]] && [[ $LOGO_CONSOLE != Yes ]]; then echo "echo disabling logo" >> $RCFILE echo "echo 0 > /proc/splash" >> $RCFILE fi fi echo "echo 0x0100 > /proc/sys/kernel/real-root-dev" >> $RCFILE echo "umount /proc" >> $RCFILE [ -n "$rootfsopts" ] && rootfsopts_msg="with flags $rootfsopts" echo "echo Mounting root filesystem $rootfsopts_msg" >> $RCFILE echo "mount --ro -t $rootfs $rootdev /sysroot $rootfsopts" >> $RCFILE echo "pivot_root /sysroot /sysroot/initrd" >> $RCFILE echo "echo Remounting devfs at correct place if necessary" >> $RCFILE echo "handledevfs" >> $RCFILE fi chmod +x $RCFILE for i in `ls -sk $MNTIMAGE/*/* | sed 's/ [^ ]*$//'`; do IMAGESIZE=$[IMAGESIZE + $i] done NB_INODES=20 for i in `find $MNTIMAGE`; do NB_INODES=$[NB_INODES + 1]; done IMAGESIZE=$[IMAGESIZE + NBFILES / 10] # 10 inodes needs 1k dd if=/dev/zero of=$IMAGE bs=1k count=$IMAGESIZE 2> /dev/null if [ -n "$verbose" ]; then echo "Contents of RCFILE:" cat $RCFILE 2> /dev/null echo "Creating filesystem with size ${IMAGESIZE}KB and $NB_INODES inodes" fi mke2fs -q -m 0 -F -N $NB_INODES -s 1 $IMAGE mkdir -p $MNTPOINT mount -t ext2 $IMAGE $MNTPOINT -o loop || { echo "Can't get a loopback device" exit 1 } # We don't need this directory, so let's save space rm -rf $MNTPOINT/lost+found (cd $MNTIMAGE; tar cf - .) | (cd $MNTPOINT; tar xf -) umount $MNTPOINT if [ -n "$compress" ]; then gzip -9 < $IMAGE > $target else cp -a $IMAGE $target fi if [[ -n "$splash" && -f "$splash_script/make-boot-splash" ]];then $splash_script/make-boot-splash $target $splash fi