All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Improve EFI grub-install to handle non-Apple systems
@ 2010-07-12 11:52 Colin Watson
  2010-07-12 21:40 ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 1 reply; 3+ messages in thread
From: Colin Watson @ 2010-07-12 11:52 UTC (permalink / raw)
  To: grub-devel

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  <cjwatson@ubuntu.com>

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

-- 
Colin Watson                                       [cjwatson@ubuntu.com]


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] Improve EFI grub-install to handle non-Apple systems
  2010-07-12 11:52 [PATCH] Improve EFI grub-install to handle non-Apple systems Colin Watson
@ 2010-07-12 21:40 ` Vladimir 'φ-coder/phcoder' Serbinenko
  2010-07-12 21:53   ` Dmitrijs Ledkovs
  0 siblings, 1 reply; 3+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2010-07-12 21:40 UTC (permalink / raw)
  To: grub-devel

[-- Attachment #1: Type: text/plain, Size: 7395 bytes --]

On 07/12/2010 01:52 PM, Colin Watson wrote:
> 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.
> 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.
> 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  <cjwatson@ubuntu.com>
>
> 	* 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'
> --- util/i386/efi/grub-install.in	2010-07-04 12:23:55 +0000
> +++ util/i386/efi/grub-install.in	2010-07-12 11:43:20 +0000
> @@ -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
> +
>   
This seems to change the meaning of --root-directory. Perhaps another
option would be better?
> +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.
>   
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

> +    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)"
>   
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.
> +# 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.
> +    # 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



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] Improve EFI grub-install to handle non-Apple systems
  2010-07-12 21:40 ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2010-07-12 21:53   ` Dmitrijs Ledkovs
  0 siblings, 0 replies; 3+ messages in thread
From: Dmitrijs Ledkovs @ 2010-07-12 21:53 UTC (permalink / raw)
  To: The development of GNU GRUB

2010/7/12 Vladimir 'φ-coder/phcoder' Serbinenko <phcoder@gmail.com>:
> On 07/12/2010 01:52 PM, Colin Watson wrote:
>> 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)

>> 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.

>> 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  <cjwatson@ubuntu.com>
>>
>>       * 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'
>> --- util/i386/efi/grub-install.in     2010-07-04 12:23:55 +0000
>> +++ util/i386/efi/grub-install.in     2010-07-12 11:43:20 +0000
>> @@ -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
>> +
>>
> This seems to change the meaning of --root-directory. Perhaps another
> option would be better?
>> +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.
>>
> 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
>
>> +    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)"
>>
> 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.
>> +# 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.
>> +    # 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
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
>
>


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2010-07-12 21:54 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-07-12 11:52 [PATCH] Improve EFI grub-install to handle non-Apple systems Colin Watson
2010-07-12 21:40 ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-07-12 21:53   ` Dmitrijs Ledkovs

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.