X-Git-Url: https://code.delx.au/refind/blobdiff_plain/b2410fb7695fb349a65a2749e9524f250a4f6420..71f1ea86f5e97c4da1adadcc62685c4030f2d740:/install.sh diff --git a/install.sh b/install.sh index d89c9ed..66d3e9c 100755 --- a/install.sh +++ b/install.sh @@ -29,6 +29,13 @@ # # Revision history: # +# 0.6.9 -- Install gptsync on Macs if evidence of Windows found +# 0.6.8 -- Bug fix: ESP scan now uses "uniq". +# 0.6.6 -- Bug fix: Upgrade drivers when installed to EFI/BOOT. Also enable +# copying shim.efi and MokManager.efi over themselves. +# 0.6.4 -- Copies ext2 driver rather than ext4 driver for ext2/3fs +# 0.6.3 -- Support for detecting rEFInd in EFI/BOOT and EFI/Microsoft/Boot +# directories & for installing to EFI/BOOT in BIOS mode # 0.6.2-1 -- Added --yes option & tweaked key-copying for use with RPM install script # 0.6.1 -- Added --root option; minor bug fixes # 0.6.0 -- Changed --drivers to --alldrivers and added --nodrivers option; @@ -53,6 +60,7 @@ RootDir="/" TargetDir=/EFI/refind LocalKeysBase="refind_local" ShimSource="none" +TargetShim="default" TargetX64="refind_x64.efi" TargetIA32="refind_ia32.efi" LocalKeys=0 @@ -179,12 +187,12 @@ CheckForFiles() { # Helper for CopyRefindFiles; copies shim files (including MokManager, if it's # available) to target. CopyShimFiles() { - cp $ShimSource $InstallDir/$TargetDir/$TargetShim + cp -fb $ShimSource $InstallDir/$TargetDir/$TargetShim if [[ $? != 0 ]] ; then Problems=1 fi if [[ -f $MokManagerSource ]] ; then - cp $MokManagerSource $InstallDir/$TargetDir/ + cp -fb $MokManagerSource $InstallDir/$TargetDir/ fi if [[ $? != 0 ]] ; then Problems=1 @@ -216,7 +224,11 @@ CopyDrivers() { BootFS=`blkid -o export $BootPart 2> /dev/null | grep TYPE= | cut -f 2 -d =` DriverType="" case $BootFS in - ext2 | ext3 | ext4) DriverType="ext4" + 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" ;; @@ -233,6 +245,20 @@ CopyDrivers() { fi } +# 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. CopyRefindFiles() { @@ -253,26 +279,30 @@ CopyRefindFiles() { if [[ $InstallDrivers == "all" ]] ; then cp -r $RefindDir/drivers_* $InstallDir/$TargetDir/ 2> /dev/null cp -r $ThisDir/drivers_* $InstallDir/$TargetDir/ 2> /dev/null + elif [[ $Upgrade == 1 ]] ; then + if [[ $Platform == 'EFI64' ]] ; then + CopyDrivers x64 + CopyTools x64 + else + CopyDrivers ia32 + CopyTools ia32 + fi fi Refind="" CopyKeys - elif [[ $Platform == 'EFI32' ]] ; then - cp $RefindDir/refind_ia32.efi $InstallDir/$TargetDir/$TargetIA32 - if [[ $? != 0 ]] ; then - Problems=1 - fi - CopyDrivers ia32 - Refind="refind_ia32.efi" - elif [[ $Platform == 'EFI64' ]] ; then + elif [[ $Platform == 'EFI64' || $TargetDir == "/EFI/Microsoft/Boot" ]] ; then cp $RefindDir/refind_x64.efi $InstallDir/$TargetDir/$TargetX64 if [[ $? != 0 ]] ; then Problems=1 fi CopyDrivers x64 + CopyTools x64 Refind="refind_x64.efi" CopyKeys if [[ $ShimSource != "none" ]] ; then - TargetShim=`basename $ShimSource` + if [[ $TargetShim == "default" ]] ; then + TargetShim=`basename $ShimSource` + fi CopyShimFiles Refind=$TargetShim if [[ $LocalKeys == 0 ]] ; then @@ -282,6 +312,14 @@ CopyRefindFiles() { cp $ThisDir/keys/refind.crt $EtcKeysDir 2> /dev/null fi fi + elif [[ $Platform == 'EFI32' ]] ; then + cp $RefindDir/refind_ia32.efi $InstallDir/$TargetDir/$TargetIA32 + if [[ $? != 0 ]] ; then + Problems=1 + fi + CopyDrivers ia32 + CopyTools ia32 + Refind="refind_ia32.efi" else echo "Unknown platform! Aborting!" exit 1 @@ -553,7 +591,7 @@ ReSignBinaries() { mkdir -p $TempDir/drivers_x64 cp $RefindDir/refind.conf-sample $TempDir 2> /dev/null cp $ThisDir/refind.conf-sample $TempDir 2> /dev/null - cp $RefindDir/refind_ia32.efi $TempDir + 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 @@ -576,7 +614,7 @@ FindLinuxESP() { fi InstallDir=`echo $EspLine | cut -d " " -f 6` if [[ -n $InstallDir ]] ; then - EspFilesystem=`grep $InstallDir /etc/mtab | cut -d " " -f 3` + EspFilesystem=`grep $InstallDir /etc/mtab | uniq | cut -d " " -f 3` fi if [[ $EspFilesystem != 'vfat' ]] ; then echo "$RootDir/boot/efi doesn't seem to be on a VFAT filesystem. The ESP must be" @@ -584,7 +622,7 @@ FindLinuxESP() { exit 1 fi echo "ESP was found at $InstallDir using $EspFilesystem" -} # MountLinuxESP +} # FindLinuxESP # Uses efibootmgr to add an entry for rEFInd to the EFI's NVRAM. # If this fails, sets Problems=1 @@ -592,17 +630,14 @@ AddBootEntry() { InstallIt="0" Efibootmgr=`which efibootmgr 2> /dev/null` if [[ $Efibootmgr ]] ; then - modprobe efivars &> /dev/null InstallDisk=`grep $InstallDir /etc/mtab | cut -d " " -f 1 | cut -c 1-8` PartNum=`grep $InstallDir /etc/mtab | cut -d " " -f 1 | cut -c 9-10` EntryFilename=$TargetDir/$Refind EfiEntryFilename=`echo ${EntryFilename//\//\\\}` EfiEntryFilename2=`echo ${EfiEntryFilename} | sed s/\\\\\\\\/\\\\\\\\\\\\\\\\/g` - ExistingEntry=`$Efibootmgr -v | grep $EfiEntryFilename2` - # NOTE: Below protects against duplicate entries, but only for non-Secure Boot - # installations. - # TODO: Improve to detect & protect against duplicating a Secure Boot entry. - if [[ $ExistingEntry && $ShimSource == "none" ]] ; then + ExistingEntry=`$Efibootmgr -v | grep -i $EfiEntryFilename2` + + if [[ $ExistingEntry ]] ; then ExistingEntryBootNum=`echo $ExistingEntry | cut -c 5-8` FirstBoot=`$Efibootmgr | grep BootOrder | cut -c 12-15` if [[ $ExistingEntryBootNum != $FirstBoot ]] ; then @@ -616,18 +651,21 @@ AddBootEntry() { else InstallIt="1" fi + if [[ $InstallIt == "1" ]] ; then echo "Installing it!" - $Efibootmgr -c -l $EfiEntryFilename -L rEFInd -d $InstallDisk -p $PartNum &> /dev/null + $Efibootmgr -c -l $EfiEntryFilename -L "rEFInd Boot Manager" -d $InstallDisk -p $PartNum &> /dev/null if [[ $? != 0 ]] ; then EfibootmgrProblems=1 Problems=1 fi fi - else + + else # efibootmgr not found EfibootmgrProblems=1 Problems=1 fi + if [[ $EfibootmgrProblems ]] ; then echo echo "ALERT: There were problems running the efibootmgr program! You may need to" @@ -662,52 +700,148 @@ GenerateRefindLinuxConf() { fi } +# Set varaibles for installation in EFI/BOOT directory +SetVarsForBoot() { + TargetDir="/EFI/BOOT" + if [[ $ShimSource == "none" ]] ; then + TargetX64="bootx64.efi" + TargetIA32="bootia32.efi" + else + TargetX64="grubx64.efi" + 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 + TargetX64="grubx64.efi" + 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() { echo "Installing rEFInd on Linux...." + modprobe efivars &> /dev/null if [[ $TargetDir == "/EFI/BOOT" ]] ; then MountDefaultTarget else FindLinuxESP + DetermineTargetDir fi CpuType=`uname -m` if [[ $CpuType == 'x86_64' ]] ; then Platform="EFI64" - if [[ $LocalKeys == 1 ]] ; then - ReSignBinaries - fi - elif [[ $CpuType == 'i386' || $CpuType == 'i486' || $CpuType == 'i586' || $CpuType == 'i686' ]] ; then - if [[ $ShimSource != "none" && $TargetDir != "/BOOT/EFI" ]] ; then - echo "" - echo "CAUTION: Neither rEFInd nor shim currently supports 32-bit systems, so you" - echo "should not use the --shim option to install on such systems. Aborting!" - echo "" - exit 1 - fi + elif [[ ($CpuType == 'i386' || $CpuType == 'i486' || $CpuType == 'i586' || $CpuType == 'i686') ]] ; then Platform="EFI32" - 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 + # 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: Neither rEFInd nor shim currently supports 32-bit systems, so you" + echo "should not 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 + fi + CheckSecureBoot CopyRefindFiles - if [[ $TargetDir != "/EFI/BOOT" ]] ; then + if [[ $TargetDir != "/EFI/BOOT" && $TargetDir != "/EFI/Microsoft/Boot" ]] ; then AddBootEntry GenerateRefindLinuxConf fi