summaryrefslogtreecommitdiff
path: root/init
blob: b0e28289ed017e16f5bac585779e58dd1d30c44e (plain)
    1 #!/bin/bash
    2 
    3 export DEBUG=0
    4 export INTERACTIVE=0
    5 export ROOTDEV=''
    6 
    7 function screen_init {
    8   # Clear screen
    9   clear
   10 
   11   # Output message file if it exists
   12   [[ -f /etc/msg ]] && cat /etc/msg
   13 }
   14 
   15 
   16 #
   17 # Mounts the fakeroot from the kernel "root" param
   18 #
   19 function mount_fakeroot {
   20   local rootdev=${1}
   21   local fakeroot=${2}
   22 
   23   mount -o ro ${rootdev} ${fakeroot}
   24 }
   25 
   26 
   27 function log {
   28   local msg="${1}"
   29   echo -e "${msg}"
   30   if [[ ${DEBUG} -ne 0 ]]; then
   31     echo "Press enter to continue"
   32     read
   33   fi
   34 }
   35  
   36  
   37 #
   38 # Resolves the path to the root device from the cmdline root= syntax.
   39 # Currently handles UUID syntax and /dev/sdx syntax
   40 #
   41 function parse_cmdline {
   42   local cmdline=${1}
   43 
   44   for i in ${cmdline[@]}; do
   45     case "${i}" in
   46       root=*)
   47         if [[ ${i:5:4} == 'UUID' ]]; then
   48           # mount by uuid
   49           local uuid=$(echo ${i} | cut -d '=' -f 3)
   50           ROOTDEV="$(blkid -U ${uuid})"
   51         elif [[ ${i:5:5} == 'LABEL' ]]; then
   52           # mount by label
   53           local label=$(echo ${i} | cut -d '=' -f 3)
   54           ROOTDEV="$(blkid -L ${label})"
   55         else
   56           # mount by dev
   57           ROOTDEV="$(echo ${i} | cut -d '=' -f 2)"
   58         fi
   59       ;;
   60       initdebug)
   61         # Enable debug mode (this is gonna be slow)
   62         DEBUG=1
   63       ;;
   64       interactive)
   65         # Enable interactive mode
   66         INTERACTIVE=1
   67       ;;
   68     esac
   69   done
   70 }
   71 
   72  
   73 #
   74 # Returns type of partition. If part is LUKS encrypted, returns 'luks'. If
   75 # anything else, returns 'fs'.
   76 #
   77 # Most installations of the mount command don't require specification of the
   78 # filesystem, but won't automatically detect luks partitions and prompt for a
   79 # password. This allows the script to be smarter about encrypted partitions.
   80 #
   81 function get_part_type {
   82   path=${1}
   83   typestr=$(blkid -s TYPE ${path})
   84   if [[ $(echo ${typestr} | grep 'crypto_LUKS') ]]; then
   85     echo 'luks'
   86   else
   87     echo 'fs'
   88   fi
   89 }
   90 
   91 
   92 #
   93 # Takes an encrypted device path and executes cryptsetup luksOpen. Returns path
   94 # to the new decrypted block device. This path takes the rough form of
   95 # /dev/mapper/_dev_sdx
   96 #
   97 function setup_encrypted {
   98   path=${1}
   99   name=$(echo ${path} | tr / _)
  100 
  101   # Decrypted block dev path is /dev/mapper/${name}
  102   cryptsetup luksOpen ${path} ${name}
  103 
  104   # Notify user and wait for input on failure
  105   if [[ $? -gt 0 ]]; then
  106     echo "An error was detected mounting the encrypted root." >&2
  107     echo "Pausing. Press enter to continue." >&2
  108     read
  109   fi
  110 
  111   # Success. Return the path of the decrypted root device
  112   echo "/dev/mapper/${name}"
  113 }
  114 
  115 
  116 #
  117 # Main function to keep the main operations code nicely separated from the
  118 # rest.
  119 #
  120 function main {
  121   # display fanciful boot image
  122   screen_init
  123 
  124   # Mount the /proc and /sys filesystems.
  125   mount -t devtmpfs none /dev
  126   mount -t proc     none /proc
  127   mount -t tmpfs    none /run
  128   mount -t sysfs    none /sys
  129 
  130   local fakeroot='/mnt/root'
  131 
  132   if [[ ! -d ${fakeroot} ]]; then
  133     log "Fake root location ${fakeroot} does not exist. Creating."
  134     mkdir ${fakeroot}
  135   fi
  136 
  137   log "Parsing cmdline arguments"
  138 
  139   parse_cmdline "$(cat /proc/cmdline)"
  140 
  141   log "Root device: ${ROOTDEV}"
  142 
  143   log "Waiting a few seconds for devices to settle."
  144   sleep 2
  145 
  146   # Drop to maintenance shell if root device does not exist.
  147   if [[ ! -b ${ROOTDEV} ]]; then
  148     log "ERROR: Root device ${ROOTDEV} does not exist or can not be accessed."
  149     log "       Dropping to maintenance shell for troubleshooting."
  150     log "       (You may just need to wait longer for the root device)"
  151     /bin/bash -i
  152   fi
  153 
  154   if [[ $(get_part_type ${ROOTDEV}) == 'luks' ]]; then
  155     # Set new rootdev location (/dev/mapper/something). This will update it to
  156     # the decrypted block device path.
  157     log "Root device ${ROOTDEV} is encrypted."
  158     ROOTDEV=$(setup_encrypted ${ROOTDEV})
  159     log "New rootdev: ${ROOTDEV}"
  160   fi
  161 
  162   # Drop to interactive shell if requested
  163   if [[ ${INTERACTIVE} == 1 ]]; then
  164     log "Interractive shell requested. Type 'exit' to continue boot sequence."
  165     /bin/bash --norc
  166   fi
  167 
  168   # Mount the fakeroot.
  169   log "Mounting fakeroot"
  170   mount_fakeroot ${ROOTDEV} ${fakeroot}
  171 
  172   # Ensure switch_root will be possible for destination fakeroot
  173   if [[ ! -f ${fakeroot}/sbin/init ]]; then
  174     log "ERROR: Destination fakeroot ${fakeroot} does not have an init script."
  175     log "       Cannot proceed. Dropping to shell for troubleshooting."
  176     /bin/bash -i
  177   fi
  178 
  179   # Boot the real McCoy
  180   log "Switching root"
  181   exec switch_root ${fakeroot} /sbin/init
  182 
  183   # This will be reached if previous command failed
  184   log "There was an error performing switch_root to ${fakeroot}."
  185   log "Starting recovery shell."
  186   /bin/bash -i
  187 }
  188 
  189 main ${@}

Generated by cgit