#!/bin/sh # Daniel Robbins # Copyright 2003 Gentoo Technologies, Inc. # Distributed under the GPL . /etc/initrd.defaults . /etc/initrd.scripts USE_DEVFS_NORMAL=1 mount -o remount,rw / mount /proc [ -n "$QUIET" ] && echo "0" > /proc/sys/kernel/printk echo "${GOOD} Gentoo initrd startup..." echo "STEP 1: Command-line parsing" 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="" ;; devfs) USE_DEVFS_NORMAL=1 ;; nodevfs) USE_DEVFS_NORMAL=0 ;; loop\=*) LOOP=`parse_opt "${x}"` ;; looptype\=*) LOOPTYPE=`parse_opt "${x}"` ;; *) ;; esac done # 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 "STEP 2: Module loading" # Load appropriate kernel modules for x in $MY_HWOPTS do modules_scan $x done else echo "STEP 2: Skipping module load. No modules in initrd" fi echo "STEP 3: Mounting necessary filesystems per boot options" 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 [ ! -e /newroot/dev/.devfsd ] && mount -t devfs devfs /newroot/dev devfsd /newroot/dev -np sleep 1 findcdmount /newroot/dev/cdroms/* # not in /dev/cdroms try /dev/ide/cd if [ "${REAL_ROOT}" = "" ] then findcdmount /newroot/dev/ide/cd/* fi if [ "${REAL_ROOT}" = "" ] then echo "Dropping to shell so you can fix your shit" exec /bin/ash # Undo stuff # kill_devfsd # We run devfsd with -np now sleep 1 umount /newroot/dev/ sleep 1 umount /newroot # shouldn't be anything in here b/c it was on tmpfs rm -rf /newroot/* CDROOT=0 echo "Could not find CD to boot, gonna need something else" fi fi # Don't do else b/c we set CDROOT=0 if it fails to detect if [ "${CDROOT}" -eq "0" -a "${USE_DEVFS_NORMAL}" -eq "1" ] then [ ! -e /dev/.devfsd ] && mount -t devfs devfs /dev devfsd /dev -np fi echo "STEP 4: Determining root device" while true do while [ "${got_good_root}" != "1" ] do if [ "${REAL_ROOT}" = "shell" ] then /bin/ash #set REAL_ROOT to "" so we get a prompt for the real root after the shell exits. REAL_ROOT="" got_good_root=0 continue elif [ "${REAL_ROOT}" = "" ] then #no REAL_ROOT determined/specified. Prompt user for root block device. echo "Root block device unspecified or not detected." echo "Please specify a device to boot, or \"shell\" for a shell." echo -n ": " read REAL_ROOT got_good_root=0 elif [ -b "${REAL_ROOT}" ] then got_good_root=1 else REAL_ROOT="" got_good_root=0 fi done if [ "${CDROOT}" -eq "1" -a "${got_good_root}" = "1" ] then break else echo "STEP 4a: Mounting root" mount -o rw ${REAL_ROOT} /newroot if [ "$?" = "0" ] then break else echo "Could not mount specified ROOT, try again" got_good_root=0 REAL_ROOT="" fi fi done [ -n "$QUIET" ] && echo "6" > /proc/sys/kernel/printk echo "STEP 5: Finishing up" 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 "STEP 5a: filling tmpfs filesystem" cd /newroot # Failsafe if some idiot didn't set loop type if [ "${LOOPTYPE}" = "" ] then echo "YOU FORGOT TO SPECIFY LOOPTYPE TRYING TO AUTODETECT" 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 echo "DETECTED LOOPTYPE: $LOOPTYPE" fi if [ "${LOOPTYPE}" = "normal" ] then check_loop # bind-mount /dev/ so that loop devices can be found mount -o bind /newroot/dev /dev echo "STEP 5a1: mounting loop filesystem" mount -t ext2 -o loop,ro /newroot/mnt/cdrom/${LOOP} /newroot/mnt/livecd if [ "$?" != "0" ] then echo "FAILED TO MOUNT LOOP FILESYSTEM, barfing out to shell" /bin/ash fi FS_LOCATION="mnt/livecd" umount /dev elif [ "${LOOPTYPE}" = "squashfs" ] then check_loop mount -o bind /newroot/dev /dev echo "STEP 5a1: mounting squashfs filesystem" mount -t squashfs -o loop,ro /newroot/mnt/cdrom/${LOOP} /newroot/mnt/livecd if [ "$?" != "0" ] then echo "FAILED TO MOUNT LOOP FILESYSTEM, barfing out to shell" /bin/ash fi FS_LOCATION="mnt/livecd" umount /dev elif [ "${LOOPTYPE}" = "gcloop" ] then check_loop mount -o bind /newroot/dev /dev echo "STEP 5a1: mounting gcloop (ext2) filesystem" echo " " | losetup -E 19 -e ucl-0 -p0 /newroot/dev/loop0 /newroot/mnt/cdrom/${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 check_loop FS_LOCATION="mnt/cdrom/${LOOP}" elif [ "${LOOPTYPE}" = "noloop" ] then FS_LOCATION="mnt/cdrom" fi echo "STEP 5a2: filling filesystem" 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 echo "STEP 5b: setting up stuff for pivot_root" mkdir -p /newroot/tmp/.initrd fi echo "STEP 5c: redirect console" console=/newroot/dev/console [ ! -e "$console" ] && mknod $console c 5 1 exec < $console > $console 2>&1 || echo "CONSOLE REDIRECTION FAILED, /dev ON ROOT DOES NOT CONTAIN console !!!" echo "STEP 6: pivot_root and exec/chroot real init" cd /newroot pivot_root . tmp/.initrd if [ "${USE_DEVFS_NORMAL}" -eq "1" -a "${CDROOT}" -eq "0" ] then # must mount a new devfs before we can # umount the old one for some reason mount -t proc proc /proc mount -t devfs devfs /dev umount /tmp/.initrd/proc || echo "COULD NOT UMOUNT tmp/.initrd/proc !!!" umount /tmp/.initrd/dev || echo "COULD NOT UMOUNT tmp/.initrd/dev !!!" # at this point it lets us umount the new # devfs, don't know why, just does, stop # asking questions! umount /dev umount /proc cp -f /etc/mtab /etc/mtab.initrd-here > /dev/null 2>&1 elif [ "${CDROOT}" -eq "1" ] then # If automount at boot was on with devfs, we'll want to umount it # also umount proc echo "STEP 6a: clean up mounts" mount -t proc proc /proc umount /tmp/.initrd/proc > /dev/null 2>&1 || echo "COULD NOT UMOUNT /tmp/.initrd/proc !!!" umount /dev > /dev/null 2>&1 umount /proc > /dev/null 2>&1 fi # /usr/src/linux/Documentation/initrd.txt # here's the line it says we should do: # exec chroot . /sbin/init /dev/console 2>&1 exec chroot . /bin/sh <<- EOF umount /tmp/.initrd || echo "UMOUNT of /tmp/.initrd FAILED!!!" && /sbin/blockdev --flushbufs /dev/ram0 echo "INIT: starting /sbin/init ${CMDLINE}" exec /sbin/init ${CMDLINE} EOF # exec chroot . /sbin/init ${CMDLINE} < /dev/console > /dev/console 2>&1 echo "IF YOU ARE SEEING THIS MESSAGE, A FATAL ERROR HAS OCCURRED" echo "MOST LIKELY /sbin/init DOES NOT EXIST, ATTEMPTING TO DROP" echo "YOU TO A SHELL" exec /bin/bash exec /bin/sh exec /bin/ash exec sh