Skip to contentSkip to conversation

Improve EFI grub-install to handle non-Apple systems

PATCH In review Colin Watson 3 participants 3 messages Jul 12, 2010

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Improve EFI grub-install to handle non-Apple systems

At the moment, the EFI grub-install script only handles Apple Mac systems. This patch adds support for systems that conform to the UEFI specification, while retaining support for Apple systems.

I couldn't find anything approaching a standard for where the EFI System Partition should be mounted, so I chose to look for it in /boot/efi, since I don't like creating new top-level directories. If there's a different convention then I'd be happy to add support for it.

Vladimir asked whether I could merge util/i386/efi/grub-install.in into util/grub-install.in at the same time. This is of course desirable but I haven't got round to it yet, and I didn't want to stall this patch indefinitely until I find time for that.

2010-07-12 Colin Watson <[email protected]>

* util/i386/efi/grub-install.in: Add support for systems that conform to the UEFI specification, as well as Apple systems. Currently looks for the EFI System Partition on /boot/efi.

=== modified file 'util/i386/efi/grub-install.in'

i386/efi/grub-install.in +192 -5
@@ -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@
@@ -43,10 +44,14 @@ rootdir=
 grub_prefix=`echo /boot/grub | sed ${transform}`
 modules=
 
+efibootmgr=`which efibootmgr 2>/dev/null || true`
+
 no_floppy=
 force_lba=
 recheck=no
+removable=no
 debug=no
+efi_quiet=
 
 # Usage: usage
 # Print the usage.
@@ -65,6 +70,7 @@ Install GRUB on your EFI partition.
   --grub-probe=FILE       use FILE as grub-probe
   --no-floppy             do not probe any floppy drive
   --recheck               probe a device map even if it already exists
+  --removable             the installation device is removable
 
 $self copies GRUB images into the DIR/boot directory specified by
 --root-directory.
@@ -127,9 +133,14 @@ do
 	no_floppy="--no-floppy" ;;
     --recheck)
 	recheck=yes ;;
+    --removable)
+	removable=yes ;;
     # This is an undocumented feature...
     --debug)
 	debug=yes ;;
+    # Intentionally undocumented; for compatibility only.
+    -f | --force)
+	;;
     *)
 	echo "Unrecognized option \`$option'" 1>&2
 	usage
@@ -138,9 +149,13 @@ do
     esac
 done
 
+# for make_system_path_relative_to_its_root()
+. ${libdir}/grub/grub-mkconfig_lib
+
 # If the debugging feature is enabled, print commands.
 if test $debug = yes; then
     set -x
+    efi_quiet=-q
 fi
 
 # Initialize these directories here, since ROOTDIR was initialized.
@@ -177,6 +192,106 @@ else
     exit 1
 fi
 
+# 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
+	    ;;
+	arm)
+	    efi_file=BOOTARM.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
+	    ;;
+	arm)
+	    efi_file=grubarm.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
+
 # Create the GRUB directory if it is not present.
 mkdir -p "$grubdir" || exit 1
 
