| 1 | #!/bin/busybox sh |
| 2 | |
| 3 | # this is the init script version |
| 4 | VERSION=1.1 |
| 5 | NEWROOT=/newroot |
| 6 | SINGLEMODE=no |
| 7 | |
| 8 | /bin/busybox --install -s |
| 9 | |
| 10 | # basic environment |
| 11 | export PATH=/usr/bin:/bin:/usr/sbin:/sbin |
| 12 | |
| 13 | # needed devs |
| 14 | [ -c /dev/null ] || mknod -m 666 /dev/null c 1 3 |
| 15 | |
| 16 | # basic mounts |
| 17 | mount -t proc -o noexec,nosuid,nodev proc /proc |
| 18 | mount -t sysfs -o noexec,nosuid,nodev sysfs /sys |
| 19 | |
| 20 | # some helpers |
| 21 | ebegin() { |
| 22 | echo -n " * $*: " |
| 23 | } |
| 24 | eend() { |
| 25 | local msg |
| 26 | if [ "$1" = 0 ] || [ $# -lt 1 ] ; then |
| 27 | echo "ok." |
| 28 | else |
| 29 | shift |
| 30 | echo "failed. $*" |
| 31 | echo "initramfs emergency recovery shell launched. Type 'exit' to continue boot" |
| 32 | /bin/busybox sh |
| 33 | fi |
| 34 | } |
| 35 | |
| 36 | scan_drivers() { |
| 37 | if [ "$AUTODETECT" != no ] ; then |
| 38 | find /sys -name modalias | xargs sort -u | xargs modprobe -a 2> /dev/null |
| 39 | fi |
| 40 | } |
| 41 | |
| 42 | find_ovl() { |
| 43 | local mnt="$1" |
| 44 | local ovl |
| 45 | local lines |
| 46 | |
| 47 | # look for apkovl's on mounted media |
| 48 | ovl=$( ls -1 "$mnt"/*.apkovl.tar.gz* 2>/dev/null ) || return 1 |
| 49 | lines=$(echo "$ovl" | wc -l) |
| 50 | |
| 51 | if [ $lines -gt 1 ] ; then |
| 52 | echo "ERROR: More than one apkovl file was found on $(basename $mnt). None will be read." >&2 |
| 53 | return 1 |
| 54 | fi |
| 55 | echo "$ovl" |
| 56 | } |
| 57 | |
| 58 | retry_mount() { |
| 59 | # usb might need some time to settle so we retry a few times |
| 60 | for i in $(seq 0 19); do |
| 61 | mount $@ 2>&1 && return 0 |
| 62 | sleep 1 |
| 63 | done |
| 64 | return 1 |
| 65 | } |
| 66 | |
| 67 | unpack_apkovl() { |
| 68 | local ovl="$1" |
| 69 | local dest="$2" |
| 70 | local suffix=${ovl##*.} |
| 71 | local i |
| 72 | if [ "$suffix" = "gz" ]; then |
| 73 | tar -C "$dest" -zxf "$ovl" |
| 74 | return $? |
| 75 | fi |
| 76 | |
| 77 | for i in $ALPINE_MNT/*/*/openssl-[0-9]*.apk $ALPINE_MNT/*/openssl-[0-9]*.apk; do |
| 78 | [ -f "$i" ] && tar --numeric-owner -C / -zxf $i && break |
| 79 | done |
| 80 | |
| 81 | if ! openssl list-cipher-commands | grep "^$suffix$" > /dev/null; then |
| 82 | errstr="Cipher $suffix is not supported" |
| 83 | return 1 |
| 84 | fi |
| 85 | local count=0 |
| 86 | # beep |
| 87 | echo -e "\007" |
| 88 | while [ $count -lt 3 ]; do |
| 89 | openssl enc -d -$suffix -in "$ovl" | tar --numeric-owner \ |
| 90 | -C "$dest" -zx 2>/dev/null && return 0 |
| 91 | count=$(( $count + 1 )) |
| 92 | done |
| 93 | return 1 |
| 94 | } |
| 95 | |
| 96 | # gotta start from somewhere :) |
| 97 | echo "Alpine Init $VERSION" |
| 98 | |
| 99 | # read the kernel options |
| 100 | for i in `cat /proc/cmdline` ; do |
| 101 | case $i in |
| 102 | s|single|1) |
| 103 | SINGLEMODE=yes ;; |
| 104 | modules=*) |
| 105 | MODULES="`echo ${i#modules=} | tr ',' ' '`";; |
| 106 | noautodetect) |
| 107 | AUTODETECT=no;; |
| 108 | *=*) eval KOPT_$i ;; |
| 109 | *) eval KOPT_$i=yes ;; |
| 110 | esac |
| 111 | done |
| 112 | |
| 113 | # start bootcharting if wanted |
| 114 | if [ -n "$KOPT_chart" ]; then |
| 115 | ebegin "Starting bootchart logging" |
| 116 | /sbin/bootchartd start-initfs "$NEWROOT" |
| 117 | eend 0 |
| 118 | fi |
| 119 | |
| 120 | ALPINE_DEV=${KOPT_alpine_dev%%:*} |
| 121 | ALPINE_DEV_FS=${KOPT_alpine_dev##*:} |
| 122 | if [ "$ALPINE_DEV_FS" = "$ALPINE_DEV" ]; then |
| 123 | unset ALPINE_DEV_FS |
| 124 | fi |
| 125 | ALPINE_MNT=/media/$ALPINE_DEV |
| 126 | |
| 127 | # hide kernel messages |
| 128 | dmesg -n 1 |
| 129 | |
| 130 | # setup /dev |
| 131 | ebegin "Starting mdev" |
| 132 | mount -t tmpfs -o exec,nosuid,mode=0755 mdev /dev |
| 133 | ln -s sr0 /dev/cdrom |
| 134 | echo "/sbin/mdev" > /proc/sys/kernel/hotplug |
| 135 | mdev -s |
| 136 | RC=$? |
| 137 | [ -d /dev/pts ] || mkdir -m 755 /dev/pts |
| 138 | [ -c /dev/ptmx ] || mknod -m 666 /dev/ptmx c 5 2 |
| 139 | mount -t devpts -o gid=5,mode=0620,noexec,nosuid devpts /dev/pts |
| 140 | [ -d /dev/shm ] || mkdir /dev/shm |
| 141 | mount -t tmpfs -o nodev,nosuid,noexec shm /dev/shm |
| 142 | eend $RC |
| 143 | |
| 144 | # load available drivers to get access to modloop media |
| 145 | ebegin "Loading boot drivers" |
| 146 | [ "$MODULES" ] && modprobe -a $MODULES 2> /dev/null |
| 147 | if [ -f /etc/modules ] ; then |
| 148 | sed 's/\#.*//g' < /etc/modules | |
| 149 | while read module args; do |
| 150 | modprobe -q $module $args |
| 151 | done |
| 152 | fi |
| 153 | scan_drivers |
| 154 | scan_drivers |
| 155 | eend 0 |
| 156 | |
| 157 | # check if root=... was set |
| 158 | if [ -n "$KOPT_root" ]; then |
| 159 | if [ "$SINGLEMODE" = "yes" ]; then |
| 160 | echo "Entering single mode. Type 'exit' to continue booting." |
| 161 | sh |
| 162 | fi |
| 163 | case "$KOPT_root" in |
| 164 | /dev/md*) |
| 165 | mknod $KOPT_root b 9 ${KOPT_root#/dev/md} |
| 166 | raidautorun "$KOPT_root" |
| 167 | ;; |
| 168 | esac |
| 169 | ebegin "Mounting root" |
| 170 | retry_mount $KOPT_root $NEWROOT 2>/dev/null |
| 171 | eend $? |
| 172 | cat /proc/mounts | while read DEV DIR TYPE OPTS ; do |
| 173 | if [ "$DIR" != "/" -a "$DIR" != "$NEWROOT" -a -d "$DIR" ]; then |
| 174 | mkdir -p $NEWROOT/$DIR |
| 175 | mount -o move $DIR $NEWROOT/$DIR |
| 176 | fi |
| 177 | done |
| 178 | sync |
| 179 | exec /bin/busybox switch_root $NEWROOT $chart_init /sbin/init $KOPT_init_args |
| 180 | echo "initramfs emergency recovery shell launched" |
| 181 | exec /bin/busybox sh |
| 182 | fi |
| 183 | |
| 184 | # locate boot media and mount it |
| 185 | ebegin "Mounting boot media" |
| 186 | mkdir -p $ALPINE_MNT |
| 187 | if [ -n "$ALPINE_DEV_FS" ]; then |
| 188 | mount_opts="-t $ALPINE_DEV_FS" |
| 189 | fi |
| 190 | |
| 191 | retry_mount $mount_opts /dev/$ALPINE_DEV $ALPINE_MNT >/dev/null 2>&1 |
| 192 | eend $? |
| 193 | |
| 194 | ebegin "Mounting loopback device for kernel modules" |
| 195 | modprobe loop |
| 196 | if [ -n "$KOPT_modloop" ]; then |
| 197 | modloop=$KOPT_modloop |
| 198 | else |
| 199 | modloop=$KOPT_BOOT_IMAGE.cmg |
| 200 | fi |
| 201 | mount -o loop,ro -t cramfs $ALPINE_MNT/$modloop /.modloop |
| 202 | rc=$? |
| 203 | if [ "$rc" = 0 ]; then |
| 204 | rm -rf /lib/modules |
| 205 | ln -sf /.modloop/modules /lib |
| 206 | fi |
| 207 | eend $? |
| 208 | |
| 209 | if [ -d $ALPINE_MNT/firmware ]; then |
| 210 | ebegin "Copying firmware from $ALPINE_MNT/firmware" |
| 211 | mkdir -p /lib |
| 212 | cp -R -a $ALPINE_MNT/firmware /lib/ |
| 213 | eend $? |
| 214 | fi |
| 215 | |
| 216 | mkdir -p /etc/apk |
| 217 | for i in $ALPINE_MNT/*/APK_INDEX.gz $ALPINE_MNT/*/*/APK_INDEX.gz; do |
| 218 | [ -r "$i" ] && echo ${i%/APK_INDEX.gz} >> /etc/apk/repositories |
| 219 | done |
| 220 | |
| 221 | # early console? |
| 222 | if [ "$SINGLEMODE" = "yes" ]; then |
| 223 | echo "Entering single mode. Type 'exit' to continue booting." |
| 224 | sh |
| 225 | fi |
| 226 | |
| 227 | # more drivers |
| 228 | ebegin "Loading hardware drivers" |
| 229 | scan_drivers |
| 230 | eend 0 |
| 231 | |
| 232 | mount -t tmpfs tmpfs $NEWROOT |
| 233 | |
| 234 | # look for apkovl |
| 235 | if dmesg | grep '^usb-storage: waiting' >/dev/null; then |
| 236 | ebegin "Waiting for USB device to settle" |
| 237 | while ! dmesg | grep 'usb-storage: device scan complete' >/dev/null; do |
| 238 | sleep 1 |
| 239 | done |
| 240 | eend 0 |
| 241 | fi |
| 242 | for i in usb floppy cdrom; do |
| 243 | mount /media/$i 2>/dev/null || continue |
| 244 | ovl=$(find_ovl /media/$i) |
| 245 | [ -f "$ovl" ] && break |
| 246 | umount /media/$i 2>/dev/null |
| 247 | done |
| 248 | if ! [ -f "$ovl" ]; then |
| 249 | ovl=$(find_ovl $ALPINE_MNT) |
| 250 | fi |
| 251 | |
| 252 | if [ -f "$ovl" ]; then |
| 253 | ebegin "Loading user settings from $ovl" |
| 254 | unpack_apkovl "$ovl" $NEWROOT |
| 255 | eend $? $errstr |
| 256 | umount /media/$i 2>/dev/null & |
| 257 | pkgs=$(sed 's/\#.*//' $NEWROOT/etc/lbu/packages.list 2>/dev/null) |
| 258 | fi |
| 259 | |
| 260 | # install new root |
| 261 | ebegin "Installing packages to root filesystem" |
| 262 | if [ -n "$KOPT_chart" ]; then |
| 263 | pkgs="$pkgs acct" |
| 264 | fi |
| 265 | apkflags="--initdb --quiet --progress --force" |
| 266 | if [ -z "$KOPT_keep_apk_new" ]; then |
| 267 | apkflags="$apkflags --clean-protected" |
| 268 | fi |
| 269 | apk add --root /newroot $apkflags $pkgs >/dev/null |
| 270 | eend $? |
| 271 | |
| 272 | # copy alpine release info |
| 273 | cp $ALPINE_MNT/.alpine-release $NEWROOT/ |
| 274 | ln -sf /.alpine-release $NEWROOT/etc/alpine-release |
| 275 | |
| 276 | # if there is no repositories file, then use the default |
| 277 | if ! [ -f $NEWROOT/etc/apk/repositories ]; then |
| 278 | cp /etc/apk/repositories $NEWROOT/etc/apk/repositories |
| 279 | fi |
| 280 | |
| 281 | # setup bootchart for switch_root |
| 282 | chart_init="" |
| 283 | if [ -n "$KOPT_chart" ]; then |
| 284 | /sbin/bootchartd stop-initfs "$NEWROOT" |
| 285 | chart_init="/sbin/bootchartd start-rootfs" |
| 286 | fi |
| 287 | |
| 288 | # switch over to new root |
| 289 | cat /proc/mounts | while read DEV DIR TYPE OPTS ; do |
| 290 | if [ "$DIR" != "/" -a "$DIR" != "$NEWROOT" -a -d "$DIR" ]; then |
| 291 | mkdir -p $NEWROOT/$DIR |
| 292 | mount -o move $DIR $NEWROOT/$DIR |
| 293 | fi |
| 294 | done |
| 295 | ln -sf /.modloop/modules $NEWROOT/lib/modules |
| 296 | sync |
| 297 | |
| 298 | echo "" |
| 299 | if [ -x $NEWROOT/sbin/init ]; then |
| 300 | exec /bin/busybox switch_root $NEWROOT $chart_init /sbin/init $KOPT_init_args |
| 301 | fi |
| 302 | |
| 303 | echo "initramfs emergency recovery shell launched" |
| 304 | exec /bin/busybox sh |
| 305 | reboot |