Initial integration of hints

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-12-23 18:19:16 +01:00
parent 9a79fcf2c9
commit 6babad5e59
11 changed files with 489 additions and 106 deletions

View file

@ -50,7 +50,6 @@ modules=
install_device=
no_floppy=
force_lba=
recheck=no
debug=no
debug_image=
@ -106,7 +105,6 @@ Install GRUB on your drive.
--no-floppy do not probe any floppy drive
--allow-floppy Make the drive also bootable as floppy
(default for fdX devices). May break on some BIOSes.
--recheck probe a device map even if it already exists
--force install even if problems are detected
EOF
if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then
@ -218,7 +216,7 @@ do
--no-floppy)
no_floppy="--no-floppy" ;;
--recheck)
recheck=yes ;;
;;
--removable)
removable=yes ;;
@ -408,27 +406,17 @@ fi
# Create the GRUB directory if it is not present.
mkdir -p "$grubdir" || exit 1
# If --recheck is specified, remove the device map, if present.
if test $recheck = yes; then
rm -f "$device_map"
fi
# Create the device map file if it is not present.
if test -f "$device_map"; then
:
# Make sure that there is no duplicated entry.
tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).*/\1/p' "$device_map" \
| sort | uniq -d | sed -n 1p`
if test -n "$tmp"; then
echo "The drive $tmp is defined multiple times in the device map $device_map" 1>&2
exit 1
fi
else
# Create a safe temporary file.
test -n "$mklog" && log_file=`$mklog`
"$grub_mkdevicemap" "--device-map=$device_map" $no_floppy || exit 1
fi
# Make sure that there is no duplicated entry.
tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).*/\1/p' "$device_map" \
| sort | uniq -d | sed -n 1p`
if test -n "$tmp"; then
echo "The drive $tmp is defined multiple times in the device map $device_map" 1>&2
exit 1
device_map=
fi
# Copy the GRUB images to the GRUB directory.
@ -536,7 +524,22 @@ if [ "x${devabstraction_module}" = "x" ] ; then
exit 1
fi
echo "search.fs_uuid ${uuid} root " >> "${grubdir}/load.cfg"
if [ x"$disk_module" != x ] && [ x"$disk_module" != xbiosdisk ]; then
hints="`"$grub_probe" --device-map="${device_map}" --target=baremetal_hints --device "${grub_device}"`"
elif [ x"$platform" = xpc ]; then
hints="`"$grub_probe" --device-map="${device_map}" --target=bios_hints --device "${grub_device}"`"
elif [ x"$platform" = xefi ]; then
hints="`"$grub_probe" --device-map="${device_map}" --target=efi_hints --device "${grub_device}"`"
elif [ x"$platform" = xieee1275 ]; then
hints="`"$grub_probe" --device-map="${device_map}" --target=ieee1275_hints --device "${grub_device}"`"
elif [ x"$platform" = xloongson ] || [ x"$platform" = xqemu ] || [ x"$platform" = xcoreboot ] || [ x"$platform" = xmultiboot ] || [ x"$platform" = xqemu-mips ]; then
hints="`"$grub_probe" --device-map="${device_map}" --target=baremetal_hints --device "${grub_device}"`"
else
echo "No hints available for your platform. Expect reduced performance"
hints=
fi
echo "search.fs_uuid ${uuid} root $hints " >> "${grubdir}/load.cfg"
echo 'set prefix=($root)'"${relative_grubdir}" >> "${grubdir}/load.cfg"
config_opt="-c ${grubdir}/load.cfg "
modules="$modules search_fs_uuid"

View file

