]> code.delx.au - refind/blob - install.sh
Reduce external command use for Mac OS X Recovery
[refind] / install.sh
1 #!/bin/bash
2 #
3 # Linux/MacOS X script to install rEFInd
4 #
5 # Usage:
6 #
7 # ./install.sh [options]
8 #
9 # options include:
10 # "--notesp" to install to the OS X root filesystem rather than to the ESP.
11 # This option may not be used under Linux.
12 # "--usedefault {devicefile}" to install as default
13 # (/EFI/BOOT/BOOTX64.EFI and similar) to the specified device
14 # (/dev/sdd1 or whatever) without registering with the NVRAM.
15 # "--ownhfs {devicefile}" to install to an HFS+ volume that's NOT currently
16 # an OS X boot volume.
17 # "--root {dir}" to specify installation using the specified directory
18 # as the system's root
19 # "--alldrivers" to install all drivers along with regular files
20 # "--nodrivers" to suppress driver installation (default in Linux is
21 # driver used on /boot; --nodrivers is OS X default)
22 # "--shim {shimfile}" to install a shim.efi file for Secure Boot
23 # "--preloader" is synonymous with "--shim"
24 # "--localkeys" to re-sign x86-64 binaries with a locally-generated key
25 # "--keepname" to keep refind_x64.efi name as such even when using shim
26 # "--yes" to assume a "yes" response to all prompts
27 #
28 # The "esp" option is valid only on Mac OS X; it causes
29 # installation to the EFI System Partition (ESP) rather than
30 # to the current OS X boot partition. Under Linux, this script
31 # installs to the ESP by default.
32 #
33 # This program is copyright (c) 2012-2015 by Roderick W. Smith
34 # It is released under the terms of the GNU GPL, version 3,
35 # a copy of which should be included in the file COPYING.txt.
36 #
37 # Revision history:
38 #
39 # 0.9.2 -- Added --keepname option.
40 # 0.8.7 -- Better detection of Secure Boot mode & fixed errors when copying
41 # Shim & MokManager files over themselves; fixed bug that caused
42 # inappropriate installation to EFI/BOOT/bootx64.efi
43 # 0.8.6 -- Fixed bugs that caused misidentification of ESP on disks with
44 # partition numbers over 10 on OS X and misidentification of mount
45 # point if already-mounted ESP had space in path.
46 # 0.8.5 -- Refinement/cleanup of new OS X ESP-as-default policy
47 # 0.8.4 -- OS X default changed to install to ESP under /EFI/BOOT
48 # 0.7.9 -- Fixed bug that caused errors if dmraid utility not installed
49 # 0.7.7 -- Fixed bug that created mangled refind_linux.conf file; added ability
50 # to locate and mount ESP on Linux, if it's not mounted
51 # 0.7.6 -- Added --ownhfs {device-filename} option
52 # 0.7.5 -- Fixed bug when installing to ESP on recent versions of OS X
53 # 0.7.2 -- Fixed code that could be confused by use of autofs to mount the ESP
54 # 0.7.0 -- Added support for the new Btrfs driver
55 # 0.6.12 -- Added support for PreLoader as well as for shim
56 # 0.6.11 -- Improvements in script's ability to handle directories with spaces
57 # in their names
58 # 0.6.9 -- Install gptsync on Macs
59 # 0.6.8 -- Bug fix: ESP scan now uses "uniq".
60 # 0.6.6 -- Bug fix: Upgrade drivers when installed to EFI/BOOT. Also enable
61 # copying shim.efi and MokManager.efi over themselves.
62 # 0.6.4 -- Copies ext2 driver rather than ext4 driver for ext2/3fs
63 # 0.6.3 -- Support for detecting rEFInd in EFI/BOOT and EFI/Microsoft/Boot
64 # directories & for installing to EFI/BOOT in BIOS mode
65 # 0.6.2-1 -- Added --yes option & tweaked key-copying for use with RPM install script
66 # 0.6.1 -- Added --root option; minor bug fixes
67 # 0.6.0 -- Changed --drivers to --alldrivers and added --nodrivers option;
68 # changed default driver installation behavior in Linux to install
69 # the driver needed to read /boot (if available)
70 # 0.5.1.2 -- Fixed bug that caused failure to generate refind_linux.conf file
71 # 0.5.1.1 -- Fixed bug that caused script failure under OS X
72 # 0.5.1 -- Added --shim & --localkeys options & create sample refind_linux.conf
73 # in /boot
74 # 0.5.0 -- Added --usedefault & --drivers options & changed "esp" option to "--esp"
75 # 0.4.5 -- Fixed check for rEFItBlesser in OS X
76 # 0.4.2 -- Added notice about BIOS-based OSes & made NVRAM changes in Linux smarter
77 # 0.4.1 -- Added check for rEFItBlesser in OS X
78 # 0.3.3.1 -- Fixed OS X 10.7 bug; also works as make target
79 # 0.3.2.1 -- Check for presence of source files; aborts if not present
80 # 0.3.2 -- Initial version
81 #
82 # Note: install.sh version numbers match those of the rEFInd package
83 # with which they first appeared.
84
85 RootDir="/"
86 TargetDir=/EFI/refind
87 LocalKeysBase="refind_local"
88 ShimSource="none"
89 ShimType="none"
90 KeepName=0
91 TargetShim="default"
92 TargetX64="refind_x64.efi"
93 TargetIA32="refind_ia32.efi"
94 LocalKeys=0
95 DeleteRefindDir=0
96 AlwaysYes=0
97
98 #
99 # Functions used by both OS X and Linux....
100 #
101
102 GetParams() {
103 InstallToEspOnMac=1
104 # Install the driver required to read Linux /boot, if it's available
105 # Note: Under OS X, this will be installed only if a Linux partition
106 # is detected, in which case the ext4fs driver will be installed.
107 InstallDrivers="boot"
108 while [[ $# -gt 0 ]]; do
109 case $1 in
110 --notesp) InstallToEspOnMac=0
111 ;;
112 --ownhfs) OwnHfs=1
113 InstallToEspOnMac=0
114 TargetPart="$2"
115 TargetDir=/System/Library/CoreServices
116 shift
117 ;;
118 --usedefault) TargetDir=/EFI/BOOT
119 TargetPart="$2"
120 TargetX64="bootx64.efi"
121 TargetIA32="bootia32.efi"
122 shift
123 ;;
124 --root) RootDir="$2"
125 InstallToEspOnMac=0
126 shift
127 ;;
128 --localkeys) LocalKeys=1
129 ;;
130 --shim | --preloader) ShimSource="$2"
131 ShimType=`basename $ShimSource`
132 shift
133 ;;
134 --keepname) KeepName=1
135 ;;
136 --drivers | --alldrivers) InstallDrivers="all"
137 ;;
138 --nodrivers) InstallDrivers="none"
139 ;;
140 --yes) AlwaysYes=1
141 ;;
142 * ) echo "Usage: $0 [--notesp | --usedefault {device-file} | --root {dir} |"
143 echo " --ownhfs {device-file} ] [--keepname]"
144 echo " [--nodrivers | --alldrivers]"
145 echo " [--localkeys] [--keepname] [--yes]"
146 exit 1
147 esac
148 shift
149 done
150 if [[ "$InstallToEspOnMac" == 0 && "$RootDir" == '/' && "$TargetDir" == '/EFI/BOOT' ]] ; then
151 echo "You may use --notesp OR --usedefault, but not both! Aborting!"
152 exit 1
153 fi
154 if [[ "$RootDir" != '/' && "$TargetDir" == '/EFI/BOOT' ]] ; then
155 echo "You may use --root OR --usedefault, but not both! Aborting!"
156 exit 1
157 fi
158 if [[ "$TargetDir" != '/System/Library/CoreServices' && "$OwnHfs" == '1' ]] ; then
159 echo "If you use --ownhfs, you may NOT use --usedefault! Aborting!"
160 exit 1
161 fi
162 if [[ "$KeepName" == 1 && "$ShimSource" == "none" ]] ; then
163 echo "The --keepname option is meaningful only in conjunction with --shim"
164 echo "or --preloader! Aborting!"
165 exit 1
166 fi
167 if [[ "$KeepName" == 1 && "$OSTYPE" != "linux-gnu" ]] ; then
168 echo "The --keepname option is valid only under Linux! Aborting!"
169 exit 1
170 fi
171 if [[ "$KeepName" == 1 && "$TargetDir" != "/EFI/BOOT" ]] ; then
172 echo "The --keepname option is incompatible with --usedefault! Aborting!"
173 exit 1
174 fi
175 RLConfFile="$RootDir/boot/refind_linux.conf"
176 EtcKeysDir="$RootDir/etc/refind.d/keys"
177 } # GetParams()
178
179 # Get a yes/no response from the user and place it in the YesNo variable.
180 # If the AlwaysYes variable is set to 1, skip the user input and set "Y"
181 # in the YesNo variable.
182 ReadYesNo() {
183 if [[ $AlwaysYes == 1 ]] ; then
184 YesNo="Y"
185 echo "Y"
186 else
187 read YesNo
188 fi
189 }
190
191 # Abort if the rEFInd files can't be found.
192 # Also sets $ConfFile to point to the configuration file,
193 # $IconsDir to point to the icons directory, and
194 # $ShimSource to the source of the shim.efi file (if necessary).
195 CheckForFiles() {
196 # Note: This check is satisfied if EITHER the 32- or the 64-bit version
197 # is found, even on the wrong platform. This is because the platform
198 # hasn't yet been determined. This could obviously be improved, but it
199 # would mean restructuring lots more code....
200 if [[ ! -f "$RefindDir/refind_ia32.efi" && ! -f "$RefindDir/refind_x64.efi" ]] ; then
201 echo "The rEFInd binary file is missing! Aborting installation!"
202 exit 1
203 fi
204
205 if [[ -f "$RefindDir/refind.conf-sample" ]] ; then
206 ConfFile="$RefindDir/refind.conf-sample"
207 elif [[ -f "$ThisDir/refind.conf-sample" ]] ; then
208 ConfFile="$ThisDir/refind.conf-sample"
209 else
210 echo "The sample configuration file is missing! Aborting installation!"
211 exit 1
212 fi
213
214 if [[ -d "$RefindDir/icons" ]] ; then
215 IconsDir="$RefindDir/icons"
216 elif [[ -d "$ThisDir/icons" ]] ; then
217 IconsDir="$ThisDir/icons"
218 else
219 echo "The icons directory is missing! Aborting installation!"
220 exit 1
221 fi
222
223 echo "ShimSource is $ShimSource"
224 if [[ "$ShimSource" != "none" ]] ; then
225 if [[ -f "$ShimSource" ]] ; then
226 if [[ $ShimType == "shimx64.efi" || $ShimType == "shim.efi" ]] ; then
227 TargetX64="grubx64.efi"
228 MokManagerSource=`dirname "$ShimSource"`/MokManager.efi
229 elif [[ $ShimType == "preloader.efi" || $ShimType == "PreLoader.efi" ]] ; then
230 TargetX64="loader.efi"
231 MokManagerSource=`dirname "$ShimSource"`/HashTool.efi
232 else
233 echo "Unknown shim/PreBootloader filename: $ShimType!"
234 echo "Known filenames are shimx64.efi, shim.efi, and PreLoader.efi. Aborting!"
235 exit 1
236 fi
237 else
238 echo "The specified shim/PreBootloader file, $ShimSource, doesn't exist!"
239 echo "Aborting installation!"
240 exit 1
241 fi
242 fi
243 } # CheckForFiles()
244
245 # Helper for CopyRefindFiles; copies shim files (including MokManager, if it's
246 # available) to target.
247 CopyShimFiles() {
248 local inode1=`ls -i "$ShimSource" 2> /dev/null | cut -f 1 -d " "`
249 local inode2=`ls -i "$InstallDir/$TargetDir/$TargetShim" 2> /dev/null | cut -f 1 -d " "`
250 if [[ $inode1 != $inode2 ]] ; then
251 cp -fb "$ShimSource" "$InstallDir/$TargetDir/$TargetShim"
252 if [[ $? != 0 ]] ; then
253 Problems=1
254 fi
255 fi
256 inode1=`ls -i "$MokManagerSource" 2> /dev/null | cut -f 1 -d " "`
257 local TargetMMName=`basename $MokManagerSource`
258 inode2=`ls -i "$InstallDir/$TargetDir/$TargetMMName" 2> /dev/null | cut -f 1 -d " "`
259 if [[ $inode1 != $inode2 ]] ; then
260 if [[ -f "$MokManagerSource" ]] ; then
261 cp -fb "$MokManagerSource" "$InstallDir/$TargetDir/"
262 fi
263 if [[ $? != 0 ]] ; then
264 Problems=1
265 fi
266 fi
267 } # CopyShimFiles()
268
269 # Copy the public keys to the installation medium
270 CopyKeys() {
271 if [[ $LocalKeys == 1 ]] ; then
272 mkdir -p "$InstallDir/$TargetDir/keys/"
273 cp "$EtcKeysDir/$LocalKeysBase.cer" "$InstallDir/$TargetDir/keys/"
274 cp "$EtcKeysDir/$LocalKeysBase.crt" "$InstallDir/$TargetDir/keys/"
275 fi
276 } # CopyKeys()
277
278 # Set varaibles for installation in EFI/BOOT directory
279 SetVarsForBoot() {
280 TargetDir="/EFI/BOOT"
281 if [[ $ShimSource == "none" ]] ; then
282 TargetX64="bootx64.efi"
283 TargetIA32="bootia32.efi"
284 else
285 if [[ $ShimType == "shim.efi" || $ShimType == "shimx64.efi" ]] ; then
286 TargetX64="grubx64.efi"
287 elif [[ $ShimType == "preloader.efi" || $ShimType == "PreLoader.efi" ]] ; then
288 TargetX64="loader.efi"
289 else
290 echo "Unknown shim/PreBootloader type: $ShimType"
291 echo "Aborting!"
292 exit 1
293 fi
294 TargetIA32="bootia32.efi"
295 TargetShim="bootx64.efi"
296 fi
297 if [[ $KeepName == 1 ]] ; then
298 echo "Installation is to /EFI/BOOT, which is incompatible with --keepname! Aborting!"
299 exit 1
300 fi
301 } # SetVarsForBoot()
302
303 # Set variables for installation in EFI/Microsoft/Boot directory
304 SetVarsForMsBoot() {
305 TargetDir="/EFI/Microsoft/Boot"
306 if [[ $ShimSource == "none" ]] ; then
307 TargetX64="bootmgfw.efi"
308 TargetIA32="bootmgfw.efi"
309 else
310 if [[ $ShimType == "shim.efi" || $ShimType == "shimx64.efi" ]] ; then
311 TargetX64="grubx64.efi"
312 elif [[ $ShimType == "preloader.efi" || $ShimType == "PreLoader.efi" ]] ; then
313 TargetX64="loader.efi"
314 else
315 echo "Unknown shim/PreBootloader type: $ShimType"
316 echo "Aborting!"
317 exit 1
318 fi
319 TargetShim="bootmgfw.efi"
320 fi
321 if [[ $KeepName == 1 ]] ; then
322 echo "Installation is to /EFI/Microsoft/Boot, which is incompatible with --keepname!"
323 echo "Aborting!"
324 exit 1
325 fi
326 } # SetVarsForMsBoot()
327
328 # TargetDir defaults to /EFI/refind; however, this function adjusts it as follows:
329 # - If an existing refind.conf is available in /EFI/BOOT or /EFI/Microsoft/Boot,
330 # install to that directory under the suitable name; but DO NOT do this if
331 # refind.conf is also in /EFI/refind.
332 # - If booted in BIOS mode and the ESP lacks any other EFI files, install to
333 # /EFI/BOOT
334 # - If booted in BIOS mode and there's no refind.conf file and there is a
335 # /EFI/Microsoft/Boot/bootmgfw.efi file, move it down one level and
336 # install under that name, "hijacking" the Windows boot loader filename
337 DetermineTargetDir() {
338 Upgrade=0
339
340 if [[ -f $InstallDir/EFI/BOOT/refind.conf && ! -f $InstallDir/EFI/refind/refind.conf ]] ; then
341 SetVarsForBoot
342 Upgrade=1
343 fi
344 if [[ -f $InstallDir/EFI/Microsoft/Boot/refind.conf && ! -f $InstallDir/EFI/refind/refind.conf ]] ; then
345 SetVarsForMsBoot
346 Upgrade=1
347 fi
348 if [[ -f $InstallDir/EFI/refind/refind.conf ]] ; then
349 TargetDir="/EFI/refind"
350 if [[ $ShimSource == "none" || $KeepName == 1 ]] ; then
351 TargetX64="refind_x64.efi"
352 TargetIA32="refind_ia32.efi"
353 fi
354 Upgrade=1
355 fi
356 if [[ $Upgrade == 1 ]] ; then
357 echo "Found rEFInd installation in $InstallDir$TargetDir; upgrading it."
358 fi
359
360 if [[ ! -d /sys/firmware/efi && ! $OSTYPE == darwin* && $Upgrade == 0 ]] ; then # BIOS-mode
361 FoundEfiFiles=`find "$InstallDir/EFI/BOOT" -name "*.efi" 2> /dev/null`
362 FoundConfFiles=`find "$InstallDir" -name "refind\.conf" 2> /dev/null`
363 if [[ ! -n "$FoundConfFiles" && -f "$InstallDir/EFI/Microsoft/Boot/bootmgfw.efi" ]] ; then
364 mv -n "$InstallDir/EFI/Microsoft/Boot/bootmgfw.efi" "$InstallDir/EFI/Microsoft" &> /dev/null
365 SetVarsForMsBoot
366 echo "Running in BIOS mode with a suspected Windows installation; moving boot loader"
367 echo "files so as to install to $InstallDir$TargetDir."
368 elif [[ ! -n "$FoundEfiFiles" ]] ; then # In BIOS mode and no default loader; install as default loader
369 SetVarsForBoot
370 echo "Running in BIOS mode with no existing default boot loader; installing to"
371 echo $InstallDir$TargetDir
372 else
373 echo "Running in BIOS mode with an existing default boot loader; backing it up and"
374 echo "installing rEFInd in its place."
375 if [[ -d "$InstallDir/EFI/BOOT-rEFIndBackup" ]] ; then
376 echo ""
377 echo "Caution: An existing backup of a default boot loader exists! If the current"
378 echo "default boot loader and the backup are different boot loaders, the current"
379 echo "one will become inaccessible."
380 echo ""
381 echo -n "Do you want to proceed with installation (Y/N)? "
382 ReadYesNo
383 if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then
384 echo "OK; continuing with the installation..."
385 else
386 exit 0
387 fi
388 fi
389 mv -n "$InstallDir/EFI/BOOT" "$InstallDir/EFI/BOOT-rEFIndBackup"
390 SetVarsForBoot
391 fi
392 fi # BIOS-mode
393 } # DetermineTargetDir()
394
395 # Determine (or guess) the filesystem used on the Linux /boot filesystem.
396 # Store the result in the BootFS global variable.
397 SetBootFS() {
398 local Blkid
399
400 BootFS=""
401 case "$OSTYPE" in
402 linux-gnu)
403 if command -v blkid 2>/dev/null; then
404 BootPart=`df /boot | grep dev | cut -f 1 -d " "`
405 BootFS=`blkid -o export $BootPart 2> /dev/null | grep TYPE= | cut -f 2 -d =`
406 fi
407 ;;
408 darwin*)
409 # 0FC63DAF-8483-4772-8E79-3D69D8477DE4 = Linux filesystem
410 # BC13C2FF-59E6-4262-A352-B275FD6F7172 = Freedesktop $boot partition
411 # 933AC7E1-2EB4-4F13-B844-0E14E2AEF915 = Freedesktop Linux /home
412 # E6D6D379-F507-44C2-A23C-238F2A3DF928 = Linux LVM
413 # A19D880F-05FC-4D3B-A006-743F0F84911E = Linux RAID
414 # 0657FD6D-A4AB-43C4-84E5-0933C84B4F4F = Linux swap
415 Temp=$(diskutil list | grep -i '0FC63DAF-8483-4772-8E79-3D69D8477DE4\|BC13C2FF-59E6-4262-A352-B275FD6F7172\|933AC7E1-2EB4-4F13-B844-0E14E2AEF915\|E6D6D379-F507-44C2-A23C-238F2A3DF928\|A19D880F-05FC-4D3B-A006-743F0F84911E\|0657FD6D-A4AB-43C4-84E5-0933C84B4F4F\|Linux')
416 BootFS=""
417 if [[ -n $Temp ]] ; then
418 echo "Found suspected Linux partition(s); installing ext4fs driver."
419 BootFS="ext4"
420 fi
421 ;;
422 esac
423 } # SetBootFS()
424
425 # Copy drivers from $RefindDir/drivers_$1 to $InstallDir/$TargetDir/drivers_$1,
426 # honoring the $InstallDrivers condition. Must be passed a suitable
427 # architecture code (ia32 or x64).
428 CopyDrivers() {
429 if [[ $InstallDrivers == "all" ]] ; then
430 mkdir -p "$InstallDir/$TargetDir/drivers_$1"
431 cp "$ThisDir"/drivers_$1/*_$1.efi "$InstallDir/$TargetDir/drivers_$1/" 2> /dev/null
432 cp "$RefindDir"/drivers_$1/*_$1.efi "$InstallDir/$TargetDir/drivers_$1/" 2> /dev/null
433 elif [[ "$InstallDrivers" == "boot" ]] ; then
434 SetBootFS
435 DriverType=""
436 case $BootFS in
437 ext2 | ext3) DriverType="ext2"
438 # Could use ext4, but that can create unwanted entries from symbolic
439 # links in / to /boot/vmlinuz if a separate /boot partition is used.
440 ;;
441 ext4) DriverType="ext4"
442 ;;
443 reiserfs) DriverType="reiserfs"
444 ;;
445 btrfs) DriverType="btrfs"
446 ;;
447 hfsplus) DriverType="hfs"
448 ;;
449 ntfs) DriverType="ntfs"
450 ;;
451 *) BootFS=""
452 esac
453 if [[ -n $BootFS ]] ; then
454 echo "Installing driver for $BootFS (${DriverType}_$1.efi)"
455 mkdir -p "$InstallDir/$TargetDir/drivers_$1"
456 cp "$ThisDir/drivers_$1/${DriverType}_$1.efi" "$InstallDir/$TargetDir/drivers_$1/" 2> /dev/null
457 cp "$RefindDir/drivers_$1/${DriverType}_$1.efi" "$InstallDir/$TargetDir/drivers_$1"/ 2> /dev/null
458 fi
459 fi
460 } # CopyDrivers()
461
462 # Copy tools (currently only gptsync, and that only on Macs) to the EFI/tools
463 # directory on the ESP. Must be passed a suitable architecture code (ia32
464 # or x64).
465 CopyTools() {
466 mkdir -p "$InstallDir/EFI/tools"
467 if [[ $OSTYPE == darwin* ]] ; then
468 cp -f "$RefindDir/tools_$1/gptsync_$1.efi" "$InstallDir/EFI/tools/"
469 if [[ -f "$InstallDir/EFI/tools/gptsync.efi" ]] ; then
470 mv "$InstallDir/EFI/tools/gptsync.efi" "$InstallDir/EFI/tools/gptsync.efi-disabled"
471 echo "Found old gptsync.efi; disabling it by renaming it to gptsync.efi-disabled"
472 fi
473 fi
474 } # CopyTools()
475
476 # Copy the rEFInd files to the ESP or OS X root partition.
477 # Sets Problems=1 if any critical commands fail.
478 CopyRefindFiles() {
479 mkdir -p "$InstallDir/$TargetDir"
480 if [[ "$TargetDir" == '/EFI/BOOT' ]] ; then
481 cp "$RefindDir/refind_ia32.efi" "$InstallDir/$TargetDir/$TargetIA32" 2> /dev/null
482 if [[ $? != 0 ]] ; then
483 echo "Note: IA32 (x86) binary not installed!"
484 fi
485 cp "$RefindDir/refind_x64.efi" "$InstallDir/$TargetDir/$TargetX64" 2> /dev/null
486 if [[ $? != 0 ]] ; then
487 Problems=1
488 fi
489 if [[ "$ShimSource" != "none" ]] ; then
490 TargetShim="bootx64.efi"
491 CopyShimFiles
492 fi
493 if [[ $InstallDrivers == "all" ]] ; then
494 cp -r "$RefindDir"/drivers_* "$InstallDir/$TargetDir/" 2> /dev/null
495 cp -r "$ThisDir"/drivers_* "$InstallDir/$TargetDir/" 2> /dev/null
496 elif [[ $Upgrade == 1 || $InstallToEspOnMac == 1 ]] ; then
497 if [[ $Platform == 'EFI64' ]] ; then
498 CopyDrivers x64
499 CopyTools x64
500 else
501 CopyDrivers ia32
502 CopyTools ia32
503 fi
504 fi
505 Refind=""
506 if [[ $Platform == 'EFI64' ]] ; then
507 Refind='bootx64.efi'
508 elif [[ $Platform == 'EFI32' ]] ; then
509 Refind='bootia32.efi'
510 fi
511 CopyKeys
512 elif [[ $Platform == 'EFI64' || $TargetDir == "/EFI/Microsoft/Boot" ]] ; then
513 cp "$RefindDir/refind_x64.efi" "$InstallDir/$TargetDir/$TargetX64"
514 if [[ $? != 0 ]] ; then
515 Problems=1
516 fi
517 CopyDrivers x64
518 CopyTools x64
519 Refind="refind_x64.efi"
520 CopyKeys
521 if [[ "$ShimSource" != "none" ]] ; then
522 if [[ "$TargetShim" == "default" ]] ; then
523 TargetShim=`basename "$ShimSource"`
524 fi
525 CopyShimFiles
526 Refind="$TargetShim"
527 if [[ $LocalKeys == 0 ]] ; then
528 echo "Storing copies of rEFInd Secure Boot public keys in $EtcKeysDir"
529 mkdir -p "$EtcKeysDir"
530 cp "$ThisDir/keys/refind.cer" "$EtcKeysDir" 2> /dev/null
531 cp "$ThisDir/keys/refind.crt" "$EtcKeysDir" 2> /dev/null
532 fi
533 fi
534 if [[ "$TargetDir" == '/System/Library/CoreServices' ]] ; then
535 SetupMacHfs $TargetX64
536 fi
537 elif [[ $Platform == 'EFI32' ]] ; then
538 cp "$RefindDir/refind_ia32.efi" "$InstallDir/$TargetDir/$TargetIA32"
539 if [[ $? != 0 ]] ; then
540 Problems=1
541 fi
542 CopyDrivers ia32
543 CopyTools ia32
544 Refind="refind_ia32.efi"
545 if [[ "$TargetDir" == '/System/Library/CoreServices' ]] ; then
546 SetupMacHfs $TargetIA32
547 fi
548 else
549 echo "Unknown platform! Aborting!"
550 exit 1
551 fi
552 echo "Copied rEFInd binary files"
553 echo ""
554 if [[ -d "$InstallDir/$TargetDir/icons" ]] ; then
555 rm -rf "$InstallDir/$TargetDir/icons-backup" &> /dev/null
556 mv -f "$InstallDir/$TargetDir/icons" "$InstallDir/$TargetDir/icons-backup"
557 echo "Notice: Backed up existing icons directory as icons-backup."
558 fi
559 cp -r "$IconsDir" "$InstallDir/$TargetDir"
560 if [[ $? != 0 ]] ; then
561 Problems=1
562 fi
563 mkdir -p "$InstallDir/$TargetDir/keys"
564 cp -rf "$ThisDir"/keys/*.[cd]er "$InstallDir/$TargetDir/keys/" 2> /dev/null
565 cp -rf "$EtcKeysDir"/*.[cd]er "$InstallDir/$TargetDir/keys/" 2> /dev/null
566 if [[ -f "$InstallDir/$TargetDir/refind.conf" ]] ; then
567 echo "Existing refind.conf file found; copying sample file as refind.conf-sample"
568 echo "to avoid overwriting your customizations."
569 echo ""
570 cp -f "$ConfFile" "$InstallDir/$TargetDir"
571 if [[ $? != 0 ]] ; then
572 Problems=1
573 fi
574 else
575 echo "Copying sample configuration file as refind.conf; edit this file to configure"
576 echo "rEFInd."
577 echo ""
578 cp -f "$ConfFile" "$InstallDir/$TargetDir/refind.conf"
579 if [[ $? != 0 ]] ; then
580 Problems=1
581 fi
582 fi
583 if [[ $DeleteRefindDir == 1 ]] ; then
584 echo "Deleting the temporary directory $RefindDir"
585 rm -r "$RefindDir"
586 fi
587 } # CopyRefindFiles()
588
589 # Mount the partition the user specified with the --usedefault or --ownhfs option
590 MountDefaultTarget() {
591 InstallDir=/tmp/refind_install
592 mkdir -p "$InstallDir"
593 UnmountEsp=1
594 if [[ $OSTYPE == darwin* ]] ; then
595 if [[ $OwnHfs == '1' ]] ; then
596 Temp=`diskutil info "$TargetPart" | grep "Mount Point"`
597 InstallDir=`echo $Temp | cut -f 3-30 -d ' '`
598 if [[ $InstallDir == '' ]] ; then
599 InstallDir=/tmp/refind_install
600 mount -t hfs "$TargetPart" "$InstallDir"
601 else
602 UnmountEsp=0
603 fi
604 else
605 mount -t msdos "$TargetPart" "$InstallDir"
606 fi
607 elif [[ $OSTYPE == linux-gnu ]] ; then
608 mount -t vfat "$TargetPart" "$InstallDir"
609 fi
610 if [[ $? != 0 ]] ; then
611 echo "Couldn't mount $TargetPart ! Aborting!"
612 rmdir "$InstallDir"
613 exit 1
614 fi
615 } # MountDefaultTarget()
616
617 #
618 # A series of OS X support functions....
619 #
620
621 # Mount the ESP at /Volumes/ESP or determine its current mount
622 # point.
623 # Sets InstallDir to the ESP mount point
624 # Sets UnmountEsp if we mounted it
625 MountOSXESP() {
626 # Identify the ESP. Note: This returns the FIRST ESP found;
627 # if the system has multiple disks, this could be wrong!
628 Temp=$(mount | sed -n -E "/^(\/dev\/disk[0-9]+s[0-9]+) on \/ \(.*$/s//\1/p")
629 if [ $Temp ]; then
630 Temp=$(diskutil list | grep " EFI " | grep -o 'disk.*' | head -n 1)
631 if [ -z $Temp ]; then
632 echo "Warning: root device doesn't have an EFI partition"
633 fi
634 else
635 echo "Warning: root device could not be found"
636 fi
637 if [ -z $Temp ]; then
638 Temp=$(diskutil list | sed -n -E '/^ *[0-9]+:[ ]+EFI EFI[ ]+[0-9.]+ [A-Z]+[ ]+(disk[0-9]+s[0-9]+)$/ { s//\1/p
639 q
640 }' )
641
642 if [ -z $Temp ]; then
643 echo "Could not find an EFI partition. Aborting!"
644 exit 1
645 fi
646 fi
647 Esp=/dev/`echo $Temp`
648 # If the ESP is mounted, use its current mount point....
649 Temp=`df -P | grep "$Esp "`
650 InstallDir=`echo $Temp | cut -f 6- -d ' '`
651 if [[ "$InstallDir" == '' ]] ; then
652 mkdir /Volumes/ESP &> /dev/null
653 mount -t msdos "$Esp" /Volumes/ESP
654 # Some systems have HFS+ "ESPs." They shouldn't, but they do. If this is
655 # detected, mount it as such and set appropriate options.
656 if [[ $? != 0 ]] ; then
657 mount -t hfs "$Esp" /Volumes/Esp
658 OwnHfs=1
659 InstallToEspOnMac=0
660 if [[ $? != 0 ]] ; then
661 echo "Unable to mount ESP! Aborting!\n"
662 exit 1
663 fi
664 fi
665 UnmountEsp=1
666 InstallDir="/Volumes/ESP"
667 fi
668 } # MountOSXESP()
669
670 # Set up for booting from Mac HFS+ volume that boots rEFInd in MJG's way
671 # (http://mjg59.dreamwidth.org/7468.html)
672 # Must be passed the original rEFInd binary filename (without a path).
673 SetupMacHfs() {
674 if [[ -s "$InstallDir/mach_kernel" ]] ; then
675 echo "Attempt to install rEFInd to a partition with a /mach_kernel file! Aborting!"
676 exit 1
677 fi
678 cp -n "$InstallDir/$TargetDir/boot.efi" "$InstallDir/$TargetDir/boot.efi-backup" &> /dev/null
679 ln -f "$InstallDir/$TargetDir/$1" "$InstallDir/$TargetDir/boot.efi"
680 touch "$InstallDir/mach_kernel"
681 rm "$InstallDir/$TargetDir/SystemVersion.plist" &> /dev/null
682 cat - << ENDOFHERE >> "$InstallDir/$TargetDir/SystemVersion.plist"
683 <xml version="1.0" encoding="UTF-8"?>
684 <plist version="1.0">
685 <dict>
686 <key>ProductBuildVersion</key>
687 <string></string>
688 <key>ProductName</key>
689 <string>rEFInd</string>
690 <key>ProductVersion</key>
691 <string>0.9.2</string>
692 </dict>
693 </plist>
694 ENDOFHERE
695 } # SetupMacHfs()
696
697 # Control the OS X installation.
698 # Sets Problems=1 if problems found during the installation.
699 InstallOnOSX() {
700 echo "Installing rEFInd on OS X...."
701 if [[ "$InstallToEspOnMac" == "1" ]] ; then
702 MountOSXESP
703 elif [[ "$TargetDir" == "/EFI/BOOT" || "$OwnHfs" == '1' ]] ; then
704 MountDefaultTarget
705 else
706 InstallDir="$RootDir/"
707 fi
708 echo "Installing rEFInd to the partition mounted at $InstallDir"
709 DetermineTargetDir
710 Platform=`ioreg -l -p IODeviceTree | grep firmware-abi | cut -d "\"" -f 4`
711 CopyRefindFiles
712 if [[ $InstallToEspOnMac == "1" ]] ; then
713 bless --mount "$InstallDir" --setBoot --file "$InstallDir/$TargetDir/$Refind" --shortform
714 elif [[ "$TargetDir" != "/EFI/BOOT" ]] ; then
715 bless --setBoot --folder "$InstallDir/$TargetDir" --file "$InstallDir/$TargetDir/$Refind"
716 fi
717 if [[ $? != 0 ]] ; then
718 Problems=1
719 fi
720 if [[ -f /Library/StartupItems/rEFItBlesser || -d /Library/StartupItems/rEFItBlesser ]] ; then
721 echo
722 echo "/Library/StartupItems/rEFItBlesser found!"
723 echo "This program is part of rEFIt, and will cause rEFInd to fail to work after"
724 echo -n "its first boot. Do you want to remove rEFItBlesser (Y/N)? "
725 ReadYesNo
726 if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then
727 echo "Deleting /Library/StartupItems/rEFItBlesser..."
728 rm -r /Library/StartupItems/rEFItBlesser
729 else
730 echo "Not deleting rEFItBlesser."
731 fi
732 fi
733 echo
734 echo "WARNING: If you have an Advanced Format disk, *DO NOT* attempt to check the"
735 echo "bless status with 'bless --info', since this is known to cause disk corruption"
736 echo "on some systems!!"
737 echo
738 } # InstallOnOSX()
739
740
741 #
742 # Now a series of Linux support functions....
743 #
744
745 # Check for evidence that we're running in Secure Boot mode. If so, and if
746 # appropriate options haven't been set, warn the user and offer to abort.
747 # If we're NOT in Secure Boot mode but the user HAS specified the --shim
748 # or --localkeys option, warn the user and offer to abort.
749 CheckSecureBoot() {
750 local IsSecureBoot
751 if [[ -f /sys/firmware/efi/vars/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c/data ]] ; then
752 IsSecureBoot=`od -An -t u1 /sys/firmware/efi/vars/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c/data | tr -d '[[:space:]]'`
753 else
754 IsSecureBoot="0"
755 fi
756 if [[ $IsSecureBoot == "1" && "$TargetDir" != '/EFI/BOOT' && "$ShimSource" == "none" ]] ; then
757 echo ""
758 echo "CAUTION: Your computer appears to be booted with Secure Boot, but you haven't"
759 echo "specified a valid shim.efi file source. Chances are you should re-run with"
760 echo "the --shim option. You can read more about this topic at"
761 echo "http://www.rodsbooks.com/refind/secureboot.html."
762 echo ""
763 echo -n "Do you want to proceed with installation (Y/N)? "
764 ReadYesNo
765 if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then
766 echo "OK; continuing with the installation..."
767 else
768 exit 0
769 fi
770 fi
771
772 if [[ "$ShimSource" != "none" && ! $IsSecureBoot == "1" ]] ; then
773 echo ""
774 echo "You've specified installing using a shim.efi file, but your computer does not"
775 echo "appear to be running in Secure Boot mode. Although installing in this way"
776 echo "should work, it's unnecessarily complex. You may continue, but unless you"
777 echo "plan to enable Secure Boot, you should consider stopping and omitting the"
778 echo "--shim option. You can read more about this topic at"
779 echo "http://www.rodsbooks.com/refind/secureboot.html."
780 echo ""
781 echo -n "Do you want to proceed with installation (Y/N)? "
782 ReadYesNo
783 if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then
784 echo "OK; continuing with the installation..."
785 else
786 exit 0
787 fi
788 fi
789
790 if [[ $LocalKeys != 0 && ! $IsSecureBoot == "1" ]] ; then
791 echo ""
792 echo "You've specified re-signing your rEFInd binaries with locally-generated keys,"
793 echo "but your computer does not appear to be running in Secure Boot mode. The"
794 echo "keys you generate will be useless unless you enable Secure Boot. You may"
795 echo "proceed with this installation, but before you do so, you may want to read"
796 echo "more about it at http://www.rodsbooks.com/refind/secureboot.html."
797 echo ""
798 echo -n "Do you want to proceed with installation (Y/N)? "
799 ReadYesNo
800 if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then
801 echo "OK; continuing with the installation..."
802 else
803 exit 0
804 fi
805 fi
806
807 } # CheckSecureBoot()
808
809 # Check for the presence of locally-generated keys from a previous installation in
810 # $EtcKeysDir (/etc/refind.d/keys). If they're not present, generate them using
811 # openssl.
812 GenerateKeys() {
813 PrivateKey="$EtcKeysDir/$LocalKeysBase.key"
814 CertKey="$EtcKeysDir/$LocalKeysBase.crt"
815 DerKey="$EtcKeysDir/$LocalKeysBase.cer"
816 OpenSSL=`which openssl 2> /dev/null`
817
818 # Do the work only if one or more of the necessary keys is missing
819 # TODO: Technically, we don't need the DerKey; but if it's missing and openssl
820 # is also missing, this will fail. This could be improved.
821 if [[ ! -f "$PrivateKey" || ! -f "$CertKey" || ! -f "$DerKey" ]] ; then
822 echo "Generating a fresh set of local keys...."
823 mkdir -p "$EtcKeysDir"
824 chmod 0700 "$EtcKeysDir"
825 if [[ ! -x "$OpenSSL" ]] ; then
826 echo "Can't find openssl, which is required to create your private signing keys!"
827 echo "Aborting!"
828 exit 1
829 fi
830 if [[ -f "$PrivateKey" ]] ; then
831 echo "Backing up existing $PrivateKey"
832 cp -f "$PrivateKey" "$PrivateKey.backup" 2> /dev/null
833 fi
834 if [[ -f "$CertKey" ]] ; then
835 echo "Backing up existing $CertKey"
836 cp -f "$CertKey" "$CertKey.backup" 2> /dev/null
837 fi
838 if [[ -f "$DerKey" ]] ; then
839 echo "Backing up existing $DerKey"
840 cp -f "$DerKey" "$DerKey.backup" 2> /dev/null
841 fi
842 "$OpenSSL" req -new -x509 -newkey rsa:2048 -keyout "$PrivateKey" -out "$CertKey" \
843 -nodes -days 3650 -subj "/CN=Locally-generated rEFInd key/"
844 "$OpenSSL" x509 -in "$CertKey" -out "$DerKey" -outform DER
845 chmod 0600 "$PrivateKey"
846 else
847 echo "Using existing local keys...."
848 fi
849 }
850
851 # Sign a single binary. Requires parameters:
852 # $1 = source file
853 # $2 = destination file
854 # Also assumes that the SBSign, PESign, UseSBSign, UsePESign, and various key variables are set
855 # appropriately.
856 # Aborts script on error
857 SignOneBinary() {
858 $SBSign --key "$PrivateKey" --cert "$CertKey" --output "$2" "$1"
859 if [[ $? != 0 ]] ; then
860 echo "Problem signing the binary $1! Aborting!"
861 exit 1
862 fi
863 }
864
865 # Re-sign the x86-64 binaries with a locally-generated key, First look for appropriate
866 # key files in $EtcKeysDir. If they're present, use them to re-sign the binaries. If
867 # not, try to generate new keys and store them in $EtcKeysDir.
868 ReSignBinaries() {
869 SBSign=`which sbsign 2> /dev/null`
870 echo "Found sbsign at $SBSign"
871 TempDir="/tmp/refind_local"
872 if [[ ! -x "$SBSign" ]] ; then
873 echo "Can't find sbsign, which is required to sign rEFInd with your own keys!"
874 echo "Aborting!"
875 exit 1
876 fi
877 GenerateKeys
878 mkdir -p "$TempDir/drivers_x64"
879 cp "$RefindDir/refind.conf-sample $TempDir" 2> /dev/null
880 cp "$ThisDir/refind.conf-sample $TempDir" 2> /dev/null
881 cp "$RefindDir/refind_ia32.efi $TempDir" 2> /dev/null
882 cp -a "$RefindDir/drivers_ia32 $TempDir" 2> /dev/null
883 cp -a "$ThisDir/drivers_ia32 $TempDir" 2> /dev/null
884 SignOneBinary "$RefindDir/refind_x64.efi" "$TempDir/refind_x64.efi"
885 SaveIFS=$IFS
886 IFS=$(echo -en "\n\b")
887 for Driver in `ls "$RefindDir"/drivers_x64/*.efi "$ThisDir"/drivers_x64/*.efi 2> /dev/null` ; do
888 TempName=`basename "$Driver"`
889 SignOneBinary "$Driver" "$TempDir/drivers_x64/$TempName"
890 done
891 IFS=$SaveIFS
892 RefindDir="$TempDir"
893 DeleteRefindDir=1
894 } # ReSignBinaries()
895
896 # Locate and mount an ESP, if possible, based on parted output.
897 # Should be called only if /boot/efi is NOT an acceptable ESP.
898 # Sets InstallDir to the mounted ESP's path ($RootDir/boot/efi)
899 # and EspFilesystem the filesystem (always "vfat")
900 FindLinuxESP() {
901 echo "The ESP doesn't seem to be mounted! Trying to find it...."
902 local Drive
903 local PartNum
904 local TableType
905 local DmStatus
906 local SkipIt
907 local Dmraid
908 for Drive in `ls /dev/[sh]d?` ; do
909 SkipIt=0
910 Dmraid=`which dmraid 2> /dev/null`
911 if [ -x "$Dmraid" ] ; then
912 DmStatus=`dmraid -r | grep $Drive`
913 if [ -n "$DmStatus" ] ; then
914 echo "$Drive seems to be part of a RAID array; skipping!"
915 SkipIt=1
916 fi
917 fi
918 TableType=`parted $Drive print -m -s 2>/dev/null | awk -F: '$1 == "'$Drive'" { print $6 }'`
919 if [[ $TableType == 'gpt' && $SkipIt == 0 ]] ; then # read only GPT disks that aren't part of dmraid array
920 PartNum=`LANG=C parted $Drive print -m -s 2>/dev/null | awk -F: '$7 ~ "(^boot| boot)" { print $1 }' | head -n 1`
921 if [ "$PartNum" -eq "$PartNum" ] 2> /dev/null ; then
922 InstallDir="$RootDir/boot/efi"
923 mkdir -p $InstallDir
924 mount $Drive$PartNum $InstallDir
925 EspFilesystem=`grep "$Drive$PartNum.*/boot/efi" /etc/mtab | uniq | grep -v autofs | cut -d " " -f 3`
926 if [[ $EspFilesystem != 'vfat' ]] ; then
927 umount $InstallDir
928 else
929 echo "Mounting ESP at $InstallDir"
930 break;
931 fi
932 fi # $PartNum -eq $PartNum
933 fi # TableType
934 done
935 } # FindLinuxESP()
936
937 # Identifies the ESP's location (/boot or /boot/efi, or these locations under
938 # the directory specified by --root); aborts if the ESP isn't mounted at
939 # either location.
940 # Sets InstallDir to the ESP mount point.
941 FindMountedESP() {
942 mount /boot &> /dev/null
943 mount /boot/efi &> /dev/null
944 EspLine=`df "$RootDir/boot/efi" 2> /dev/null | grep boot/efi`
945 if [[ ! -n "$EspLine" ]] ; then
946 EspLine=`df "$RootDir"/boot | grep boot`
947 fi
948 InstallDir=`echo $EspLine | cut -d " " -f 6`
949
950 if [[ -n "$InstallDir" ]] ; then
951 EspFilesystem=`grep -w "$InstallDir" /etc/mtab | uniq | grep -v autofs | cut -d " " -f 3`
952 fi
953 if [[ $EspFilesystem != 'vfat' ]] ; then
954 FindLinuxESP
955 fi
956 if [[ $EspFilesystem != 'vfat' ]] ; then
957 echo "$RootDir/$InstallDir doesn't seem to be on a VFAT filesystem. The ESP must be"
958 echo "mounted at $RootDir/boot or $RootDir/boot/efi and it must be VFAT! Aborting!"
959 exit 1
960 fi
961 echo "ESP was found at $InstallDir using $EspFilesystem"
962 } # FindMountedESP
963
964 # Uses efibootmgr to add an entry for rEFInd to the EFI's NVRAM.
965 # If this fails, sets Problems=1
966 AddBootEntry() {
967 local PartNum
968 Efibootmgr=`which efibootmgr 2> /dev/null`
969 if [[ "$Efibootmgr" ]] ; then
970 InstallDisk=`grep "$InstallDir" /etc/mtab | cut -d " " -f 1 | cut -c 1-8`
971 PartNum=`grep "$InstallDir" /etc/mtab | cut -d " " -f 1 | cut -c 9-10`
972 EntryFilename="$TargetDir/$Refind"
973 EfiEntryFilename=`echo ${EntryFilename//\//\\\}`
974 EfiEntryFilename2=`echo ${EfiEntryFilename} | sed s/\\\\\\\\/\\\\\\\\\\\\\\\\/g`
975 ExistingEntry=`"$Efibootmgr" -v | grep -i "$EfiEntryFilename2"`
976
977 if [[ "$ExistingEntry" ]] ; then
978 ExistingEntryBootNum=`echo "$ExistingEntry" | cut -c 5-8`
979 FirstBoot=`"$Efibootmgr" | grep BootOrder | cut -c 12-15`
980 if [[ "$ExistingEntryBootNum" != "$FirstBoot" ]] ; then
981 echo "An existing rEFInd boot entry exists, but isn't set as the default boot"
982 echo "manager. The boot order is being adjusted to make rEFInd the default boot"
983 echo "manager. If this is NOT what you want, you should use efibootmgr to"
984 echo "manually adjust your EFI's boot order."
985 fi
986 "$Efibootmgr" -b $ExistingEntryBootNum -B &> /dev/null
987 fi
988
989 echo "Installing it!"
990 if [[ "$KeepName" == 0 ]] ; then
991 "$Efibootmgr" -c -l "$EfiEntryFilename" -L "rEFInd Boot Manager" -d $InstallDisk -p $PartNum &> /dev/null
992 else
993 "$Efibootmgr" -c -l "$EfiEntryFilename" -L "rEFInd Boot Manager" -d $InstallDisk -p $PartNum \
994 -u "$TargetShim $TargetX64" &> /dev/null
995 fi
996 if [[ $? != 0 ]] ; then
997 EfibootmgrProblems=1
998 Problems=1
999 fi
1000
1001 else # efibootmgr not found
1002 EfibootmgrProblems=1
1003 Problems=1
1004 fi
1005
1006 if [[ $EfibootmgrProblems ]] ; then
1007 echo
1008 echo "ALERT: There were problems running the efibootmgr program! You may need to"
1009 echo "rename the $Refind binary to the default name (EFI/boot/bootx64.efi"
1010 echo "on x86-64 systems or EFI/boot/bootia32.efi on x86 systems) to have it run!"
1011 echo
1012 else
1013 echo "rEFInd has been set as the default boot manager."
1014 fi
1015 } # AddBootEntry()
1016
1017 # Create a minimal/sample refind_linux.conf file in /boot.
1018 GenerateRefindLinuxConf() {
1019 if [[ -f "$RLConfFile" ]] ; then
1020 echo "Existing $RLConfFile found; not overwriting."
1021 else
1022 echo "Creating $RLConfFile; edit it to adjust kernel options."
1023 if [[ -f "$RootDir/etc/default/grub" ]] ; then
1024 # We want the default options used by the distribution, stored here....
1025 source "$RootDir/etc/default/grub"
1026 echo "Setting default boot options based on $RootDir/etc/default/grub"
1027 fi
1028 RootFS=`df "$RootDir" | grep dev | cut -f 1 -d " "`
1029 StartOfDevname=`echo "$RootFS" | cut -b 1-7`
1030 if [[ "$StartOfDevname" == "/dev/sd" || "$StartOfDevName" == "/dev/hd" ]] ; then
1031 # Identify root filesystem by UUID rather than by device node, if possible
1032 Uuid=`blkid -o export -s UUID "$RootFS" 2> /dev/null | grep UUID=`
1033 if [[ -n $Uuid ]] ; then
1034 RootFS="$Uuid"
1035 fi
1036 fi
1037 DefaultOptions="$GRUB_CMDLINE_LINUX $GRUB_CMDLINE_LINUX_DEFAULT"
1038 echo "\"Boot with standard options\" \"ro root=$RootFS $DefaultOptions \"" > $RLConfFile
1039 echo "\"Boot to single-user mode\" \"ro root=$RootFS $DefaultOptions single\"" >> $RLConfFile
1040 echo "\"Boot with minimal options\" \"ro root=$RootFS\"" >> $RLConfFile
1041 fi
1042 }
1043
1044 # Controls rEFInd installation under Linux.
1045 # Sets Problems=1 if something goes wrong.
1046 InstallOnLinux() {
1047 if [[ "$TargetDir" == "/System/Library/CoreServices" ]] ; then
1048 echo "You may not use the --ownhfs option under Linux! Aborting!"
1049 exit 1
1050 fi
1051 echo "Installing rEFInd on Linux...."
1052 modprobe efivars &> /dev/null
1053 if [[ $TargetDir == "/EFI/BOOT" ]] ; then
1054 MountDefaultTarget
1055 else
1056 FindMountedESP
1057 DetermineTargetDir
1058 fi
1059 CpuType=`uname -m`
1060 if [[ $CpuType == 'x86_64' ]] ; then
1061 Platform="EFI64"
1062 elif [[ ($CpuType == 'i386' || $CpuType == 'i486' || $CpuType == 'i586' || $CpuType == 'i686') ]] ; then
1063 Platform="EFI32"
1064 # If we're in EFI mode, do some sanity checks, and alert the user or even
1065 # abort. Not in BIOS mode, though, since that could be used on an emergency
1066 # disc to try to recover a troubled Linux installation.
1067 if [[ -d /sys/firmware/efi ]] ; then
1068 if [[ "$ShimSource" != "none" && "$TargetDir" != "/BOOT/EFI" ]] ; then
1069 echo ""
1070 echo "CAUTION: shim does not currently supports 32-bit systems, so you should not"
1071 echo "use the --shim option to install on such systems. Aborting!"
1072 echo ""
1073 exit 1
1074 fi
1075 echo
1076 echo "CAUTION: This Linux installation uses a 32-bit kernel. 32-bit EFI-based"
1077 echo "computers are VERY RARE. If you've installed a 32-bit version of Linux"
1078 echo "on a 64-bit computer, you should manually install the 64-bit version of"
1079 echo "rEFInd. If you're installing on a Mac, you should do so from OS X. If"
1080 echo "you're positive you want to continue with this installation, answer 'Y'"
1081 echo "to the following question..."
1082 echo
1083 echo -n "Are you sure you want to continue (Y/N)? "
1084 ReadYesNo
1085 if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then
1086 echo "OK; continuing with the installation..."
1087 else
1088 exit 0
1089 fi
1090 fi # in EFI mode
1091 else
1092 echo "Unknown CPU type '$CpuType'; aborting!"
1093 exit 1
1094 fi
1095
1096 if [[ $LocalKeys == 1 ]] ; then
1097 ReSignBinaries
1098 fi
1099
1100 CheckSecureBoot
1101 CopyRefindFiles
1102 if [[ "$TargetDir" != "/EFI/BOOT" && "$TargetDir" != "/EFI/Microsoft/Boot" ]] ; then
1103 AddBootEntry
1104 GenerateRefindLinuxConf
1105 fi
1106 } # InstallOnLinux()
1107
1108 #
1109 # The main part of the script. Sets a few environment variables,
1110 # performs a few startup checks, and then calls functions to
1111 # install under OS X or Linux, depending on the detected platform.
1112 #
1113 GetParams "$@"
1114 ThisDir="$( cd -P "${BASH_SOURCE%/*}" && pwd )"
1115 RefindDir="$ThisDir/refind"
1116 if [[ $UID != 0 ]] ; then
1117 echo "Not running as root; attempting to elevate privileges via sudo...."
1118 sudo "$BASH_SOURCE" "$@"
1119 if [[ $? != 0 ]] ; then
1120 echo "This script must be run as root (or using sudo). Exiting!"
1121 exit 1
1122 else
1123 exit 0
1124 fi
1125 fi
1126 CheckForFiles
1127 case "$OSTYPE" in
1128 darwin*)
1129 if [[ "$ShimSource" != "none" ]] ; then
1130 echo "The --shim option is not supported on OS X! Exiting!"
1131 exit 1
1132 fi
1133 if [[ "$LocalKeys" != 0 ]] ; then
1134 echo "The --localkeys option is not supported on OS X! Exiting!"
1135 exit 1
1136 fi
1137 InstallOnOSX $1
1138 ;;
1139 linux-gnu)
1140 InstallOnLinux
1141 ;;
1142 *)
1143 echo "Running on unknown OS; aborting!"
1144 if [[ "$InstallToEspOnMac" == 0 ]] ; then
1145 echo "The --notesp option is not supported on Linux! Exiting!"
1146 exit 1
1147 fi
1148 esac
1149
1150 if [[ $Problems ]] ; then
1151 echo
1152 echo "ALERT:"
1153 echo "Installation has completed, but problems were detected. Review the output for"
1154 echo "error messages and take corrective measures as necessary. You may need to"
1155 echo "re-run this script or install manually before rEFInd will work."
1156 echo
1157 else
1158 echo
1159 echo "Installation has completed successfully."
1160 echo
1161 fi
1162
1163 if [[ $UnmountEsp == '1' ]] ; then
1164 echo "Unmounting install dir"
1165 umount $InstallDir
1166 fi
1167
1168 if [[ "$InstallDir" == /tmp/refind_install ]] ; then
1169 # sleep 5
1170 rmdir "$InstallDir"
1171 fi