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