@ -36,7 +36,6 @@ grub_mkconfig_dir=${sysconfdir}/grub.d
self=`basename $0`
grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed "${transform}"`
grub_probe=${sbindir}/`echo grub-probe | sed "${transform}"`
grub_script_check="${bindir}/`echo grub-script-check | sed "${transform}"`"
@ -118,14 +117,6 @@ if [ "$EUID" != 0 ] ; then
fi
fi
set $grub_mkdevicemap dummy
if test -f "$1"; then
:
else
echo "$1: Not found." 1>&2
exit 1
fi
set $grub_probe dummy
if test -f "$1"; then
:
@ -136,10 +127,6 @@ fi
mkdir -p ${GRUB_PREFIX}
if test -e ${GRUB_PREFIX}/device.map ; then : ; else
${grub_mkdevicemap}
fi
# Device containing our userland. Typically used for root= parameter.
GRUB_DEVICE="`${grub_probe} --target=device /`"
GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true

View file

@ -128,9 +128,14 @@ prepare_grub_to_access_device ()
# If there's a filesystem UUID that GRUB is capable of identifying, use it;
# otherwise set root as per value in device.map.
echo "set root='`"${grub_probe}" --device "${device}" --target=drive`'"
echo "set root='`"${grub_probe}" --device "${device}" --target=compatibility_hint`'"
if fs_uuid="`"${grub_probe}" --device "${device}" --target=fs_uuid 2> /dev/null`" ; then
echo "search --no-floppy --fs-uuid --set=root ${fs_uuid}"
hints="`"${grub_probe}" --device "${device}" --target=hints_string 2> /dev/null`"
echo "if [ x$feature_platform_search_hint = xy ]; then"
echo " search --no-floppy --fs-uuid --set=root ${hints} ${fs_uuid}"
echo "else"
echo " search --no-floppy --fs-uuid --set=root ${fs_uuid}"
echo "fi"
fi
}

View file

@ -34,6 +34,8 @@
#include <grub/env.h>
#include <grub/raid.h>
#include <grub/i18n.h>
#include <grub/emu/misc.h>
#include <grub/util/ofpath.h>
#include <stdio.h>
#include <unistd.h>
@ -54,6 +56,13 @@ enum {
PRINT_DEVICE,
PRINT_PARTMAP,
PRINT_ABSTRACTION,
PRINT_HINT_STR,
PRINT_BIOS_HINT,
PRINT_IEEE1275_HINT,
PRINT_BAREMETAL_HINT,
PRINT_EFI_HINT,
PRINT_ARC_HINT,
PRINT_COMPATIBILITY_HINT
};
int print = PRINT_FS;
@ -88,6 +97,131 @@ probe_raid_level (grub_disk_t disk)
return ((struct grub_raid_array *) disk->data)->level;
}
/* Since OF path names can have "," characters in them, and GRUB
internally uses "," to indicate partitions (unlike OF which uses
":" for this purpose) we escape such commas. */
static char *
escape_of_path (const char *orig_path)
{
char *new_path, *d, c;
const char *p;
if (!strchr (orig_path, ','))
return (char *) orig_path;
new_path = xmalloc (strlen (orig_path) * 2 + sizeof ("ieee1275/"));
p = orig_path;
grub_strcpy (new_path, "ieee1275/");
d = new_path + sizeof ("ieee1275/") - 1;
while ((c = *p++) != '\0')
{
if (c == ',')
*d++ = '\\';
*d++ = c;
}
free ((char *) orig_path);
return new_path;
}
static char *
guess_bios_drive (const char *orig_path)
{
char *canon;
char *ptr;
canon = canonicalize_file_name (orig_path);
if (!canon)
return NULL;
ptr = strrchr (orig_path, '/');
if (ptr)
ptr++;
else
ptr = canon;
if ((ptr[0] == 's' || ptr[0] == 'h') && ptr[1] == 'd')
{
int num = ptr[2] - 'a';
free (canon);
return xasprintf ("hd%d", num);
}
if (ptr[0] == 'f' && ptr[1] == 'd')
{
int num = atoi (ptr + 2);
free (canon);
return xasprintf ("fd%d", num);
}
free (canon);
return NULL;
}
static char *
guess_efi_drive (const char *orig_path)
{
char *canon;
char *ptr;
canon = canonicalize_file_name (orig_path);
if (!canon)
return NULL;
ptr = strrchr (orig_path, '/');
if (ptr)
ptr++;
else
ptr = canon;
if ((ptr[0] == 's' || ptr[0] == 'h') && ptr[1] == 'd')
{
int num = ptr[2] - 'a';
free (canon);
return xasprintf ("hd%d", num);
}
if (ptr[0] == 'f' && ptr[1] == 'd')
{
int num = atoi (ptr + 2);
free (canon);
return xasprintf ("fd%d", num);
}
free (canon);
return NULL;
}
static char *
guess_baremetal_drive (const char *orig_path)
{
char *canon;
char *ptr;
canon = canonicalize_file_name (orig_path);
if (!canon)
return NULL;
ptr = strrchr (orig_path, '/');
if (ptr)
ptr++;
else
ptr = canon;
if (ptr[0] == 'h' && ptr[1] == 'd')
{
int num = ptr[2] - 'a';
free (canon);
return xasprintf ("ata%d", num);
}
if (ptr[0] == 's' && ptr[1] == 'd')
{
int num = ptr[2] - 'a';
free (canon);
return xasprintf ("ahci%d", num);
}
free (canon);
return NULL;
}
static void
print_full_name (const char *drive, grub_device_t dev)
{
if (dev->disk->partition)
printf ("%s,%s", drive, grub_partition_get_name (dev->disk->partition));
else
printf ("%s", drive);
}
static void
probe (const char *path, char *device_name)
{
@ -134,6 +268,173 @@ probe (const char *path, char *device_name)
if (! dev)
grub_util_error ("%s", grub_errmsg);
if (print == PRINT_HINT_STR)
{
const char *orig_path = grub_util_devname_to_ofpath (device_name);
char *ofpath = escape_of_path (orig_path);
char *biosname, *bare, *efi;
const char *map;
printf ("--hint-ieee1275=");
print_full_name (ofpath, dev);
printf (" ");
free (ofpath);
biosname = guess_bios_drive (device_name);
if (biosname)
{
printf ("--hint-bios=");
print_full_name (biosname, dev);
printf (" ");
}
free (biosname);
efi = guess_efi_drive (device_name);
if (efi)
{
printf ("--hint-efi=");
print_full_name (efi, dev);
printf (" ");
}
free (efi);
bare = guess_baremetal_drive (device_name);
if (bare)
{
printf ("--hint-baremetal=");
print_full_name (bare, dev);
printf (" ");
}
free (biosname);
/* FIXME: Add ARC hint. */
map = grub_util_biosdisk_get_compatibility_hint (dev->disk);
if (map)
{
printf ("--hint=");
print_full_name (map, dev);
printf (" ");
}
printf ("\n");
goto end;
}
if (print == PRINT_COMPATIBILITY_HINT)
{
const char *map;
char *biosname;
map = grub_util_biosdisk_get_compatibility_hint (dev->disk);
if (map)
{
printf ("%s\n", map);
goto end;
}
biosname = guess_bios_drive (device_name);
if (biosname)
print_full_name (biosname, dev);
printf ("\n");
free (biosname);
goto end;
}
if (print == PRINT_BIOS_HINT)
{
char *biosname;
biosname = guess_bios_drive (device_name);
if (biosname)
print_full_name (biosname, dev);
printf ("\n");
free (biosname);
goto end;
}
if (print == PRINT_IEEE1275_HINT)
{
const char *orig_path = grub_util_devname_to_ofpath (device_name);
char *ofpath = escape_of_path (orig_path);
const char *map;
map = grub_util_biosdisk_get_compatibility_hint (dev->disk);
if (map)
{
printf (" ");
print_full_name (map, dev);
}
printf (" ");
print_full_name (ofpath, dev);
printf ("\n");
free (ofpath);
goto end;
}
if (print == PRINT_EFI_HINT)
{
char *biosname;
char *name;
const char *map;
biosname = guess_efi_drive (device_name);
map = grub_util_biosdisk_get_compatibility_hint (dev->disk);
if (map)
{
printf (" ");
print_full_name (map, dev);
}
if (biosname)
{
printf (" ");
print_full_name (biosname, dev);
}
printf ("\n");
free (biosname);
goto end;
}
if (print == PRINT_BAREMETAL_HINT)
{
char *biosname;
char *name;
const char *map;
biosname = guess_baremetal_drive (device_name);
map = grub_util_biosdisk_get_compatibility_hint (dev->disk);
if (map)
{
printf (" ");
print_full_name (map, dev);
}
if (biosname)
{
printf (" ");
print_full_name (biosname, dev);
}
printf ("\n");
free (biosname);
goto end;
}
if (print == PRINT_ARC_HINT)
{
const char *map;
map = grub_util_biosdisk_get_compatibility_hint (dev->disk);
if (map)
{
printf (" ");
print_full_name (map, dev);
}
printf ("\n");
/* FIXME */
goto end;
}
if (print == PRINT_ABSTRACTION)
{
grub_disk_memberlist_t list = NULL, tmp;
@ -348,6 +649,20 @@ main (int argc, char *argv[])
print = PRINT_PARTMAP;
else if (!strcmp (optarg, "abstraction"))
print = PRINT_ABSTRACTION;
else if (!strcmp (optarg, "hints_string"))
print = PRINT_HINT_STR;
else if (!strcmp (optarg, "bios_hints"))
print = PRINT_BIOS_HINT;
else if (!strcmp (optarg, "ieee1275_hints"))
print = PRINT_IEEE1275_HINT;
else if (!strcmp (optarg, "baremetal_hints"))
print = PRINT_BAREMETAL_HINT;
else if (!strcmp (optarg, "efi_hints"))
print = PRINT_EFI_HINT;
else if (!strcmp (optarg, "arc_hints"))
print = PRINT_ARC_HINT;
else if (!strcmp (optarg, "compatibility_hint"))
print = PRINT_COMPATIBILITY_HINT;
else
usage (1);
break;

View file

@ -1,49 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <grub/types.h>
#include <grub/util/deviceiter.h>
#include <grub/util/ofpath.h>
#include <grub/util/misc.h>
/* Since OF path names can have "," characters in them, and GRUB
internally uses "," to indicate partitions (unlike OF which uses
":" for this purpose) we escape such commas. */
static char *
escape_of_path (const char *orig_path)
{
char *new_path, *d, c;
const char *p;
if (!strchr (orig_path, ','))
return (char *) orig_path;
new_path = xmalloc (strlen (orig_path) * 2);
p = orig_path;
d = new_path;
while ((c = *p++) != '\0')
{
if (c == ',')
*d++ = '\\';
*d++ = c;
}
free ((char *) orig_path);
return new_path;
}
void
grub_util_emit_devicemap_entry (FILE *fp, char *name,
int is_floppy __attribute__((unused)),
int *num_fd __attribute__((unused)),
int *num_hd __attribute__((unused)))
{
const char *orig_path = grub_util_devname_to_ofpath (name);
char *ofpath = escape_of_path (orig_path);
fprintf(fp, "(%s)\t%s\n", ofpath, name);
free (ofpath);
}