#!/bin/busybox sh # 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:/bin:/sbin" # 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 root="" rootflags="" recovery=false for opt in $(cat /proc/cmdline); do case "$opt" in root=*) root=${opt:5} ;; rootflags=*) rootflags=${opt:10} ;; recovery) recovery=true ;; BOOT_IMAGE=*|initrd=*) # Ignore those ;; *) echo -e "${C_YELLOW}Unknown kernel argument: $opt${C_NO}" ;; esac done $recovery && fail "Requested recovery." [ -z "$root" ] && fail "Missing root argument!" echo -ne "${C_GRAY}Waiting for root ($root)..." CNT=10 while [ ! -e "$root" ] && [ $CNT -gt 0 ]; do CNT=$(expr $CNT - 1) sleep 1 echo -n " $CNT" done echo -e "${C_NO}" [ -e "$root" ] || fail "Root not located!" # TODO mount boot parition and look for key saved there (on unlock remove it) echo -e "${C_GREEN}Unlocking root...${C_NO}" cryptsetup open "$root" encroot || 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!"