@@ -221,13 +336,16 @@ for dir in ${localedir}/*; do
     fi
 done
 
+# Write device to a variable so we don't have to traverse /dev every time.
+grub_device=`$grub_probe --target=device --device-map=${device_map} ${grubdir}` || exit 1
+
 if ! test -f ${grubdir}/grubenv; then
     $grub_editenv ${grubdir}/grubenv create
 fi
 
 # Create the core image. First, auto-detect the filesystem module.
-fs_module=`$grub_probe --target=fs --device-map=${device_map} ${grubdir}`
-if test "x$fs_module" = xfat; then :; else
+fs_module=`$grub_probe --target=fs --device-map=${device_map} --device ${grub_device}`
+if test "$efidir" != "$grubdir" || test "x$fs_module" = xfat; then :; else
     echo "${grubdir} doesn't look like an EFI partition." 1>&2
     exit 1
 fi
@@ -236,17 +354,86 @@ fi
 # this command is allowed to fail (--target=fs already grants us that the
 # filesystem will be accessible).
 partmap_module=
-for x in `$grub_probe --target=partmap --device-map=${device_map} ${grubdir} 2> /dev/null`; do
+for x in `$grub_probe --target=partmap --device-map=${device_map} --device ${grub_device} 2> /dev/null`; do
    partmap_module="$partmap_module part_$x";
 done
 
 # Device abstraction module, if any (lvm, raid).
-devabstraction_module=`$grub_probe --target=abstraction --device-map=${device_map} ${grubdir}`
+devabstraction_module=`$grub_probe --target=abstraction --device-map=${device_map} --device ${grub_device}`
 
 # The order in this list is critical.  Be careful when modifying it.
 modules="$modules $fs_module $partmap_module $devabstraction_module"
 
-$grub_mkimage -O ${target_cpu}-efi --output=${grubdir}/grub.efi $modules || exit 1
+relative_grubdir=`make_system_path_relative_to_its_root ${grubdir}` || exit 1
+if [ "x${relative_grubdir}" = "x" ] ; then
+    relative_grubdir=/
+fi
+
+prefix_drive=
+config_opt=
+
+if [ "x${devabstraction_module}" = "x" ] ; then
+    if [ x"${install_device}" != x ]; then
+      if echo "${install_device}" | grep -qx "(.*)" ; then
+        install_drive="${install_device}"
+      else
+        install_drive="`$grub_probe --target=drive --device-map=${device_map} --device ${install_device}`" || exit 1
+      fi
+      install_drive="`echo ${install_drive} | sed -e s/,[a-z0-9,]*//g`"
+    fi
+    grub_drive="`$grub_probe --target=drive --device-map=${device_map} --device ${grub_device}`" || exit 1
+
+    # Strip partition number
+    grub_drive="`echo ${grub_drive} | sed -e s/,[a-z0-9,]*//g`"
+    if [ "x${grub_drive}" != "x${install_drive}" ] ; then
+        uuid="`$grub_probe --target=fs_uuid --device ${grub_device}`"
+        if [ "x${uuid}" = "x" ] ; then
+          echo "You attempted a cross-disk install, but the filesystem containing ${grubdir} does not support UUIDs." 1>&2
+          exit 1
+        fi
+        echo "search.fs_uuid ${uuid} root " > ${grubdir}/load.cfg
+	echo 'set prefix=($root)'"${relative_grubdir}" >> ${grubdir}/load.cfg
+	config_opt="-c ${grubdir}/load.cfg "
+        modules="$modules search_fs_uuid"
+    fi
+else
+    prefix_drive=`$grub_probe --target=drive --device ${grub_device}` || exit 1
+fi
+
+$grub_mkimage ${config_opt} -O ${target_cpu}-efi --output=${efidir}/${efi_file} --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1
+
+# 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
 
 # Prompt the user to check if the device map is correct.
 echo "Installation finished. No error reported."

Thanks,

Signature · 1 line
Colin Watson                                       [[email protected]]
#1 lore raw
Quoted 5 lines · Colin Watson

At the moment, the EFI grub-install script only handles Apple Mac systems. This patch adds support for systems that conform to the UEFI specification, while retaining support for Apple systems.

Apple systems seem to support generic way too. So if this way is properly tested on different Apple systems we should switch to generic way altogether.

Quoted 6 lines

I couldn't find anything approaching a standard for where the EFI System Partition should be mounted, so I chose to look for it in /boot/efi, since I don't like creating new top-level directories. If there's a different convention then I'd be happy to add support for it.

Where to mount X or Y depends on distribution. I'm happy to support whatever you feel is right. This will probably set a precedent and other distros will follow.

Quoted 92 lines

Vladimir asked whether I could merge util/i386/efi/grub-install.in into util/grub-install.in at the same time. This is of course desirable but I haven't got round to it yet, and I didn't want to stall this patch indefinitely until I find time for that.

2010-07-12 Colin Watson <[email protected]>

* util/i386/efi/grub-install.in: Add support for systems that conform to the UEFI specification, as well as Apple systems. Currently looks for the EFI System Partition on /boot/efi.

=== modified file 'util/i386/efi/grub-install.in'

i386/efi/grub-install.in +29 -0
@@ -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@
@@ -43,10 +44,14 @@ rootdir=
 grub_prefix=`echo /boot/grub | sed ${transform}`
 modules=
 
+efibootmgr=`which efibootmgr 2>/dev/null || true`
+
 no_floppy=
 force_lba=
 recheck=no
+removable=no
 debug=no
+efi_quiet=
 
 # Usage: usage
 # Print the usage.
@@ -65,6 +70,7 @@ Install GRUB on your EFI partition.
   --grub-probe=FILE       use FILE as grub-probe
   --no-floppy             do not probe any floppy drive
   --recheck               probe a device map even if it already exists
+  --removable             the installation device is removable
 
 $self copies GRUB images into the DIR/boot directory specified by
 --root-directory.
@@ -127,9 +133,14 @@ do
 	no_floppy="--no-floppy" ;;
     --recheck)
 	recheck=yes ;;
+    --removable)
+	removable=yes ;;
     # This is an undocumented feature...
     --debug)
 	debug=yes ;;
+    # Intentionally undocumented; for compatibility only.
+    -f | --force)
+	;;
     *)
 	echo "Unrecognized option \`$option'" 1>&2
 	usage
@@ -138,9 +149,13 @@ do
     esac
 done
 
