X-Git-Url: https://code.delx.au/refind/blobdiff_plain/16ed1bfb9ca9b0b491572d515810c3889e652617..142fe053a4e2633defe56c403b0ae6a9d4551cee:/install.sh diff --git a/install.sh b/install.sh index ede3e08..eca8777 100755 --- a/install.sh +++ b/install.sh @@ -29,12 +29,18 @@ # 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 @@ -196,6 +202,7 @@ CheckForFiles() { exit 1 fi + echo "ShimSource is $ShimSource" if [[ "$ShimSource" != "none" ]] ; then if [[ -f "$ShimSource" ]] ; then if [[ $ShimType == "shimx64.efi" || $ShimType == "shim.efi" ]] ; then @@ -220,15 +227,24 @@ 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/" + 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() @@ -241,6 +257,113 @@ CopyKeys() { 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() { @@ -292,6 +415,8 @@ CopyDrivers() { ;; hfsplus) DriverType="hfs" ;; + ntfs) DriverType="ntfs" + ;; *) BootFS="" esac if [[ -n $BootFS ]] ; then @@ -490,8 +615,8 @@ MountOSXESP() { 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 @@ -532,7 +657,7 @@ SetupMacHfs() { ProductName rEFInd ProductVersion - 0.7.6 + 0.8.7 ENDOFHERE @@ -550,10 +675,11 @@ InstallOnOSX() { 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 @@ -589,20 +715,18 @@ InstallOnOSX() { # 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)? " @@ -614,7 +738,7 @@ CheckSecureBoot() { 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" @@ -632,7 +756,7 @@ CheckSecureBoot() { 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" @@ -887,109 +1011,6 @@ 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 - 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() { @@ -1084,11 +1105,6 @@ if [[ $OSName == 'Darwin' ]] ; then 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