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 ${@}
|