#include <grub/env.h>
#include <grub/raid.h>
#include <grub/i18n.h>
+#include <grub/emu/misc.h>
+#include <grub/util/ofpath.h>
+ #include <grub/crypto.h>
+ #include <grub/cryptodisk.h>
#include <stdio.h>
#include <unistd.h>
PRINT_DEVICE,
PRINT_PARTMAP,
PRINT_ABSTRACTION,
- PRINT_CRYPTODISK_UUID
++ PRINT_CRYPTODISK_UUID,
+ 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;
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_abstraction (grub_disk_t disk)
+ {
+ grub_disk_memberlist_t list = NULL, tmp;
+ int raid_level;
+
+ if (disk->dev->memberlist)
+ list = disk->dev->memberlist (disk);
+ while (list)
+ {
+ probe_abstraction (list->disk);
+
+ tmp = list->next;
+ free (list);
+ list = tmp;
+ }
+
+ if (disk->dev->id == GRUB_DISK_DEVICE_LVM_ID)
+ printf ("lvm ");
+
+ if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
+ grub_util_cryptodisk_print_abstraction (disk);
+
+ raid_level = probe_raid_level (disk);
+ if (raid_level >= 0)
+ {
+ printf ("raid ");
+ if (disk->dev->raidname)
+ printf ("%s ", disk->dev->raidname (disk));
+ }
+ if (raid_level == 5)
+ printf ("raid5rec ");
+ if (raid_level == 6)
+ printf ("raid6rec ");
+ }
+
static void
probe (const char *path, char *device_name)
{
grub_util_info ("opening %s", drive_name);
dev = grub_device_open (drive_name);
if (! dev)
- grub_util_error ("%s", grub_errmsg);
+ 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;
- const int is_lvm = (dev->disk->dev->id == GRUB_DISK_DEVICE_LVM_ID);
- int is_raid = 0;
- int is_raid5 = 0;
- int is_raid6 = 0;
- int raid_level;
- grub_disk_t raid_disk;
-
- raid_level = probe_raid_level (dev->disk);
- if (raid_level >= 0)
- {
- is_raid = 1;
- is_raid5 |= (raid_level == 5);
- is_raid6 |= (raid_level == 6);
- raid_disk = dev->disk;
- }
-
- if ((is_lvm) && (dev->disk->dev->memberlist))
- list = dev->disk->dev->memberlist (dev->disk);
- while (list)
- {
- raid_level = probe_raid_level (list->disk);
- if (raid_level >= 0)
- {
- is_raid = 1;
- is_raid5 |= (raid_level == 5);
- is_raid6 |= (raid_level == 6);
- raid_disk = list->disk;
- }
-
- tmp = list->next;
- free (list);
- list = tmp;
- }
-
- if (is_raid)
- {
- printf ("raid ");
- if (is_raid5)
- printf ("raid5rec ");
- if (is_raid6)
- printf ("raid6rec ");
- if (raid_disk->dev->raidname)
- printf ("%s ", raid_disk->dev->raidname (raid_disk));
- }
-
- if (is_lvm)
- printf ("lvm ");
-
+ probe_abstraction (dev->disk);
printf ("\n");
+ goto end;
+ }
+ if (print == PRINT_CRYPTODISK_UUID)
+ {
+ probe_cryptodisk_uuid (dev->disk);
+ printf ("\n");
goto end;
}
print = PRINT_PARTMAP;
else if (!strcmp (optarg, "abstraction"))
print = PRINT_ABSTRACTION;
+ else if (!strcmp (optarg, "cryptodisk_uuid"))
+ print = PRINT_CRYPTODISK_UUID;
+ 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;