It seems that Windows sometimes installs legacy bootloader even on UEFI systems. This causes os-prober to put chainload entry for legacy boot in grub2 menu, which fails to boot on UEFI.
Attached are suggested patches, which - skip legacy MS loader detection on UEFI platform - add framework for searching EFI System Partition - add scripts that detect Microsoft bootloader and ELILO (Agnelo). These scripts need patched for 30_os-prober (attached). Patches are included in unofficial os-prober package for openSUSE maintained by Agnelo and tested on UEFI systems. Thank you -andrey
Index: b/os-probes/mounted/x86/20microsoft =================================================================== --- a/os-probes/mounted/x86/20microsoft +++ b/os-probes/mounted/x86/20microsoft @@ -7,6 +7,12 @@ partition="$1" mpoint="$2" type="$3" +# This script looks for legacy BIOS bootloaders only. Skip if running UEFI +if [ -d /sys/firmware/efi ]; then + debug "Skipping legacy bootloaders on UEFI system" + exit 1 +fi + # Weed out stuff that doesn't apply to us case "$type" in ntfs|ntfs-3g) debug "$1 is a NTFS partition" ;;
Index: os-prober-1.56/os-probes/mounted/x86/05efi =================================================================== --- /dev/null 2012-10-10 10:42:25.367517060 -0700 +++ os-prober-1.56/os-probes/mounted/x86/05efi 2012-10-10 16:29:49.000000000 -0700 @@ -0,0 +1,70 @@ +#!/bin/sh +# Detects all Microsoft OSes on a collection of partitions. + +. /usr/share/os-prober/common.sh + +partition="$1" +mpoint="$2" +type="$3" + +# This file is for UEFI platform only +if [ ! -d /sys/firmware/efi ]; then + debug "Not on UEFI platform" + exit 1 +fi + +# Weed out stuff that doesn't apply to us +case "$type" in + vfat) debug "$1 is a FAT32 partition" ;; + msdos) debug "$1 is a FAT16 partition" ;; + *) debug "$1 is $type partition: exiting"; exit 1 ;; +esac + +if type udevadm > /dev/null 2>&1; then + udevinfo () { + udevadm info "$@" + } +fi + +if type udevinfo > /dev/null 2>&1; then + # Skip virtual devices + if udevinfo -q path -n $partition | grep -q /virtual/; then + debug "$1 is virtual device: exiting" + exit 1 + fi + + eval "$(udevinfo -q property -n "$partition" | grep -E '^ID_PART_ENTRY_(TYPE|SCHEME)=')" + debug "$partition partition scheme is $ID_PART_ENTRY_SCHEME" + debug "$partition partition type is $ID_PART_ENTRY_TYPE" + + if [ -z "$ID_PART_ENTRY_TYPE" -o -z "$ID_PART_ENTRY_SCHEME" -o \ + \( "$ID_PART_ENTRY_SCHEME" != gpt -a "$ID_PART_ENTRY_SCHEME" != msdos \) -o \ + \( "$ID_PART_ENTRY_SCHEME" = gpt -a "$ID_PART_ENTRY_TYPE" != c12a7328-f81f-11d2-ba4b-00a0c93ec93b \) -o \ + \( "$ID_PART_ENTRY_SCHEME" = msdos -a "$ID_PART_ENTRY_TYPE" != 0xef \) ]; then + debug "$partition is not a ESP partition: exiting" + exit 1 + fi +else + debug "udevinfo and udevadm missing - cannot check partition type" +fi + +efi=$(item_in_dir efi "$mpoint") +if [ -z "$efi" ]; then + debug "$mpoint does not have /EFI directory: exiting" + exit 1 +fi + +ret=1 +for test in /usr/lib/os-probes/mounted/efi/*; do + debug "running subtest $test" + if [ -f "$test" ] && [ -x "$test" ]; then + entry=$("$test" "$mpoint/$efi") + if [ -n "$entry" ]; then + debug "bootloader $entry found by subtest $test" + ret=0 + result "${partition}@/$efi/${entry}:efi" + fi + fi +done + +exit $ret Index: os-prober-1.56/os-probes/mounted/x86/efi/20microsoft =================================================================== --- /dev/null 2012-10-10 10:42:25.367517060 -0700 +++ os-prober-1.56/os-probes/mounted/x86/efi/20microsoft 2012-10-10 16:29:49.000000000 -0700 @@ -0,0 +1,28 @@ +#!/bin/sh +# Detects Microsoft bootloader on a EFI System Partition + +. /usr/share/os-prober/common.sh + +efi="$1" + +found= +for microsoft in $(item_in_dir microsoft "$efi"); do + for boot in $(item_in_dir boot "$efi/$microsoft"); do + bcd=$(item_in_dir bcd "$efi/$microsoft/$boot") + bootmgfw=$(item_in_dir bootmgfw.efi "$efi/$microsoft/$boot") + if [ -n "$bcd" -a -n "$bootmgfw" ]; then + long="Windows Boot Manager" + short=Windows + path="$microsoft/$boot/$bootmgfw" + found=true + break + fi + done +done + + +if [ -n "$found" ]; then + label="$(count_next_label "$short")" + result "${path}:${long}:${label}" +fi +exit 0 Index: os-prober-1.56/os-probes/mounted/x86/efi/10elilo =================================================================== --- /dev/null 2012-10-10 10:42:25.367517060 -0700 +++ os-prober-1.56/os-probes/mounted/x86/efi/10elilo 2012-10-10 18:28:55.000000000 -0700 @@ -0,0 +1,24 @@ +#!/bin/sh +# Detects ELILO bootloader on a EFI System Partition + +. /usr/share/os-prober/common.sh + +efi="$1" + +found= + +elilo=`find $1 -name "elilo.efi"` +if [ -n "$elilo" ]; then + bdir=`dirname $elilo` + bdir=`basename $bdir` + long="ELILO Boot Manager" + short="ELILO" + path=${bdir}/elilo.efi + found=true +fi + +if [ -n "$found" ]; then + label="$(count_next_label "$short")" + result "${path}:${long}:${label}" +fi +exit 0
--- /etc/grub.d/30_os-prober.orig 2012-09-28 22:12:51.047085849 +0400 +++ /etc/grub.d/30_os-prober 2012-09-29 18:35:25.949036128 +0400 @@ -144,6 +144,22 @@ EOF } EOF ;; + efi) + + EFIPATH=${DEVICE#*@} + DEVICE=${DEVICE%@*} + onstr="$(gettext_printf "(on %s)" "${DEVICE}")" + cat << EOF +menuentry '$(echo "${LONGNAME} $onstr" | grub_quote)' --class windows --class os \$menuentry_id_option 'osprober-efi-$(grub_get_device_id "${DEVICE}")' { +EOF + save_default_entry | sed -e "s/^/\t/" + prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" + + cat <<EOF + chainloader ${EFIPATH} +} +EOF + ;; linux) LINUXPROBED="`linux-boot-prober ${DEVICE} 2> /dev/null | tr ' ' '^' | paste -s -d ' '`" prepare_boot_cache=