]> code.delx.au - refind/blobdiff - install.sh
Version 0.6.1 official release
[refind] / install.sh
index 76fc27bda90f683532ff073fc4e964a38d8115b3..10b274ef0648bcf1b82a76313a3bce224328f70f 100755 (executable)
 #    "--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
-#    "--drivers" to install drivers along with regular files
+#           (/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.5.1   -- Added --shim option
+# 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
@@ -38,8 +48,8 @@
 # Note: install.sh version numbers match those of the rEFInd package
 # with which they first appeared.
 
+RootDir="/"
 TargetDir=/EFI/refind
-EtcKeysDir=/etc/refind.d/keys
 LocalKeysBase="refind_local"
 ShimSource="none"
 TargetX64="refind_x64.efi"
@@ -53,7 +63,12 @@ DeleteRefindDir=0
 
 GetParams() {
    InstallToEspOnMac=0
-   InstallDrivers=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
@@ -64,25 +79,41 @@ GetParams() {
               TargetIA32="bootia32.efi"
               shift
               ;;
+         --root) RootDir=$2
+              shift
+              ;;
+         --localkeys) LocalKeys=1
+              ;;
          --shim) ShimSource=$2
               shift
               ;;
-         --drivers) InstallDrivers=1
+         --drivers | --alldrivers) InstallDrivers="all"
               ;;
-         --localkeys) LocalKeys=1
+         --nodrivers) InstallDrivers="none"
               ;;