+# for make_system_path_relative_to_its_root()
+. ${libdir}/grub/grub-mkconfig_lib
+
 # If the debugging feature is enabled, print commands.
 if test $debug = yes; then
     set -x
+    efi_quiet=-q
 fi
 
 # Initialize these directories here, since ROOTDIR was initialized.
@@ -177,6 +192,106 @@ else
     exit 1
 fi
 
+# 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

i386/efi/grub-install.in else · line 218

Quoted 10 lines
i386/efi/grub-install.in +9 -0
+    # 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
+
 

This seems to change the meaning of --root-directory. Perhaps another option would be better?

Quoted 5 lines
i386/efi/grub-install.in +5 -0
+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=

i386/efi/grub-install.in else

Quoted 10 lines
i386/efi/grub-install.in +9 -0
+    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.
 

I'm not sure how well this is implemented in a real world. We may need to change that to

efi_distributor=BOOT

If real implementations don't work as well as expected

Quoted 16 lines
i386/efi/grub-install.in +16 -0
+    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.

i386/efi/grub-install.in else · line 297

Quoted 10 lines
i386/efi/grub-install.in +9 -0
+	ia64)
+	    efi_file=BOOTIA64.EFI
+	    ;;
+	arm)
+	    efi_file=BOOTARM.EFI
+	    ;;
+	esac
+    else
+	efi_distributor="$(echo "$GRUB_DISTRIBUTOR" | tr '[A-Z]' '[a-z]' | cut -d' ' -f1)"
 

Perhaps we need a check that name contains no non-ASCII characters. EFI is supposed to support unicode but some parts of its spec contradict Unicode.

i386/efi/grub-install.in fi · line 414

Quoted 11 lines
i386/efi/grub-install.in +10 -0
+# 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
+

What about using efi_distributor=boot if efivars fails to load? Many people have a mismatchin Linux and EFI and so use "noefi" on command line. Or "noefi" is there for some other reason.

i386/efi/grub-install.in fi · line 420

Quoted 7 lines
i386/efi/grub-install.in +6 -0
+    # 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
+

This would conflict with installing both ia32 and x64 because second install will erase first one.
Sane way may be to use efibootmgr only if installed version matches current EFI.

Signature · 2 lines
Regards
Vladimir 'φ-coder/phcoder' Serbinenko
#2 lore raw

2010/7/12 Vladimir 'φ-coder/phcoder' Serbinenko <[email protected]>:

Quoted 9 lines · Colin Watson
Quoted 5 lines

At the moment, the EFI grub-install script only handles Apple Mac systems.  This patch adds support for systems that conform to the UEFI specification, while retaining support for Apple systems.

Apple systems seem to support generic way too. So if this way is properly tested on different Apple systems we should switch to generic way altogether.

During firmware upgrade apple does use /efi/apple (where efi is system efi root partition)

Quoted 9 lines
Quoted 6 lines

I couldn't find anything approaching a standard for where the EFI System Partition should be mounted, so I chose to look for it in /boot/efi, since I don't like creating new top-level directories.  If there's a different convention then I'd be happy to add support for it.

Where to mount X or Y depends on distribution. I'm happy to support whatever you feel is right. This will probably set a precedent and other distros will follow.

Is there intent to support grub on the system efi partition as in:

/efi/grub or /efi/fsf where /efi is system efi fat partition?

Also see http://www.uefi.org/specs/esp_registry where redhat, suse, dell and ibm among others have already reserved well-known directories on the efi partition.

Quoted 194 lines
Quoted 92 lines

Vladimir asked whether I could merge util/i386/efi/grub-install.in into util/grub-install.in at the same time.  This is of course desirable but I haven't got round to it yet, and I didn't want to stall this patch indefinitely until I find time for that.

2010-07-12  Colin Watson  <[email protected]>

      * util/i386/efi/grub-install.in: Add support for systems that conform to the UEFI specification, as well as Apple systems. Currently looks for the EFI System Partition on /boot/efi.

=== modified file 'util/i386/efi/grub-install.in'

i386/efi/grub-install.in     2010-07-12 11:43:20 +0000 renamed from i386/efi/grub-install.in     2010-07-04 12:23:55 +0000 +0 -0
@@ -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@

i386/efi/grub-install.in     2010-07-12 11:43:20 +0000 renamed from i386/efi/grub-install.in     2010-07-04 12:23:55 +0000 +0 -0
@@ -43,10 +44,14 @@ rootdir=

 grub_prefix=echo /boot/grub | sed ${transform}
 modules=

i386/efi/grub-install.in     2010-07-12 11:43:20 +0000 renamed from i386/efi/grub-install.in     2010-07-04 12:23:55 +0000 +2 -0
+efibootmgr=`which efibootmgr 2>/dev/null || true`
+

 no_floppy=
 force_lba=
 recheck=no
