# installs to the ESP by default.
#
# 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.
#
+# This program is licensed under the terms of the GNU GPL, version 3,
+# or (at your option) any later version.
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
# Revision history:
#
-# 0.9.3 -- Enable running under OS X's recovery system & add warning about
+# 0.10.4 -- Improved handling of disks (other than /dev/[sh]d? disks).
+# 0.10.2 -- Improved Secure Boot detection in Linux, fixed --usedefault in OS X,
+# and fixed bug that could cause mountesp to be installed as a FILE
+# called /usr/local/bin in OS X.
+# 0.10.1 -- Improve extraction of default kernel options from /proc/cmdline.
+# Add support for AMD64 (aka AARCH64, aa64) platform. Added
+# warning when --alldrivers used without --usedefault.
+# 0.10.0 -- Enable running under OS X's recovery system & add warning about
# SIP & brief instructions on how to deal with it if SIP is
-# detected to be enabled.
+# detected to be enabled. Also change way refind_linux.conf default
+# options are found; use /proc/cmdline as base.
# 0.9.2 -- Added --keepname option.
# 0.8.7 -- Better detection of Secure Boot mode & fixed errors when copying
# Shim & MokManager files over themselves; fixed bug that caused
echo "or --preloader! Aborting!"
exit 1
fi
- if [[ "$KeepName" == 1 && ("$OSTYPE" != "linux" && "$OSTYPE" != "linux-gnu") ]] ; then
+ if [[ "$KeepName" == 1 && "$OSTYPE" != "linux" && "$OSTYPE" != "linux-gnu" ]] ; then
echo "The --keepname option is valid only under Linux! Aborting!"
exit 1
fi
echo "The --keepname option is incompatible with --usedefault! Aborting!"
exit 1
fi
+ if [[ "$InstallDrivers" == "all" && "$TargetDir" != "/EFI/BOOT" ]] ; then
+ echo "The --alldrivers option is meant for creating USB flash drives with (near-)"
+ echo "universal boot support. Using it on a hard disk partition runs the risk of"
+ echo "creating serious problems, up to and including rendering your computer"
+ echo -n "unbootable. Are you SURE you want to proceed (Y/N)? "
+ ReadYesNo
+ if [[ "$YesNo" != "Y" && "$YesNo" != "y" ]] ; then
+ echo "Aborting installation!"
+ exit 0
+ fi
+ fi
RLConfFile="$RootDir/boot/refind_linux.conf"
EtcKeysDir="$RootDir/etc/refind.d/keys"
} # GetParams()
fi
}
+# Determine what CPU type and EFI bit depth we're using.
+# Sets Platform global variable to lowercase EFI platform code (currently
+# "x64", "ia32", or "aa64") -- the same code used in filenames.
+DeterminePlatform() {
+ local CpuType
+ case "$OSTYPE" in
+ darwin*)
+ CpuType=`ioreg -l -p IODeviceTree | grep firmware-abi | cut -d "\"" -f 4`
+ if [[ "$CpuType" == EFI32 ]] ; then
+ Platform="ia32"
+ else
+ Platform="x64"
+ fi
+ ;;
+ linux*)
+ CpuType=`uname -m`
+ case "$CpuType" in
+ aarch64)
+ Platform="aa64"
+ ;;
+ x86_64)
+ Platform="x64"
+ ;;
+ i?86)
+ Platform="ia32"
+ # If we're in EFI mode, do some sanity checks, and alert the user or even
+ # abort. Not in BIOS mode, though, since that could be used on an emergency
+ # disc to try to recover a troubled Linux installation.
+ if [[ -d /sys/firmware/efi ]] ; then
+ if [[ "$ShimSource" != "none" && "$TargetDir" != "/BOOT/EFI" ]] ; then
+ echo ""
+ echo "CAUTION: shim does not currently supports 32-bit systems, so you should not"
+ echo "use the --shim option to install on such systems. Aborting!"
+ echo ""
+ exit 1
+ fi
+ echo
+ echo "CAUTION: This Linux installation uses a 32-bit kernel. 32-bit EFI-based"
+ echo "computers are VERY RARE. If you've installed a 32-bit version of Linux"
+ echo "on a 64-bit computer, you should manually install the 64-bit version of"
+ echo "rEFInd. If you're positive you want to continue with this installation,"
+ echo "answer 'Y' to the following question..."
+ echo
+ echo -n "Are you sure you want to continue (Y/N)? "
+ ReadYesNo
+ if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then
+ echo "OK; continuing with the installation..."
+ else
+ exit 0
+ fi
+ fi # In EFI mode
+ ;;
+ *)
+ echo "Unknown CPU type '$CpuType'; aborting!"
+ exit 1
+ ;;
+ esac # case "$CpuType"....
+ ;;
+ *)
+ echo "Unknown OS; aborting!"
+ exit 1
+ ;;
+ esac # case "$OSTYPE"....
+} # DeterminePlatform()
+
# 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).
+# $IconsDir to point to the icons directory,
+# $ShimSource to the source of the shim.efi file (if necessary),
+# $ThisDir to point to the directory in which this script resides,
+# and $RefindDir to point to where the rEFInd binaries live
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
+ # Note: $ThisDir points to real (not symlinked) script home on Linux,
+ # enabling creating a symlink in /usr/sbin (or wherever); but on OS X,
+ # "readlink" doesn't do the same thing as under Linux, so the script
+ # must not be a symlink under OS X.
+ case "$OSTYPE" in
+ darwin*)
+ ThisDir="$( cd -P "${BASH_SOURCE%/*}" && pwd )"
+ ;;
+ linux*)
+ ThisDir="$(dirname "$(readlink -f "$0")")"
+ ;;
+ esac
+ RefindDir="$ThisDir/refind"
+
+ if [[ ! -f "$RefindDir/refind_$Platform.efi" ]] ; then
echo "The rEFInd binary file is missing! Aborting installation!"
exit 1
fi
if [[ -f "$ShimSource" ]] ; then
if [[ $ShimType == "shimx64.efi" || $ShimType == "shim.efi" ]] ; then
TargetX64="grubx64.efi"
+ TargetAARCH64="grubaa64.efi"
MokManagerSource=`dirname "$ShimSource"`/MokManager.efi
elif [[ $ShimType == "preloader.efi" || $ShimType == "PreLoader.efi" ]] ; then
TargetX64="loader.efi"
if [[ $ShimSource == "none" ]] ; then
TargetX64="bootx64.efi"
TargetIA32="bootia32.efi"
+ TargetAARCH64="bootaa64.efi"
else
- if [[ $ShimType == "shim.efi" || $ShimType == "shimx64.efi" ]] ; then
+ if [[ $ShimType == "shim.efi" || $ShimType == "shimx64.efi" || $ShimType = "shimaa64.efi" ]] ; then
TargetX64="grubx64.efi"
+ TargetAARCH64="grubaa64.efi"
elif [[ $ShimType == "preloader.efi" || $ShimType == "PreLoader.efi" ]] ; then
TargetX64="loader.efi"
else
exit 1
fi
TargetIA32="bootia32.efi"
- TargetShim="bootx64.efi"
+ TargetShim="boot$Platform.efi"
fi
if [[ $KeepName == 1 ]] ; then
echo "Installation is to /EFI/BOOT, which is incompatible with --keepname! Aborting!"
if [[ $ShimSource == "none" ]] ; then
TargetX64="bootmgfw.efi"
TargetIA32="bootmgfw.efi"
+ TargetAARCH64="bootmgfw.efi"
else
- if [[ $ShimType == "shim.efi" || $ShimType == "shimx64.efi" ]] ; then
+ if [[ $ShimType == "shim.efi" || $ShimType == "shimx64.efi" || $ShimType == "shimaa64.efi" ]] ; then
TargetX64="grubx64.efi"
+ TargetAARCH64="grubaa64.efi"
elif [[ $ShimType == "preloader.efi" || $ShimType == "PreLoader.efi" ]] ; then
TargetX64="loader.efi"
else
if [[ $ShimSource == "none" || $KeepName == 1 ]] ; then
TargetX64="refind_x64.efi"
TargetIA32="refind_ia32.efi"
+ TargetAARCH64="refind_aa64.efi"
fi
Upgrade=1
fi
if [[ $? != 0 ]] ; then
Problems=1
fi
+ cp "$RefindDir/refind_aa64.efi" "$InstallDir/$TargetDir/$TargetAARCH64" 2> /dev/null
+ if [[ $? != 0 && $Platform == "aa64" ]] ; then
+ Problems=1
+ fi
if [[ "$ShimSource" != "none" ]] ; then
TargetShim="bootx64.efi"
CopyShimFiles
cp -r "$RefindDir"/drivers_* "$InstallDir/$TargetDir/" 2> /dev/null
cp -r "$ThisDir"/drivers_* "$InstallDir/$TargetDir/" 2> /dev/null
elif [[ $Upgrade == 1 || $InstallToEspOnMac == 1 ]] ; then
- if [[ $Platform == 'EFI64' ]] ; then
- CopyDrivers x64
- CopyTools x64
- else
- CopyDrivers ia32
- CopyTools ia32
- fi
- fi
- Refind=""
- if [[ $Platform == 'EFI64' ]] ; then
- Refind='bootx64.efi'
- elif [[ $Platform == 'EFI32' ]] ; then
- Refind='bootia32.efi'
+ CopyDrivers "$Platform"
+ CopyTools "$Platform"
fi
+ Refind="boot$Platform.efi"
CopyKeys
- elif [[ $Platform == 'EFI64' || $TargetDir == "/EFI/Microsoft/Boot" ]] ; then
+ elif [[ $Platform == 'x64' || $TargetDir == "/EFI/Microsoft/Boot" ]] ; then
cp "$RefindDir/refind_x64.efi" "$InstallDir/$TargetDir/$TargetX64"
if [[ $? != 0 ]] ; then
Problems=1
if [[ "$TargetDir" == '/System/Library/CoreServices' ]] ; then
SetupMacHfs $TargetX64
fi
- elif [[ $Platform == 'EFI32' ]] ; then
- cp "$RefindDir/refind_ia32.efi" "$InstallDir/$TargetDir/$TargetIA32"
- if [[ $? != 0 ]] ; then
- Problems=1
+ elif [[ $Platform == 'ia32' || $Platform == 'aa64' ]] ; then
+ if [[ $Platform == 'ia32' ]] ; then
+ cp "$RefindDir/refind_ia32.efi" "$InstallDir/$TargetDir/$TargetIA32"
+ if [[ $? != 0 ]] ; then
+ Problems=1
+ fi
+ else
+ cp "$RefindDir/refind_aa64.efi" "$InstallDir/$TargetDir/$TargetAARCH64"
+ if [[ $? != 0 ]] ; then
+ Problems=1
+ fi
fi
- CopyDrivers ia32
- CopyTools ia32
- Refind="refind_ia32.efi"
+ CopyDrivers $Platform
+ CopyTools $Platform
+ Refind="refind_$Platform.efi"
if [[ "$TargetDir" == '/System/Library/CoreServices' ]] ; then
SetupMacHfs $TargetIA32
fi
<key>ProductName</key>
<string>rEFInd</string>
<key>ProductVersion</key>
- <string>0.9.2</string>
+ <string>0.10.4</string>
</dict>
</plist>
ENDOFHERE
} # SetupMacHfs()
CheckForSIP() {
- if [[ -x "/usr/bin/csrutil" ]] ; then
- local OKToInstall=`/usr/bin/csrutil status | grep "Protection status: enabled (Custom Configuration\|Apple Internal)"`
+ if [[ -x "/usr/bin/csrutil" && -z "$TargetPart" ]] ; then
+ local OKToInstall=`/usr/bin/csrutil status | \
+ grep "Protection status: disabled\|enabled (Apple Internal)\|NVRAM Protections: disabled"`
if [[ -z "$OKToInstall" ]] ; then
echo
echo "**** ALERT: SIP ENABLED! ****"
# Sets Problems=1 if problems found during the installation.
InstallOnOSX() {
echo "Installing rEFInd on OS X...."
- if [[ "$InstallToEspOnMac" == "1" ]] ; then
+ if [[ "$InstallToEspOnMac" == "1" && -z "$TargetPart" ]] ; then
MountOSXESP
elif [[ "$TargetDir" == "/EFI/BOOT" || "$OwnHfs" == '1' ]] ; then
MountDefaultTarget
echo "Installing rEFInd to the partition mounted at $InstallDir"
DetermineTargetDir
CheckForSIP
- Platform=`ioreg -l -p IODeviceTree | grep firmware-abi | cut -d "\"" -f 4`
CopyRefindFiles
- cp "$ThisDir/mountesp" /usr/local/bin
- if [[ $InstallToEspOnMac == "1" ]] ; then
+ mkdir -p /usr/local/bin &> /dev/null
+ cp "$ThisDir/mountesp" /usr/local/bin/ &> /dev/null
+ if [[ $InstallToEspOnMac == "1" && -z "$TargetPart" ]] ; then
bless --mount "$InstallDir" --setBoot --file "$InstallDir/$TargetDir/$Refind" --shortform
elif [[ "$TargetDir" != "/EFI/BOOT" ]] ; then
bless --setBoot --folder "$InstallDir/$TargetDir" --file "$InstallDir/$TargetDir/$Refind"
echo "Not deleting rEFItBlesser."
fi
fi
- echo
- echo "WARNING: If you have an Advanced Format disk, *DO NOT* attempt to check the"
- echo "bless status with 'bless --info', since this is known to cause disk corruption"
- echo "on some systems!!"
- echo
} # InstallOnOSX()
# 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.
CheckSecureBoot() {
- local IsSecureBoot
- if [[ -f /sys/firmware/efi/vars/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c/data ]] ; then
+ IsSecureBoot="0"
+ if [[ -f /sys/firmware/efi/efivars/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c ]] ; then
+ IsSecureBoot=`od -An -t u1 /sys/firmware/efi/efivars/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c | awk '{print substr($0,length,1)}'`
+ elif [[ -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 ""
# Sign a single binary. Requires parameters:
# $1 = source file
# $2 = destination file
-# Also assumes that the SBSign, PESign, UseSBSign, UsePESign, and various key variables are set
-# appropriately.
+# Also assumes that the SBSign and various key variables are set appropriately.
# Aborts script on error
SignOneBinary() {
- $SBSign --key "$PrivateKey" --cert "$CertKey" --output "$2" "$1"
- if [[ $? != 0 ]] ; then
+ $SBSign --key "$PrivateKey" --cert "$CertKey" --output "$2" "$1" 2>&1 >/dev/null | \
+ grep -v "data remaining.*gaps between PE/COFF sections"
+ if [[ "${PIPESTATUS[0]}" != 0 ]] ; then
echo "Problem signing the binary $1! Aborting!"
exit 1
fi
exit 1
fi
GenerateKeys
- mkdir -p "$TempDir/drivers_x64"
+ mkdir -p "$TempDir/drivers_$Platform"
cp "$RefindDir/refind.conf-sample $TempDir" 2> /dev/null
cp "$ThisDir/refind.conf-sample $TempDir" 2> /dev/null
cp "$RefindDir/refind_ia32.efi $TempDir" 2> /dev/null
cp -a "$RefindDir/drivers_ia32 $TempDir" 2> /dev/null
cp -a "$ThisDir/drivers_ia32 $TempDir" 2> /dev/null
- SignOneBinary "$RefindDir/refind_x64.efi" "$TempDir/refind_x64.efi"
+ SignOneBinary "$RefindDir/refind_$Platform.efi" "$TempDir/refind_$Platform.efi"
SaveIFS=$IFS
IFS=$(echo -en "\n\b")
- for Driver in `ls "$RefindDir"/drivers_x64/*.efi "$ThisDir"/drivers_x64/*.efi 2> /dev/null` ; do
+ for Driver in `ls "$RefindDir"/drivers_$Platform/*.efi "$ThisDir"/drivers_$Platform/*.efi 2> /dev/null` ; do
TempName=`basename "$Driver"`
- SignOneBinary "$Driver" "$TempDir/drivers_x64/$TempName"
+ SignOneBinary "$Driver" "$TempDir/drivers_$Platform/$TempName"
done
IFS=$SaveIFS
RefindDir="$TempDir"
# and EspFilesystem the filesystem (always "vfat")
FindLinuxESP() {
echo "The ESP doesn't seem to be mounted! Trying to find it...."
+ local Name
local Drive
local PartNum
local TableType
local DmStatus
local SkipIt
local Dmraid
- for Drive in `ls /dev/[sh]d?` ; do
+ for Name in `lsblk -r | grep disk | cut -f 1 -d " "` ; do
+ Drive="/dev/$Name"
SkipIt=0
Dmraid=`which dmraid 2> /dev/null`
if [ -x "$Dmraid" ] ; then
if [[ $EspFilesystem != 'vfat' ]] ; then
echo "$RootDir/$InstallDir doesn't seem to be on a VFAT filesystem. The ESP must be"
echo "mounted at $RootDir/boot or $RootDir/boot/efi and it must be VFAT! Aborting!"
- exit 1
+ if [[ -d /sys/firmware/efi ]] ; then
+ exit 1
+ else
+ echo "The computer appears to be running in BIOS mode and has no ESP. You should"
+ echo "create an ESP, and ideally boot in EFI mode, before installing rEFInd."
+ exit 0
+ fi
fi
echo "ESP was found at $InstallDir using $EspFilesystem"
} # FindMountedESP
if [[ $EfibootmgrProblems ]] ; then
echo
echo "ALERT: There were problems running the efibootmgr program! You may need to"
- echo "rename the $Refind binary to the default name (EFI/boot/bootx64.efi"
- echo "on x86-64 systems or EFI/boot/bootia32.efi on x86 systems) to have it run!"
+ echo "rename the $Refind binary to the default name (EFI/BOOT/bootx64.efi"
+ echo "on x86-64 systems, EFI/BOOT/bootia32.efi on x86 systems, or"
+ echo "EFI/BOOT/bootaa64.efi on ARM64 systems) to have it run!"
echo
else
echo "rEFInd has been set as the default boot manager."
else
echo "Creating $RLConfFile; edit it to adjust kernel options."
RootFS=`df "$RootDir" | grep dev | cut -f 1 -d " "`
- echo "RootFS starts as $RootFS"
StartOfDevname=`echo "$RootFS" | cut -b 1-7`
if [[ "$StartOfDevname" == "/dev/sd" || "$StartOfDevName" == "/dev/hd" ]] ; then
# Identify root filesystem by UUID rather than by device node, if possible
Uuid=`blkid -o export -s UUID "$RootFS" 2> /dev/null | grep UUID=`
if [[ -n $Uuid ]] ; then
RootFS="$Uuid"
- echo "Uuid is $Uuid"
- echo "Adjusting RootFS to $RootFS"
fi
fi
if [[ $RootDir == "/" ]] ; then
- DefaultOptions=`cat /proc/cmdline | cut -d ' ' -f 2- | sed 's/$/ /' | sed 's/initrd=.* //g' | sed 's/ *$//'`
+ local FirstCmdlineOption=`cat /proc/cmdline | cut -d ' ' -f 1`
+ if [[ "$FirstCmdlineOption" =~ (vmlinuz|bzImage|kernel) ]] ; then
+ DefaultOptions=`cat /proc/cmdline | cut -d ' ' -f 2- | sed 's/\S*initrd=\S*//g' | sed 's/ *$//' | sed 's/^ *//'`
+ else
+ DefaultOptions=`cat /proc/cmdline | sed 's/\S*initrd=\S*//g' | sed 's/ *$//' | sed 's/^ *//'`
+ fi
else
if [[ -f "$RootDir/etc/default/grub" ]] ; then
# We want the default options used by the distribution, stored here....
FindMountedESP
DetermineTargetDir
fi
- CpuType=`uname -m`
- if [[ $CpuType == 'x86_64' ]] ; then
- Platform="EFI64"
- elif [[ ($CpuType == 'i386' || $CpuType == 'i486' || $CpuType == 'i586' || $CpuType == 'i686') ]] ; then
- Platform="EFI32"
- # If we're in EFI mode, do some sanity checks, and alert the user or even
- # abort. Not in BIOS mode, though, since that could be used on an emergency
- # disc to try to recover a troubled Linux installation.
- if [[ -d /sys/firmware/efi ]] ; then
- if [[ "$ShimSource" != "none" && "$TargetDir" != "/BOOT/EFI" ]] ; then
- echo ""
- echo "CAUTION: shim does not currently supports 32-bit systems, so you should not"
- echo "use the --shim option to install on such systems. Aborting!"
- echo ""
- exit 1
- fi
- echo
- echo "CAUTION: This Linux installation uses a 32-bit kernel. 32-bit EFI-based"
- echo "computers are VERY RARE. If you've installed a 32-bit version of Linux"
- echo "on a 64-bit computer, you should manually install the 64-bit version of"
- echo "rEFInd. If you're installing on a Mac, you should do so from OS X. If"
- echo "you're positive you want to continue with this installation, answer 'Y'"
- echo "to the following question..."
- echo
- echo -n "Are you sure you want to continue (Y/N)? "
- ReadYesNo
- if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then
- echo "OK; continuing with the installation..."
- else
- exit 0
- fi
- fi # in EFI mode
- else
- echo "Unknown CPU type '$CpuType'; aborting!"
- exit 1
- fi
if [[ $LocalKeys == 1 ]] ; then
ReSignBinaries
# install under OS X or Linux, depending on the detected platform.
#
GetParams "$@"
-ThisDir="$( cd -P "${BASH_SOURCE%/*}" && pwd )"
-RefindDir="$ThisDir/refind"
if [[ $UID != 0 ]] ; then
echo "Not running as root; attempting to elevate privileges via sudo...."
sudo "$BASH_SOURCE" "$@"
exit 0
fi
fi
+DeterminePlatform
CheckForFiles
case "$OSTYPE" in
darwin*)
if [[ $UnmountEsp == '1' ]] ; then
echo "Unmounting install dir"
- umount $InstallDir
+ case "$OSTYPE" in
+ darwin*)
+ diskutil unmount $InstallDir
+ ;;
+ *)
+ umount $InstallDir
+ ;;
+ esac
fi
if [[ "$InstallDir" == /tmp/refind_install ]] ; then