]>
code.delx.au - refind/blob - install.sh
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 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.4 -- OS X default changed to install to ESP under /EFI/BOOT
39 # 0.7.9 -- Fixed bug that caused errors if dmraid utility not installed
40 # 0.7.7 -- Fixed bug that created mangled refind_linux.conf file; added ability
41 # to locate and mount ESP on Linux, if it's not mounted
42 # 0.7.6 -- Added --ownhfs {device-filename} option
43 # 0.7.5 -- Fixed bug when installing to ESP on recent versions of OS X
44 # 0.7.2 -- Fixed code that could be confused by use of autofs to mount the ESP
45 # 0.7.0 -- Added support for the new Btrfs driver
46 # 0.6.12 -- Added support for PreLoader as well as for shim
47 # 0.6.11 -- Improvements in script's ability to handle directories with spaces
49 # 0.6.9 -- Install gptsync on Macs
50 # 0.6.8 -- Bug fix: ESP scan now uses "uniq".
51 # 0.6.6 -- Bug fix: Upgrade drivers when installed to EFI/BOOT. Also enable
52 # copying shim.efi and MokManager.efi over themselves.
53 # 0.6.4 -- Copies ext2 driver rather than ext4 driver for ext2/3fs
54 # 0.6.3 -- Support for detecting rEFInd in EFI/BOOT and EFI/Microsoft/Boot
55 # directories & for installing to EFI/BOOT in BIOS mode
56 # 0.6.2-1 -- Added --yes option & tweaked key-copying for use with RPM install script
57 # 0.6.1 -- Added --root option; minor bug fixes
58 # 0.6.0 -- Changed --drivers to --alldrivers and added --nodrivers option;
59 # changed default driver installation behavior in Linux to install
60 # the driver needed to read /boot (if available)
61 # 0.5.1.2 -- Fixed bug that caused failure to generate refind_linux.conf file
62 # 0.5.1.1 -- Fixed bug that caused script failure under OS X
63 # 0.5.1 -- Added --shim & --localkeys options & create sample refind_linux.conf
65 # 0.5.0 -- Added --usedefault & --drivers options & changed "esp" option to "--esp"
66 # 0.4.5 -- Fixed check for rEFItBlesser in OS X
67 # 0.4.2 -- Added notice about BIOS-based OSes & made NVRAM changes in Linux smarter
68 # 0.4.1 -- Added check for rEFItBlesser in OS X
69 # 0.3.3.1 -- Fixed OS X 10.7 bug; also works as make target
70 # 0.3.2.1 -- Check for presence of source files; aborts if not present
71 # 0.3.2 -- Initial version
73 # Note: install.sh version numbers match those of the rEFInd package
74 # with which they first appeared.
78 LocalKeysBase
= "refind_local"
82 TargetX64
= "refind_x64.efi"
83 TargetIA32
= "refind_ia32.efi"
89 # Functions used by both OS X and Linux....
94 # Install the driver required to read Linux /boot, if it's available
95 # Note: Under OS X, this will be installed only if a Linux partition
96 # is detected, in which case the ext4fs driver will be installed.
98 while [[ $# -gt 0 ]]; do
100 --notesp ) InstallToEspOnMac
= 0
105 TargetDir
=/ System
/ Library
/ CoreServices
108 --usedefault ) TargetDir
=/ EFI
/ BOOT
110 TargetX64
= "bootx64.efi"
111 TargetIA32
= "bootia32.efi"
118 --localkeys ) LocalKeys
= 1
120 --shim |
--preloader ) ShimSource
= " $2 "
121 ShimType
= `basename $ShimSource `
124 --drivers |
--alldrivers ) InstallDrivers
= "all"
126 --nodrivers ) InstallDrivers
= "none"
130 * ) echo "Usage: $0 [--notesp | --usedefault {device-file} | --root {dir} |"
131 echo " --ownhfs {device-file} ]"
132 echo " [--nodrivers | --alldrivers] [--shim {shim-filename}]"
133 echo " [--localkeys] [--yes]"
139 if [[ " $RootDir " != '/' && " $TargetDir " == '/EFI/BOOT' ]] ; then
140 echo "You may use --usedefault OR --root, but not both! Aborting!"
143 if [[ " $TargetDir " != '/System/Library/CoreServices' && " $OwnHfs " == '1' ]] ; then
144 echo "If you use --ownhfs, you may NOT use --usedefault! Aborting!"
148 RLConfFile
= " $RootDir /boot/refind_linux.conf"
149 EtcKeysDir
= " $RootDir /etc/refind.d/keys"
152 # Get a yes/no response from the user and place it in the YesNo variable.
153 # If the AlwaysYes variable is set to 1, skip the user input and set "Y"
154 # in the YesNo variable.
156 if [[ $AlwaysYes == 1 ]] ; then
164 # Abort if the rEFInd files can't be found.
165 # Also sets $ConfFile to point to the configuration file,
166 # $IconsDir to point to the icons directory, and
167 # $ShimSource to the source of the shim.efi file (if necessary).
169 # Note: This check is satisfied if EITHER the 32- or the 64-bit version
170 # is found, even on the wrong platform. This is because the platform
171 # hasn't yet been determined. This could obviously be improved, but it
172 # would mean restructuring lots more code....
173 if [[ ! -f " $RefindDir /refind_ia32.efi" && ! -f " $RefindDir /refind_x64.efi" ]] ; then
174 echo "The rEFInd binary file is missing! Aborting installation!"
178 if [[ -f " $RefindDir /refind.conf-sample" ]] ; then
179 ConfFile
= " $RefindDir /refind.conf-sample"
180 elif [[ -f " $ThisDir /refind.conf-sample" ]] ; then
181 ConfFile
= " $ThisDir /refind.conf-sample"
183 echo "The sample configuration file is missing! Aborting installation!"
187 if [[ -d " $RefindDir /icons" ]] ; then
188 IconsDir
= " $RefindDir /icons"
189 elif [[ -d " $ThisDir /icons" ]] ; then
190 IconsDir
= " $ThisDir /icons"
192 echo "The icons directory is missing! Aborting installation!"
196 if [[ " $ShimSource " != "none" ]] ; then
197 if [[ -f " $ShimSource " ]] ; then
198 if [[ $ShimType == "shimx64.efi" ||
$ShimType == "shim.efi" ]] ; then
199 TargetX64
= "grubx64.efi"
200 MokManagerSource
= `dirname " $ShimSource "` / MokManager.efi
201 elif [[ $ShimType == "preloader.efi" ||
$ShimType == "PreLoader.efi" ]] ; then
202 TargetX64
= "loader.efi"
203 MokManagerSource
= `dirname " $ShimSource "` / HashTool.efi
205 echo "Unknown shim/PreBootloader filename: $ShimType !"
206 echo "Known filenames are shimx64.efi, shim.efi, and PreLoader.efi. Aborting!"
210 echo "The specified shim/PreBootloader file, $ShimSource , doesn't exist!"
211 echo "Aborting installation!"
217 # Helper for CopyRefindFiles; copies shim files (including MokManager, if it's
218 # available) to target.
220 cp -fb " $ShimSource " " $InstallDir / $TargetDir / $TargetShim "
221 if [[ $?
!= 0 ]] ; then
224 if [[ -f " $MokManagerSource " ]] ; then
225 cp -fb " $MokManagerSource " " $InstallDir / $TargetDir /"
227 if [[ $?
!= 0 ]] ; then
232 # Copy the public keys to the installation medium
234 if [[ $LocalKeys == 1 ]] ; then
235 mkdir
-p " $InstallDir / $TargetDir /keys/"
236 cp " $EtcKeysDir / $LocalKeysBase .cer" " $InstallDir / $TargetDir /keys/"
237 cp " $EtcKeysDir / $LocalKeysBase .crt" " $InstallDir / $TargetDir /keys/"
241 # Determine (or guess) the filesystem used on the Linux /boot filesystem.
242 # Store the result in the BootFS global variable.
246 Blkid
= `which blkid 2> /dev/null`
248 if [[ $OSName == 'Linux' && -x " $Blkid " ]] ; then
249 BootPart
= `df /boot | grep dev | cut -f 1 -d " "`
250 BootFS
= ` $Blkid -o export $BootPart 2> /dev/null | grep TYPE= | cut -f 2 -d =`
252 if [[ $OSName == 'Darwin' ]] ; then
253 # 0FC63DAF-8483-4772-8E79-3D69D8477DE4 = Linux filesystem
254 # BC13C2FF-59E6-4262-A352-B275FD6F7172 = Freedesktop $boot partition
255 # 933AC7E1-2EB4-4F13-B844-0E14E2AEF915 = Freedesktop Linux /home
256 # E6D6D379-F507-44C2-A23C-238F2A3DF928 = Linux LVM
257 # A19D880F-05FC-4D3B-A006-743F0F84911E = Linux RAID
258 # 0657FD6D-A4AB-43C4-84E5-0933C84B4F4F = Linux swap
259 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' )
261 if [[ -n $Temp ]] ; then
262 echo "Found suspected Linux partition(s); installing ext4fs driver."
268 # Copy drivers from $RefindDir/drivers_$1 to $InstallDir/$TargetDir/drivers_$1,
269 # honoring the $InstallDrivers condition. Must be passed a suitable
270 # architecture code (ia32 or x64).
272 if [[ $InstallDrivers == "all" ]] ; then
273 mkdir
-p " $InstallDir / $TargetDir /drivers_ $1 "
274 cp " $ThisDir " / drivers_
$1 /* _
$1 .efi
" $InstallDir / $TargetDir /drivers_ $1 /" 2 > / dev
/ null
275 cp " $RefindDir " / drivers_
$1 /* _
$1 .efi
" $InstallDir / $TargetDir /drivers_ $1 /" 2 > / dev
/ null
276 elif [[ " $InstallDrivers " == "boot" ]] ; then
280 ext2 | ext3
) DriverType
= "ext2"
281 # Could use ext4, but that can create unwanted entries from symbolic
282 # links in / to /boot/vmlinuz if a separate /boot partition is used.
284 ext4
) DriverType
= "ext4"
286 reiserfs
) DriverType
= "reiserfs"
288 btrfs
) DriverType
= "btrfs"
290 hfsplus
) DriverType
= "hfs"
294 if [[ -n $BootFS ]] ; then
295 echo "Installing driver for $BootFS ( ${DriverType} _ $1 .efi)"
296 mkdir
-p " $InstallDir / $TargetDir /drivers_ $1 "
297 cp " $ThisDir /drivers_ $1 / ${DriverType} _ $1 .efi" " $InstallDir / $TargetDir /drivers_ $1 /" 2 > / dev
/ null
298 cp " $RefindDir /drivers_ $1 / ${DriverType} _ $1 .efi" " $InstallDir / $TargetDir /drivers_ $1 " / 2 > / dev
/ null
303 # Copy tools (currently only gptsync, and that only on Macs) to the EFI/tools
304 # directory on the ESP. Must be passed a suitable architecture code (ia32
307 mkdir
-p $InstallDir / EFI
/ tools
308 if [[ $OSName == 'Darwin' ]] ; then
309 cp -f " $RefindDir /tools_ $1 /gptsync_ $1 .efi" " $InstallDir /EFI/tools/"
310 if [[ -f " $InstallDir /EFI/tools/gptsync.efi" ]] ; then
311 mv " $InstallDir /EFI/tools/gptsync.efi" " $InstallDir /EFI/tools/gptsync.efi-disabled"
312 echo "Found old gptsync.efi; disabling it by renaming it to gptsync.efi-disabled"
317 # Copy the rEFInd files to the ESP or OS X root partition.
318 # Sets Problems=1 if any critical commands fail.
320 mkdir
-p " $InstallDir / $TargetDir "
321 if [[ " $TargetDir " == '/EFI/BOOT' ]] ; then
322 cp " $RefindDir /refind_ia32.efi" " $InstallDir / $TargetDir / $TargetIA32 " 2 > / dev
/ null
323 if [[ $?
!= 0 ]] ; then
324 echo "Note: IA32 (x86) binary not installed!"
326 cp " $RefindDir /refind_x64.efi" " $InstallDir / $TargetDir / $TargetX64 " 2 > / dev
/ null
327 if [[ $?
!= 0 ]] ; then
330 if [[ " $ShimSource " != "none" ]] ; then
331 TargetShim
= "bootx64.efi"
334 if [[ $InstallDrivers == "all" ]] ; then
335 cp -r " $RefindDir " / drivers_
* " $InstallDir / $TargetDir /" 2 > / dev
/ null
336 cp -r " $ThisDir " / drivers_
* " $InstallDir / $TargetDir /" 2 > / dev
/ null
337 elif [[ $Upgrade == 1 ||
$InstallToEspOnMac == 1 ]] ; then
338 if [[ $Platform == 'EFI64' ]] ; then
347 if [[ $Platform == 'EFI64' ]] ; then
349 elif [[ $Platform == 'EFI32' ]] ; then
350 Refind
= 'bootia32.efi'
353 elif [[ $Platform == 'EFI64' ||
$TargetDir == "/EFI/Microsoft/Boot" ]] ; then
354 cp " $RefindDir /refind_x64.efi" " $InstallDir / $TargetDir / $TargetX64 "
355 if [[ $?
!= 0 ]] ; then
360 Refind
= "refind_x64.efi"
362 if [[ " $ShimSource " != "none" ]] ; then
363 if [[ " $TargetShim " == "default" ]] ; then
364 TargetShim
= `basename " $ShimSource "`
368 if [[ $LocalKeys == 0 ]] ; then
369 echo "Storing copies of rEFInd Secure Boot public keys in $EtcKeysDir "
370 mkdir
-p " $EtcKeysDir "
371 cp " $ThisDir /keys/refind.cer" " $EtcKeysDir " 2 > / dev
/ null
372 cp " $ThisDir /keys/refind.crt" " $EtcKeysDir " 2 > / dev
/ null
375 if [[ " $TargetDir " == '/System/Library/CoreServices' ]] ; then
376 SetupMacHfs
$TargetX64
378 elif [[ $Platform == 'EFI32' ]] ; then
379 cp " $RefindDir /refind_ia32.efi" " $InstallDir / $TargetDir / $TargetIA32 "
380 if [[ $?
!= 0 ]] ; then
385 Refind
= "refind_ia32.efi"
386 if [[ " $TargetDir " == '/System/Library/CoreServices' ]] ; then
387 SetupMacHfs
$TargetIA32
390 echo "Unknown platform! Aborting!"
393 echo "Copied rEFInd binary files"
395 if [[ -d " $InstallDir / $TargetDir /icons" ]] ; then
396 rm -rf " $InstallDir / $TargetDir /icons-backup" &> / dev
/ null
397 mv -f " $InstallDir / $TargetDir /icons" " $InstallDir / $TargetDir /icons-backup"
398 echo "Notice: Backed up existing icons directory as icons-backup."
400 cp -r " $IconsDir " " $InstallDir / $TargetDir "
401 if [[ $?
!= 0 ]] ; then
404 mkdir
-p " $InstallDir / $TargetDir /keys"
405 cp -rf " $ThisDir " / keys
/* .
[ cd ] er
" $InstallDir / $TargetDir /keys/" 2 > / dev
/ null
406 cp -rf " $EtcKeysDir " /* .
[ cd ] er
" $InstallDir / $TargetDir /keys/" 2 > / dev
/ null
407 if [[ -f " $InstallDir / $TargetDir /refind.conf" ]] ; then
408 echo "Existing refind.conf file found; copying sample file as refind.conf-sample"
409 echo "to avoid overwriting your customizations."
411 cp -f " $ConfFile " " $InstallDir / $TargetDir "
412 if [[ $?
!= 0 ]] ; then
416 echo "Copying sample configuration file as refind.conf; edit this file to configure"
419 cp -f " $ConfFile " " $InstallDir / $TargetDir /refind.conf"
420 if [[ $?
!= 0 ]] ; then
424 if [[ $DeleteRefindDir == 1 ]] ; then
425 echo "Deleting the temporary directory $RefindDir "
428 } # CopyRefindFiles()
430 # Mount the partition the user specified with the --usedefault or --ownhfs option
431 MountDefaultTarget
() {
432 InstallDir
=/ tmp
/ refind_install
433 mkdir
-p " $InstallDir "
435 if [[ $OSName == 'Darwin' ]] ; then
436 if [[ $OwnHfs == '1' ]] ; then
437 Temp
= `diskutil info " $TargetPart " | grep "Mount Point"`
438 InstallDir
= `echo $Temp | cut -f 3-30 -d ' '`
439 if [[ $InstallDir == '' ]] ; then
440 InstallDir
=/ tmp
/ refind_install
441 mount
-t hfs
" $TargetPart " " $InstallDir "
446 mount
-t msdos
" $TargetPart " " $InstallDir "
448 elif [[ $OSName == 'Linux' ]] ; then
449 mount
-t vfat
" $TargetPart " " $InstallDir "
451 if [[ $?
!= 0 ]] ; then
452 echo "Couldn't mount $TargetPart ! Aborting!"
456 } # MountDefaultTarget()
459 # A series of OS X support functions....
462 # Mount the ESP at /Volumes/ESP or determine its current mount
464 # Sets InstallDir to the ESP mount point
465 # Sets UnmountEsp if we mounted it
467 # Identify the ESP. Note: This returns the FIRST ESP found;
468 # if the system has multiple disks, this could be wrong!
469 Temp
= $
( mount |
sed -n -E "/^(\/dev\/disk[0-9]+s[0-9]+) on \/ \(.*$/s//\1/p" )
471 Temp
= $
( diskutil list |
grep " EFI " |
grep -o 'disk.*' |
head -n 1 )
472 if [ -z $Temp ]; then
473 echo "Warning: root device doesn't have an EFI partition"
476 echo "Warning: root device could not be found"
478 if [ -z $Temp ]; then
479 Temp
= $
( diskutil list |
sed -n -E '/^ *[0-9]+:[ ]+EFI EFI[ ]+[0-9.]+ [A-Z]+[ ]+(disk[0-9]+s[0-9]+)$/ { s//\1/p
483 if [ -z $Temp ]; then
484 echo "Could not find an EFI partition. Aborting!"
488 Esp
=/ dev
/ `echo $Temp `
489 # If the ESP is mounted, use its current mount point....
490 Temp
= `df -P | grep " $Esp "`
491 InstallDir
= `echo $Temp | cut -f 6 -d ' '`
492 if [[ " $InstallDir " == '' ]] ; then
493 mkdir
/ Volumes
/ ESP
&> / dev
/ null
494 mount
-t msdos
" $Esp " / Volumes
/ ESP
495 if [[ $?
!= 0 ]] ; then
496 echo "Unable to mount ESP! Aborting! \n "
500 InstallDir
= "/Volumes/ESP"
504 # Set up for booting from Mac HFS+ volume that boots rEFInd in MJG's way
505 # (http://mjg59.dreamwidth.org/7468.html)
506 # Must be passed the original rEFInd binary filename (without a path).
508 if [[ -s " $InstallDir /mach_kernel" ]] ; then
509 echo "Attempt to install rEFInd to a partition with a /mach_kernel file! Aborting!"
512 cp -n " $InstallDir / $TargetDir /boot.efi" " $InstallDir / $TargetDir /boot.efi-backup" &> / dev
/ null
513 ln -f " $InstallDir / $TargetDir / $1 " " $InstallDir / $TargetDir /boot.efi"
514 touch " $InstallDir /mach_kernel"
515 rm " $InstallDir / $TargetDir /SystemVersion.plist" &> / dev
/ null
516 cat - << ENDOFHERE >> " $InstallDir / $TargetDir /SystemVersion.plist"
517 <xml version="1.0" encoding="UTF-8"?>
518 <plist version="1.0">
520 <key>ProductBuildVersion</key>
522 <key>ProductName</key>
523 <string>rEFInd</string>
524 <key>ProductVersion</key>
525 <string>0.7.6</string>
531 # Control the OS X installation.
532 # Sets Problems=1 if problems found during the installation.
534 echo "Installing rEFInd on OS X...."
535 if [[ " $InstallToEspOnMac " == "1" ]] ; then
537 elif [[ " $TargetDir " == "/EFI/BOOT" ||
" $OwnHfs " == '1' ]] ; then
540 InstallDir
= " $RootDir /"
542 echo "Installing rEFInd to the partition mounted at $InstallDir "
543 Platform
= `ioreg -l -p IODeviceTree | grep firmware-abi | cut -d " \" " -f 4`
545 if [[ $InstallToEspOnMac == "1" ]] ; then
546 bless
--mount " $InstallDir " --setBoot --file " $InstallDir / $TargetDir / $Refind "
547 elif [[ " $TargetDir " != "/EFI/BOOT" ]] ; then
548 bless
--setBoot --folder " $InstallDir / $TargetDir " --file " $InstallDir / $TargetDir / $Refind "
550 if [[ $?
!= 0 ]] ; then
553 if [[ -f / Library
/ StartupItems
/ rEFItBlesser ||
-d / Library
/ StartupItems
/ rEFItBlesser
]] ; then
555 echo "/Library/StartupItems/rEFItBlesser found!"
556 echo "This program is part of rEFIt, and will cause rEFInd to fail to work after"
557 echo -n "its first boot. Do you want to remove rEFItBlesser (Y/N)? "
559 if [[ $YesNo == "Y" ||
$YesNo == "y" ]] ; then
560 echo "Deleting /Library/StartupItems/rEFItBlesser..."
561 rm -r / Library
/ StartupItems
/ rEFItBlesser
563 echo "Not deleting rEFItBlesser."
567 echo "WARNING: If you have an Advanced Format disk, *DO NOT* attempt to check the"
568 echo "bless status with 'bless --info', since this is known to cause disk corruption"
569 echo "on some systems!!"
575 # Now a series of Linux support functions....
578 # Check for evidence that we're running in Secure Boot mode. If so, and if
579 # appropriate options haven't been set, warn the user and offer to abort.
580 # If we're NOT in Secure Boot mode but the user HAS specified the --shim
581 # or --localkeys option, warn the user and offer to abort.
583 # FIXME: Although I checked the presence (and lack thereof) of the
584 # /sys/firmware/efi/vars/SecureBoot* files on my Secure Boot test system
585 # before releasing this script, I've since found that they are at least
586 # sometimes present when Secure Boot is absent. This means that the first
587 # test can produce false alarms. A better test is highly desirable.
589 VarFile
= `ls -d /sys/firmware/efi/vars/SecureBoot* 2> /dev/null`
590 if [[ -n " $VarFile " && " $TargetDir " != '/EFI/BOOT' && " $ShimSource " == "none" ]] ; then
592 echo "CAUTION: Your computer appears to support Secure Boot, but you haven't"
593 echo "specified a valid shim.efi file source. If you've disabled Secure Boot and"
594 echo "intend to leave it disabled, this is fine; but if Secure Boot is active, the"
595 echo "resulting installation won't boot. You can read more about this topic at"
596 echo "http://www.rodsbooks.com/refind/secureboot.html."
598 echo -n "Do you want to proceed with installation (Y/N)? "
600 if [[ $YesNo == "Y" ||
$YesNo == "y" ]] ; then
601 echo "OK; continuing with the installation..."
607 if [[ " $ShimSource " != "none" && ! -n " $VarFile " ]] ; then
609 echo "You've specified installing using a shim.efi file, but your computer does not"
610 echo "appear to be running in Secure Boot mode. Although installing in this way"
611 echo "should work, it's unnecessarily complex. You may continue, but unless you"
612 echo "plan to enable Secure Boot, you should consider stopping and omitting the"
613 echo "--shim option. You can read more about this topic at"
614 echo "http://www.rodsbooks.com/refind/secureboot.html."
616 echo -n "Do you want to proceed with installation (Y/N)? "
618 if [[ $YesNo == "Y" ||
$YesNo == "y" ]] ; then
619 echo "OK; continuing with the installation..."
625 if [[ $LocalKeys != 0 && ! -n " $VarFile " ]] ; then
627 echo "You've specified re-signing your rEFInd binaries with locally-generated keys,"
628 echo "but your computer does not appear to be running in Secure Boot mode. The"
629 echo "keys you generate will be useless unless you enable Secure Boot. You may"
630 echo "proceed with this installation, but before you do so, you may want to read"
631 echo "more about it at http://www.rodsbooks.com/refind/secureboot.html."
633 echo -n "Do you want to proceed with installation (Y/N)? "
635 if [[ $YesNo == "Y" ||
$YesNo == "y" ]] ; then
636 echo "OK; continuing with the installation..."
642 } # CheckSecureBoot()
644 # Check for the presence of locally-generated keys from a previous installation in
645 # $EtcKeysDir (/etc/refind.d/keys). If they're not present, generate them using
648 PrivateKey
= " $EtcKeysDir / $LocalKeysBase .key"
649 CertKey
= " $EtcKeysDir / $LocalKeysBase .crt"
650 DerKey
= " $EtcKeysDir / $LocalKeysBase .cer"
651 OpenSSL
= `which openssl 2> /dev/null`
653 # Do the work only if one or more of the necessary keys is missing
654 # TODO: Technically, we don't need the DerKey; but if it's missing and openssl
655 # is also missing, this will fail. This could be improved.
656 if [[ ! -f " $PrivateKey " ||
! -f " $CertKey " ||
! -f " $DerKey " ]] ; then
657 echo "Generating a fresh set of local keys...."
658 mkdir
-p " $EtcKeysDir "
659 chmod 0700 " $EtcKeysDir "
660 if [[ ! -x " $OpenSSL " ]] ; then
661 echo "Can't find openssl, which is required to create your private signing keys!"
665 if [[ -f " $PrivateKey " ]] ; then
666 echo "Backing up existing $PrivateKey "
667 cp -f " $PrivateKey " " $PrivateKey .backup" 2 > / dev
/ null
669 if [[ -f " $CertKey " ]] ; then
670 echo "Backing up existing $CertKey "
671 cp -f " $CertKey " " $CertKey .backup" 2 > / dev
/ null
673 if [[ -f " $DerKey " ]] ; then
674 echo "Backing up existing $DerKey "
675 cp -f " $DerKey " " $DerKey .backup" 2 > / dev
/ null
677 " $OpenSSL " req
-new -x509 -newkey rsa
: 2048 -keyout " $PrivateKey " -out " $CertKey " \
678 -nodes -days 3650 -subj "/CN=Locally-generated rEFInd key/"
679 " $OpenSSL " x509
-in " $CertKey " -out " $DerKey " -outform DER
680 chmod 0600 " $PrivateKey "
682 echo "Using existing local keys...."
686 # Sign a single binary. Requires parameters:
688 # $2 = destination file
689 # Also assumes that the SBSign, PESign, UseSBSign, UsePESign, and various key variables are set
691 # Aborts script on error
693 $SBSign --key " $PrivateKey " --cert " $CertKey " --output " $2 " " $1 "
694 if [[ $?
!= 0 ]] ; then
695 echo "Problem signing the binary $1 ! Aborting!"
700 # Re-sign the x86-64 binaries with a locally-generated key, First look for appropriate
701 # key files in $EtcKeysDir. If they're present, use them to re-sign the binaries. If
702 # not, try to generate new keys and store them in $EtcKeysDir.
704 SBSign
= `which sbsign 2> /dev/null`
705 echo "Found sbsign at $SBSign "
706 TempDir
= "/tmp/refind_local"
707 if [[ ! -x " $SBSign " ]] ; then
708 echo "Can't find sbsign, which is required to sign rEFInd with your own keys!"
713 mkdir
-p " $TempDir /drivers_x64"
714 cp " $RefindDir /refind.conf-sample $TempDir " 2 > / dev
/ null
715 cp " $ThisDir /refind.conf-sample $TempDir " 2 > / dev
/ null
716 cp " $RefindDir /refind_ia32.efi $TempDir " 2 > / dev
/ null
717 cp -a " $RefindDir /drivers_ia32 $TempDir " 2 > / dev
/ null
718 cp -a " $ThisDir /drivers_ia32 $TempDir " 2 > / dev
/ null
719 SignOneBinary
" $RefindDir /refind_x64.efi" " $TempDir /refind_x64.efi"
721 IFS
= $
( echo -en " \n\b " )
722 for Driver
in `ls " $RefindDir "/drivers_x64/*.efi " $ThisDir "/drivers_x64/*.efi 2> /dev/null` ; do
723 TempName
= `basename " $Driver "`
724 SignOneBinary
" $Driver " " $TempDir /drivers_x64/ $TempName "
731 # Locate and mount an ESP, if possible, based on parted output.
732 # Should be called only if /boot/efi is NOT an acceptable ESP.
733 # Sets InstallDir to the mounted ESP's path ($RootDir/boot/efi)
734 # and EspFilesystem the filesystem (always "vfat")
736 echo "The ESP doesn't seem to be mounted! Trying to find it...."
743 for Drive
in `ls /dev/[sh]d?` ; do
745 Dmraid
= `which dmraid 2> /dev/null`
746 if [ -x " $Dmraid " ] ; then
747 DmStatus
= `dmraid -r | grep $Drive `
748 if [ -n " $DmStatus " ] ; then
749 echo " $Drive seems to be part of a RAID array; skipping!"
753 TableType
= `parted $Drive print -m -s 2>/dev/null | awk -F: ' $1 == "' $Drive '" { print $6 }'`
754 if [[ $TableType == 'gpt' && $SkipIt == 0 ]] ; then # read only GPT disks that aren't part of dmraid array
755 PartNum
= `LANG=C parted $Drive print -m -s 2>/dev/null | awk -F: ' $7 ~ "(^boot| boot)" { print $1 }' | head -n 1`
756 if [ " $PartNum " -eq " $PartNum " ] 2 > / dev
/ null
; then
757 InstallDir
= " $RootDir /boot/efi"
759 mount
$Drive$PartNum $InstallDir
760 EspFilesystem
= `grep " $Drive $PartNum .*/boot/efi" /etc/mtab | uniq | grep -v autofs | cut -d " " -f 3`
761 if [[ $EspFilesystem != 'vfat' ]] ; then
764 echo "Mounting ESP at $InstallDir "
767 fi # $PartNum -eq $PartNum
772 # Identifies the ESP's location (/boot or /boot/efi, or these locations under
773 # the directory specified by --root); aborts if the ESP isn't mounted at
775 # Sets InstallDir to the ESP mount point.
777 mount
/ boot
&> / dev
/ null
778 mount
/ boot
/ efi
&> / dev
/ null
779 EspLine
= `df " $RootDir /boot/efi" 2> /dev/null | grep boot/efi`
780 if [[ ! -n " $EspLine " ]] ; then
781 EspLine
= `df " $RootDir "/boot | grep boot`
783 InstallDir
= `echo $EspLine | cut -d " " -f 6`
785 if [[ -n " $InstallDir " ]] ; then
786 EspFilesystem
= `grep -w " $InstallDir " /etc/mtab | uniq | grep -v autofs | cut -d " " -f 3`
788 if [[ $EspFilesystem != 'vfat' ]] ; then
791 if [[ $EspFilesystem != 'vfat' ]] ; then
792 echo " $RootDir / $InstallDir doesn't seem to be on a VFAT filesystem. The ESP must be"
793 echo "mounted at $RootDir /boot or $RootDir /boot/efi and it must be VFAT! Aborting!"
796 echo "ESP was found at $InstallDir using $EspFilesystem "
799 # Uses efibootmgr to add an entry for rEFInd to the EFI's NVRAM.
800 # If this fails, sets Problems=1
804 Efibootmgr
= `which efibootmgr 2> /dev/null`
805 if [[ " $Efibootmgr " ]] ; then
806 InstallDisk
= `grep " $InstallDir " /etc/mtab | cut -d " " -f 1 | cut -c 1-8`
807 PartNum
= `grep " $InstallDir " /etc/mtab | cut -d " " -f 1 | cut -c 9-10`
808 EntryFilename
= " $TargetDir / $Refind "
809 EfiEntryFilename
= `echo ${EntryFilename//\//\\\} `
810 EfiEntryFilename2
= `echo ${EfiEntryFilename} | sed s/ \\\\\\\\ / \\\\\\\\\\\\\\\\ /g`
811 ExistingEntry
= `" $Efibootmgr " -v | grep -i " $EfiEntryFilename2 "`
813 if [[ " $ExistingEntry " ]] ; then
814 ExistingEntryBootNum
= `echo " $ExistingEntry " | cut -c 5-8`
815 FirstBoot
= `" $Efibootmgr " | grep BootOrder | cut -c 12-15`
816 if [[ " $ExistingEntryBootNum " != " $FirstBoot " ]] ; then
817 echo "An existing rEFInd boot entry exists, but isn't set as the default boot"
818 echo "manager. The boot order is being adjusted to make rEFInd the default boot"
819 echo "manager. If this is NOT what you want, you should use efibootmgr to"
820 echo "manually adjust your EFI's boot order."
821 " $Efibootmgr " -b $ExistingEntryBootNum -B &> / dev
/ null
828 if [[ $InstallIt == "1" ]] ; then
829 echo "Installing it!"
830 " $Efibootmgr " -c -l " $EfiEntryFilename " -L "rEFInd Boot Manager" -d $InstallDisk -p $PartNum &> / dev
/ null
831 if [[ $?
!= 0 ]] ; then
837 else # efibootmgr not found
842 if [[ $EfibootmgrProblems ]] ; then
844 echo "ALERT: There were problems running the efibootmgr program! You may need to"
845 echo "rename the $Refind binary to the default name (EFI/boot/bootx64.efi"
846 echo "on x86-64 systems or EFI/boot/bootia32.efi on x86 systems) to have it run!"
849 echo "rEFInd has been set as the default boot manager."
853 # Create a minimal/sample refind_linux.conf file in /boot.
854 GenerateRefindLinuxConf
() {
855 if [[ -f " $RLConfFile " ]] ; then
856 echo "Existing $RLConfFile found; not overwriting."
858 echo "Creating $RLConfFile ; edit it to adjust kernel options."
859 if [[ -f " $RootDir /etc/default/grub" ]] ; then
860 # We want the default options used by the distribution, stored here....
861 source " $RootDir /etc/default/grub"
862 echo "Setting default boot options based on $RootDir /etc/default/grub"
864 RootFS
= `df " $RootDir " | grep dev | cut -f 1 -d " "`
865 StartOfDevname
= `echo " $RootFS " | cut -b 1-7`
866 if [[ " $StartOfDevname " == "/dev/sd" ||
" $StartOfDevName " == "/dev/hd" ]] ; then
867 # Identify root filesystem by UUID rather than by device node, if possible
868 Uuid
= `blkid -o export -s UUID " $RootFS " 2> /dev/null | grep UUID=`
869 if [[ -n $Uuid ]] ; then
873 DefaultOptions
= " $GRUB_CMDLINE_LINUX $GRUB_CMDLINE_LINUX_DEFAULT "
874 echo " \" Boot with standard options \" \" ro root= $RootFS $DefaultOptions \" " > $RLConfFile
875 echo " \" Boot to single-user mode \" \" ro root= $RootFS $DefaultOptions single \" " >> $RLConfFile
876 echo " \" Boot with minimal options \" \" ro root= $RootFS \" " >> $RLConfFile
880 # Set varaibles for installation in EFI/BOOT directory
882 TargetDir
= "/EFI/BOOT"
883 if [[ $ShimSource == "none" ]] ; then
884 TargetX64
= "bootx64.efi"
885 TargetIA32
= "bootia32.efi"
887 if [[ $ShimType == "shim.efi" ||
$ShimType == "shimx64.efi" ]] ; then
888 TargetX64
= "grubx64.efi"
889 elif [[ $ShimType == "preloader.efi" ||
$ShimType == "PreLoader.efi" ]] ; then
890 TargetX64
= "loader.efi"
892 echo "Unknown shim/PreBootloader type: $ShimType "
896 TargetIA32
= "bootia32.efi"
897 TargetShim
= "bootx64.efi"
899 } # SetFilenamesForBoot()
901 # Set variables for installation in EFI/Microsoft/Boot directory
903 TargetDir
= "/EFI/Microsoft/Boot"
904 if [[ $ShimSource == "none" ]] ; then
905 TargetX64
= "bootmgfw.efi"
907 if [[ $ShimType == "shim.efi" ||
$ShimType == "shimx64.efi" ]] ; then
908 TargetX64
= "grubx64.efi"
909 elif [[ $ShimType == "preloader.efi" ||
$ShimType == "PreLoader.efi" ]] ; then
910 TargetX64
= "loader.efi"
912 echo "Unknown shim/PreBootloader type: $ShimType "
916 TargetShim
= "bootmgfw.efi"
920 # TargetDir defaults to /EFI/refind; however, this function adjusts it as follows:
921 # - If an existing refind.conf is available in /EFI/BOOT or /EFI/Microsoft/Boot,
922 # install to that directory under the suitable name; but DO NOT do this if
923 # refind.conf is also in /EFI/refind.
924 # - If booted in BIOS mode and the ESP lacks any other EFI files, install to
926 # - If booted in BIOS mode and there's no refind.conf file and there is a
927 # /EFI/Microsoft/Boot/bootmgfw.efi file, move it down one level and
928 # install under that name, "hijacking" the Windows boot loader filename
929 DetermineTargetDir
() {
932 if [[ -f $InstallDir / EFI
/ BOOT
/ refind.conf
]] ; then
936 if [[ -f $InstallDir / EFI
/ Microsoft
/ Boot
/ refind.conf
]] ; then
940 if [[ -f $InstallDir / EFI
/ refind
/ refind.conf
]] ; then
941 TargetDir
= "/EFI/refind"
944 if [[ $Upgrade == 1 ]] ; then
945 echo "Found rEFInd installation in $InstallDir $TargetDir ; upgrading it."
948 if [[ ! -d / sys
/ firmware
/ efi
&& $Upgrade == 0 ]] ; then # BIOS-mode
949 FoundEfiFiles
= `find " $InstallDir /EFI/BOOT" -name "*.efi" 2> /dev/null`
950 FoundConfFiles
= `find " $InstallDir " -name "refind\.conf" 2> /dev/null`
951 if [[ ! -n " $FoundConfFiles " && -f " $InstallDir /EFI/Microsoft/Boot/bootmgfw.efi" ]] ; then
952 mv -n " $InstallDir /EFI/Microsoft/Boot/bootmgfw.efi" " $InstallDir /EFI/Microsoft" &> / dev
/ null
954 echo "Running in BIOS mode with a suspected Windows installation; moving boot loader"
955 echo "files so as to install to $InstallDir $TargetDir ."
956 elif [[ ! -n " $FoundEfiFiles " ]] ; then # In BIOS mode and no default loader; install as default loader
958 echo "Running in BIOS mode with no existing default boot loader; installing to"
959 echo $InstallDir$TargetDir
961 echo "Running in BIOS mode with an existing default boot loader; backing it up and"
962 echo "installing rEFInd in its place."
963 if [[ -d " $InstallDir /EFI/BOOT-rEFIndBackup" ]] ; then
965 echo "Caution: An existing backup of a default boot loader exists! If the current"
966 echo "default boot loader and the backup are different boot loaders, the current"
967 echo "one will become inaccessible."
969 echo -n "Do you want to proceed with installation (Y/N)? "
971 if [[ $YesNo == "Y" ||
$YesNo == "y" ]] ; then
972 echo "OK; continuing with the installation..."
977 mv -n " $InstallDir /EFI/BOOT" " $InstallDir /EFI/BOOT-rEFIndBackup"
981 } # DetermineTargetDir()
983 # Controls rEFInd installation under Linux.
984 # Sets Problems=1 if something goes wrong.
986 if [[ " $TargetDir " == "/System/Library/CoreServices" ]] ; then
987 echo "You may not use the --ownhfs option under Linux! Aborting!"
990 echo "Installing rEFInd on Linux...."
991 modprobe efivars
&> / dev
/ null
992 if [[ $TargetDir == "/EFI/BOOT" ]] ; then
999 if [[ $CpuType == 'x86_64' ]] ; then
1001 elif [[ ( $CpuType == 'i386' ||
$CpuType == 'i486' ||
$CpuType == 'i586' ||
$CpuType == 'i686' ) ]] ; then
1003 # If we're in EFI mode, do some sanity checks, and alert the user or even
1004 # abort. Not in BIOS mode, though, since that could be used on an emergency
1005 # disc to try to recover a troubled Linux installation.
1006 if [[ -d / sys
/ firmware
/ efi
]] ; then
1007 if [[ " $ShimSource " != "none" && " $TargetDir " != "/BOOT/EFI" ]] ; then
1009 echo "CAUTION: shim does not currently supports 32-bit systems, so you should not"
1010 echo "use the --shim option to install on such systems. Aborting!"
1015 echo "CAUTION: This Linux installation uses a 32-bit kernel. 32-bit EFI-based"
1016 echo "computers are VERY RARE. If you've installed a 32-bit version of Linux"
1017 echo "on a 64-bit computer, you should manually install the 64-bit version of"
1018 echo "rEFInd. If you're installing on a Mac, you should do so from OS X. If"
1019 echo "you're positive you want to continue with this installation, answer 'Y'"
1020 echo "to the following question..."
1022 echo -n "Are you sure you want to continue (Y/N)? "
1024 if [[ $YesNo == "Y" ||
$YesNo == "y" ]] ; then
1025 echo "OK; continuing with the installation..."
1031 echo "Unknown CPU type ' $CpuType '; aborting!"
1035 if [[ $LocalKeys == 1 ]] ; then
1041 if [[ " $TargetDir " != "/EFI/BOOT" && " $TargetDir " != "/EFI/Microsoft/Boot" ]] ; then
1043 GenerateRefindLinuxConf
1045 } # InstallOnLinux()
1048 # The main part of the script. Sets a few environment variables,
1049 # performs a few startup checks, and then calls functions to
1050 # install under OS X or Linux, depending on the detected platform.
1055 ThisDir
= "$( cd -P " $
( dirname " ${BASH_SOURCE[0]} " ) " && pwd )"
1056 RefindDir
= " $ThisDir /refind"
1057 ThisScript
= " $ThisDir /`basename $0 `"
1058 if [[ `whoami` != "root" ]] ; then
1059 echo "Not running as root; attempting to elevate privileges via sudo...."
1060 sudo
" $ThisScript " "$@"
1061 if [[ $?
!= 0 ]] ; then
1062 echo "This script must be run as root (or using sudo). Exiting!"
1069 if [[ $OSName == 'Darwin' ]] ; then
1070 if [[ " $ShimSource " != "none" ]] ; then
1071 echo "The --shim option is not supported on OS X! Exiting!"
1074 if [[ " $LocalKeys " != 0 ]] ; then
1075 echo "The --localkeys option is not supported on OS X! Exiting!"
1078 if [[ $InstallToEspOnMac == 1 ]] ; then
1080 TargetX64
= "bootx64.efi"
1081 TargetIA32
= "bootia32.efi"
1084 elif [[ $OSName == 'Linux' ]] ; then
1087 echo "Running on unknown OS; aborting!"
1088 if [[ " $InstallToEspOnMac " == 0 ]] ; then
1089 echo "The --notesp option is not supported on Linux! Exiting!"
1094 if [[ $Problems ]] ; then
1097 echo "Installation has completed, but problems were detected. Review the output for"
1098 echo "error messages and take corrective measures as necessary. You may need to"
1099 echo "re-run this script or install manually before rEFInd will work."
1103 echo "Installation has completed successfully."
1107 if [[ $UnmountEsp == '1' ]] ; then
1108 echo "Unmounting install dir"
1112 if [[ " $InstallDir " == / tmp
/ refind_install
]] ; then