#! /bin/sh # This function checks for the presence of a real filesystem and loop-images on the target # $1 = folder of rootfs, $2 = runlevel (defaults to 5) # $2 = name of calling module check_target() { # Check if there is a /sbin/init or /sbin/init.sysvinit on the card if test -x $1/sbin/init -o -x $1/$REAL_INIT then real_fs_found=1 else echo -e "Note: No INIT [$REAL_INIT] found on target" fi # Check for loop-images if (ls $1/$IMAGE_PATH/*rootfs.bin) >/dev/null 2>&1 then image_found=1 else echo "Note: No boot-images found in [$1/$IMAGE_PATH]" fi # Check if we have both, a real fs and boot-images. If so, ask the user what to boot if test "$real_fs_found" = 1 -a "$image_found" = 1 then echo -e "\nI have found a real filesystem and boot-images on the target" echo -e "What do you want to boot?\n" echo -e "\t[1] The real filesystem" echo -e "\t[2] A loop-image" echo "" while test -z "$ans" do echo -n "Your choice: " if test "$AUTOBOOT" != "yes" then read junk < /dev/tty1 else if test -e /etc/.altboot-real-or-loop.last then junk="`cat /etc/.altboot-real-or-loop.last`" test -z "$junk" && read junk < /dev/tty1 || echo "$junk (autoboot)" else read junk < /dev/tty1 fi fi if test "$junk" = 1 -o "$junk" = 2 then ans="$junk" echo "$junk" > /etc/.altboot-real-or-loop.last fi done case "$ans" in 1) pivot_realfs "$1" "$2">/dev/tty0;; 2) pivot_image "$1" "$2">/dev/tty0;; esac exit 0 fi # Boot a real filesystem test "$real_fs_found" = 1 && pivot_realfs "$1" >/dev/tty0 # Boot a loop-image test "$image_found" = 1 && pivot_image "$1" >/dev/tty0 if test "$real_fs_found" != 1 -a "$image_found" != 1 then die "Nothing to do!" fi } boot_new_rootfs_splash() { C_RED="\033[37;44m" C_RESET="\033[0m" echo -e "${C_RED}+----------------------------------------------------------+${C_RESET}" echo -e "${C_RED}| |${C_RESET}" echo -e "${C_RED}| Booting the selected rootfs... |${C_RESET}" echo -e "${C_RED}| |${C_RESET}" echo -e "${C_RED}+----------------------------------------------------------+${C_RESET}" } # This function pivot_root's into a real filesystem calling $newrootfs/sbin/init # $1 = The new rootfs pivot_realfs() { #test -z "$2" && RL="5" || RL="$2" mkdir -p $1/media/ROM || die "mkdir -p $1/media/ROM failed" mount -o remount,ro / >/dev/null 2>&1 do_pivot "$1" "$RL" } # This function loop-mounts an image-file and pivot_root's into it # $1: The new rootfs pivot_image() { #test -z "$2" && RL="5" || RL="$2" cd $1/$IMAGE_PATH # Check for rootfs images on the card if test "`ls *rootfs.bin | wc -l | tr -d " "`" -gt 1 then echo -e "\n\nPlease select a rootfs:\n" # Show all available images x=0 for file in `ls *rootfs.bin` do let x=$x+1 echo -e "\t\t[$x] $file" done echo "" IMAGE_NAME="" while test -z "$IMAGE_NAME" do echo -en "Please choose one of the above: " if test "$AUTOBOOT" != "yes" then read junk < /dev/tty1 else if test -e /etc/.altboot-loopimage.last then junk="`cat /etc/.altboot-loopimage.last`" test -z "$junk" && read junk < /dev/tty1 || echo "$junk (autoboot)" else read junk < /dev/tty1 fi fi x=0 for file in `ls *rootfs.bin` do let x=$x+1 if test "$x" = "$junk" then IMAGE_NAME="$file" echo "$junk" > /etc/.altboot-loopimage.last fi done done else IMAGE_NAME="`ls *rootfs.bin`" test -z "$IMAGE_NAME" && die "No rootfs found (*rootfs.bin) in $1/$IMAGE_PATH" fi echo "" echo "Using [$IMAGE_NAME]" mkdir -p /media/image || die "mkdir -p /media/image failed" echo "Setting up loopback (/dev/loop0) for $IMAGE_NAME" losetup /dev/loop0 $1/$IMAGE_PATH/$IMAGE_NAME || die "losetup /dev/loop0 $1/$IMAGE_PATH/$IMAGE_NAME failed!" check_fs /dev/loop0 $IMAGE_TYPE echo -e "\n* * * Booting rootfs image * * *\n" # Busybox's "mount" doesn't seem to like "-o loop" for some reason # It works on collie and b0rks on poodle. if [ "$IMAGE_TYPE" = "" ]; then IMAGE_TYPE="auto" fi # If mount fails it has the tendency to spew out a _lot_ of error messages. # We direct the output to /dev/null so the user can see which step actually failed. mount /dev/loop0 -t $IMAGE_TYPE /media/image >/dev/null 2>&1 || die "mount -t $IMAGE_TYPE /dev/loop0 /media/image failed!" mkdir -p /media/image/media/ROM || die "mkdir -p /media/image/media/ROM failed" do_pivot /media/image "$RL" } #$1=mountpoint of the soon-to-be rootfs, $2=Runlevel do_pivot(){ echo -n "Pivoting root..." if (/sbin/pivot_root "$1" "$1/media/ROM") then echo "Success" # This is important since we are still cd'ed into the old root cd / ! test -d "$1" && mkdir -p "$1" # Move mountpoints from the old rootfs into the new one. # The *real* mount is kinda touchy feely about that /bin/busybox mount -o move /media/ROM/proc /proc >/dev/null 2>&1 for mpt in ` mount | grep "/media/ROM/" | awk '{print $3}'` do new_mpt="`echo "$mpt" | sed -n "s/\/media\/ROM//p"`" echo "Moving mountpoint [$mpt] -> [$new_mpt]" >/dev/tty0 2>&1 ! test -d "$new_mpt" && mkdir -p "$new_mpt" /bin/busybox mount -o move "$mpt" "$new_mpt" done clear boot_new_rootfs_splash echo "Calling INIT" exec /usr/sbin/chroot . /sbin/init $2 >/dev/tty0 2>&1 else echo "FAILED" die "* * * pivot_root failed! * * *" fi } # This functions configures the master password for altboot if none is set set_password() { mount -o remount,rw / if test -z "$MASTER_PASSWORD" then echo -e "\nAltboot is a boot-manager which allows to boot from SD,\nCF, USB-Storage and NFS" echo -e "\nFor security reasons altboot requires a password\nto boot into init=/bin/sh." echo -e "${C_RED}This is *not* your root password!\nIt is used by altboot alone!${C_RESET}\n" while true do echo -en "\nNew password: " stty -echo read junk1 < /dev/tty0 stty echo if ! test -z "$junk1" then echo -en "\nRepeat: " stty -echo read junk2 < /dev/tty0 stty echo echo "" if test "$junk1" = "$junk2" then crypt_pw="`echo "$junk1" | md5sum | awk '{print $1}'`" if test -e "${ALTBOOT_CFG_FILE}" then sed "/^MASTER_PASSWORD/s/\(.*\=\).*/\1\"$crypt_pw\"/" "${ALTBOOT_CFG_FILE}" > ${ALTBOOT_CFG_FILE}_ mv ${ALTBOOT_CFG_FILE}_ ${ALTBOOT_CFG_FILE} MASTER_PASSWORD="$crypt_pw" echo "Password changed." else echo "${ALTBOOT_CFG_FILE} is missing, no password saved" fi break else echo -e "Passwords didn't match, try again\n" fi fi done fi } # This function asks for altboots master password. It only returns if the correct password was supplied verify_master_pw() { if ! test -z "$MASTER_PASSWORD" then auth_timeout="3" echo "Please enter your altboot master password" cnt=0 while true do let cnt=$cnt+$auth_timeout echo -n "Password: " read junk < /dev/tty0 if test "`echo "$junk" | md5sum | awk '{print $1}'`" = "$MASTER_PASSWORD" then break else echo "[`echo "$junk" | md5sum | awk '{print $1}'`]" echo "[$MASTER_PASSWORD]" echo "Wrong password, sleeping $cnt seconds..." sleep $cnt # if test "$cnt" -gt 10 # then # break # fi fi done fi } check_fs() { if [ "$FSCK_IMAGES" = "yes" ] then FSCK="" if [ "$2" = "" ]; then FSTYPE="ext2" else FSTYPE="$2" fi case "$FSTYPE" in ext2 | ext3) if [ -e /sbin/fsck.ext3 ]; then FSCK="/sbin/fsck.ext3" elif [ -e /sbin/e3fsck ]; then FSCK="/sbin/e3fsck" elif [ -e /sbin/fsck.ext2 ]; then FSCK="/sbin/fsck.ext2" elif [ -e /sbin/e2fsck ]; then FSCK="/sbin/e2fsck" fi test -n "$FSCK" && FSCK="$FSCK -p" ;; vfat) if [ -e /sbin/dosfsck ]; then FSCK="/sbin/dosfsck -a" fi ;; esac if [ "$FSCK" = "" ]; then echo "Could not find fsck for $FSTYPE!" else echo "Checking file system on $1" $FSCK $1 || sleep 2 fi fi } # Make the initial rootfs a bit more usable init_rootfs(){ echo -n "Mounting rootfs rw..." >/dev/tty0 mount -o remount,rw / >/dev/tty0 2>&1 && echo ok >/dev/tty0|| die "mount -o remount,rw / failed" mount | grep -q "/proc " >/dev/null 2>&1 && echo "Note: /proc is already mounted" || mount proc -t proc /proc >/dev/tty0 2>&1 if ( uname -r | grep -q "2.6." ) then mount | grep -q "/sys " >/dev/null 2>&1 && echo "Note: /sys is already mounted" || mount sys -t sysfs /sys >/dev/tty0 2>&1 fi echo -n "Generating device files..." >/dev/tty0 /etc/init.d/devices start && echo ok >/dev/tty0 || die "FAILED" } mount_sd(){ if mount | grep -q "/media/card" then echo "Note: /media/card is already mounted" else # We can't trust that the SD device file is there when running kernel 2.6 w/ udev # and starting udev at this point may not be the best idea... if `uname -r | grep -q "2.6"` then #Let's just assume the device file name never changes... dev_no="`echo "$SD_DEVICE" | sed -n "s/\/dev\/mmcblk\(.*\)p\(.*\)/\1/p"`" part_no="`echo "$SD_DEVICE" | sed -n "s/\/dev\/mmcblk\(.*\)p\(.*\)/\2/p"`" ! test -e /dev/mmcblk${dev_no} && mknod /dev/mmcblk${dev_no} b 254 0 ! test -e /dev/mmcblk${dev_no}p${part_no} && mknod /dev/mmcblk${dev_no}p${part_no} b 254 $part_no fi # Kernel 2.6 has the SD driver compiled into the kernel if test -n "$SD_KERNEL_MODULE" then echo -n "Loading SD kernel module..." /sbin/insmod $SD_KERNEL_MODULE >/dev/null 2>&1 && echo ok || die "insmod failed" else echo "No SD kernel module configured, assuming it's build-in" fi check_fs "$SD_DEVICE" echo -n "Mounting $SD_MOUNTPOINT..." >/dev/tty0 /bin/mount -t auto -o defaults,noatime $SD_DEVICE $SD_MOUNTPOINT >/dev/null 2>&1 && echo ok >/dev/tty0|| die "/bin/mount -t auto -o defaults,noatime $SD_DEVICE $SD_MOUNTPOINT failed" fi echo "" # Give the SD and CF mounting some time. This is a must for SD sleep 2 } mount_cf(){ if mount | grep -q "/media/cf " then echo "Note: /media/cf is already mounted" else /etc/init.d/pcmcia status | grep -q running || /etc/init.d/pcmcia start && echo "Note: cardmgr is already active" echo "" # Give the SD and CF mounting some time. This is a must for SD sleep 2 mount | grep -q "/media/cf " || mount /media/cf fi } mount_home(){ if mount | grep -q "/home " then echo "Note: /home is already mounted" else if ( cat /etc/fstab | grep -v "^#" | grep "/home " ) then echo "Mounting /home" home_fstab="`grep "/home " /etc/fstab`" home_dev="`echo "$home_fstab" | awk '{print $1}'`" home_fs="`echo "$home_fstab" | awk '{print $3}'`" home_options="`echo "$home_fstab" | awk '{print $4}'`" mount -t "$home_fs" -o $home_options "$home_dev" /home fi fi }