# to the current OS X boot partition. Under Linux, this script
# installs to the ESP by default.
#
-# This program is copyright (c) 2012 by Roderick W. Smith
+# This program is copyright (c) 2012-2015 by Roderick W. Smith
# It is released under the terms of the GNU GPL, version 3,
# a copy of which should be included in the file COPYING.txt.
#
# Revision history:
#
+# 0.8.7 -- Better detection of Secure Boot mode & fixed errors when copying
+# Shim & MokManager files over themselves; fixed bug that caused
+# inappropriate installation to EFI/BOOT/bootx64.efi
+# 0.8.6 -- Fixed bugs that caused misidentification of ESP on disks with
+# partition numbers over 10 on OS X and misidentification of mount
+# point if already-mounted ESP had space in path.
+# 0.8.5 -- Refinement/cleanup of new OS X ESP-as-default policy
# 0.8.4 -- OS X default changed to install to ESP under /EFI/BOOT
# 0.7.9 -- Fixed bug that caused errors if dmraid utility not installed
# 0.7.7 -- Fixed bug that created mangled refind_linux.conf file; added ability
esac
shift
done
-
if [[ "$InstallToEspOnMac" == 0 && "$RootDir" == '/' && "$TargetDir" == '/EFI/BOOT' ]] ; then
echo "You may use --notesp OR --usedefault, but not both! Aborting!"
exit 1
echo "If you use --ownhfs, you may NOT use --usedefault! Aborting!"
exit 1
fi
- exit
RLConfFile="$RootDir/boot/refind_linux.conf"
EtcKeysDir="$RootDir/etc/refind.d/keys"
} # GetParams()
exit 1
fi
+ echo "ShimSource is $ShimSource"
if [[ "$ShimSource" != "none" ]] ; then
if [[ -f "$ShimSource" ]] ; then
if [[ $ShimType == "shimx64.efi" || $ShimType == "shim.efi" ]] ; then
# Helper for CopyRefindFiles; copies shim files (including MokManager, if it's
# available) to target.
CopyShimFiles() {
- cp -fb "$ShimSource" "$InstallDir/$TargetDir/$TargetShim"
- if [[ $? != 0 ]] ; then
- Problems=1
- fi
- if [[ -f "$MokManagerSource" ]] ; then
- cp -fb "$MokManagerSource" "$InstallDir/$TargetDir/"
+ local inode1=`ls -i "$ShimSource" 2> /dev/null | cut -f 1 -d " "`
+ local inode2=`ls -i "$InstallDir/$TargetDir/$TargetShim" 2> /dev/null | cut -f 1 -d " "`
+ if [[ $inode1 != $inode2 ]] ; then
+ cp -fb "$ShimSource" "$InstallDir/$TargetDir/$TargetShim"
+ if [[ $? != 0 ]] ; then
+ Problems=1
+ fi
fi
- if [[ $? != 0 ]] ; then
- Problems=1
+ inode1=`ls -i "$MokManagerSource" 2> /dev/null | cut -f 1 -d " "`
+ local TargetMMName=`basename $MokManagerSource`
+ inode2=`ls -i "$InstallDir/$TargetDir/$TargetMMName" 2> /dev/null | cut -f 1 -d " "`
+ if [[ $inode1 != $inode2 ]] ; then
+ if [[ -f "$MokManagerSource" ]] ; then
+ cp -fb "$MokManagerSource" "$InstallDir/$TargetDir/"
+ fi
+ if [[ $? != 0 ]] ; then
+ Problems=1
+ fi
fi
} # CopyShimFiles()
fi
} # CopyKeys()
+# Set varaibles for installation in EFI/BOOT directory
+SetVarsForBoot() {
+ TargetDir="/EFI/BOOT"
+ if [[ $ShimSource == "none" ]] ; then
+ TargetX64="bootx64.efi"
+ TargetIA32="bootia32.efi"
+ else
+ if [[ $ShimType == "shim.efi" || $ShimType == "shimx64.efi" ]] ; then
+ TargetX64="grubx64.efi"
+ elif [[ $ShimType == "preloader.efi" || $ShimType == "PreLoader.efi" ]] ; then
+ TargetX64="loader.efi"
+ else
+ echo "Unknown shim/PreBootloader type: $ShimType"
+ echo "Aborting!"
+ exit 1
+ fi
+ TargetIA32="bootia32.efi"
+ TargetShim="bootx64.efi"
+ fi
+} # SetVarsForBoot()
+
+# Set variables for installation in EFI/Microsoft/Boot directory
+SetVarsForMsBoot() {
+ TargetDir="/EFI/Microsoft/Boot"
+ if [[ $ShimSource == "none" ]] ; then
+ TargetX64="bootmgfw.efi"
+ else
+ if [[ $ShimType == "shim.efi" || $ShimType == "shimx64.efi" ]] ; then
+ TargetX64="grubx64.efi"
+ elif [[ $ShimType == "preloader.efi" || $ShimType == "PreLoader.efi" ]] ; then
+ TargetX64="loader.efi"
+ else
+ echo "Unknown shim/PreBootloader type: $ShimType"
+ echo "Aborting!"
+ exit 1
+ fi
+ TargetShim="bootmgfw.efi"
+ fi
+} # SetVarsForMsBoot()
+
+# TargetDir defaults to /EFI/refind; however, this function adjusts it as follows:
+# - If an existing refind.conf is available in /EFI/BOOT or /EFI/Microsoft/Boot,
+# install to that directory under the suitable name; but DO NOT do this if
+# refind.conf is also in /EFI/refind.
+# - If booted in BIOS mode and the ESP lacks any other EFI files, install to
+# /EFI/BOOT
+# - If booted in BIOS mode and there's no refind.conf file and there is a
+# /EFI/Microsoft/Boot/bootmgfw.efi file, move it down one level and
+# install under that name, "hijacking" the Windows boot loader filename
+DetermineTargetDir() {
+ Upgrade=0
+
+ if [[ -f $InstallDir/EFI/BOOT/refind.conf && ! -f $InstallDir/EFI/refind/refind.conf ]] ; then
+ SetVarsForBoot
+ Upgrade=1
+ fi
+ if [[ -f $InstallDir/EFI/Microsoft/Boot/refind.conf && ! -f $InstallDir/EFI/refind/refind.conf ]] ; then
+ SetVarsForMsBoot
+ Upgrade=1
+ fi
+ if [[ -f $InstallDir/EFI/refind/refind.conf && foofoo ]] ; then
+ TargetDir="/EFI/refind"
+ if [[ $ShimSource == "none" ]] ; then
+ TargetX64="refind_x64.efi"
+ TargetIA32="refind_ia32.efi"
+ fi
+ Upgrade=1
+ fi
+ if [[ $Upgrade == 1 ]] ; then
+ echo "Found rEFInd installation in $InstallDir$TargetDir; upgrading it."
+ fi
+
+ if [[ ! -d /sys/firmware/efi && ! $OSName == 'Darwin' && $Upgrade == 0 ]] ; then # BIOS-mode
+ FoundEfiFiles=`find "$InstallDir/EFI/BOOT" -name "*.efi" 2> /dev/null`
+ FoundConfFiles=`find "$InstallDir" -name "refind\.conf" 2> /dev/null`
+ if [[ ! -n "$FoundConfFiles" && -f "$InstallDir/EFI/Microsoft/Boot/bootmgfw.efi" ]] ; then
+ mv -n "$InstallDir/EFI/Microsoft/Boot/bootmgfw.efi" "$InstallDir/EFI/Microsoft" &> /dev/null
+ SetVarsForMsBoot
+ echo "Running in BIOS mode with a suspected Windows installation; moving boot loader"
+ echo "files so as to install to $InstallDir$TargetDir."
+ elif [[ ! -n "$FoundEfiFiles" ]] ; then # In BIOS mode and no default loader; install as default loader
+ SetVarsForBoot
+ echo "Running in BIOS mode with no existing default boot loader; installing to"
+ echo $InstallDir$TargetDir
+ else
+ echo "Running in BIOS mode with an existing default boot loader; backing it up and"
+ echo "installing rEFInd in its place."
+ if [[ -d "$InstallDir/EFI/BOOT-rEFIndBackup" ]] ; then
+ echo ""
+ echo "Caution: An existing backup of a default boot loader exists! If the current"
+ echo "default boot loader and the backup are different boot loaders, the current"
+ echo "one will become inaccessible."
+ echo ""
+ echo -n "Do you want to proceed with installation (Y/N)? "
+ ReadYesNo
+ if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then
+ echo "OK; continuing with the installation..."
+ else
+ exit 0
+ fi
+ fi
+ mv -n "$InstallDir/EFI/BOOT" "$InstallDir/EFI/BOOT-rEFIndBackup"
+ SetVarsForBoot
+ fi
+ fi # BIOS-mode
+} # DetermineTargetDir()
+
# Determine (or guess) the filesystem used on the Linux /boot filesystem.
# Store the result in the BootFS global variable.
SetBootFS() {
;;
hfsplus) DriverType="hfs"
;;
+ ntfs) DriverType="ntfs"
+ ;;
*) BootFS=""
esac
if [[ -n $BootFS ]] ; then
# directory on the ESP. Must be passed a suitable architecture code (ia32
# or x64).
CopyTools() {
- mkdir -p $InstallDir/EFI/tools
+ mkdir -p "$InstallDir/EFI/tools"
if [[ $OSName == 'Darwin' ]] ; then
cp -f "$RefindDir/tools_$1/gptsync_$1.efi" "$InstallDir/EFI/tools/"
if [[ -f "$InstallDir/EFI/tools/gptsync.efi" ]] ; then
fi
Esp=/dev/`echo $Temp`
# If the ESP is mounted, use its current mount point....
- Temp=`df -P | grep "$Esp"`
- InstallDir=`echo $Temp | cut -f 6 -d ' '`
+ Temp=`df -P | grep "$Esp "`
+ InstallDir=`echo $Temp | cut -f 6- -d ' '`
if [[ "$InstallDir" == '' ]] ; then
mkdir /Volumes/ESP &> /dev/null
mount -t msdos "$Esp" /Volumes/ESP
+ # Some systems have HFS+ "ESPs." They shouldn't, but they do. If this is
+ # detected, mount it as such and set appropriate options.
if [[ $? != 0 ]] ; then
- echo "Unable to mount ESP! Aborting!\n"
- exit 1
+ mount -t hfs "$Esp" /Volumes/Esp
+ OwnHfs=1
+ InstallToEspOnMac=0
+ if [[ $? != 0 ]] ; then
+ echo "Unable to mount ESP! Aborting!\n"
+ exit 1
+ fi
fi
UnmountEsp=1
InstallDir="/Volumes/ESP"
<key>ProductName</key>
<string>rEFInd</string>
<key>ProductVersion</key>
- <string>0.7.6</string>
+ <string>0.9.1</string>
</dict>
</plist>
ENDOFHERE
InstallDir="$RootDir/"
fi
echo "Installing rEFInd to the partition mounted at $InstallDir"
+ DetermineTargetDir
Platform=`ioreg -l -p IODeviceTree | grep firmware-abi | cut -d "\"" -f 4`
CopyRefindFiles
if [[ $InstallToEspOnMac == "1" ]] ; then
- bless --mount "$InstallDir" --setBoot --file "$InstallDir/$TargetDir/$Refind"
+ bless --mount "$InstallDir" --setBoot --file "$InstallDir/$TargetDir/$Refind" --shortform
elif [[ "$TargetDir" != "/EFI/BOOT" ]] ; then
bless --setBoot --folder "$InstallDir/$TargetDir" --file "$InstallDir/$TargetDir/$Refind"
fi
# appropriate options haven't been set, warn the user and offer to abort.
# If we're NOT in Secure Boot mode but the user HAS specified the --shim
# or --localkeys option, warn the user and offer to abort.
-#
-# FIXME: Although I checked the presence (and lack thereof) of the
-# /sys/firmware/efi/vars/SecureBoot* files on my Secure Boot test system
-# before releasing this script, I've since found that they are at least
-# sometimes present when Secure Boot is absent. This means that the first
-# test can produce false alarms. A better test is highly desirable.
CheckSecureBoot() {
- VarFile=`ls -d /sys/firmware/efi/vars/SecureBoot* 2> /dev/null`
- if [[ -n "$VarFile" && "$TargetDir" != '/EFI/BOOT' && "$ShimSource" == "none" ]] ; then
+ local IsSecureBoot
+ if [[ -f /sys/firmware/efi/vars/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c/data ]] ; then
+ IsSecureBoot=`od -An -t u1 /sys/firmware/efi/vars/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c/data | tr -d '[[:space:]]'`
+ else
+ IsSecureBoot="0"
+ fi
+ if [[ $IsSecureBoot == "1" && "$TargetDir" != '/EFI/BOOT' && "$ShimSource" == "none" ]] ; then
echo ""
- echo "CAUTION: Your computer appears to support Secure Boot, but you haven't"
- echo "specified a valid shim.efi file source. If you've disabled Secure Boot and"
- echo "intend to leave it disabled, this is fine; but if Secure Boot is active, the"
- echo "resulting installation won't boot. You can read more about this topic at"
+ echo "CAUTION: Your computer appears to be booted with Secure Boot, but you haven't"
+ echo "specified a valid shim.efi file source. Chances are you should re-run with"
+ echo "the --shim option. You can read more about this topic at"
echo "http://www.rodsbooks.com/refind/secureboot.html."
echo ""
echo -n "Do you want to proceed with installation (Y/N)? "
fi
fi
- if [[ "$ShimSource" != "none" && ! -n "$VarFile" ]] ; then
+ if [[ "$ShimSource" != "none" && ! $IsSecureBoot == "1" ]] ; then
echo ""
echo "You've specified installing using a shim.efi file, but your computer does not"
echo "appear to be running in Secure Boot mode. Although installing in this way"
fi
fi
- if [[ $LocalKeys != 0 && ! -n "$VarFile" ]] ; then
+ if [[ $LocalKeys != 0 && ! $IsSecureBoot == "1" ]] ; then
echo ""
echo "You've specified re-signing your rEFInd binaries with locally-generated keys,"
echo "but your computer does not appear to be running in Secure Boot mode. The"
fi
}
-# Set varaibles for installation in EFI/BOOT directory
-SetVarsForBoot() {
- TargetDir="/EFI/BOOT"
- if [[ $ShimSource == "none" ]] ; then
- TargetX64="bootx64.efi"
- TargetIA32="bootia32.efi"
- else
- if [[ $ShimType == "shim.efi" || $ShimType == "shimx64.efi" ]] ; then
- TargetX64="grubx64.efi"
- elif [[ $ShimType == "preloader.efi" || $ShimType == "PreLoader.efi" ]] ; then
- TargetX64="loader.efi"
- else
- echo "Unknown shim/PreBootloader type: $ShimType"
- echo "Aborting!"
- exit 1
- fi
- TargetIA32="bootia32.efi"
- TargetShim="bootx64.efi"
- fi
-} # SetFilenamesForBoot()
-
-# Set variables for installation in EFI/Microsoft/Boot directory
-SetVarsForMsBoot() {
- TargetDir="/EFI/Microsoft/Boot"
- if [[ $ShimSource == "none" ]] ; then
- TargetX64="bootmgfw.efi"
- else
- if [[ $ShimType == "shim.efi" || $ShimType == "shimx64.efi" ]] ; then
- TargetX64="grubx64.efi"
- elif [[ $ShimType == "preloader.efi" || $ShimType == "PreLoader.efi" ]] ; then
- TargetX64="loader.efi"
- else
- echo "Unknown shim/PreBootloader type: $ShimType"
- echo "Aborting!"
- exit 1
- fi
- TargetShim="bootmgfw.efi"
- fi
-}
-
-# TargetDir defaults to /EFI/refind; however, this function adjusts it as follows:
-# - If an existing refind.conf is available in /EFI/BOOT or /EFI/Microsoft/Boot,
-# install to that directory under the suitable name; but DO NOT do this if
-# refind.conf is also in /EFI/refind.
-# - If booted in BIOS mode and the ESP lacks any other EFI files, install to
-# /EFI/BOOT
-# - If booted in BIOS mode and there's no refind.conf file and there is a
-# /EFI/Microsoft/Boot/bootmgfw.efi file, move it down one level and
-# install under that name, "hijacking" the Windows boot loader filename
-DetermineTargetDir() {
- Upgrade=0
-
- if [[ -f $InstallDir/EFI/BOOT/refind.conf ]] ; then
- SetVarsForBoot
- Upgrade=1
- fi
- if [[ -f $InstallDir/EFI/Microsoft/Boot/refind.conf ]] ; then
- SetVarsForMsBoot
- Upgrade=1
- fi
- if [[ -f $InstallDir/EFI/refind/refind.conf ]] ; then
- TargetDir="/EFI/refind"
- Upgrade=1
- fi
- if [[ $Upgrade == 1 ]] ; then
- echo "Found rEFInd installation in $InstallDir$TargetDir; upgrading it."
- fi
-
- if [[ ! -d /sys/firmware/efi && $Upgrade == 0 ]] ; then # BIOS-mode
- FoundEfiFiles=`find "$InstallDir/EFI/BOOT" -name "*.efi" 2> /dev/null`
- FoundConfFiles=`find "$InstallDir" -name "refind\.conf" 2> /dev/null`
- if [[ ! -n "$FoundConfFiles" && -f "$InstallDir/EFI/Microsoft/Boot/bootmgfw.efi" ]] ; then
- mv -n "$InstallDir/EFI/Microsoft/Boot/bootmgfw.efi" "$InstallDir/EFI/Microsoft" &> /dev/null
- SetVarsForMsBoot
- echo "Running in BIOS mode with a suspected Windows installation; moving boot loader"
- echo "files so as to install to $InstallDir$TargetDir."
- elif [[ ! -n "$FoundEfiFiles" ]] ; then # In BIOS mode and no default loader; install as default loader
- SetVarsForBoot
- echo "Running in BIOS mode with no existing default boot loader; installing to"
- echo $InstallDir$TargetDir
- else
- echo "Running in BIOS mode with an existing default boot loader; backing it up and"
- echo "installing rEFInd in its place."
- if [[ -d "$InstallDir/EFI/BOOT-rEFIndBackup" ]] ; then
- echo ""
- echo "Caution: An existing backup of a default boot loader exists! If the current"
- echo "default boot loader and the backup are different boot loaders, the current"
- echo "one will become inaccessible."
- echo ""
- echo -n "Do you want to proceed with installation (Y/N)? "
- ReadYesNo
- if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then
- echo "OK; continuing with the installation..."
- else
- exit 0
- fi
- fi
- mv -n "$InstallDir/EFI/BOOT" "$InstallDir/EFI/BOOT-rEFIndBackup"
- SetVarsForBoot
- fi
- fi # BIOS-mode
-} # DetermineTargetDir()
-
# Controls rEFInd installation under Linux.
# Sets Problems=1 if something goes wrong.
InstallOnLinux() {
# performs a few startup checks, and then calls functions to
# install under OS X or Linux, depending on the detected platform.
#
-
OSName=`uname -s`
GetParams "$@"
ThisDir="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
echo "The --localkeys option is not supported on OS X! Exiting!"
exit 1
fi
- if [[ $InstallToEspOnMac == 1 ]] ; then
- TargetDir=/EFI/BOOT
- TargetX64="bootx64.efi"
- TargetIA32="bootia32.efi"
- fi
InstallOnOSX $1
elif [[ $OSName == 'Linux' ]] ; then
InstallOnLinux