X-Git-Url: https://code.delx.au/refind/blobdiff_plain/99a75c0d391580161f651db61bb43afb46f4e5cd..119f040f3c096ef2ab59f5d02059e9d872047dcd:/install.sh diff --git a/install.sh b/install.sh index 0559d58..8268e40 100755 --- a/install.sh +++ b/install.sh @@ -29,6 +29,10 @@ # # Revision history: # +# 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; # changed default driver installation behavior in Linux to install @@ -52,10 +56,12 @@ RootDir="/" TargetDir=/EFI/refind LocalKeysBase="refind_local" ShimSource="none" +TargetShim="default" TargetX64="refind_x64.efi" TargetIA32="refind_ia32.efi" LocalKeys=0 DeleteRefindDir=0 +AlwaysYes=0 # # Functions used by both OS X and Linux.... @@ -91,9 +97,11 @@ GetParams() { ;; --nodrivers) InstallDrivers="none" ;; + --yes) AlwaysYes=1 + ;; * ) echo "Usage: $0 [--esp | --usedefault {device-file} | --root {directory} ]" echo " [--nodrivers | --alldrivers] [--shim {shim-filename}]" - echo " [--localkeys]" + echo " [--localkeys] [--yes]" exit 1 esac shift @@ -116,6 +124,18 @@ GetParams() { 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 @@ -200,12 +220,17 @@ 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" ;; hfsplus) DriverType="hfs" ;; + *) BootFS="" esac if [[ -n $BootFS ]] ; then echo "Installing driver for $BootFS (${DriverType}_$1.efi)" @@ -219,7 +244,7 @@ CopyDrivers() { # Copy the rEFInd files to the ESP or OS X root partition. # Sets Problems=1 if any critical commands fail. CopyRefindFiles() { - mkdir -p $InstallDir/$TargetDir &> /dev/null + mkdir -p $InstallDir/$TargetDir if [[ $TargetDir == '/EFI/BOOT' ]] ; then cp $RefindDir/refind_ia32.efi $InstallDir/$TargetDir/$TargetIA32 2> /dev/null if [[ $? != 0 ]] ; then @@ -239,14 +264,7 @@ CopyRefindFiles() { 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 @@ -255,16 +273,25 @@ CopyRefindFiles() { 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 echo "Storing copies of rEFInd Secure Boot public keys in $EtcKeysDir" mkdir -p $EtcKeysDir - cp $ThisDir/keys/refind.cer $EtcKeysDir - cp $ThisDir/keys/refind.crt $EtcKeysDir + cp $ThisDir/keys/refind.cer $EtcKeysDir 2> /dev/null + 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 + Refind="refind_ia32.efi" else echo "Unknown platform! Aborting!" exit 1 @@ -280,7 +307,9 @@ CopyRefindFiles() { if [[ $? != 0 ]] ; then Problems=1 fi - cp -rf $ThisDir/keys $InstallDir/$TargetDir/ + mkdir -p $InstallDir/$TargetDir/keys + cp -rf $ThisDir/keys/*.[cd]er $InstallDir/$TargetDir/keys/ 2> /dev/null + cp -rf $EtcKeysDir/*.[cd]er $InstallDir/$TargetDir/keys/ 2> /dev/null if [[ -f $InstallDir/$TargetDir/refind.conf ]] ; then echo "Existing refind.conf file found; copying sample file as refind.conf-sample" echo "to avoid overwriting your customizations." @@ -376,7 +405,7 @@ InstallOnOSX() { echo "/Library/StartupItems/rEFItBlesser found!" echo "This program is part of rEFIt, and will cause rEFInd to fail to work after" echo -n "its first boot. Do you want to remove rEFItBlesser (Y/N)? " - read YesNo + ReadYesNo if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then echo "Deleting /Library/StartupItems/rEFItBlesser..." rm -r /Library/StartupItems/rEFItBlesser @@ -417,8 +446,8 @@ CheckSecureBoot() { echo "http://www.rodsbooks.com/refind/secureboot.html." echo "" echo -n "Do you want to proceed with installation (Y/N)? " - read ContYN - if [[ $ContYN == "Y" || $ContYN == "y" ]] ; then + ReadYesNo + if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then echo "OK; continuing with the installation..." else exit 0 @@ -435,8 +464,8 @@ CheckSecureBoot() { echo "http://www.rodsbooks.com/refind/secureboot.html." echo "" echo -n "Do you want to proceed with installation (Y/N)? " - read ContYN - if [[ $ContYN == "Y" || $ContYN == "y" ]] ; then + ReadYesNo + if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then echo "OK; continuing with the installation..." else exit 0 @@ -452,8 +481,8 @@ CheckSecureBoot() { echo "more about it at http://www.rodsbooks.com/refind/secureboot.html." echo "" echo -n "Do you want to proceed with installation (Y/N)? " - read ContYN - if [[ $ContYN == "Y" || $ContYN == "y" ]] ; then + ReadYesNo + if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then echo "OK; continuing with the installation..." else exit 0 @@ -534,7 +563,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 @@ -565,7 +594,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 @@ -573,17 +602,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 @@ -597,18 +623,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" @@ -620,10 +649,12 @@ AddBootEntry() { # Create a minimal/sample refind_linux.conf file in /boot. GenerateRefindLinuxConf() { - if [[ ! -f $RLConfFile ]] ; then - if [[ -f /etc/default/grub ]] ; then + if [[ -f $RLConfFile ]] ; then + echo "Existing $RLConfFile found; not overwriting." + else + if [[ -f "$RootDir/etc/default/grub" ]] ; then # We want the default options used by the distribution, stored here.... - source /etc/default/grub + source "$RootDir/etc/default/grub" fi RootFS=`df $RootDir | grep dev | cut -f 1 -d " "` StartOfDevname=`echo $RootFS | cut -b 1-7` @@ -641,52 +672,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)? " - read ContYN - if [[ $ContYN == "Y" || $ContYN == "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