]> code.delx.au - refind/blobdiff - install.sh
Version 0.6.1 official release
[refind] / install.sh
index d77b8b0af0f73c152488d3b008dbac39c7c459a6..10b274ef0648bcf1b82a76313a3bce224328f70f 100755 (executable)
@@ -4,7 +4,19 @@
 #
 # Usage:
 #
-# ./install.sh [esp]
+# ./install.sh [options]
+#
+# options include:
+#    "--esp" to install to the ESP rather than to the system's root
+#           filesystem. This is the default on Linux
+#    "--usedefault {devicefile}" to install as default
+#           (/EFI/BOOT/BOOTX64.EFI and similar) to the specified device
+#           (/dev/sdd1 or whatever) without registering with the NVRAM.
+#    "--alldrivers" to install all drivers along with regular files
+#    "--nodrivers" to suppress driver installation (default in Linux is
+#           driver used on /boot; --nodrivers is OS X default)
+#    "--shim {shimfile}" to install a shim.efi file for Secure Boot
+#    "--localkeys" to re-sign x86-64 binaries with a locally-generated key
 #
 # The "esp" option is valid only on Mac OS X; it causes
 # installation to the EFI System Partition (ESP) rather than
 #
 # Revision history:
 #
+# 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
+#            the driver needed to read /boot (if available)
+# 0.5.1.2 -- Fixed bug that caused failure to generate refind_linux.conf file
+# 0.5.1.1 -- Fixed bug that caused script failure under OS X
+# 0.5.1   -- Added --shim & --localkeys options & create sample refind_linux.conf
+#            in /boot
+# 0.5.0   -- Added --usedefault & --drivers options & changed "esp" option to "--esp"
 # 0.4.5   -- Fixed check for rEFItBlesser in OS X
 # 0.4.2   -- Added notice about BIOS-based OSes & made NVRAM changes in Linux smarter
 # 0.4.1   -- Added check for rEFItBlesser in OS X
 # Note: install.sh version numbers match those of the rEFInd package
 # with which they first appeared.
 
+RootDir="/"
 TargetDir=/EFI/refind
+LocalKeysBase="refind_local"
+ShimSource="none"
+TargetX64="refind_x64.efi"
+TargetIA32="refind_ia32.efi"
+LocalKeys=0
+DeleteRefindDir=0
 
 #
 # Functions used by both OS X and Linux....
 #
 
+GetParams() {
+   InstallToEspOnMac=0
+   if [[ $OSName == "Linux" ]] ; then
+      # Install the driver required to read /boot, if it's available
+      InstallDrivers="boot"
+   else
+      InstallDrivers="none"
+   fi
+   while [[ $# -gt 0 ]]; do
+      case $1 in
+         --esp | --ESP) InstallToEspOnMac=1
+              ;;
+         --usedefault) TargetDir=/EFI/BOOT
+              TargetPart=$2
+              TargetX64="bootx64.efi"
+              TargetIA32="bootia32.efi"
+              shift
+              ;;
+         --root) RootDir=$2
+              shift
+              ;;
+         --localkeys) LocalKeys=1
+              ;;
+         --shim) ShimSource=$2
+              shift
+              ;;
+         --drivers | --alldrivers) InstallDrivers="all"
+              ;;
+         --nodrivers) InstallDrivers="none"
+              ;;
+         * ) echo "Usage: $0 [--esp | --usedefault {device-file} | --root {directory} ]"
+             echo "                  [--nodrivers | --alldrivers] [--shim {shim-filename}]"
+             echo "                  [--localkeys]"
+             exit 1
+      esac
+      shift
+   done
+
+   if [[ $InstallToEspOnMac == 1 && $TargetDir == '/EFI/BOOT' ]] ; then
+      echo "You may use --esp OR --usedefault, but not both! Aborting!"
+      exit 1
+   fi
+   if [[ $RootDir != '/' && $TargetDir == '/EFI/BOOT' ]] ; then
+      echo "You may use --usedefault OR --root, but not both! Aborting!"
+      exit 1
+   fi
+   if [[ $RootDir != '/' && $InstallToEspOnMac == 1 ]] ; then
+      echo "You may use --root OR --esp, but not both! Aborting!"
+      exit 1
+   fi
+
+   RLConfFile="$RootDir/boot/refind_linux.conf"
+   EtcKeysDir="$RootDir/etc/refind.d/keys"
+} # GetParams()
+
 # Abort if the rEFInd files can't be found.
