1#!/bin/sh 2 3PATH=/sbin:/bin:/usr/sbin:/usr/bin 4 5ROOT_MOUNT="/rootfs" 6ROOT_IMAGE="rootfs.img" 7MOUNT="/bin/mount" 8UMOUNT="/bin/umount" 9ISOLINUX="" 10 11ROOT_DISK="" 12 13# Copied from initramfs-framework. The core of this script probably should be 14# turned into initramfs-framework modules to reduce duplication. 15udev_daemon() { 16 OPTIONS="/sbin/udev/udevd /sbin/udevd /lib/udev/udevd /lib/systemd/systemd-udevd" 17 18 for o in $OPTIONS; do 19 if [ -x "$o" ]; then 20 echo $o 21 return 0 22 fi 23 done 24 25 return 1 26} 27 28_UDEV_DAEMON=`udev_daemon` 29 30early_setup() { 31 mkdir -p /proc /sys /run /var/run 32 mount -t proc proc /proc 33 mount -t sysfs sysfs /sys 34 mount -t devtmpfs none /dev 35 36 # support modular kernel 37 modprobe isofs 2> /dev/null 38 39 $_UDEV_DAEMON --daemon 40 udevadm trigger --action=add 41} 42 43read_args() { 44 [ -z "$CMDLINE" ] && CMDLINE=`cat /proc/cmdline` 45 for arg in $CMDLINE; do 46 optarg=`expr "x$arg" : 'x[^=]*=\(.*\)'` 47 case $arg in 48 root=*) 49 ROOT_DEVICE=$optarg ;; 50 rootimage=*) 51 ROOT_IMAGE=$optarg ;; 52 rootfstype=*) 53 modprobe $optarg 2> /dev/null ;; 54 LABEL=*) 55 label=$optarg ;; 56 video=*) 57 video_mode=$arg ;; 58 vga=*) 59 vga_mode=$arg ;; 60 console=*) 61 if [ -z "${console_params}" ]; then 62 console_params=$arg 63 else 64 console_params="$console_params $arg" 65 fi ;; 66 debugshell*) 67 if [ -z "$optarg" ]; then 68 shelltimeout=30 69 else 70 shelltimeout=$optarg 71 fi 72 esac 73 done 74} 75 76boot_live_root() { 77 # Watches the udev event queue, and exits if all current events are handled 78 udevadm settle --timeout=3 --quiet 79 # Kills the current udev running processes, which survived after 80 # device node creation events were handled, to avoid unexpected behavior 81 killall -9 "${_UDEV_DAEMON##*/}" 2>/dev/null 82 83 # Don't run systemd-update-done on systemd-based live systems 84 # because it triggers a slow rebuild of ldconfig caches. 85 touch ${ROOT_MOUNT}/etc/.updated ${ROOT_MOUNT}/var/.updated 86 87 # Allow for identification of the real root even after boot 88 mkdir -p ${ROOT_MOUNT}/media/realroot 89 mount -n --move "/run/media/${ROOT_DISK}" ${ROOT_MOUNT}/media/realroot 90 91 # Move the mount points of some filesystems over to 92 # the corresponding directories under the real root filesystem. 93 for dir in `awk '/\/dev.* \/run\/media/{print $2}' /proc/mounts`; do 94 # Parse any OCT or HEX encoded chars such as spaces 95 # in the mount points to actual ASCII chars 96 dir=`printf $dir` 97 mkdir -p "${ROOT_MOUNT}/media/${dir##*/}" 98 mount -n --move "$dir" "${ROOT_MOUNT}/media/${dir##*/}" 99 done 100 mount -n --move /proc ${ROOT_MOUNT}/proc 101 mount -n --move /sys ${ROOT_MOUNT}/sys 102 mount -n --move /dev ${ROOT_MOUNT}/dev 103 104 cd $ROOT_MOUNT 105 106 # busybox switch_root supports -c option 107 exec switch_root -c /dev/console $ROOT_MOUNT /sbin/init $CMDLINE || 108 fatal "Couldn't switch_root, dropping to shell" 109} 110 111fatal() { 112 echo $1 >$CONSOLE 113 echo >$CONSOLE 114 exec sh 115} 116 117early_setup 118 119[ -z "$CONSOLE" ] && CONSOLE="/dev/console" 120 121read_args 122 123echo "Waiting for removable media..." 124C=0 125while true 126do 127 for i in `ls /run/media 2>/dev/null`; do 128 if [ -f /run/media/$i/$ROOT_IMAGE ] ; then 129 found="yes" 130 ROOT_DISK="$i" 131 break 132 elif [ -f /run/media/$i/isolinux/$ROOT_IMAGE ]; then 133 found="yes" 134 ISOLINUX="isolinux" 135 ROOT_DISK="$i" 136 break 137 fi 138 done 139 if [ "$found" = "yes" ]; then 140 break; 141 fi 142 # don't wait for more than $shelltimeout seconds, if it's set 143 if [ -n "$shelltimeout" ]; then 144 echo -n " " $(( $shelltimeout - $C )) 145 if [ $C -ge $shelltimeout ]; then 146 echo "..." 147 echo "Mounted filesystems" 148 mount | grep media 149 echo "Available block devices" 150 cat /proc/partitions 151 fatal "Cannot find $ROOT_IMAGE file in /run/media/* , dropping to a shell " 152 fi 153 C=$(( C + 1 )) 154 fi 155 sleep 1 156done 157 158# Try to mount the root image read-write and then boot it up. 159# This function distinguishes between a read-only image and a read-write image. 160# In the former case (typically an iso), it tries to make a union mount if possible. 161# In the latter case, the root image could be mounted and then directly booted up. 162mount_and_boot() { 163 mkdir $ROOT_MOUNT 164 mknod /dev/loop0 b 7 0 2>/dev/null 165 166 if ! mount -o rw,loop,noatime,nodiratime /run/media/$ROOT_DISK/$ISOLINUX/$ROOT_IMAGE $ROOT_MOUNT ; then 167 fatal "Could not mount rootfs image" 168 fi 169 170 if touch $ROOT_MOUNT/bin 2>/dev/null; then 171 # The root image is read-write, directly boot it up. 172 boot_live_root 173 fi 174 175 # determine which unification filesystem to use 176 union_fs_type="" 177 if grep -q -w "overlay" /proc/filesystems; then 178 union_fs_type="overlay" 179 elif grep -q -w "aufs" /proc/filesystems; then 180 union_fs_type="aufs" 181 else 182 union_fs_type="" 183 fi 184 185 # make a union mount if possible 186 case $union_fs_type in 187 "overlay") 188 mkdir -p /rootfs.ro /rootfs.rw 189 if ! mount -n --move $ROOT_MOUNT /rootfs.ro; then 190 rm -rf /rootfs.ro /rootfs.rw 191 fatal "Could not move rootfs mount point" 192 else 193 mount -t tmpfs -o rw,noatime,mode=755 tmpfs /rootfs.rw 194 mkdir -p /rootfs.rw/upperdir /rootfs.rw/work 195 mount -t overlay overlay -o "lowerdir=/rootfs.ro,upperdir=/rootfs.rw/upperdir,workdir=/rootfs.rw/work" $ROOT_MOUNT 196 mkdir -p $ROOT_MOUNT/rootfs.ro $ROOT_MOUNT/rootfs.rw 197 mount --move /rootfs.ro $ROOT_MOUNT/rootfs.ro 198 mount --move /rootfs.rw $ROOT_MOUNT/rootfs.rw 199 fi 200 ;; 201 "aufs") 202 mkdir -p /rootfs.ro /rootfs.rw 203 if ! mount -n --move $ROOT_MOUNT /rootfs.ro; then 204 rm -rf /rootfs.ro /rootfs.rw 205 fatal "Could not move rootfs mount point" 206 else 207 mount -t tmpfs -o rw,noatime,mode=755 tmpfs /rootfs.rw 208 mount -t aufs -o "dirs=/rootfs.rw=rw:/rootfs.ro=ro" aufs $ROOT_MOUNT 209 mkdir -p $ROOT_MOUNT/rootfs.ro $ROOT_MOUNT/rootfs.rw 210 mount --move /rootfs.ro $ROOT_MOUNT/rootfs.ro 211 mount --move /rootfs.rw $ROOT_MOUNT/rootfs.rw 212 fi 213 ;; 214 "") 215 mount -t tmpfs -o rw,noatime,mode=755 tmpfs $ROOT_MOUNT/media 216 ;; 217 esac 218 219 # boot the image 220 boot_live_root 221} 222 223if [ "$label" != "boot" -a -f $label.sh ] ; then 224 if [ -f /run/media/$i/$ISOLINUX/$ROOT_IMAGE ] ; then 225 ./$label.sh $i/$ISOLINUX $ROOT_IMAGE $video_mode $vga_mode $console_params 226 else 227 fatal "Could not find $label script" 228 fi 229 230 # If we're getting here, we failed... 231 fatal "Target $label failed" 232fi 233 234mount_and_boot 235 236