3 # Linux/MacOS X script to install rEFInd
7 # ./install.sh [options]
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 # "--yes" to assume a "yes" response to all prompts
27 # The "esp" option is valid only on Mac OS X; it causes
28 # installation to the EFI System Partition (ESP) rather than
29 # to the current OS X boot partition. Under Linux, this script
30 # installs to the ESP by default.
32 # This program is copyright (c) 2012-2015 by Roderick W. Smith
33 # It is released under the terms of the GNU GPL, version 3,
34 # a copy of which should be included in the file COPYING.txt.
38 # 0.8.7 -- Better detection of Secure Boot mode & fixed errors when copying
39 # Shim & MokManager files over themselves.
40 # 0.8.6 -- Fixed bugs that caused misidentification of ESP on disks with
41 # partition numbers over 10 on OS X and misidentification of mount
42 # point if already-mounted ESP had space in path.
43 # 0.8.5 -- Refinement/cleanup of new OS X ESP-as-default policy
44 # 0.8.4 -- OS X default changed to install to ESP under /EFI/BOOT
45 # 0.7.9 -- Fixed bug that caused errors if dmraid utility not installed
46 # 0.7.7 -- Fixed bug that created mangled refind_linux.conf file; added ability
47 # to locate and mount ESP on Linux, if it's not mounted
48 # 0.7.6 -- Added --ownhfs {device-filename} option
49 # 0.7.5 -- Fixed bug when installing to ESP on recent versions of OS X
50 # 0.7.2 -- Fixed code that could be confused by use of autofs to mount the ESP
51 # 0.7.0 -- Added support for the new Btrfs driver
52 # 0.6.12 -- Added support for PreLoader as well as for shim
53 # 0.6.11 -- Improvements in script's ability to handle directories with spaces
55 # 0.6.9 -- Install gptsync on Macs
56 # 0.6.8 -- Bug fix: ESP scan now uses "uniq".
57 # 0.6.6 -- Bug fix: Upgrade drivers when installed to EFI/BOOT. Also enable
58 # copying shim.efi and MokManager.efi over themselves.
59 # 0.6.4 -- Copies ext2 driver rather than ext4 driver for ext2/3fs
60 # 0.6.3 -- Support for detecting rEFInd in EFI/BOOT and EFI/Microsoft/Boot
61 # directories & for installing to EFI/BOOT in BIOS mode
62 # 0.6.2-1 -- Added --yes option & tweaked key-copying for use with RPM install script
63 # 0.6.1 -- Added --root option; minor bug fixes
64 # 0.6.0 -- Changed --drivers to --alldrivers and added --nodrivers option;
65 # changed default driver installation behavior in Linux to install
66 # the driver needed to read /boot (if available)
67 # 0.5.1.2 -- Fixed bug that caused failure to generate refind_linux.conf file
68 # 0.5.1.1 -- Fixed bug that caused script failure under OS X
69 # 0.5.1 -- Added --shim & --localkeys options & create sample refind_linux.conf
71 # 0.5.0 -- Added --usedefault & --drivers options & changed "esp" option to "--esp"
72 # 0.4.5 -- Fixed check for rEFItBlesser in OS X
73 # 0.4.2 -- Added notice about BIOS-based OSes & made NVRAM changes in Linux smarter
74 # 0.4.1 -- Added check for rEFItBlesser in OS X
75 # 0.3.3.1 -- Fixed OS X 10.7 bug; also works as make target
76 # 0.3.2.1 -- Check for presence of source files; aborts if not present
77 # 0.3.2 -- Initial version
79 # Note: install.sh version numbers match those of the rEFInd package
80 # with which they first appeared.
84 LocalKeysBase
="refind_local"
88 TargetX64
="refind_x64.efi"
89 TargetIA32
="refind_ia32.efi"
95 # Functions used by both OS X and Linux....
100 # Install the driver required to read Linux /boot, if it's available
101 # Note: Under OS X, this will be installed only if a Linux partition
102 # is detected, in which case the ext4fs driver will be installed.
103 InstallDrivers
="boot"
104 while [[ $# -gt 0 ]]; do
106 --notesp) InstallToEspOnMac
=0
111 TargetDir
=/System
/Library
/CoreServices
114 --usedefault) TargetDir
=/EFI
/BOOT
116 TargetX64
="bootx64.efi"
117 TargetIA32
="bootia32.efi"
124 --localkeys) LocalKeys
=1
126 --shim |
--preloader) ShimSource
="$2"
127 ShimType
=`basename $ShimSource`
130 --drivers |
--alldrivers) InstallDrivers
="all"
132 --nodrivers) InstallDrivers
="none"
136 * ) echo "Usage: $0 [--notesp | --usedefault {device-file} | --root {dir} |"
137 echo " --ownhfs {device-file} ]"
138 echo " [--nodrivers | --alldrivers] [--shim {shim-filename}]"
139 echo " [--localkeys] [--yes]"
144 if [[ "$InstallToEspOnMac" == 0 && "$RootDir" == '/' && "$TargetDir" == '/EFI/BOOT' ]] ; then
145 echo "You may use --notesp OR --usedefault, but not both! Aborting!"
148 if [[ "$RootDir" != '/' && "$TargetDir" == '/EFI/BOOT' ]] ; then
149 echo "You may use --root OR --usedefault, but not both! Aborting!"
152 if [[ "$TargetDir" != '/System/Library/CoreServices' && "$OwnHfs" == '1' ]] ; then
153 echo "If you use --ownhfs, you may NOT use --usedefault! Aborting!"
156 RLConfFile
="$RootDir/boot/refind_linux.conf"
157 EtcKeysDir
="$RootDir/etc/refind.d/keys"
160 # Get a yes/no response from the user and place it in the YesNo variable.
161 # If the AlwaysYes variable is set to 1, skip the user input and set "Y"
162 # in the YesNo variable.
164 if [[ $AlwaysYes == 1 ]] ; then
172 # Abort if the rEFInd files can't be found.
173 # Also sets $ConfFile to point to the configuration file,
174 # $IconsDir to point to the icons directory, and
175 # $ShimSource to the source of the shim.efi file (if necessary).
177 # Note: This check is satisfied if EITHER the 32- or the 64-bit version
178 # is found, even on the wrong platform. This is because the platform
179 # hasn't yet been determined. This could obviously be improved, but it
180 # would mean restructuring lots more code....
181 if [[ ! -f "$RefindDir/refind_ia32.efi" && ! -f "$RefindDir/refind_x64.efi" ]] ; then
182 echo "The rEFInd binary file is missing! Aborting installation!"
186 if [[ -f "$RefindDir/refind.conf-sample" ]] ; then
187 ConfFile
="$RefindDir/refind.conf-sample"
188 elif [[ -f "$ThisDir/refind.conf-sample" ]] ; then
189 ConfFile
="$ThisDir/refind.conf-sample"
191 echo "The sample configuration file is missing! Aborting installation!"
195 if [[ -d "$RefindDir/icons" ]] ; then
196 IconsDir
="$RefindDir/icons"
197 elif [[ -d "$ThisDir/icons" ]] ; then
198 IconsDir
="$ThisDir/icons"
200 echo "The icons directory is missing! Aborting installation!"
204 if [[ "$ShimSource" != "none" ]] ; then
205 if [[ -f "$ShimSource" ]] ; then
206 if [[ $ShimType == "shimx64.efi" ||
$ShimType == "shim.efi" ]] ; then
207 TargetX64
="grubx64.efi"
208 MokManagerSource
=`dirname "$ShimSource"`/MokManager.efi
209 elif [[ $ShimType == "preloader.efi" ||
$ShimType == "PreLoader.efi" ]] ; then
210 TargetX64
="loader.efi"
211 MokManagerSource
=`dirname "$ShimSource"`/HashTool.efi
213 echo "Unknown shim/PreBootloader filename: $ShimType!"
214 echo "Known filenames are shimx64.efi, shim.efi, and PreLoader.efi. Aborting!"
218 echo "The specified shim/PreBootloader file, $ShimSource, doesn't exist!"
219 echo "Aborting installation!"
225 # Helper for CopyRefindFiles; copies shim files (including MokManager, if it's
226 # available) to target.
228 local inode1
=`ls -i "$ShimSource" | cut -f 1 -d " "`
229 local inode2
=`ls -i "$InstallDir/$TargetDir/$TargetShim" | cut -f 1 -d " "`
230 if [[ $inode1 != $inode2 ]] ; then
231 cp -fb "$ShimSource" "$InstallDir/$TargetDir/$TargetShim"
232 if [[ $?
!= 0 ]] ; then
236 inode1
= `ls -i "$MokManagerSource" | cut -f 1 -d " "`
237 local TargetMMName
=`basename $MokManagerSource`
238 inode2
= `ls -i "$InstallDir/$TargetDir/$TargetShim/$TargetMMName" | cut -f 1 -d " "`
239 if [[ $inode1 != $inode2 ]] ; then
240 if [[ -f "$MokManagerSource" ]] ; then
241 cp -fb "$MokManagerSource" "$InstallDir/$TargetDir/"
243 if [[ $?
!= 0 ]] ; then
249 # Copy the public keys to the installation medium
251 if [[ $LocalKeys == 1 ]] ; then
252 mkdir
-p "$InstallDir/$TargetDir/keys/"
253 cp "$EtcKeysDir/$LocalKeysBase.cer" "$InstallDir/$TargetDir/keys/"
254 cp "$EtcKeysDir/$LocalKeysBase.crt" "$InstallDir/$TargetDir/keys/"
258 # Set varaibles for installation in EFI/BOOT directory
260 TargetDir
="/EFI/BOOT"
261 if [[ $ShimSource == "none" ]] ; then
262 TargetX64
="bootx64.efi"
263 TargetIA32
="bootia32.efi"
265 if [[ $ShimType == "shim.efi" ||
$ShimType == "shimx64.efi" ]] ; then
266 TargetX64
="grubx64.efi"
267 elif [[ $ShimType == "preloader.efi" ||
$ShimType == "PreLoader.efi" ]] ; then
268 TargetX64
="loader.efi"
270 echo "Unknown shim/PreBootloader type: $ShimType"
274 TargetIA32
="bootia32.efi"
275 TargetShim
="bootx64.efi"
279 # Set variables for installation in EFI/Microsoft/Boot directory
281 TargetDir
="/EFI/Microsoft/Boot"
282 if [[ $ShimSource == "none" ]] ; then
283 TargetX64
="bootmgfw.efi"
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"
290 echo "Unknown shim/PreBootloader type: $ShimType"
294 TargetShim
="bootmgfw.efi"
296 } # SetVarsForMsBoot()
298 # TargetDir defaults to /EFI/refind; however, this function adjusts it as follows:
299 # - If an existing refind.conf is available in /EFI/BOOT or /EFI/Microsoft/Boot,
300 # install to that directory under the suitable name; but DO NOT do this if
301 # refind.conf is also in /EFI/refind.
302 # - If booted in BIOS mode and the ESP lacks any other EFI files, install to
304 # - If booted in BIOS mode and there's no refind.conf file and there is a
305 # /EFI/Microsoft/Boot/bootmgfw.efi file, move it down one level and
306 # install under that name, "hijacking" the Windows boot loader filename
307 DetermineTargetDir
() {
310 if [[ -f $InstallDir/EFI
/BOOT
/refind.conf
]] ; then
314 if [[ -f $InstallDir/EFI
/Microsoft
/Boot
/refind.conf
]] ; then
318 if [[ -f $InstallDir/EFI
/refind
/refind.conf
]] ; then
319 TargetDir
="/EFI/refind"
320 if [[ "$OSName" == 'Darwin' ]] ; then
321 TargetX64
="refind_x64.efi"
322 TargetIA32
="refind_ia32.efi"
326 if [[ $Upgrade == 1 ]] ; then
327 echo "Found rEFInd installation in $InstallDir$TargetDir; upgrading it."
330 if [[ ! -d /sys
/firmware
/efi
&& ! $OSName == 'Darwin' && $Upgrade == 0 ]] ; then # BIOS-mode
331 FoundEfiFiles
=`find "$InstallDir/EFI/BOOT" -name "*.efi" 2> /dev/null`
332 FoundConfFiles
=`find "$InstallDir" -name "refind\.conf" 2> /dev/null`
333 if [[ ! -n "$FoundConfFiles" && -f "$InstallDir/EFI/Microsoft/Boot/bootmgfw.efi" ]] ; then
334 mv -n "$InstallDir/EFI/Microsoft/Boot/bootmgfw.efi" "$InstallDir/EFI/Microsoft" &> /dev
/null
336 echo "Running in BIOS mode with a suspected Windows installation; moving boot loader"
337 echo "files so as to install to $InstallDir$TargetDir."
338 elif [[ ! -n "$FoundEfiFiles" ]] ; then # In BIOS mode and no default loader; install as default loader
340 echo "Running in BIOS mode with no existing default boot loader; installing to"
341 echo $InstallDir$TargetDir
343 echo "Running in BIOS mode with an existing default boot loader; backing it up and"
344 echo "installing rEFInd in its place."
345 if [[ -d "$InstallDir/EFI/BOOT-rEFIndBackup" ]] ; then
347 echo "Caution: An existing backup of a default boot loader exists! If the current"
348 echo "default boot loader and the backup are different boot loaders, the current"
349 echo "one will become inaccessible."
351 echo -n "Do you want to proceed with installation (Y/N)? "
353 if [[ $YesNo == "Y" ||
$YesNo == "y" ]] ; then
354 echo "OK; continuing with the installation..."
359 mv -n "$InstallDir/EFI/BOOT" "$InstallDir/EFI/BOOT-rEFIndBackup"
363 } # DetermineTargetDir()
365 # Determine (or guess) the filesystem used on the Linux /boot filesystem.
366 # Store the result in the BootFS global variable.
370 Blkid
=`which blkid 2> /dev/null`
372 if [[ $OSName == 'Linux' && -x "$Blkid" ]] ; then
373 BootPart
=`df /boot | grep dev | cut -f 1 -d " "`
374 BootFS
=`$Blkid -o export $BootPart 2> /dev/null | grep TYPE= | cut -f 2 -d =`
376 if [[ $OSName == 'Darwin' ]] ; then
377 # 0FC63DAF-8483-4772-8E79-3D69D8477DE4 = Linux filesystem
378 # BC13C2FF-59E6-4262-A352-B275FD6F7172 = Freedesktop $boot partition
379 # 933AC7E1-2EB4-4F13-B844-0E14E2AEF915 = Freedesktop Linux /home
380 # E6D6D379-F507-44C2-A23C-238F2A3DF928 = Linux LVM
381 # A19D880F-05FC-4D3B-A006-743F0F84911E = Linux RAID
382 # 0657FD6D-A4AB-43C4-84E5-0933C84B4F4F = Linux swap
383 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')
385 if [[ -n $Temp ]] ; then
386 echo "Found suspected Linux partition(s); installing ext4fs driver."
392 # Copy drivers from $RefindDir/drivers_$1 to $InstallDir/$TargetDir/drivers_$1,
393 # honoring the $InstallDrivers condition. Must be passed a suitable
394 # architecture code (ia32 or x64).
396 if [[ $InstallDrivers == "all" ]] ; then
397 mkdir
-p "$InstallDir/$TargetDir/drivers_$1"
398 cp "$ThisDir"/drivers_
$1/*_
$1.efi
"$InstallDir/$TargetDir/drivers_$1/" 2> /dev
/null
399 cp "$RefindDir"/drivers_
$1/*_
$1.efi
"$InstallDir/$TargetDir/drivers_$1/" 2> /dev
/null
400 elif [[ "$InstallDrivers" == "boot" ]] ; then
404 ext2 | ext3
) DriverType
="ext2"
405 # Could use ext4, but that can create unwanted entries from symbolic
406 # links in / to /boot/vmlinuz if a separate /boot partition is used.
408 ext4
) DriverType
="ext4"
410 reiserfs
) DriverType
="reiserfs"
412 btrfs
) DriverType
="btrfs"
414 hfsplus
) DriverType
="hfs"
416 ntfs
) DriverType
="ntfs"
420 if [[ -n $BootFS ]] ; then
421 echo "Installing driver for $BootFS (${DriverType}_$1.efi)"
422 mkdir
-p "$InstallDir/$TargetDir/drivers_$1"
423 cp "$ThisDir/drivers_$1/${DriverType}_$1.efi" "$InstallDir/$TargetDir/drivers_$1/" 2> /dev
/null
424 cp "$RefindDir/drivers_$1/${DriverType}_$1.efi" "$InstallDir/$TargetDir/drivers_$1"/ 2> /dev
/null
429 # Copy tools (currently only gptsync, and that only on Macs) to the EFI/tools
430 # directory on the ESP. Must be passed a suitable architecture code (ia32
433 mkdir
-p "$InstallDir/EFI/tools"
434 if [[ $OSName == 'Darwin' ]] ; then
435 cp -f "$RefindDir/tools_$1/gptsync_$1.efi" "$InstallDir/EFI/tools/"
436 if [[ -f "$InstallDir/EFI/tools/gptsync.efi" ]] ; then
437 mv "$InstallDir/EFI/tools/gptsync.efi" "$InstallDir/EFI/tools/gptsync.efi-disabled"
438 echo "Found old gptsync.efi; disabling it by renaming it to gptsync.efi-disabled"
443 # Copy the rEFInd files to the ESP or OS X root partition.
444 # Sets Problems=1 if any critical commands fail.
446 mkdir
-p "$InstallDir/$TargetDir"
447 if [[ "$TargetDir" == '/EFI/BOOT' ]] ; then
448 cp "$RefindDir/refind_ia32.efi" "$InstallDir/$TargetDir/$TargetIA32" 2> /dev
/null
449 if [[ $?
!= 0 ]] ; then
450 echo "Note: IA32 (x86) binary not installed!"
452 cp "$RefindDir/refind_x64.efi" "$InstallDir/$TargetDir/$TargetX64" 2> /dev
/null
453 if [[ $?
!= 0 ]] ; then
456 if [[ "$ShimSource" != "none" ]] ; then
457 TargetShim
="bootx64.efi"
460 if [[ $InstallDrivers == "all" ]] ; then
461 cp -r "$RefindDir"/drivers_
* "$InstallDir/$TargetDir/" 2> /dev
/null
462 cp -r "$ThisDir"/drivers_
* "$InstallDir/$TargetDir/" 2> /dev
/null
463 elif [[ $Upgrade == 1 ||
$InstallToEspOnMac == 1 ]] ; then
464 if [[ $Platform == 'EFI64' ]] ; then
473 if [[ $Platform == 'EFI64' ]] ; then
475 elif [[ $Platform == 'EFI32' ]] ; then
476 Refind
='bootia32.efi'
479 elif [[ $Platform == 'EFI64' ||
$TargetDir == "/EFI/Microsoft/Boot" ]] ; then
480 cp "$RefindDir/refind_x64.efi" "$InstallDir/$TargetDir/$TargetX64"
481 if [[ $?
!= 0 ]] ; then
486 Refind
="refind_x64.efi"
488 if [[ "$ShimSource" != "none" ]] ; then
489 if [[ "$TargetShim" == "default" ]] ; then
490 TargetShim
=`basename "$ShimSource"`
494 if [[ $LocalKeys == 0 ]] ; then
495 echo "Storing copies of rEFInd Secure Boot public keys in $EtcKeysDir"
496 mkdir
-p "$EtcKeysDir"
497 cp "$ThisDir/keys/refind.cer" "$EtcKeysDir" 2> /dev
/null
498 cp "$ThisDir/keys/refind.crt" "$EtcKeysDir" 2> /dev
/null
501 if [[ "$TargetDir" == '/System/Library/CoreServices' ]] ; then
502 SetupMacHfs
$TargetX64
504 elif [[ $Platform == 'EFI32' ]] ; then
505 cp "$RefindDir/refind_ia32.efi" "$InstallDir/$TargetDir/$TargetIA32"
506 if [[ $?
!= 0 ]] ; then
511 Refind
="refind_ia32.efi"
512 if [[ "$TargetDir" == '/System/Library/CoreServices' ]] ; then
513 SetupMacHfs
$TargetIA32
516 echo "Unknown platform! Aborting!"
519 echo "Copied rEFInd binary files"
521 if [[ -d "$InstallDir/$TargetDir/icons" ]] ; then
522 rm -rf "$InstallDir/$TargetDir/icons-backup" &> /dev
/null
523 mv -f "$InstallDir/$TargetDir/icons" "$InstallDir/$TargetDir/icons-backup"
524 echo "Notice: Backed up existing icons directory as icons-backup."
526 cp -r "$IconsDir" "$InstallDir/$TargetDir"
527 if [[ $?
!= 0 ]] ; then
530 mkdir
-p "$InstallDir/$TargetDir/keys"
531 cp -rf "$ThisDir"/keys
/*.
[cd]er
"$InstallDir/$TargetDir/keys/" 2> /dev
/null
532 cp -rf "$EtcKeysDir"/*.
[cd]er
"$InstallDir/$TargetDir/keys/" 2> /dev
/null
533 if [[ -f "$InstallDir/$TargetDir/refind.conf" ]] ; then
534 echo "Existing refind.conf file found; copying sample file as refind.conf-sample"
535 echo "to avoid overwriting your customizations."
537 cp -f "$ConfFile" "$InstallDir/$TargetDir"
538 if [[ $?
!= 0 ]] ; then
542 echo "Copying sample configuration file as refind.conf; edit this file to configure"
545 cp -f "$ConfFile" "$InstallDir/$TargetDir/refind.conf"
546 if [[ $?
!= 0 ]] ; then
550 if [[ $DeleteRefindDir == 1 ]] ; then
551 echo "Deleting the temporary directory $RefindDir"
554 } # CopyRefindFiles()
556 # Mount the partition the user specified with the --usedefault or --ownhfs option
557 MountDefaultTarget
() {
558 InstallDir
=/tmp
/refind_install
559 mkdir
-p "$InstallDir"
561 if [[ $OSName == 'Darwin' ]] ; then
562 if [[ $OwnHfs == '1' ]] ; then
563 Temp
=`diskutil info "$TargetPart" | grep "Mount Point"`
564 InstallDir
=`echo $Temp | cut -f 3-30 -d ' '`
565 if [[ $InstallDir == '' ]] ; then
566 InstallDir
=/tmp
/refind_install
567 mount
-t hfs
"$TargetPart" "$InstallDir"
572 mount
-t msdos
"$TargetPart" "$InstallDir"
574 elif [[ $OSName == 'Linux' ]] ; then
575 mount
-t vfat
"$TargetPart" "$InstallDir"
577 if [[ $?
!= 0 ]] ; then
578 echo "Couldn't mount $TargetPart ! Aborting!"
582 } # MountDefaultTarget()
585 # A series of OS X support functions....
588 # Mount the ESP at /Volumes/ESP or determine its current mount
590 # Sets InstallDir to the ESP mount point
591 # Sets UnmountEsp if we mounted it
593 # Identify the ESP. Note: This returns the FIRST ESP found;
594 # if the system has multiple disks, this could be wrong!
595 Temp
=$
(mount |
sed -n -E "/^(\/dev\/disk[0-9]+s[0-9]+) on \/ \(.*$/s//\1/p")
597 Temp
=$
(diskutil list |
grep " EFI " |
grep -o 'disk.*' |
head -n 1)
598 if [ -z $Temp ]; then
599 echo "Warning: root device doesn't have an EFI partition"
602 echo "Warning: root device could not be found"
604 if [ -z $Temp ]; then
605 Temp
=$
(diskutil list |
sed -n -E '/^ *[0-9]+:[ ]+EFI EFI[ ]+[0-9.]+ [A-Z]+[ ]+(disk[0-9]+s[0-9]+)$/ { s//\1/p
609 if [ -z $Temp ]; then
610 echo "Could not find an EFI partition. Aborting!"
614 Esp
=/dev
/`echo $Temp`
615 # If the ESP is mounted, use its current mount point....
616 Temp
=`df -P | grep "$Esp "`
617 InstallDir
=`echo $Temp | cut -f 6- -d ' '`
618 if [[ "$InstallDir" == '' ]] ; then
619 mkdir
/Volumes
/ESP
&> /dev
/null
620 mount
-t msdos
"$Esp" /Volumes
/ESP
621 # Some systems have HFS+ "ESPs." They shouldn't, but they do. If this is
622 # detected, mount it as such and set appropriate options.
623 if [[ $?
!= 0 ]] ; then
624 mount
-t hfs
"$Esp" /Volumes
/Esp
627 if [[ $?
!= 0 ]] ; then
628 echo "Unable to mount ESP! Aborting!\n"
633 InstallDir
="/Volumes/ESP"
637 # Set up for booting from Mac HFS+ volume that boots rEFInd in MJG's way
638 # (http://mjg59.dreamwidth.org/7468.html)
639 # Must be passed the original rEFInd binary filename (without a path).
641 if [[ -s "$InstallDir/mach_kernel" ]] ; then
642 echo "Attempt to install rEFInd to a partition with a /mach_kernel file! Aborting!"
645 cp -n "$InstallDir/$TargetDir/boot.efi" "$InstallDir/$TargetDir/boot.efi-backup" &> /dev
/null
646 ln -f "$InstallDir/$TargetDir/$1" "$InstallDir/$TargetDir/boot.efi"
647 touch "$InstallDir/mach_kernel"
648 rm "$InstallDir/$TargetDir/SystemVersion.plist" &> /dev
/null
649 cat - << ENDOFHERE >> "$InstallDir/$TargetDir/SystemVersion.plist"
650 <xml version="1.0" encoding="UTF-8"?>
651 <plist version="1.0">
653 <key>ProductBuildVersion</key>
655 <key>ProductName</key>
656 <string>rEFInd</string>
657 <key>ProductVersion</key>
658 <string>0.8.6</string>
664 # Control the OS X installation.
665 # Sets Problems=1 if problems found during the installation.
667 echo "Installing rEFInd on OS X...."
668 if [[ "$InstallToEspOnMac" == "1" ]] ; then
670 elif [[ "$TargetDir" == "/EFI/BOOT" ||
"$OwnHfs" == '1' ]] ; then
673 InstallDir
="$RootDir/"
675 echo "Installing rEFInd to the partition mounted at $InstallDir"
677 Platform
=`ioreg -l -p IODeviceTree | grep firmware-abi | cut -d "\"" -f 4`
679 if [[ $InstallToEspOnMac == "1" ]] ; then
680 bless
--mount "$InstallDir" --setBoot --file "$InstallDir/$TargetDir/$Refind" --shortform
681 elif [[ "$TargetDir" != "/EFI/BOOT" ]] ; then
682 bless
--setBoot --folder "$InstallDir/$TargetDir" --file "$InstallDir/$TargetDir/$Refind"
684 if [[ $?
!= 0 ]] ; then
687 if [[ -f /Library
/StartupItems
/rEFItBlesser ||
-d /Library
/StartupItems
/rEFItBlesser
]] ; then
689 echo "/Library/StartupItems/rEFItBlesser found!"
690 echo "This program is part of rEFIt, and will cause rEFInd to fail to work after"
691 echo -n "its first boot. Do you want to remove rEFItBlesser (Y/N)? "
693 if [[ $YesNo == "Y" ||
$YesNo == "y" ]] ; then
694 echo "Deleting /Library/StartupItems/rEFItBlesser..."
695 rm -r /Library
/StartupItems
/rEFItBlesser
697 echo "Not deleting rEFItBlesser."
701 echo "WARNING: If you have an Advanced Format disk, *DO NOT* attempt to check the"
702 echo "bless status with 'bless --info', since this is known to cause disk corruption"
703 echo "on some systems!!"
709 # Now a series of Linux support functions....
712 # Check for evidence that we're running in Secure Boot mode. If so, and if
713 # appropriate options haven't been set, warn the user and offer to abort.
714 # If we're NOT in Secure Boot mode but the user HAS specified the --shim
715 # or --localkeys option, warn the user and offer to abort.
718 if [[ -f /sys
/firmware
/efi
/vars
/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c
/data
]] ; then
719 IsSecureBoot
=`od -An -t u1 /sys/firmware/efi/vars/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c/data | tr -d '[[:space:]]'`
723 if [[ $IsSecureBoot == "1" && "$TargetDir" != '/EFI/BOOT' && "$ShimSource" == "none" ]] ; then
725 echo "CAUTION: Your computer appears to be booted with Secure Boot, but you haven't"
726 echo "specified a valid shim.efi file source. Chances are you should re-run with"
727 echo "the --shim option. You can read more about this topic at"
728 echo "http://www.rodsbooks.com/refind/secureboot.html."
730 echo -n "Do you want to proceed with installation (Y/N)? "
732 if [[ $YesNo == "Y" ||
$YesNo == "y" ]] ; then
733 echo "OK; continuing with the installation..."
739 if [[ "$ShimSource" != "none" && ! $IsSecureBoot == "1" ]] ; then
741 echo "You've specified installing using a shim.efi file, but your computer does not"
742 echo "appear to be running in Secure Boot mode. Although installing in this way"
743 echo "should work, it's unnecessarily complex. You may continue, but unless you"
744 echo "plan to enable Secure Boot, you should consider stopping and omitting the"
745 echo "--shim option. You can read more about this topic at"
746 echo "http://www.rodsbooks.com/refind/secureboot.html."
748 echo -n "Do you want to proceed with installation (Y/N)? "
750 if [[ $YesNo == "Y" ||
$YesNo == "y" ]] ; then
751 echo "OK; continuing with the installation..."
757 if [[ $LocalKeys != 0 && ! $IsSecureBoot == "1" ]] ; then
759 echo "You've specified re-signing your rEFInd binaries with locally-generated keys,"
760 echo "but your computer does not appear to be running in Secure Boot mode. The"
761 echo "keys you generate will be useless unless you enable Secure Boot. You may"
762 echo "proceed with this installation, but before you do so, you may want to read"
763 echo "more about it at http://www.rodsbooks.com/refind/secureboot.html."
765 echo -n "Do you want to proceed with installation (Y/N)? "
767 if [[ $YesNo == "Y" ||
$YesNo == "y" ]] ; then
768 echo "OK; continuing with the installation..."
774 } # CheckSecureBoot()
776 # Check for the presence of locally-generated keys from a previous installation in
777 # $EtcKeysDir (/etc/refind.d/keys). If they're not present, generate them using
780 PrivateKey
="$EtcKeysDir/$LocalKeysBase.key"
781 CertKey
="$EtcKeysDir/$LocalKeysBase.crt"
782 DerKey
="$EtcKeysDir/$LocalKeysBase.cer"
783 OpenSSL
=`which openssl 2> /dev/null`
785 # Do the work only if one or more of the necessary keys is missing
786 # TODO: Technically, we don't need the DerKey; but if it's missing and openssl
787 # is also missing, this will fail. This could be improved.
788 if [[ ! -f "$PrivateKey" ||
! -f "$CertKey" ||
! -f "$DerKey" ]] ; then
789 echo "Generating a fresh set of local keys...."
790 mkdir
-p "$EtcKeysDir"
791 chmod 0700 "$EtcKeysDir"
792 if [[ ! -x "$OpenSSL" ]] ; then
793 echo "Can't find openssl, which is required to create your private signing keys!"
797 if [[ -f "$PrivateKey" ]] ; then
798 echo "Backing up existing $PrivateKey"
799 cp -f "$PrivateKey" "$PrivateKey.backup" 2> /dev
/null
801 if [[ -f "$CertKey" ]] ; then
802 echo "Backing up existing $CertKey"
803 cp -f "$CertKey" "$CertKey.backup" 2> /dev
/null
805 if [[ -f "$DerKey" ]] ; then
806 echo "Backing up existing $DerKey"
807 cp -f "$DerKey" "$DerKey.backup" 2> /dev
/null
809 "$OpenSSL" req
-new -x509 -newkey rsa
:2048 -keyout "$PrivateKey" -out "$CertKey" \
810 -nodes -days 3650 -subj "/CN=Locally-generated rEFInd key/"
811 "$OpenSSL" x509
-in "$CertKey" -out "$DerKey" -outform DER
812 chmod 0600 "$PrivateKey"
814 echo "Using existing local keys...."
818 # Sign a single binary. Requires parameters:
820 # $2 = destination file
821 # Also assumes that the SBSign, PESign, UseSBSign, UsePESign, and various key variables are set
823 # Aborts script on error
825 $SBSign --key "$PrivateKey" --cert "$CertKey" --output "$2" "$1"
826 if [[ $?
!= 0 ]] ; then
827 echo "Problem signing the binary $1! Aborting!"
832 # Re-sign the x86-64 binaries with a locally-generated key, First look for appropriate
833 # key files in $EtcKeysDir. If they're present, use them to re-sign the binaries. If
834 # not, try to generate new keys and store them in $EtcKeysDir.
836 SBSign
=`which sbsign 2> /dev/null`
837 echo "Found sbsign at $SBSign"
838 TempDir
="/tmp/refind_local"
839 if [[ ! -x "$SBSign" ]] ; then
840 echo "Can't find sbsign, which is required to sign rEFInd with your own keys!"
845 mkdir
-p "$TempDir/drivers_x64"
846 cp "$RefindDir/refind.conf-sample $TempDir" 2> /dev
/null
847 cp "$ThisDir/refind.conf-sample $TempDir" 2> /dev
/null
848 cp "$RefindDir/refind_ia32.efi $TempDir" 2> /dev
/null
849 cp -a "$RefindDir/drivers_ia32 $TempDir" 2> /dev
/null
850 cp -a "$ThisDir/drivers_ia32 $TempDir" 2> /dev
/null
851 SignOneBinary
"$RefindDir/refind_x64.efi" "$TempDir/refind_x64.efi"
853 IFS
=$
(echo -en "\n\b")
854 for Driver
in `ls "$RefindDir"/drivers_x64/*.efi "$ThisDir"/drivers_x64/*.efi 2> /dev/null` ; do
855 TempName
=`basename "$Driver"`
856 SignOneBinary
"$Driver" "$TempDir/drivers_x64/$TempName"
863 # Locate and mount an ESP, if possible, based on parted output.
864 # Should be called only if /boot/efi is NOT an acceptable ESP.
865 # Sets InstallDir to the mounted ESP's path ($RootDir/boot/efi)
866 # and EspFilesystem the filesystem (always "vfat")
868 echo "The ESP doesn't seem to be mounted! Trying to find it...."
875 for Drive
in `ls /dev/[sh]d?` ; do
877 Dmraid
=`which dmraid 2> /dev/null`
878 if [ -x "$Dmraid" ] ; then
879 DmStatus
=`dmraid -r | grep $Drive`
880 if [ -n "$DmStatus" ] ; then
881 echo "$Drive seems to be part of a RAID array; skipping!"
885 TableType
=`parted $Drive print -m -s 2>/dev/null | awk -F: '$1 == "'$Drive'" { print $6 }'`
886 if [[ $TableType == 'gpt' && $SkipIt == 0 ]] ; then # read only GPT disks that aren't part of dmraid array
887 PartNum
=`LANG=C parted $Drive print -m -s 2>/dev/null | awk -F: '$7 ~ "(^boot| boot)" { print $1 }' | head -n 1`
888 if [ "$PartNum" -eq "$PartNum" ] 2> /dev
/null
; then
889 InstallDir
="$RootDir/boot/efi"
891 mount
$Drive$PartNum $InstallDir
892 EspFilesystem
=`grep "$Drive$PartNum.*/boot/efi" /etc/mtab | uniq | grep -v autofs | cut -d " " -f 3`
893 if [[ $EspFilesystem != 'vfat' ]] ; then
896 echo "Mounting ESP at $InstallDir"
899 fi # $PartNum -eq $PartNum
904 # Identifies the ESP's location (/boot or /boot/efi, or these locations under
905 # the directory specified by --root); aborts if the ESP isn't mounted at
907 # Sets InstallDir to the ESP mount point.
909 mount
/boot
&> /dev
/null
910 mount
/boot
/efi
&> /dev
/null
911 EspLine
=`df "$RootDir/boot/efi" 2> /dev/null | grep boot/efi`
912 if [[ ! -n "$EspLine" ]] ; then
913 EspLine
=`df "$RootDir"/boot | grep boot`
915 InstallDir
=`echo $EspLine | cut -d " " -f 6`
917 if [[ -n "$InstallDir" ]] ; then
918 EspFilesystem
=`grep -w "$InstallDir" /etc/mtab | uniq | grep -v autofs | cut -d " " -f 3`
920 if [[ $EspFilesystem != 'vfat' ]] ; then
923 if [[ $EspFilesystem != 'vfat' ]] ; then
924 echo "$RootDir/$InstallDir doesn't seem to be on a VFAT filesystem. The ESP must be"
925 echo "mounted at $RootDir/boot or $RootDir/boot/efi and it must be VFAT! Aborting!"
928 echo "ESP was found at $InstallDir using $EspFilesystem"
931 # Uses efibootmgr to add an entry for rEFInd to the EFI's NVRAM.
932 # If this fails, sets Problems=1
936 Efibootmgr
=`which efibootmgr 2> /dev/null`
937 if [[ "$Efibootmgr" ]] ; then
938 InstallDisk
=`grep "$InstallDir" /etc/mtab | cut -d " " -f 1 | cut -c 1-8`
939 PartNum
=`grep "$InstallDir" /etc/mtab | cut -d " " -f 1 | cut -c 9-10`
940 EntryFilename
="$TargetDir/$Refind"
941 EfiEntryFilename
=`echo ${EntryFilename//\//\\\}`
942 EfiEntryFilename2
=`echo ${EfiEntryFilename} | sed s/\\\\\\\\/\\\\\\\\\\\\\\\\/g`
943 ExistingEntry
=`"$Efibootmgr" -v | grep -i "$EfiEntryFilename2"`
945 if [[ "$ExistingEntry" ]] ; then
946 ExistingEntryBootNum
=`echo "$ExistingEntry" | cut -c 5-8`
947 FirstBoot
=`"$Efibootmgr" | grep BootOrder | cut -c 12-15`
948 if [[ "$ExistingEntryBootNum" != "$FirstBoot" ]] ; then
949 echo "An existing rEFInd boot entry exists, but isn't set as the default boot"
950 echo "manager. The boot order is being adjusted to make rEFInd the default boot"
951 echo "manager. If this is NOT what you want, you should use efibootmgr to"
952 echo "manually adjust your EFI's boot order."
953 "$Efibootmgr" -b $ExistingEntryBootNum -B &> /dev
/null
960 if [[ $InstallIt == "1" ]] ; then
961 echo "Installing it!"
962 "$Efibootmgr" -c -l "$EfiEntryFilename" -L "rEFInd Boot Manager" -d $InstallDisk -p $PartNum &> /dev
/null
963 if [[ $?
!= 0 ]] ; then
969 else # efibootmgr not found
974 if [[ $EfibootmgrProblems ]] ; then
976 echo "ALERT: There were problems running the efibootmgr program! You may need to"
977 echo "rename the $Refind binary to the default name (EFI/boot/bootx64.efi"
978 echo "on x86-64 systems or EFI/boot/bootia32.efi on x86 systems) to have it run!"
981 echo "rEFInd has been set as the default boot manager."
985 # Create a minimal/sample refind_linux.conf file in /boot.
986 GenerateRefindLinuxConf
() {
987 if [[ -f "$RLConfFile" ]] ; then
988 echo "Existing $RLConfFile found; not overwriting."
990 echo "Creating $RLConfFile; edit it to adjust kernel options."
991 if [[ -f "$RootDir/etc/default/grub" ]] ; then
992 # We want the default options used by the distribution, stored here....
993 source "$RootDir/etc/default/grub"
994 echo "Setting default boot options based on $RootDir/etc/default/grub"
996 RootFS
=`df "$RootDir" | grep dev | cut -f 1 -d " "`
997 StartOfDevname
=`echo "$RootFS" | cut -b 1-7`
998 if [[ "$StartOfDevname" == "/dev/sd" ||
"$StartOfDevName" == "/dev/hd" ]] ; then
999 # Identify root filesystem by UUID rather than by device node, if possible
1000 Uuid
=`blkid -o export -s UUID "$RootFS" 2> /dev/null | grep UUID=`
1001 if [[ -n $Uuid ]] ; then
1005 DefaultOptions
="$GRUB_CMDLINE_LINUX $GRUB_CMDLINE_LINUX_DEFAULT"
1006 echo "\"Boot with standard options\" \"ro root=$RootFS $DefaultOptions \"" > $RLConfFile
1007 echo "\"Boot to single-user mode\" \"ro root=$RootFS $DefaultOptions single\"" >> $RLConfFile
1008 echo "\"Boot with minimal options\" \"ro root=$RootFS\"" >> $RLConfFile
1012 # Controls rEFInd installation under Linux.
1013 # Sets Problems=1 if something goes wrong.
1015 if [[ "$TargetDir" == "/System/Library/CoreServices" ]] ; then
1016 echo "You may not use the --ownhfs option under Linux! Aborting!"
1019 echo "Installing rEFInd on Linux...."
1020 modprobe efivars
&> /dev
/null
1021 if [[ $TargetDir == "/EFI/BOOT" ]] ; then
1028 if [[ $CpuType == 'x86_64' ]] ; then
1030 elif [[ ($CpuType == 'i386' ||
$CpuType == 'i486' ||
$CpuType == 'i586' ||
$CpuType == 'i686') ]] ; then
1032 # If we're in EFI mode, do some sanity checks, and alert the user or even
1033 # abort. Not in BIOS mode, though, since that could be used on an emergency
1034 # disc to try to recover a troubled Linux installation.
1035 if [[ -d /sys
/firmware
/efi
]] ; then
1036 if [[ "$ShimSource" != "none" && "$TargetDir" != "/BOOT/EFI" ]] ; then
1038 echo "CAUTION: shim does not currently supports 32-bit systems, so you should not"
1039 echo "use the --shim option to install on such systems. Aborting!"
1044 echo "CAUTION: This Linux installation uses a 32-bit kernel. 32-bit EFI-based"
1045 echo "computers are VERY RARE. If you've installed a 32-bit version of Linux"
1046 echo "on a 64-bit computer, you should manually install the 64-bit version of"
1047 echo "rEFInd. If you're installing on a Mac, you should do so from OS X. If"
1048 echo "you're positive you want to continue with this installation, answer 'Y'"
1049 echo "to the following question..."
1051 echo -n "Are you sure you want to continue (Y/N)? "
1053 if [[ $YesNo == "Y" ||
$YesNo == "y" ]] ; then
1054 echo "OK; continuing with the installation..."
1060 echo "Unknown CPU type '$CpuType'; aborting!"
1064 if [[ $LocalKeys == 1 ]] ; then
1070 if [[ "$TargetDir" != "/EFI/BOOT" && "$TargetDir" != "/EFI/Microsoft/Boot" ]] ; then
1072 GenerateRefindLinuxConf
1074 } # InstallOnLinux()
1077 # The main part of the script. Sets a few environment variables,
1078 # performs a few startup checks, and then calls functions to
1079 # install under OS X or Linux, depending on the detected platform.
1083 ThisDir
="$( cd -P "$
( dirname "${BASH_SOURCE[0]}" )" && pwd )"
1084 RefindDir
="$ThisDir/refind"
1085 ThisScript
="$ThisDir/`basename $0`"
1086 if [[ `whoami` != "root" ]] ; then
1087 echo "Not running as root; attempting to elevate privileges via sudo...."
1088 sudo
"$ThisScript" "$@"
1089 if [[ $?
!= 0 ]] ; then
1090 echo "This script must be run as root (or using sudo). Exiting!"
1097 if [[ $OSName == 'Darwin' ]] ; then
1098 if [[ "$ShimSource" != "none" ]] ; then
1099 echo "The --shim option is not supported on OS X! Exiting!"
1102 if [[ "$LocalKeys" != 0 ]] ; then
1103 echo "The --localkeys option is not supported on OS X! Exiting!"
1107 elif [[ $OSName == 'Linux' ]] ; then
1110 echo "Running on unknown OS; aborting!"
1111 if [[ "$InstallToEspOnMac" == 0 ]] ; then
1112 echo "The --notesp option is not supported on Linux! Exiting!"
1117 if [[ $Problems ]] ; then
1120 echo "Installation has completed, but problems were detected. Review the output for"
1121 echo "error messages and take corrective measures as necessary. You may need to"
1122 echo "re-run this script or install manually before rEFInd will work."
1126 echo "Installation has completed successfully."
1130 if [[ $UnmountEsp == '1' ]] ; then
1131 echo "Unmounting install dir"
1135 if [[ "$InstallDir" == /tmp
/refind_install
]] ; then