]> code.delx.au - refind/blobdiff - refind-install
Fix for refind-install script to handle a wider range of disk devices,
[refind] / refind-install
index f0fc2b22ace0c795927101e13adc905a3971d8d5..19da6a0b09d225cfbfde70caff12b70b3dd7b649 100755 (executable)
 # 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.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. Also change way refind_linux.conf default
@@ -176,6 +186,17 @@ GetParams() {
       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()
@@ -192,6 +213,71 @@ ReadYesNo() {
    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,
@@ -212,11 +298,8 @@ CheckForFiles() {
            ;;
    esac
    RefindDir="$ThisDir/refind"
-   # 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
+
+   if [[ ! -f "$RefindDir/refind_$Platform.efi" ]] ; then
       echo "The rEFInd binary file is missing! Aborting installation!"
       exit 1
    fi
@@ -244,6 +327,7 @@ CheckForFiles() {
       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"
@@ -300,9 +384,11 @@ SetVarsForBoot() {
    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
@@ -311,7 +397,7 @@ SetVarsForBoot() {
          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!"
@@ -325,9 +411,11 @@ SetVarsForMsBoot() {
    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
@@ -369,6 +457,7 @@ DetermineTargetDir() {
       if [[ $ShimSource == "none" || $KeepName == 1 ]] ; then
          TargetX64="refind_x64.efi"
          TargetIA32="refind_ia32.efi"
+         TargetAARCH64="refind_aa64.efi"
       fi
       Upgrade=1
    fi
@@ -503,6 +592,10 @@ CopyRefindFiles() {
       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
@@ -511,22 +604,12 @@ CopyRefindFiles() {
          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
@@ -551,14 +634,21 @@ CopyRefindFiles() {
       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
@@ -705,14 +795,14 @@ SetupMacHfs() {
         <key>ProductName</key>
         <string>rEFInd</string>
         <key>ProductVersion</key>
-        <string>0.10.0</string>
+        <string>0.10.3</string>
 </dict>
 </plist>
 ENDOFHERE
 } # SetupMacHfs()
 
 CheckForSIP() {
-   if [[ -x "/usr/bin/csrutil" ]] ; then
+   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
@@ -765,7 +855,7 @@ CheckForSIP() {
 # 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
@@ -775,10 +865,10 @@ InstallOnOSX() {
    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 &> /dev/null
-   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"
@@ -799,11 +889,6 @@ InstallOnOSX() {
          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()
 
 
@@ -816,11 +901,11 @@ 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 ""
@@ -920,12 +1005,12 @@ GenerateKeys() {
 # 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
@@ -944,18 +1029,18 @@ ReSignBinaries() {
       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"
@@ -968,13 +1053,15 @@ ReSignBinaries() {
 # 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
@@ -1025,7 +1112,13 @@ FindMountedESP() {
    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
@@ -1075,8 +1168,9 @@ AddBootEntry() {
    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."
@@ -1134,41 +1228,6 @@ InstallOnLinux() {
       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 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
-   else
-      echo "Unknown CPU type '$CpuType'; aborting!"
-      exit 1
-   fi
 
    if [[ $LocalKeys == 1 ]] ; then
       ReSignBinaries
@@ -1198,6 +1257,7 @@ if [[ $UID != 0 ]] ; then
       exit 0
    fi
 fi
+DeterminePlatform
 CheckForFiles
 case "$OSTYPE" in
    darwin*)