+GetParams() {
+ InstallToEspOnMac=1
+ # Install the driver required to read Linux /boot, if it's available
+ # Note: Under OS X, this will be installed only if a Linux partition
+ # is detected, in which case the ext4fs driver will be installed.
+ InstallDrivers="boot"
+ while [[ $# -gt 0 ]]; do
+ case $1 in
+ --notesp) InstallToEspOnMac=0
+ ;;
+ --ownhfs) OwnHfs=1
+ InstallToEspOnMac=0
+ TargetPart="$2"
+ TargetDir=/System/Library/CoreServices
+ shift
+ ;;
+ --usedefault) TargetDir=/EFI/BOOT
+ TargetPart="$2"
+ TargetX64="bootx64.efi"
+ TargetIA32="bootia32.efi"
+ shift
+ ;;
+ --root) RootDir="$2"
+ InstallToEspOnMac=0
+ shift
+ ;;
+ --localkeys) LocalKeys=1
+ ;;
+ --shim | --preloader) ShimSource="$2"
+ ShimType=`basename $ShimSource`
+ shift
+ ;;
+ --drivers | --alldrivers) InstallDrivers="all"
+ ;;
+ --nodrivers) InstallDrivers="none"
+ ;;
+ --yes) AlwaysYes=1
+ ;;
+ * ) echo "Usage: $0 [--notesp | --usedefault {device-file} | --root {dir} |"
+ echo " --ownhfs {device-file} ]"
+ echo " [--nodrivers | --alldrivers] [--shim {shim-filename}]"
+ echo " [--localkeys] [--yes]"
+ exit 1
+ esac
+ shift
+ done
+ if [[ "$InstallToEspOnMac" == 0 && "$RootDir" == '/' && "$TargetDir" == '/EFI/BOOT' ]] ; then
+ echo "You may use --notesp OR --usedefault, but not both! Aborting!"
+ exit 1
+ fi
+ if [[ "$RootDir" != '/' && "$TargetDir" == '/EFI/BOOT' ]] ; then
+ echo "You may use --root OR --usedefault, but not both! Aborting!"
+ exit 1
+ fi
+ if [[ "$TargetDir" != '/System/Library/CoreServices' && "$OwnHfs" == '1' ]] ; then
+ echo "If you use --ownhfs, you may NOT use --usedefault! Aborting!"
+ exit 1
+ fi
+ RLConfFile="$RootDir/boot/refind_linux.conf"
+ EtcKeysDir="$RootDir/etc/refind.d/keys"
+} # GetParams()
+
+# Get a yes/no response from the user and place it in the YesNo variable.
+# If the AlwaysYes variable is set to 1, skip the user input and set "Y"
+# in the YesNo variable.
+ReadYesNo() {
+ if [[ $AlwaysYes == 1 ]] ; then
+ YesNo="Y"
+ echo "Y"
+ else
+ read YesNo
+ fi
+}
+
+# Abort if the rEFInd files can't be found.
+# Also sets $ConfFile to point to the configuration file,
+# $IconsDir to point to the icons directory, and
+# $ShimSource to the source of the shim.efi file (if necessary).
+CheckForFiles() {
+ # Note: This check is satisfied if EITHER the 32- or the 64-bit version
+ # is found, even on the wrong platform. This is because the platform
+ # hasn't yet been determined. This could obviously be improved, but it
+ # would mean restructuring lots more code....
+ if [[ ! -f "$RefindDir/refind_ia32.efi" && ! -f "$RefindDir/refind_x64.efi" ]] ; then
+ echo "The rEFInd binary file is missing! Aborting installation!"
+ exit 1
+ fi
+
+ if [[ -f "$RefindDir/refind.conf-sample" ]] ; then
+ ConfFile="$RefindDir/refind.conf-sample"
+ elif [[ -f "$ThisDir/refind.conf-sample" ]] ; then
+ ConfFile="$ThisDir/refind.conf-sample"
+ else
+ echo "The sample configuration file is missing! Aborting installation!"
+ exit 1
+ fi
+
+ if [[ -d "$RefindDir/icons" ]] ; then
+ IconsDir="$RefindDir/icons"
+ elif [[ -d "$ThisDir/icons" ]] ; then
+ IconsDir="$ThisDir/icons"
+ else
+ echo "The icons directory is missing! Aborting installation!"
+ exit 1
+ fi
+
+ if [[ "$ShimSource" != "none" ]] ; then
+ if [[ -f "$ShimSource" ]] ; then
+ if [[ $ShimType == "shimx64.efi" || $ShimType == "shim.efi" ]] ; then
+ TargetX64="grubx64.efi"
+ MokManagerSource=`dirname "$ShimSource"`/MokManager.efi
+ elif [[ $ShimType == "preloader.efi" || $ShimType == "PreLoader.efi" ]] ; then
+ TargetX64="loader.efi"
+ MokManagerSource=`dirname "$ShimSource"`/HashTool.efi
+ else
+ echo "Unknown shim/PreBootloader filename: $ShimType!"
+ echo "Known filenames are shimx64.efi, shim.efi, and PreLoader.efi. Aborting!"
+ exit 1
+ fi
+ else
+ echo "The specified shim/PreBootloader file, $ShimSource, doesn't exist!"
+ echo "Aborting installation!"
+ exit 1
+ fi
+ fi
+} # CheckForFiles()
+
+# 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/"
+ fi
+ if [[ $? != 0 ]] ; then
+ Problems=1
+ fi
+} # CopyShimFiles()
+
+# Copy the public keys to the installation medium
+CopyKeys() {
+ if [[ $LocalKeys == 1 ]] ; then
+ mkdir -p "$InstallDir/$TargetDir/keys/"
+ cp "$EtcKeysDir/$LocalKeysBase.cer" "$InstallDir/$TargetDir/keys/"
+ cp "$EtcKeysDir/$LocalKeysBase.crt" "$InstallDir/$TargetDir/keys/"
+ 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 ]] ; 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"
+ if [[ "$OSName" == 'Darwin' ]] ; 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() {
+ local Blkid
+
+ Blkid=`which blkid 2> /dev/null`
+ BootFS=""
+ if [[ $OSName == 'Linux' && -x "$Blkid" ]] ; then
+ BootPart=`df /boot | grep dev | cut -f 1 -d " "`
+ BootFS=`$Blkid -o export $BootPart 2> /dev/null | grep TYPE= | cut -f 2 -d =`
+ fi
+ if [[ $OSName == 'Darwin' ]] ; then
+ # 0FC63DAF-8483-4772-8E79-3D69D8477DE4 = Linux filesystem
+ # BC13C2FF-59E6-4262-A352-B275FD6F7172 = Freedesktop $boot partition
+ # 933AC7E1-2EB4-4F13-B844-0E14E2AEF915 = Freedesktop Linux /home
+ # E6D6D379-F507-44C2-A23C-238F2A3DF928 = Linux LVM
+ # A19D880F-05FC-4D3B-A006-743F0F84911E = Linux RAID
+ # 0657FD6D-A4AB-43C4-84E5-0933C84B4F4F = Linux swap
+ 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')
+ BootFS=""
+ if [[ -n $Temp ]] ; then
+ echo "Found suspected Linux partition(s); installing ext4fs driver."
+ BootFS="ext4"
+ fi
+ fi
+} # SetBootFS()
+
+# Copy drivers from $RefindDir/drivers_$1 to $InstallDir/$TargetDir/drivers_$1,
+# honoring the $InstallDrivers condition. Must be passed a suitable
+# architecture code (ia32 or x64).
+CopyDrivers() {
+ if [[ $InstallDrivers == "all" ]] ; then
+ mkdir -p "$InstallDir/$TargetDir/drivers_$1"
+ cp "$ThisDir"/drivers_$1/*_$1.efi "$InstallDir/$TargetDir/drivers_$1/" 2> /dev/null
+ cp "$RefindDir"/drivers_$1/*_$1.efi "$InstallDir/$TargetDir/drivers_$1/" 2> /dev/null
+ elif [[ "$InstallDrivers" == "boot" ]] ; then
+ SetBootFS
+ DriverType=""
+ case $BootFS in
+ ext2 | ext3) DriverType="ext2"
+ # Could use ext4, but that can create unwanted entries from symbolic
+ # links in / to /boot/vmlinuz if a separate /boot partition is used.
+ ;;
+ ext4) DriverType="ext4"
+ ;;
+ reiserfs) DriverType="reiserfs"
+ ;;
+ btrfs) DriverType="btrfs"
+ ;;
+ hfsplus) DriverType="hfs"
+ ;;
+ ntfs) DriverType="ntfs"
+ ;;
+ *) BootFS=""
+ esac
+ if [[ -n $BootFS ]] ; then
+ echo "Installing driver for $BootFS (${DriverType}_$1.efi)"
+ mkdir -p "$InstallDir/$TargetDir/drivers_$1"
+ cp "$ThisDir/drivers_$1/${DriverType}_$1.efi" "$InstallDir/$TargetDir/drivers_$1/" 2> /dev/null
+ cp "$RefindDir/drivers_$1/${DriverType}_$1.efi" "$InstallDir/$TargetDir/drivers_$1"/ 2> /dev/null
+ fi
+ fi
+} # CopyDrivers()
+
+# Copy tools (currently only gptsync, and that only on Macs) to the EFI/tools
+# directory on the ESP. Must be passed a suitable architecture code (ia32
+# or x64).
+CopyTools() {
+ 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
+ mv "$InstallDir/EFI/tools/gptsync.efi" "$InstallDir/EFI/tools/gptsync.efi-disabled"
+ echo "Found old gptsync.efi; disabling it by renaming it to gptsync.efi-disabled"
+ fi
+ fi
+} # CopyTools()
+
+# Copy the rEFInd files to the ESP or OS X root partition.
+# Sets Problems=1 if any critical commands fail.