-         * ) echo "Usage: $0 [--esp | --usedefault {device-file}] [--drivers] "
-             echo "         [--localkeys] [--shim {shim-filename}]"
-             echo "Aborting!"
+         * ) 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
-#   exit 1
+   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.
@@ -147,14 +178,45 @@ CopyShimFiles() {
 # Copy the public keys to the installation medium
 CopyKeys() {
    if [[ $LocalKeys == 1 ]] ; then
-      cp $EtcKeysDir/$LocalKeysBase.cer $InstallDir/$TargetDir
-      cp $EtcKeysDir/$LocalKeysBase.crt $InstallDir/$TargetDir
-   else
-      cp $ThisDir/refind.cer $InstallDir/$TargetDir
-      cp $ThisDir/refind.crt $InstallDir/$TargetDir
+      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() {
@@ -172,8 +234,9 @@ CopyRefindFiles() {
          TargetShim="bootx64.efi"
          CopyShimFiles
       fi
-      if [[ $InstallDrivers == 1 ]] ; then
-         cp -r $RefindDir/drivers_* $InstallDir/$TargetDir/
+      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
@@ -182,20 +245,14 @@ CopyRefindFiles() {
       if [[ $? != 0 ]] ; then
          Problems=1
       fi
-      if [[ $InstallDrivers == 1 ]] ; then
-         mkdir -p $InstallDir/$TargetDir/drivers_ia32
-         cp -r $RefindDir/drivers_ia32/*_ia32.efi $InstallDir/$TargetDir/drivers_ia32/
-      fi
+      CopyDrivers ia32
       Refind="refind_ia32.efi"
    elif [[ $Platform == 'EFI64' ]] ; then
       cp $RefindDir/refind_x64.efi $InstallDir/$TargetDir/$TargetX64
       if [[ $? != 0 ]] ; then
          Problems=1
       fi
-      if [[ $InstallDrivers == 1 ]] ; then
-         mkdir -p $InstallDir/$TargetDir/drivers_x64
-         cp -r $RefindDir/drivers_x64/*_x64.efi $InstallDir/$TargetDir/drivers_x64/
-      fi
+      CopyDrivers x64
       Refind="refind_x64.efi"
       CopyKeys
       if [[ $ShimSource != "none" ]] ; then
@@ -205,8 +262,8 @@ CopyRefindFiles() {
          if [[ $LocalKeys == 0 ]] ; then
             echo "Storing copies of rEFInd Secure Boot public keys in $EtcKeysDir"
             mkdir -p $EtcKeysDir
-            cp $ThisDir/refind.cer $EtcKeysDir
-            cp $ThisDir/refind.crt $EtcKeysDir
+            cp $ThisDir/keys/refind.cer $EtcKeysDir
+            cp $ThisDir/keys/refind.crt $EtcKeysDir
          fi
       fi
    else
@@ -224,6 +281,7 @@ CopyRefindFiles() {
    if [[ $? != 0 ]] ; then
       Problems=1
    fi
+   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 overwriting your customizations."
@@ -301,7 +359,7 @@ InstallOnOSX() {
    elif [[ $InstallToEspOnMac == "1" ]] ; then
       MountOSXESP
    else
-      InstallDir="/"
+      InstallDir="$RootDir/"
    fi
    echo "Installing rEFInd to the partition mounted at '$InstallDir'"
    Platform=`ioreg -l -p IODeviceTree | grep firmware-abi | cut -d "\"" -f 4`
@@ -343,15 +401,21 @@ 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
       echo ""
-      echo "CAUTION: The computer seems to have been booted with Secure Boot active, but"
-      echo "you haven't specified a valid shim.efi file source. The resulting installation"
-      echo "will not boot unless you disable Secure Boot. You may continue, but you should"
-      echo "consider using --shim to specify a working shim.efi file. You can read more"
-      echo "about this topic at http://www.rodsbooks.com/refind/secureboot.html."
+      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
@@ -448,14 +512,9 @@ GenerateKeys() {
 # appropriately.
 # Aborts script on error
 SignOneBinary() {
-   if [[ $UseSBSign == 1 ]] ; then
-      $SBSign --key $PrivateKey --cert $CertKey --output $2 $1
-      if [[ $? != 0 ]] ; then
-         echo "Problem signing the binary $1! Aborting!"
-         exit 1
-      fi
-   else
-      echo "PESign code not yet written; aborting!"
+   $SBSign --key $PrivateKey --cert $CertKey --output $2 $1
+   if [[ $? != 0 ]] ; then
+      echo "Problem signing the binary $1! Aborting!"
       exit 1
    fi
 }
@@ -465,19 +524,22 @@ SignOneBinary() {
 # 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 either sbsign or pesign; one of these is required to sign rEFInd"
-      echo "with your own keys! Aborting!"
+      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
+   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
+   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` ; do
+   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
@@ -485,16 +547,22 @@ ReSignBinaries() {
    DeleteRefindDir=1
 }
 
-# Identifies the ESP's location (/boot or /boot/efi); aborts if
-# the ESP isn't mounted at either location.
+# 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`
+   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`
-   EspFilesystem=`grep $InstallDir /etc/mtab | cut -d " " -f 3`
+   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 $InstallDir using $EspFilesystem"
@@ -551,6 +619,29 @@ 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() {
@@ -598,6 +689,7 @@ InstallOnLinux() {
    CopyRefindFiles
    if [[ $TargetDir != "/EFI/BOOT" ]] ; then
       AddBootEntry
+      GenerateRefindLinuxConf
    fi
 } # InstallOnLinux()
 
@@ -607,14 +699,14 @@ InstallOnLinux() {
 # install under OS X or Linux, depending on the detected platform.
 #
 
-GetParams $@
 OSName=`uname -s`
+GetParams $@
 ThisDir="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
 RefindDir="$ThisDir/refind"
 ThisScript="$ThisDir/`basename $0`"
 if [[ `whoami` != "root" ]] ; then
    echo "Not running as root; attempting to elevate privileges via sudo...."
-   sudo $ThisScript $1 $2 $3 $4 $5 $6
+   sudo $ThisScript "$@"
    if [[ $? != 0 ]] ; then
       echo "This script must be run as root (or using sudo). Exiting!"
       exit 1
@@ -624,7 +716,7 @@ if [[ `whoami` != "root" ]] ; then
 fi
 CheckForFiles
 if [[ $OSName == 'Darwin' ]] ; then
-   if [[ $ShimDir != "none" ]] ; then
+   if [[ $ShimSource != "none" ]] ; then
       echo "The --shim option is not supported on OS X! Exiting!"
       exit 1
    fi