+removable=no
 debug=no
+efi_quiet=

 # Usage: usage
 # Print the usage.

i386/efi/grub-install.in     2010-07-12 11:43:20 +0000 renamed from i386/efi/grub-install.in     2010-07-04 12:23:55 +0000 +0 -0
@@ -65,6 +70,7 @@ Install GRUB on your EFI partition.

   --grub-probe=FILE       use FILE as grub-probe --no-floppy             do not probe any floppy drive --recheck               probe a device map even if it already exists
+  --removable             the installation device is removable

 $self copies GRUB images into the DIR/boot directory specified by --root-directory.

i386/efi/grub-install.in     2010-07-12 11:43:20 +0000 renamed from i386/efi/grub-install.in     2010-07-04 12:23:55 +0000 +5 -0
@@ -127,9 +133,14 @@ do
       no_floppy="--no-floppy" ;;
      --recheck)
       recheck=yes ;;
+    --removable)
+     removable=yes ;;
      # This is an undocumented feature...
      --debug)
       debug=yes ;;
+    # Intentionally undocumented; for compatibility only.
+    -f | --force)
+     ;;
      *)

      echo "Unrecognized option \`$option'" 1>&2
      usage

i386/efi/grub-install.in     2010-07-12 11:43:20 +0000 renamed from i386/efi/grub-install.in     2010-07-04 12:23:55 +0000 +0 -0
@@ -138,9 +149,13 @@ do

     esac
 done

i386/efi/grub-install.in     2010-07-12 11:43:20 +0000 renamed from i386/efi/grub-install.in     2010-07-04 12:23:55 +0000 +3 -0
+# for make_system_path_relative_to_its_root()
+. ${libdir}/grub/grub-mkconfig_lib
+

 # If the debugging feature is enabled, print commands. if test $debug = yes; then
     set -x
+    efi_quiet=-q
 fi

 # Initialize these directories here, since ROOTDIR was initialized.

i386/efi/grub-install.in     2010-07-12 11:43:20 +0000 renamed from i386/efi/grub-install.in     2010-07-04 12:23:55 +0000 +0 -0
@@ -177,6 +192,106 @@ else

     exit 1
 fi

i386/efi/grub-install.in     2010-07-12 11:43:20 +0000 renamed from i386/efi/grub-install.in     2010-07-04 12:23:55 +0000 +13 -0
+# 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

i386/efi/grub-install.in     2010-07-12 11:43:20 +0000

Quoted 10 lines
i386/efi/grub-install.in     2010-07-12 11:43:20 +0000 renamed from i386/efi/grub-install.in     2010-07-04 12:23:55 +0000 +10 -0
+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
+

This seems to change the meaning of --root-directory. Perhaps another option would be better?

Quoted 5 lines
i386/efi/grub-install.in     2010-07-12 11:43:20 +0000 renamed from i386/efi/grub-install.in     2010-07-04 12:23:55 +0000 +4 -0
+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

i386/efi/grub-install.in     2010-07-12 11:43:20 +0000

Quoted 10 lines
i386/efi/grub-install.in     2010-07-12 11:43:20 +0000 renamed from i386/efi/grub-install.in     2010-07-04 12:23:55 +0000 +10 -0
+     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.

I'm not sure how well this is implemented in a real world. We may need to change that to

efi_distributor=BOOT

If real implementations don't work as well as expected

Quoted 17 lines

+    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)

Quoted 9 lines

+         efi_file=BOOTIA64.EFI
+         ;;
+     arm)
+         efi_file=BOOTARM.EFI
+         ;;
+     esac
+    else
+     efi_distributor="$(echo "$GRUB_DISTRIBUTOR" | tr '[A-Z]' '[a-z]' | cut -d' ' -f1)"

Perhaps we need a check that name contains no non-ASCII characters. EFI is supposed to support unicode but some parts of its spec contradict Unicode.

i386/efi/grub-install.in     2010-07-12 11:43:20 +0000

Quoted 11 lines
i386/efi/grub-install.in     2010-07-12 11:43:20 +0000 renamed from i386/efi/grub-install.in     2010-07-04 12:23:55 +0000 +10 -0
+# 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
+

What about using efi_distributor=boot if efivars fails to load? Many people have a mismatchin Linux and EFI and so use "noefi" on command line. Or "noefi" is there for some other reason.

Quoted 7 lines

+    # 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
+

This would conflict with installing both ia32 and x64 because second install will erase first one.
Sane way may be to use efibootmgr only if installed version matches current EFI.

--
Regards
Vladimir 'φ-coder/phcoder' Serbinenko

_______________________________________________
Grub-devel mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/grub-devel