]> git.proxmox.com Git - grub2.git/commitdiff
Import EFI patch by cjwatson
authorColin Watson <cjwatson@ubuntu.com>
Mon, 30 Aug 2010 19:00:48 +0000 (21:00 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Mon, 30 Aug 2010 19:00:48 +0000 (21:00 +0200)
util/grub-install.in

index 910549d3001e2924a962cadfe4da1ee38fccc954..4ce451d11eae6f1adbe4e0acca2b92fd606237c0 100644 (file)
@@ -24,6 +24,7 @@ exec_prefix=@exec_prefix@
 sbindir=@sbindir@
 bindir=@bindir@
 libdir=@libdir@
+sysconfdir=@sysconfdir@
 PACKAGE_NAME=@PACKAGE_NAME@
 PACKAGE_TARNAME=@PACKAGE_TARNAME@
 PACKAGE_VERSION=@PACKAGE_VERSION@
@@ -56,6 +57,9 @@ update_nvram=yes
 
 ofpathname=`which ofpathname`
 nvsetenv=`which nvsetenv`
+efibootmgr=`which efibootmgr 2>/dev/null || true`
+removable=no
+efi_quiet=
 
 if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
     disk_module=biosdisk
@@ -103,6 +107,11 @@ if [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platf
     cat <<EOF
   --no-nvram              don't update the boot-device NVRAM variable
 EOF
+fi
+if [ "${platform}" = "efi" ]; then
+    cat <<EOF
+   --removable             the installation device is removable
+EOF
 fi
     cat <<EOF
 
@@ -188,6 +197,8 @@ do
        no_floppy="--no-floppy" ;;
     --recheck)
        recheck=yes ;;
+    --removable)
+       removable=yes ;;
 
     --disk-module)
        if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
@@ -241,6 +252,7 @@ setup_verbose=
 if test $debug = yes; then
     set -x
     setup_verbose="--verbose"
+    efi_quiet=-q
 fi
 
 # Initialize these directories here, since ROOTDIR was initialized.
@@ -488,6 +500,126 @@ elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${pla
            exit 1
        }
     fi
+elif [ x"$platform" = xefi ]; then
+    # Get GRUB_DISTRIBUTOR.
+    if test -f ${sysconfdir}/default/grub ; then
+       . ${sysconfdir}/default/grub
+    fi
+
+    # Find the EFI System Partition.
+    efidir=
+    if test -d ${bootdir}/efi; then
+       install_device=`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${bootdir}/efi`
+        # Is it a mount point?
+       if test "x$install_device" != "x`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${bootdir}`"; then
+           efidir=${bootdir}/efi
+       fi
+    elif test -n "$rootdir" && test "x$rootdir" != "x/"; then
+        # The EFI System Partition may have been given directly using
+        # --root-directory.
+       install_device=`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${rootdir}`
+        # Is it a mount point?
+       if test "x$install_device" != "x`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${rootdir}/..`"; then
+           efidir=${rootdir}
+       fi
+    fi
+    
+    if test -n "$efidir"; then
+       efi_fs=`$grub_probe --target=fs --device-map=${device_map} ${efidir}`
+       if test "x$efi_fs" = xfat; then :; else
+           echo "${efidir} doesn't look like an EFI partition." 1>&2
+           efidir=
+       fi
+    fi
+    
+    if test -n "$efidir"; then
+        # The EFI specification requires that an EFI System Partition must
+        # contain an "EFI" subdirectory, and that OS loaders are stored in
+        # subdirectories below EFI.  Vendors are expected to pick names that do
+        # not collide with other vendors.  To minimise collisions, we use the
+        # name of our distributor if possible.
+       if test $removable = yes; then
+          # The specification makes stricter requirements of removable
+          # devices, in order that only one image can be automatically loaded
+          # from them.  The image must always reside under /EFI/BOOT, and it
+          # must have a specific file name depending on the architecture.
+           efi_distributor=BOOT
+           case "$target_cpu" in
+               i386)
+                   efi_file=BOOTIA32.EFI ;;
+               x86-64)
+                   efi_file=BOOTX64.EFI ;;
+           # GRUB does not yet support these architectures, but they're defined
+           # by the specification so we include them here to ease future
+           # expansion.
+               ia64)
+                   efi_file=BOOTIA64.EFI ;;
+           esac
+       else
+           efi_distributor="$(echo "$GRUB_DISTRIBUTOR" | tr '[A-Z]' '[a-z]' | cut -d' ' -f1)"
+           if test -z "$efi_distributor"; then
+               efi_distributor=grub
+           fi
+           # It is convenient for each architecture to have a different
+           # efi_file, so that different versions can be installed in parallel.
+           case "$target_cpu" in
+               i386)
+                   efi_file=grubia32.efi ;;
+               x86-64)
+                   efi_file=grubx64.efi ;;
+        # GRUB does not yet support these architectures, but they're defined
+        # by the specification so we include them here to ease future
+        # expansion.
+               ia64)
+                   efi_file=grubia64.efi ;;
+               *)
+                   efi_file=grub.efi ;;
+           esac
+          # TODO: We should also use efibootmgr, if available, to add a Boot
+          # entry for ourselves.
+       fi
+       efidir="$efidir/EFI/$efi_distributor"
+       mkdir -p "$efidir" || exit 1
+    else
+        # We don't know what's going on.  Fall back to traditional
+        # (non-specification-compliant) behaviour.
+       efidir="$grubdir"
+       efi_distributor=
+       efi_file=grub.efi
+    fi
+    cp ${grubdir}/core.${imgext} ${efidir}/${efi_file}
+    # Try to make this image bootable using the EFI Boot Manager, if available.
+    if test "$removable" = no && test -n "$efi_distributor" && \
+       test -n "$efibootmgr"; then
+        # On Linux, we need the efivars kernel modules.
+       case "$host_os" in
+           linux*)
+               modprobe -q efivars 2>/dev/null || true ;;
+       esac
+
+        # Delete old entries from the same distributor.
+       for bootnum in `efibootmgr | grep '^Boot[0-9]' | \
+           fgrep " $efi_distributor" | cut -b5-8`; do
+           efibootmgr $efi_quiet -b "$bootnum" -B
+       done
+
+        # Add a new entry for the image we just created.  efibootmgr needs to be
+        # given the disk device and partition number separately, so we have to
+        # fiddle about with grub-probe to get hold of this reasonably reliably.
+        # Use fresh device map text to avoid any problems with stale data, since
+        # all we need here is a one-to-one mapping.
+       clean_devmap="$($grub_mkdevicemap --device-map=/dev/stdout)"
+       efidir_drive="$(echo "$clean_devmap" | $grub_probe --target=drive --device-map=/dev/stdin "$efidir")"
+       if test -z "$efidir_drive"; then
+           echo "Can't find GRUB drive for $efidir; unable to create EFI Boot Manager entry." >&2
+       else
+           efidir_disk="$(echo "$clean_devmap" | grep "^$(echo "$efidir_drive" | sed 's/,[^)]*//')" | cut -f2)"
+           efidir_part="$(echo "$efidir_drive" | sed 's/^([^,]*,[^0-9]*//; s/[^0-9].*//')"
+           efibootmgr $efi_quiet -c -d "$efidir_disk" -p "$efidir_part" -w \
+               -L "$GRUB_DISTRIBUTOR" -l "\\EFI\\$efi_distributor\\$efi_file"
+       fi
+    fi
+
 fi
 
 echo "Installation finished. No error reported."