-# Also sets $ConfFile to point to the configuration file, and
-# $IconsDir to point to the icons directory
+# 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).
 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
@@ -61,45 +145,148 @@ CheckForFiles() {
       IconsDir=$ThisDir/icons
    else
       echo "The icons directory is missing! Aborting installation!"
+      exit 1
+   fi
+
+   if [[ $ShimSource != "none" ]] ; then
+      if [[ -f $ShimSource ]] ; then
+         TargetX64="grubx64.efi"
+         MokManagerSource=`dirname $ShimSource`/MokManager.efi
+      else
+         echo "The specified shim file, $ShimSource, doesn't exist!"
+         echo "Aborting installation!"
+         exit 1
+      fi
    fi
 } # CheckForFiles()
 
+# Helper for CopyRefindFiles; copies shim files (including MokManager, if it's
+# available) to target.
+CopyShimFiles() {
+   cp $ShimSource $InstallDir/$TargetDir/$TargetShim
+   if [[ $? != 0 ]] ; then
+      Problems=1
+   fi
+   if [[ -f $MokManagerSource ]] ; then
+      cp $MokManagerSource $InstallDir/$TargetDir/
+   fi
+   if [[ $? != 0 ]] ; then
+      Problems=1
+   fi
+} # CopyShimFiles()
+
+# Copy the public keys to the installation medium
+CopyKeys() {
+   if [[ $LocalKeys == 1 ]] ; then
+      mkdir -p $InstallDir/$TargetDir/keys/
+      cp $EtcKeysDir/$LocalKeysBase.cer $InstallDir/$TargetDir/keys/
+      cp $EtcKeysDir/$LocalKeysBase.crt $InstallDir/$TargetDir/keys/
+#    else
+#       cp $ThisDir/refind.cer $InstallDir/$TargetDir/keys/
+#       cp $ThisDir/refind.crt $InstallDir/$TargetDir/keys/
+   fi
+} # CopyKeys()
+
+# Copy drivers from $RefindDir/drivers_$1 to $InstallDir/$TargetDir/drivers_$1,
+# honoring the $InstallDrivers condition. Must be passed a suitable
+# architecture code (ia32 or x64).
+CopyDrivers() {
+   if [[ $InstallDrivers == "all" ]] ; then
+      mkdir -p $InstallDir/$TargetDir/drivers_$1
+      cp $RefindDir/drivers_$1/*_$1.efi $InstallDir/$TargetDir/drivers_$1/ 2> /dev/null
+      cp $ThisDir/drivers_$1/*_$1.efi $InstallDir/$TargetDir/drivers_$1/ 2> /dev/null
+   elif [[ $InstallDrivers == "boot" && -x `which blkid` ]] ; then
+      BootPart=`df /boot | grep dev | cut -f 1 -d " "`
+      BootFS=`blkid -o export $BootPart 2> /dev/null | grep TYPE= | cut -f 2 -d =`
+      DriverType=""
+      case $BootFS in
+         ext2 | ext3 | ext4) DriverType="ext4"
+              ;;
+         reiserfs) DriverType="reiserfs"
+              ;;
+         hfsplus) DriverType="hfs"
+              ;;
+         *) BootFS=""
+      esac
+      if [[ -n $BootFS ]] ; then
+         echo "Installing driver for $BootFS (${DriverType}_$1.efi)"
+         mkdir -p $InstallDir/$TargetDir/drivers_$1
+         cp $RefindDir/drivers_$1/${DriverType}_$1.efi $InstallDir/$TargetDir/drivers_$1/ 2> /dev/null
+         cp $ThisDir/drivers_$1/${DriverType}_$1.efi $InstallDir/$TargetDir/drivers_$1/ 2> /dev/null
+      fi
+   fi
+}
+
 # Copy the rEFInd files to the ESP or OS X root partition.
 # Sets Problems=1 if any critical commands fail.
 CopyRefindFiles() {
-   mkdir -p $InstallPart/$TargetDir &> /dev/null
-   if [[ $Platform == 'EFI32' ]] ; then
-      cp $RefindDir/refind_ia32.efi $InstallPart/$TargetDir
+   mkdir -p $InstallDir/$TargetDir &> /dev/null
+   if [[ $TargetDir == '/EFI/BOOT' ]] ; then
+      cp $RefindDir/refind_ia32.efi $InstallDir/$TargetDir/$TargetIA32 2> /dev/null
+      if [[ $? != 0 ]] ; then
+         echo "Note: IA32 (x86) binary not installed!"
+      fi
+      cp $RefindDir/refind_x64.efi $InstallDir/$TargetDir/$TargetX64 2> /dev/null
       if [[ $? != 0 ]] ; then
          Problems=1
       fi
+      if [[ $ShimSource != "none" ]] ; then
+         TargetShim="bootx64.efi"
+         CopyShimFiles
+      fi
+      if [[ $InstallDrivers == "all" ]] ; then
+         cp -r $RefindDir/drivers_* $InstallDir/$TargetDir/ 2> /dev/null
+         cp -r $ThisDir/drivers_* $InstallDir/$TargetDir/ 2> /dev/null
+      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
-      cp $RefindDir/refind_x64.efi $InstallPart/$TargetDir
+      cp $RefindDir/refind_x64.efi $InstallDir/$TargetDir/$TargetX64
       if [[ $? != 0 ]] ; then
          Problems=1
       fi
+      CopyDrivers x64
       Refind="refind_x64.efi"
+      CopyKeys
+      if [[ $ShimSource != "none" ]] ; then
+         TargetShim=`basename $ShimSource`
+         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
+         fi
+      fi
    else
       echo "Unknown platform! Aborting!"
       exit 1
    fi
-   echo "Copied rEFInd binary file $Refind"
+   echo "Copied rEFInd binary files"
    echo ""
-   if [[ -d $InstallPart/$TargetDir/icons ]] ; then
-      rm -rf $InstallPart/$TargetDir/icons-backup &> /dev/null
-      mv -f $InstallPart/$TargetDir/icons $InstallPart/$TargetDir/icons-backup
+   if [[ -d $InstallDir/$TargetDir/icons ]] ; then
+      rm -rf $InstallDir/$TargetDir/icons-backup &> /dev/null
+      mv -f $InstallDir/$TargetDir/icons $InstallDir/$TargetDir/icons-backup
       echo "Notice: Backed up existing icons directory as icons-backup."
    fi
-   cp -r $IconsDir $InstallPart/$TargetDir
+   cp -r $IconsDir $InstallDir/$TargetDir
    if [[ $? != 0 ]] ; then
       Problems=1
    fi
-   if [[ -f $InstallPart/$TargetDir/refind.conf ]] ; then
+   cp -rf $ThisDir/keys $InstallDir/$TargetDir/
+   if [[ -f $InstallDir/$TargetDir/refind.conf ]] ; then
       echo "Existing refind.conf file found; copying sample file as refind.conf-sample"
-      echo "to avoid collision."
+      echo "to avoid overwriting your customizations."
       echo ""
-      cp -f $ConfFile $InstallPart/$TargetDir
+      cp -f $ConfFile $InstallDir/$TargetDir
       if [[ $? != 0 ]] ; then
          Problems=1
       fi
@@ -107,13 +294,33 @@ CopyRefindFiles() {
       echo "Copying sample configuration file as refind.conf; edit this file to configure"
       echo "rEFInd."
       echo ""
-      cp -f $ConfFile $InstallPart/$TargetDir/refind.conf
+      cp -f $ConfFile $InstallDir/$TargetDir/refind.conf
       if [[ $? != 0 ]] ; then
          Problems=1
       fi
    fi
+   if [[ $DeleteRefindDir == 1 ]] ; then
+      echo "Deleting the temporary directory $RefindDir"
+      rm -r $RefindDir
+   fi
 } # CopyRefindFiles()
 
+# Mount the partition the user specified with the --usedefault option
+MountDefaultTarget() {
+   InstallDir=/tmp/refind_install
+   mkdir -p $InstallDir
+   if [[ $OSName == 'Darwin' ]] ; then
+      mount -t msdos $TargetPart $InstallDir
+   elif [[ $OSName == 'Linux' ]] ; then
+      mount -t vfat $TargetPart $InstallDir
+   fi
+   if [[ $? != 0 ]] ; then
+      echo "Couldn't mount $TargetPart ! Aborting!"
+      rmdir $InstallDir
+      exit 1
+   fi
+   UnmountEsp=1
+} # MountDefaultTarget()
 
 #
 # A series of OS X support functions....
@@ -121,7 +328,7 @@ CopyRefindFiles() {
 
 # Mount the ESP at /Volumes/ESP or determine its current mount
 # point.
-# Sets InstallPart to the ESP mount point
+# Sets InstallDir to the ESP mount point
 # Sets UnmountEsp if we mounted it
 MountOSXESP() {
    # Identify the ESP. Note: This returns the FIRST ESP found;
@@ -130,8 +337,8 @@ MountOSXESP() {
    Esp=/dev/`echo $Temp | cut -f 5 -d ' '`
    # If the ESP is mounted, use its current mount point....
    Temp=`df | grep $Esp`
-   InstallPart=`echo $Temp | cut -f 6 -d ' '`
-   if [[ $InstallPart == '' ]] ; then
+   InstallDir=`echo $Temp | cut -f 6 -d ' '`
+   if [[ $InstallDir == '' ]] ; then
       mkdir /Volumes/ESP &> /dev/null
       mount -t msdos $Esp /Volumes/ESP
       if [[ $? != 0 ]] ; then
@@ -139,7 +346,7 @@ MountOSXESP() {
          exit 1
       fi
       UnmountEsp=1
-      InstallPart="/Volumes/ESP"
+      InstallDir="/Volumes/ESP"
    fi
 } # MountOSXESP()
 
@@ -147,18 +354,20 @@ MountOSXESP() {
 # Sets Problems=1 if problems found during the installation.
 InstallOnOSX() {
    echo "Installing rEFInd on OS X...."
-   if [[ $1 == 'esp' || $1 == 'ESP' ]] ; then
+   if [[ $TargetDir == "/EFI/BOOT" ]] ; then
+      MountDefaultTarget
+   elif [[ $InstallToEspOnMac == "1" ]] ; then
       MountOSXESP
    else
-      InstallPart="/"
+      InstallDir="$RootDir/"
    fi
-   echo "Installing rEFInd to the partition mounted at '$InstallPart'"
+   echo "Installing rEFInd to the partition mounted at '$InstallDir'"
    Platform=`ioreg -l -p IODeviceTree | grep firmware-abi | cut -d "\"" -f 4`
    CopyRefindFiles
-   if [[ $1 == 'esp' || $1 == 'ESP' ]] ; then
-      bless --mount $InstallPart --setBoot --file $InstallPart/$TargetDir/$Refind
-   else
-      bless --setBoot --folder $InstallPart/$TargetDir --file $InstallPart/$TargetDir/$Refind
+   if [[ $InstallToEspOnMac == "1" ]] ; then
+      bless --mount $InstallDir --setBoot --file $InstallDir/$TargetDir/$Refind
+   elif [[ $TargetDir != "/EFI/BOOT" ]] ; then
+      bless --setBoot --folder $InstallDir/$TargetDir --file $InstallDir/$TargetDir/$Refind
    fi
    if [[ $? != 0 ]] ; then
       Problems=1
@@ -171,7 +380,7 @@ InstallOnOSX() {
       read YesNo
       if [[ $YesNo == "Y" || $YesNo == "y" ]] ; then
          echo "Deleting /Library/StartupItems/rEFItBlesser..."
-        rm -r /Library/StartupItems/rEFItBlesser
+         rm -r /Library/StartupItems/rEFItBlesser
       else
          echo "Not deleting rEFItBlesser."
       fi
@@ -181,11 +390,6 @@ InstallOnOSX() {
    echo "bless status with 'bless --info', since this is known to cause disk corruption"
    echo "on some systems!!"
    echo
-   echo "NOTE: If you want to boot an OS via BIOS emulation (such as Windows or some"
-   echo "Linux installations), you *MUST* edit the $InstallPart/$TargetDir/refind.conf"
-   echo "file's 'scanfor' line to include the 'hdbios' option, and perhaps"
-   echo "'biosexternal' and 'cd', as well."
-   echo
 } # InstallOnOSX()
 
 
@@ -193,19 +397,175 @@ InstallOnOSX() {
 # Now a series of Linux support functions....
 #
 
-# Identifies the ESP's location (/boot or /boot/efi); aborts if
-# the ESP isn't mounted at either location.
-# Sets InstallPart to the ESP mount point.
+# Check for evidence that we're running in Secure Boot mode. If so, and if
+# 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
+      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 "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
+         echo "OK; continuing with the installation..."
+      else
+         exit 0
+      fi
+   fi
+
+   if [[ $ShimSource != "none" && ! -n $VarFile ]] ; 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"
+      echo "should work, it's unnecessarily complex. You may continue, but unless you"
+      echo "plan to enable Secure Boot, you should consider stopping and omitting the"
+      echo "--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)? "
+      read ContYN
+      if [[ $ContYN == "Y" || $ContYN == "y" ]] ; then
+         echo "OK; continuing with the installation..."
+      else
+         exit 0
+      fi
+   fi
+
+   if [[ $LocalKeys != 0 && ! -n $VarFile ]] ; 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"
+      echo "keys you generate will be useless unless you enable Secure Boot. You may"
+      echo "proceed with this installation, but before you do so, you may want to read"
+      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
+         echo "OK; continuing with the installation..."
+      else
+         exit 0
+      fi
+   fi
+
+} # CheckSecureBoot()
+
+# Check for the presence of locally-generated keys from a previous installation in
+# $EtcKeysDir (/etc/refind.d/keys). If they're not present, generate them using
+# openssl.
+GenerateKeys() {
+   PrivateKey=$EtcKeysDir/$LocalKeysBase.key
+   CertKey=$EtcKeysDir/$LocalKeysBase.crt
+   DerKey=$EtcKeysDir/$LocalKeysBase.cer
+   OpenSSL=`which openssl 2> /dev/null`
+
+   # Do the work only if one or more of the necessary keys is missing
+   # TODO: Technically, we don't need the DerKey; but if it's missing and openssl
+   # is also missing, this will fail. This could be improved.
+   if [[ ! -f $PrivateKey || ! -f $CertKey || ! -f $DerKey ]] ; then
+      echo "Generating a fresh set of local keys...."
+      mkdir -p $EtcKeysDir
+      chmod 0700 $EtcKeysDir
+      if [[ ! -x $OpenSSL ]] ; then
+         echo "Can't find openssl, which is required to create your private signing keys!"
+         echo "Aborting!"
+         exit 1
+      fi
+      if [[ -f $PrivateKey ]] ; then
+         echo "Backing up existing $PrivateKey"
+         cp -f $PrivateKey $PrivateKey.backup 2> /dev/null
+      fi
+      if [[ -f $CertKey ]] ; then
+         echo "Backing up existing $CertKey"
+         cp -f $CertKey $CertKey.backup 2> /dev/null
+      fi
+      if [[ -f $DerKey ]] ; then
+         echo "Backing up existing $DerKey"
+         cp -f $DerKey $DerKey.backup 2> /dev/null
+      fi
+      $OpenSSL req -new -x509 -newkey rsa:2048 -keyout $PrivateKey -out $CertKey \
+                   -nodes -days 3650 -subj "/CN=Locally-generated rEFInd key/"
+      $OpenSSL x509 -in $CertKey -out $DerKey -outform DER
+      chmod 0600 $PrivateKey
+   else
+      echo "Using existing local keys...."
+   fi
+}
+
+# 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.
+# Aborts script on error
+SignOneBinary() {
+   $SBSign --key $PrivateKey --cert $CertKey --output $2 $1
+   if [[ $? != 0 ]] ; then
+      echo "Problem signing the binary $1! Aborting!"
+      exit 1
+   fi
+}
+
+# Re-sign the x86-64 binaries with a locally-generated key, First look for appropriate
+# key files in $EtcKeysDir. If they're present, use them to re-sign the binaries. If
+# not, try to generate new keys and store them in $EtcKeysDir.
+ReSignBinaries() {
+   SBSign=`which sbsign 2> /dev/null`
+   echo "Found sbsign at $SBSign"
+   TempDir="/tmp/refind_local"
+   if [[ ! -x $SBSign ]] ; then
+      echo "Can't find sbsign, which is required to sign rEFInd with your own keys!"
+      echo "Aborting!"
+      exit 1
+   fi
+   GenerateKeys
+   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 -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
+   for Driver in `ls $RefindDir/drivers_x64/*.efi $ThisDir/drivers_x64/*.efi 2> /dev/null` ; do
+      TempName=`basename $Driver`
+      SignOneBinary $Driver $TempDir/drivers_x64/$TempName
+   done
+   RefindDir=$TempDir
+   DeleteRefindDir=1
+}
+
+# Identifies the ESP's location (/boot or /boot/efi, or these locations under
+# the directory specified by --root); aborts if the ESP isn't mounted at
+# either location.
+# Sets InstallDir to the ESP mount point.
 FindLinuxESP() {
-   EspLine=`df /boot/efi | grep boot`
-   InstallPart=`echo $EspLine | cut -d " " -f 6`
-   EspFilesystem=`grep $InstallPart /etc/mtab | cut -d " " -f 3`
+   EspLine=`df $RootDir/boot/efi 2> /dev/null | grep boot/efi`
+   if [[ ! -n $EspLine ]] ; then
+      EspLine=`df $RootDir/boot | grep boot`
+   fi
+   InstallDir=`echo $EspLine | cut -d " " -f 6`
+   if [[ -n $InstallDir ]] ; then
+      EspFilesystem=`grep $InstallDir /etc/mtab | cut -d " " -f 3`
+   fi
    if [[ $EspFilesystem != 'vfat' ]] ; then
-      echo "/boot/efi doesn't seem to be on a VFAT filesystem. The ESP must be mounted at"
-      echo "/boot or /boot/efi and it must be VFAT! Aborting!"
+      echo "$RootDir/boot/efi 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
    fi
-   echo "ESP was found at $InstallPart using $EspFilesystem"
+   echo "ESP was found at $InstallDir using $EspFilesystem"
 } # MountLinuxESP
 
 # Uses efibootmgr to add an entry for rEFInd to the EFI's NVRAM.
@@ -215,13 +575,16 @@ AddBootEntry() {
    Efibootmgr=`which efibootmgr 2> /dev/null`
    if [[ $Efibootmgr ]] ; then
       modprobe efivars &> /dev/null
-      InstallDisk=`grep $InstallPart /etc/mtab | cut -d " " -f 1 | cut -c 1-8`
-      PartNum=`grep $InstallPart /etc/mtab | cut -d " " -f 1 | cut -c 9-10`
+      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`
-      if [[ $ExistingEntry ]] ; then
+      # 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
          ExistingEntryBootNum=`echo $ExistingEntry | cut -c 5-8`
          FirstBoot=`$Efibootmgr | grep BootOrder | cut -c 12-15`
          if [[ $ExistingEntryBootNum != $FirstBoot ]] ; then
@@ -230,7 +593,7 @@ AddBootEntry() {
             echo "manager. If this is NOT what you want, you should use efibootmgr to"
             echo "manually adjust your EFI's boot order."
             $Efibootmgr -b $ExistingEntryBootNum -B &> /dev/null
-           InstallIt="1"
+            InstallIt="1"
          fi
       else
          InstallIt="1"
@@ -256,15 +619,52 @@ AddBootEntry() {
    fi
 } # AddBootEntry()
 
+# Create a minimal/sample refind_linux.conf file in /boot.
+GenerateRefindLinuxConf() {
+   if [[ ! -f $RLConfFile ]] ; then
+      if [[ -f "$RootDir/etc/default/grub" ]] ; then
+         # We want the default options used by the distribution, stored here....
+         source "$RootDir/etc/default/grub"
+      fi
+      RootFS=`df $RootDir | grep dev | cut -f 1 -d " "`
+      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 $RootFS 2> /dev/null | grep UUID=`
+         if [[ -n $Uuid ]] ; then
+            RootFS=$Uuid
+         fi
+      fi
+      DefaultOptions="$GRUB_CMDLINE_LINUX $GRUB_CMDLINE_LINUX_DEFAULT"
+      echo "\"Boot with standard options\" \"ro root=$RootFS $DefaultOptions \"" > $RLConfFile
+      echo "\"Boot to single-user mode\"   \"ro root=$RootFS $DefaultOptions single\"" >> $RLConfFile
+      echo "\"Boot with minimal options\"  \"ro root=$RootFS\"" >> $RLConfFile
+   fi
+}
+
 # Controls rEFInd installation under Linux.
 # Sets Problems=1 if something goes wrong.
 InstallOnLinux() {
    echo "Installing rEFInd on Linux...."
-   FindLinuxESP
+   if [[ $TargetDir == "/EFI/BOOT" ]] ; then
+      MountDefaultTarget
+   else
+      FindLinuxESP
+   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
       Platform="EFI32"
       echo
       echo "CAUTION: This Linux installation uses a 32-bit kernel. 32-bit EFI-based"
@@ -285,8 +685,12 @@ InstallOnLinux() {
       echo "Unknown CPU type '$CpuType'; aborting!"
       exit 1
    fi
+   CheckSecureBoot
    CopyRefindFiles
-   AddBootEntry
+   if [[ $TargetDir != "/EFI/BOOT" ]] ; then
+      AddBootEntry
+      GenerateRefindLinuxConf
+   fi
 } # InstallOnLinux()
 
 #
@@ -296,13 +700,13 @@ InstallOnLinux() {
 #
 
 OSName=`uname -s`
+GetParams $@
 ThisDir="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
 RefindDir="$ThisDir/refind"
 ThisScript="$ThisDir/`basename $0`"
-CheckForFiles
 if [[ `whoami` != "root" ]] ; then
    echo "Not running as root; attempting to elevate privileges via sudo...."
-   sudo $ThisScript $1
+   sudo $ThisScript "$@"
    if [[ $? != 0 ]] ; then
       echo "This script must be run as root (or using sudo). Exiting!"
       exit 1
@@ -310,7 +714,16 @@ if [[ `whoami` != "root" ]] ; then
       exit 0
    fi
 fi
+CheckForFiles
 if [[ $OSName == 'Darwin' ]] ; then
+   if [[ $ShimSource != "none" ]] ; then
+      echo "The --shim option is not supported on OS X! Exiting!"
+      exit 1
+   fi
+   if [[ $LocalKeys != 0 ]] ; then
+      echo "The --localkeys option is not supported on OS X! Exiting!"
+      exit 1
+   fi
    InstallOnOSX $1
 elif [[ $OSName == 'Linux' ]] ; then
    InstallOnLinux
@@ -332,5 +745,11 @@ else
 fi
 
 if [[ $UnmountEsp ]] ; then
-   umount $InstallPart
+   echo "Unmounting install dir"
+   umount $InstallDir
+fi
+
+if [[ $InstallDir == /tmp/refind_install ]] ; then
+#   sleep 5
+   rmdir $InstallDir
 fi