#!/bin/busybox ash # vim:ft=sh # Init must have pid 1 otherwise switch_root won't work. if [ $$ -ne 1 ]; then echo "init must have pid 1!" exit 1 fi # Predefice colors C_NO="\e[0m" C_GRAY="\e[1;30m" C_RED="\e[1;31m" C_GREEN="\e[1;32m" C_YELLOW="\e[1;33m" PATH="$PATH:/usr/sbin:/usr/bin:/sbin:/bin" # disable kernel message from terminal and clear screen echo 0 > /proc/sys/kernel/printk clear # TODO print some welcome ascii art :-) # Function called if we fail. Argument is error message. fail() { echo -e "${C_RED}$@${C_NO}" echo -e "${C_YELLOW}Dropping to interactive shell${C_NO}" busybox --install -s while true; do echo -e "${C_GRAY}Mount root to /mnt/root and exit shell to switch root.${C_NO}" # Note: this is hack to enable job control setsid sh -c 'exec sh /dev/tty1 2>&1' echo exec switch_root /mnt/root /sbin/init || echo -e "${C_RED}Root switch failed!${C_NO}" done } # Preliminary mounts busybox mount -t proc none /proc || fail "/proc mount failed!" busybox mount -t sysfs none /sys || fail "/sys mount failed!" busybox mount -t devtmpfs none /dev || fail "/dev mount failed!" # Now open and mount root uuid="" rootflags="" recovery=false for opt in $(cat /proc/cmdline); do case "$opt" in rootuuid=*) uuid="${opt:9}" ;; rootflags=*) rootflags=${opt:10} ;; recovery) recovery=true ;; BOOT_IMAGE=*|initrd=*|fbcon=*) # Ignore those ;; *) echo -e "${C_YELLOW}Unknown kernel argument: $opt${C_NO}" ;; esac done $recovery && fail "Requested recovery." [ -z "$uuid" ] && fail "Missing rootuuid argument!" echo -ne "${C_GRAY}Waiting for root ($uuid)..." CNT=10 while [ $CNT -gt 0 ] && ! blkid | grep -q "UUID=\"$uuid\""; do CNT=$((CNT - 1)) sleep 1 echo -n " $CNT" done echo -e "${C_NO}" root="$(blkid | awk -v uuid="UUID=\"$uuid\"" '$2 == uuid { gsub(/:$/,"",$1); print $1 }')" [ -e "$root" ] || fail "Root not located!" echo -e "${C_GREEN}Unlocking root...${C_NO}" if command -v initramfs_password >/dev/null; then initramfs_password | cryptsetup open --key-file=- "$root" encroot else cryptsetup open "$root" encroot fi || fail "Unlocking root failed! /proc/cmdline=$(cat /proc/cmdline)" echo -e "${C_GREEN}Mounting root...${C_NO}" mount -t btrfs -o "$rootflags" /dev/mapper/encroot /mnt/root \ || fail "Mounting root failed! /proc/cmdline=$(cat /proc/cmdline)" echo -e "${C_GREEN}Switching to real root${C_NO}" # First clean up. The init process will remount proc, sys and dev later on busybox umount /dev /sys /proc || fail "Unmouns failed!" # Now do switch exec switch_root /mnt/root /sbin/init || fail "Root switch failed!"