You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
494 lines
12 KiB
494 lines
12 KiB
#!/bin/sh
|
|
# Daniel Robbins <drobbins@gentoo.org>
|
|
# Copyright 2003 Gentoo Technologies, Inc.
|
|
# Distributed under the GPL
|
|
|
|
. /etc/initrd.defaults
|
|
. /etc/initrd.scripts
|
|
|
|
USE_DEVFS_NORMAL=1
|
|
USE_UDEV_NORMAL=2
|
|
USE_EVMS_NORMAL=1
|
|
USE_LVM2_NORMAL=1
|
|
|
|
if [ "$$" != '1' ]
|
|
then
|
|
echo '/linuxrc has to be run as the init process as the one'
|
|
echo 'with a PID of 1. Try adding init="/linuxrc" to the'
|
|
echo 'kernel command line or running "exec /linuxrc".'
|
|
exit 1
|
|
fi
|
|
|
|
mount -o remount,rw /
|
|
mount -t proc proc /proc
|
|
|
|
[ -n "$QUIET" ] && echo '0' > /proc/sys/kernel/printk
|
|
|
|
CMDLINE=`cat /proc/cmdline`
|
|
# Scan CMDLINE for any specified real_root= or cdroot arguments
|
|
for x in ${CMDLINE}
|
|
do
|
|
case "${x}" in
|
|
real_root\=*)
|
|
REAL_ROOT=`parse_opt "${x}"`
|
|
;;
|
|
cdroot)
|
|
CDROOT=1
|
|
REAL_ROOT=''
|
|
;;
|
|
cdroot\=*)
|
|
CDROOT=1
|
|
CDROOT_DEV=`parse_opt "${x}"`
|
|
REAL_ROOT=''
|
|
;;
|
|
devfs)
|
|
USE_DEVFS_NORMAL=1
|
|
USE_UDEV_NORMAL=0
|
|
;;
|
|
nodevfs)
|
|
USE_DEVFS_NORMAL=0
|
|
;;
|
|
nolvm2)
|
|
USE_LVM2_NORMAL=0
|
|
;;
|
|
noevms)
|
|
USE_EVMS_NORMAL=0
|
|
;;
|
|
udev)
|
|
USE_UDEV_NORMAL=1
|
|
USE_DEVFS_NORMAL=0
|
|
;;
|
|
noudev)
|
|
USE_UDEV_NORMAL=0
|
|
;;
|
|
loop\=*)
|
|
LOOP=`parse_opt "${x}"`
|
|
;;
|
|
looptype\=*)
|
|
LOOPTYPE=`parse_opt "${x}"`
|
|
;;
|
|
real_init\=*)
|
|
REAL_INIT=`parse_opt "${x}"`
|
|
;;
|
|
scandelay=\*)
|
|
SDELAY=`parse_opt "${x}"`
|
|
;;
|
|
scandelay)
|
|
SDELAY=10
|
|
;;
|
|
noload\=*)
|
|
MLIST=`parse_opt "${x}"`
|
|
MLIST="`echo ${MLIST} | sed -e \"s/,/ /\"`"
|
|
export MLIST
|
|
;;
|
|
esac
|
|
done
|
|
|
|
[ -e /proc/scsi/scsi ] && echo 'scsi add-single-device 0 0 0 0' > /proc/scsi/scsi
|
|
|
|
# Scan CMDLINE for any "doscsi" or "noscsi"-type arguments
|
|
for x in $HWOPTS
|
|
do
|
|
for y in $CMDLINE
|
|
do
|
|
if [ "${y}" = "do${x}" ]
|
|
then
|
|
MY_HWOPTS="${MY_HWOPTS} $x"
|
|
elif [ "${y}" = "no${x}" ]
|
|
then
|
|
MY_HWOPTS="`echo ${MY_HWOPTS} | sed -e \"s/${x}//g\" -`"
|
|
fi
|
|
done
|
|
done
|
|
|
|
if [ -d '/lib/modules' ]
|
|
then
|
|
echo -e "${GOOD}>>${NORMAL}${BOLD} Loading modules...${NORMAL}"
|
|
# Load appropriate kernel modules
|
|
for modules in $MY_HWOPTS
|
|
do
|
|
modules_scan $modules
|
|
eval DO_`echo $modules | sed 's/-//'`=1
|
|
done
|
|
else
|
|
echo -e "${GREEN}>>${NORMAL}${BOLD} Skipping module load; no modules in the initrd!${NORMAL}"
|
|
fi
|
|
|
|
chooseKeymap() {
|
|
echo -e "${GOOD}>>${NORMAL}${BOLD} Loading keymaps...${NORMAL}"
|
|
cat /lib/keymaps/keymapList
|
|
read -t 10 -p '<< Load keymap (Enter for default): ' keymap
|
|
if [ -e /lib/keymaps/${keymap}.map ]
|
|
then
|
|
echo -e "${GOOD}>>${NORMAL}${BOLD} Loading the ''${keymap}'' keymap...${NORMAL}"
|
|
loadkmap < /lib/keymaps/${keymap}.map
|
|
elif [ "$keymap" = '' ]
|
|
then
|
|
echo -e "${GOOD}>>${NORMAL}${BOLD} Keeping default keymap...${NORMAL}"
|
|
else
|
|
echo -e "${BAD}!! ${NORMAL}${BOLD}Sorry, but keymap ''${keymap}'' is invalid!${NORMAL}"
|
|
chooseKeymap
|
|
fi
|
|
}
|
|
|
|
echo -e "${GOOD}>>${NORMAL}${BOLD} Mounting filesystems${NORMAL}"
|
|
|
|
# Check udev is on...
|
|
# [ "${KMAJOR}" -ge 2 ] && USE_UDEV_SUPPORT=1
|
|
# [ "${KMAJOR}" -eq 2 -a "${KMINOR}" -ge '6' -a ! "${USE_UDEV_SUPPORT}" -eq '0' ] && USE_UDEV_SUPPORT=1
|
|
[ "${USE_UDEV_NORMAL}" -eq '1' -a ! -x /sbin/udev ] && USE_UDEV_NORMAL=0
|
|
|
|
# If using 2.4 and udev; back off...
|
|
[ "${KMAJOR}" -eq 2 -a "${KMINOR}" -lt '6' -a "${USE_UDEV_NORMAL}" -eq 1 ] &&
|
|
USE_UDEV_NORMAL=0
|
|
|
|
# Disable devfs if we want udev...
|
|
[ -e /dev/.devfsd -a "${USE_UDEV_NORMAL}" -eq 1 ] && echo '>> Enabling devfsd in favour of udev; use "nodevfs" if this is not intended...' && USE_UDEV_NORMAL=0
|
|
|
|
mkdir /newroot
|
|
if [ "${CDROOT}" -eq '1' ]
|
|
then
|
|
mount -t tmpfs tmpfs /newroot
|
|
mkdir /newroot/dev /newroot/mnt /newroot/mnt/cdrom /newroot/mnt/livecd /newroot/tmp /newroot/tmp/.initrd /newroot/mnt/gentoo /newroot/sys
|
|
if [ "${USE_UDEV_NORMAL}" -eq '1' ]
|
|
then
|
|
# Udev is semi-broken on non /sys sysfs mount points.
|
|
mount -t sysfs none /sys
|
|
[ "$?" -eq '0' ] || USE_UDEV_NORMAL=0
|
|
fi
|
|
|
|
if [ "${USE_UDEV_NORMAL}" -eq '1' ]
|
|
then
|
|
cd /sys
|
|
kill_devfsd
|
|
echo -e "${GOOD}>>${NORMAL}${BOLD} Activating udev...${NORMAL}"
|
|
runUdev
|
|
mv /dev/* /newroot/dev
|
|
else
|
|
if [ ! -e /newroot/dev/.devfsd ]
|
|
then
|
|
mount -t devfs devfs /newroot/dev
|
|
devfsd /newroot/dev -np
|
|
if [ -n "${SDELAY}" ]; then
|
|
sleep ${SDELAY}
|
|
else
|
|
sleep 1
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
bootstrapCD() {
|
|
if [ "${CDROOT_DEV}" = '' ]
|
|
then
|
|
findcdmount /newroot/dev/cdroms/*
|
|
|
|
# Not in /dev/cdroms: try /dev/ide/cd
|
|
[ "${REAL_ROOT}" = '' ] && findcdmount /newroot/dev/ide/cd/*
|
|
[ "${REAL_ROOT}" = '' ] && findcdmount /newroot/dev/sr0
|
|
else
|
|
# Device specified on command line
|
|
findcdmount /newroot/${CDROOT_DEV}
|
|
fi
|
|
}
|
|
|
|
bootstrapCD
|
|
if [ "${REAL_ROOT}" = '' ]
|
|
then
|
|
echo -n -e "${WARN}>>${NORMAL}${BOLD} No bootable medium found. Waiting for new devices"
|
|
sleep 3
|
|
echo -n '.'
|
|
sleep 3
|
|
echo -n '.'
|
|
sleep 3
|
|
echo -n '.'
|
|
sleep 1
|
|
echo -e "${NORMAL}"
|
|
bootstrapCD
|
|
fi
|
|
|
|
if [ "${REAL_ROOT}" = '' ]
|
|
then
|
|
# Undo stuff
|
|
umount /newroot/dev 2>/dev/null
|
|
umount /newroot/sys 2>/dev/null
|
|
umount /sys 2>/dev/null
|
|
|
|
umount /newroot
|
|
rm -rf /newroot/*
|
|
|
|
echo 'Could not find CD to boot, something else needed!'
|
|
CDROOT=0
|
|
fi
|
|
fi
|
|
|
|
if [ "${DO_keymap}" ]
|
|
then
|
|
if [ ! -e /dev/vc/0 ]
|
|
then
|
|
DEVBIND=1
|
|
mount -o bind /newroot/dev /dev
|
|
fi
|
|
chooseKeymap
|
|
[ "${DEVBIND}" -eq '1' ] && umount /dev
|
|
fi
|
|
|
|
# FIX: indent me in one $CDROOT -eq '0'
|
|
|
|
# Try to mount sysfs, and if it fails, do not use udev
|
|
if [ "${USE_UDEV_NORMAL}" -eq '1' -a "${CDROOT}" -eq '0' ]
|
|
then
|
|
mount -t sysfs none /sys
|
|
[ "$?" -eq '0' ] || USE_UDEV_NORMAL=0
|
|
fi
|
|
|
|
# Don't merge these two blocks; ^^ USE_UDEV_NORMAL=0...
|
|
if [ "${USE_UDEV_NORMAL}" -eq '1' -a "${CDROOT}" -eq '0' ]
|
|
then
|
|
USE_DEVFS_NORMAL=0
|
|
cd /sys
|
|
echo -e "${GOOD}>>${NORMAL}${BOLD} Activating udev...${NORMAL}"
|
|
runUdev
|
|
elif [ "${CDROOT}" -eq '0' -a "${USE_DEVFS_NORMAL}" -eq '1' ]
|
|
then
|
|
[ ! -e /dev/.devfsd ] && mount -t devfs devfs /dev
|
|
devfsd /dev -np
|
|
fi
|
|
|
|
if [ "${DO_lvm2}" -a "${USE_LVM2_NORMAL}" -eq '1' ]
|
|
then
|
|
if [ -e '/sbin/vgscan' -a -e '/sbin/vgchange' ]
|
|
then
|
|
echo -e "${GOOD}>>${NORMAL}${BOLD} Scanning for Volume Groups...${NORMAL}"
|
|
/sbin/vgscan
|
|
echo -e "${GOOD}>>${NORMAL}${BOLD} Activating Volume Groups...${NORMAL}"
|
|
/sbin/vgchange -ay
|
|
fi
|
|
fi
|
|
|
|
if [ "${DO_evms2}" -a "${USE_LVM2_NORMAL}" -eq '1' ]
|
|
then
|
|
if [ -e '/sbin/evms_activate' ]
|
|
then
|
|
echo -e "${GOOD}>>${NORMAL}${BOLD} Activating EVMS...${NORMAL}"
|
|
evms_activate
|
|
fi
|
|
fi
|
|
|
|
echo -e "${GOOD}>>${NORMAL}${BOLD} Determining root device...${NORMAL}"
|
|
|
|
while true
|
|
do
|
|
while [ "${got_good_root}" != '1' ]
|
|
do
|
|
if [ "${REAL_ROOT}" = 'shell' ]
|
|
then
|
|
/bin/ash
|
|
|
|
REAL_ROOT=''
|
|
got_good_root=0
|
|
continue
|
|
elif [ "${REAL_ROOT}" = '' ]
|
|
then
|
|
# No REAL_ROOT determined/specified. Prompt user for root block device.
|
|
echo -e "${BAD}>>${NORMAL} The root block device is unspecified or not detected."
|
|
echo ' Please specify a device to boot, or "shell" for a shell...'
|
|
echo -n 'boot() :: '
|
|
read REAL_ROOT
|
|
got_good_root=0
|
|
elif [ -b "${REAL_ROOT}" ]
|
|
then
|
|
got_good_root=1
|
|
else
|
|
echo -e "${BAD}>>${NORMAL} Block device ${REAL_ROOT} is not a valid root device..."
|
|
REAL_ROOT=""
|
|
got_good_root=0
|
|
fi
|
|
done
|
|
|
|
if [ "${CDROOT}" -eq '1' -a "${got_good_root}" = '1' ]
|
|
then
|
|
break
|
|
else
|
|
echo -e "${GOOD}>>${NORMAL}${BOLD} Mounting root...${NORMAL}"
|
|
mount -o rw ${REAL_ROOT} /newroot
|
|
|
|
if [ "$?" = '0' ]
|
|
then
|
|
break
|
|
else
|
|
echo -e "${BAD}>> ${NORMAL}Could not mount specified ROOT, try again"
|
|
got_good_root=0
|
|
REAL_ROOT=''
|
|
fi
|
|
fi
|
|
done
|
|
|
|
[ -n "$QUIET" ] && echo '6' > /proc/sys/kernel/printk
|
|
check_loop() {
|
|
if [ "${LOOP}" = '' -o ! -e "mnt/cdrom/${LOOP}" ]
|
|
then
|
|
echo "Invalid loop location: ${LOOP}"
|
|
echo 'Please export LOOP with a valid location, or reboot and pass a proper loop=...'
|
|
echo 'kernel command line!'
|
|
/bin/ash
|
|
fi
|
|
}
|
|
|
|
if [ "${CDROOT}" = '1' ]
|
|
then
|
|
echo -e "${GOOD}>>${NORMAL}${BOLD} Filling tmpfs...${NORMAL}"
|
|
cd /newroot
|
|
|
|
# Failsafe the loop type wasn't set
|
|
if [ "${LOOPTYPE}" = '' ]
|
|
then
|
|
echo -e "${WARN}** ${NORMAL}${BOLD}Warning: loop type unspecified!${NORMAL}"
|
|
if [ "${LOOP}" = '/livecd.loop' ]
|
|
then
|
|
LOOPTYPE='normal'
|
|
elif [ "${LOOP}" = '/zisofs' ]
|
|
then
|
|
LOOPTYPE='zisofs'
|
|
elif [ "${LOOP}" = '/livecd.squashfs' ]
|
|
then
|
|
LOOPTYPE='squashfs'
|
|
elif [ "${LOOP}" = '/livecd.gcloop' ]
|
|
then
|
|
LOOPTYPE='gcloop'
|
|
else
|
|
LOOPTYPE='noloop'
|
|
fi
|
|
fi
|
|
|
|
if [ "${LOOPTYPE}" != 'noloop' ]
|
|
then
|
|
check_loop
|
|
if [ "${DO_cache}" ]
|
|
then
|
|
echo -e "${GOOD}>>${NORMAL}${BOLD} Copying loop file for caching...${NORMAL}"
|
|
cp -a /newroot/mnt/cdrom/${LOOP} /newroot/mnt/${LOOP}
|
|
if [ $? -ne 0 ]
|
|
then
|
|
echo -e "${BAD}!!${NORMAL}${BOLD} Failed to cache the loop file! Lack of space?"
|
|
rm -rf /newroot/mnt/livecd.* 2>/dev/null
|
|
rm -rf /newroot/mnt/zisofs 2>/dev/null
|
|
else
|
|
LOOPEXT='../'
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
if [ "${LOOPTYPE}" = 'normal' ]
|
|
then
|
|
# bind-mount /dev/ so that loop devices can be found
|
|
mount -o bind /newroot/dev /dev
|
|
|
|
echo -e "${GOOD}>>${NORMAL}${BOLD} Mounting loop filesystem...${NORMAL}"
|
|
mount -t ext2 -o loop,ro /newroot/mnt/cdrom/${LOOPEXT}${LOOP} /newroot/mnt/livecd
|
|
if [ "$?" != '0' ]
|
|
then
|
|
echo 'Failed to mount filesystem; failing back to the shell...'
|
|
/bin/ash
|
|
fi
|
|
FS_LOCATION='mnt/livecd'
|
|
umount /dev
|
|
elif [ "${LOOPTYPE}" = 'squashfs' ]
|
|
then
|
|
mount -o bind /newroot/dev /dev
|
|
echo -e "${GOOD}>>${NORMAL}${BOLD} Mounting squashfs filesystem...${NORMAL}"
|
|
mount -t squashfs -o loop,ro /newroot/mnt/cdrom/${LOOPEXT}${LOOP} /newroot/mnt/livecd
|
|
if [ "$?" != '0' ]
|
|
then
|
|
echo 'Failed to mount filesystem; failing back to the shell...'
|
|
/bin/ash
|
|
fi
|
|
FS_LOCATION='mnt/livecd'
|
|
umount /dev
|
|
elif [ "${LOOPTYPE}" = 'gcloop' ]
|
|
then
|
|
echo -e "${GOOD}>>${NORMAL}${BOLD} Mounting gcloop filesystem...${NORMAL}"
|
|
mount -o bind /newroot/dev /dev
|
|
echo ' ' | losetup -E 19 -e ucl-0 -p0 /newroot/dev/loop0 /newroot/mnt/cdrom/${LOOPEXT}${LOOP}
|
|
if [ "$?" != '0' ]
|
|
then
|
|
echo "FAILED TO losetup THE LOOP DEVICE"
|
|
/bin/ash
|
|
fi
|
|
mount -t ext2 -o ro /newroot/dev/loop0 /newroot/mnt/livecd
|
|
FS_LOCATION='mnt/livecd'
|
|
umount /dev
|
|
elif /tmp/.initrd/bin/[ "${LOOPTYPE}" = 'zisofs' ]
|
|
then
|
|
FS_LOCATION="mnt/cdrom/${LOOPEXT}${LOOP}"
|
|
elif /tmp/.initrd/bin/[ "${LOOPTYPE}" = 'noloop' ]
|
|
then
|
|
FS_LOCATION='mnt/cdrom'
|
|
fi
|
|
|
|
echo -e "${GOOD}>>${NORMAL}${BOLD} Filling filesystem...${NORMAL}"
|
|
for x in ${ROOT_LINKS}
|
|
do
|
|
ln -s "${FS_LOCATION}/${x}" "${x}"
|
|
done
|
|
mkdir initrd proc tmp sys
|
|
chmod 1777 tmp
|
|
(cd /newroot/${FS_LOCATION}; cp -a ${ROOT_TREES} /newroot)
|
|
else
|
|
mkdir -p /newroot/tmp/.initrd
|
|
fi
|
|
|
|
/tmp/.initrd/bin/[ ! -e /newroot/dev/console ] && mknod /newroot/dev/console c 5 1
|
|
echo -ne "${GOOD}>>${NORMAL}${BOLD} Booting"
|
|
|
|
cd /newroot
|
|
mkdir /newroot/proc /newroot/sys 2>/dev/null
|
|
pivot_root . tmp/.initrd
|
|
echo -n '.'
|
|
|
|
if /tmp/.initrd/bin/[ "${USE_DEVFS_NORMAL}" -eq '1' -a "${CDROOT}" -eq '0' ]
|
|
then
|
|
umount /tmp/.initrd/proc || echo '*: Failed to unmount the initrd /proc!'
|
|
mount -n --move /tmp/.initrd/dev dev || echo '*: Failed to move over the /dev tree!'
|
|
rm -rf /tmp/.initrd/dev || echo '*: Failed to remove the initrd /dev!'
|
|
elif /tmp/.initrd/bin/[ "${USE_UDEV_NORMAL}" -eq '1' ]
|
|
then
|
|
/tmp/.initrd/bin/[ -e /tmp/.initrd/dev/fd ] && rm /tmp/.initrd/dev/fd
|
|
/tmp/.initrd/bin/[ -e /tmp/.initrd/dev/stdin ] && rm /tmp/.initrd/dev/stdin
|
|
/tmp/.initrd/bin/[ -e /tmp/.initrd/dev/stdout ] && rm /tmp/.initrd/dev/stdout
|
|
/tmp/.initrd/bin/[ -e /tmp/.initrd/dev/stderr ] && rm /tmp/.initrd/dev/stderr
|
|
/tmp/.initrd/bin/[ -e /tmp/.initrd/dev/core ] && rm /tmp/.initrd/dev/core
|
|
umount /tmp/.initrd/dev || echo '*: Failed to unmount the initrd /dev!'
|
|
umount /tmp/.initrd/proc || echo '*: Failed to unmount the initrd /proc!'
|
|
umount /tmp/.initrd/sys || echo '*: Failed to unmount the initrd /sys!'
|
|
elif /tmp/.initrd/bin/[ "${CDROOT}" -eq '1' ]
|
|
then
|
|
umount /tmp/.initrd/proc || echo "*: Failed to unmount the initrd /proc!"
|
|
umount /dev 2>/dev/null
|
|
mount -n --move /tmp/.initrd/dev dev 2>/dev/null
|
|
rm -rf /tmp/.initrd/dev || echo '*: Failed to remove the initrd /dev!'
|
|
|
|
umount /sys 2>/dev/null
|
|
umount /tmp/.initrd/sys 2>/dev/null
|
|
fi
|
|
echo -n '.'
|
|
|
|
# /usr/src/linux/Documentation/initrd.txt
|
|
# here's the line it says we should do:
|
|
# exec chroot . /sbin/init </dev/console >/dev/console 2>&1
|
|
|
|
exec <dev/console >dev/console 2>&1
|
|
echo '.'
|
|
exec chroot . /bin/sh <<- EOF
|
|
umount /tmp/.initrd || echo "*: Failed to unmount the initrd!"
|
|
/sbin/blockdev --flushbufs /dev/ram0 >/dev/null 2>&1
|
|
exec /sbin/init ${REAL_INIT}
|
|
EOF
|
|
|
|
echo 'A fatal error has probably occured since /sbin/init did not'
|
|
echo 'boot correctly. Trying to open a shell...'
|
|
echo
|
|
exec /bin/bash
|
|
exec /bin/sh
|
|
exec /bin/ash
|
|
exec sh
|