#!/bin/sh # Daniel Robbins # 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 USE_DMRAID_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 if [ "$0" = '/init' ] then /bin/busybox --install -s rm /linuxrc if [ -e /sbin/udev ] then ln -s /sbin/udev /sbin/udevstart fi if [ -e /bin/lvm ] then ln -s /bin/lvm /bin/vgscan ln -s /bin/lvm /bin/vgchange fi fi [ -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 ;; nodmraid) USE_DMRAID_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 xkeymap=${keymap} echo ${keymap} | egrep -e "[0-9]+" >/dev/null 2>&1 if [ "$?" -eq '0' ]; then xkeymap=`tail -n 7 /lib/keymaps/keymapList | grep ${keymap} | sed -r "s/.*\s+${keymap}\s+([a-z-]+).*/\1/g" | egrep -v 1` fi mkdir -p /etc/sysconfig echo "XKEYBOARD=${xkeymap}" > /etc/sysconfig/keyboard 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 } startVolumes() { if [ "${DO_dmraid}" -a "${USE_DMRAID_NORMAL}" -eq '1' ] then if [ -e '/sbin/dmraid' ] then echo -e "${GOOD}>>${NORMAL}${BOLD} Activating Device-Mapper raid(s)...${NORMAL}" /sbin/dmraid -ay fi fi if [ "${DO_lvm2}" -a "${USE_LVM2_NORMAL}" -eq '1' ] then if [ -e '/bin/vgscan' -a -e '/bin/vgchange' ] then echo -e "${GOOD}>>${NORMAL}${BOLD} Scanning for Volume Groups...${NORMAL}" /bin/vgscan --ignorelockingfailure --mknodes echo -e "${GOOD}>>${NORMAL}${BOLD} Activating Volume Groups...${NORMAL}" /bin/vgchange -ay --ignorelockingfailure fi fi if [ "${DO_evms2}" -a "${USE_EVMS_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} Mounting filesystems${NORMAL}" # Check udev is on... [ "${KMAJOR}" -eq 2 -a "${KMINOR}" -ge '6' -a ! "${USE_UDEV_NORMAL}" -eq '0' ] && USE_UDEV_NORMAL=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 startVolumes mv /dev/* /newroot/dev cd / else if [ ! -e /newroot/dev/.devfsd ] then mount -t devfs devfs /newroot/dev devfsd /newroot/dev -np fi fi if [ -n "${SDELAY}" ]; then sleep ${SDELAY} else sleep 1 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 [ "${REAL_ROOT}" = '' ] && findcdmount /newroot/dev/sd* # USB Keychain 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 if [ -e /etc/sysconfig/keyboard -a "${CDROOT}" -eq '1' ] then mkdir -p /newroot/etc/sysconfig/ cp /etc/sysconfig/keyboard /newroot/etc/sysconfig/keyboard fi 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 cd / elif [ "${CDROOT}" -eq '0' -a "${USE_DEVFS_NORMAL}" -eq '1' ] then [ ! -e /dev/.devfsd ] && mount -t devfs devfs /dev devfsd /dev -np fi [ "${CDROOT}" -eq '0' ] && startVolumes 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 [ "${LOOPTYPE}" = 'zisofs' ] then FS_LOCATION="mnt/cdrom/${LOOPEXT}${LOOP}" elif [ "${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 if [ -x /newroot/mnt/cdrom/cdupdate.sh ] then /newroot/mnt/cdrom/cdupdate.sh if [ "$?" != '0' ] then echo "FAILED TO EXECUTE cdupdate.sh" /bin/ash fi fi if [ "$0" = '/linuxrc' ] then [ ! -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 2>&1 exec 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 elif [ "$0" = '/init' ] then [ ! -e /newroot/dev/console ] && mknod /newroot/dev/console c 5 1 echo -ne "${GOOD}>>${NORMAL}${BOLD} Booting (initramfs method)" cd /newroot mkdir /newroot/proc /newroot/sys 2>/dev/null echo -n '.' if [ "${USE_DEVFS_NORMAL}" -eq '1' -a "${CDROOT}" -eq '0' ] then umount /dev || echo '*: Failed to unmount the initrd /dev!' umount /sys || echo '*: Failed to unmount the initrd /sys!' umount /proc || echo '*: Failed to unmount the initrd /proc!' elif [ "${USE_UDEV_NORMAL}" -eq '1' ] then umount /dev || echo '*: Failed to unmount the initrd /dev!' umount /sys || echo '*: Failed to unmount the initrd /sys!' umount /proc || echo '*: Failed to unmount the initrd /proc!' elif [ "${CDROOT}" -eq '1' ] then umount /dev 2>/dev/null umount /sys 2>/dev/null umount /proc || echo "*: Failed to unmount the initrd /proc!" fi echo -n '.' exec dev/console 2>&1 echo '.' # Cleanup initramfs in the background # to reclaim initramfs tmpfs memoryspace INITRAMFS_FILES=`ls /|grep -v newroot` (sleep 10; cd /; rm -rf ${INITRAMFS_FILES}) & # End initramfs cleanup # Start the real root init exec chroot . /bin/sh <<- EOF exec /sbin/init ${REAL_INIT} EOF fi 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