1 /* grub-probe.c - probe device information for a given path */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
21 #include <grub/types.h>
22 #include <grub/emu/misc.h>
23 #include <grub/util/misc.h>
24 #include <grub/device.h>
25 #include <grub/disk.h>
26 #include <grub/file.h>
28 #include <grub/partition.h>
29 #include <grub/msdos_partition.h>
30 #include <grub/emu/hostdisk.h>
31 #include <grub/emu/getroot.h>
32 #include <grub/term.h>
34 #include <grub/raid.h>
35 #include <grub/i18n.h>
36 #include <grub/emu/misc.h>
37 #include <grub/util/ofpath.h>
38 #include <grub/crypto.h>
39 #include <grub/cryptodisk.h>
60 PRINT_CRYPTODISK_UUID
,
67 PRINT_COMPATIBILITY_HINT
70 static int print
= PRINT_FS
;
71 static unsigned int argument_is_device
= 0;
74 probe_partmap (grub_disk_t disk
)
76 grub_partition_t part
;
77 grub_disk_memberlist_t list
= NULL
, tmp
;
79 if (disk
->partition
== NULL
)
81 grub_util_info ("no partition map found for %s", disk
->name
);
84 for (part
= disk
->partition
; part
; part
= part
->parent
)
85 printf ("%s ", part
->partmap
->name
);
87 /* In case of LVM/RAID, check the member devices as well. */
88 if (disk
->dev
->memberlist
)
90 list
= disk
->dev
->memberlist (disk
);
94 probe_partmap (list
->disk
);
102 probe_cryptodisk_uuid (grub_disk_t disk
)
104 grub_disk_memberlist_t list
= NULL
, tmp
;
106 /* In case of LVM/RAID, check the member devices as well. */
107 if (disk
->dev
->memberlist
)
109 list
= disk
->dev
->memberlist (disk
);
113 probe_cryptodisk_uuid (list
->disk
);
118 if (disk
->dev
->id
== GRUB_DISK_DEVICE_CRYPTODISK_ID
)
119 grub_util_cryptodisk_print_uuid (disk
);
123 probe_raid_level (grub_disk_t disk
)
125 /* disk might be NULL in the case of a LVM physical volume with no LVM
126 signature. Ignore such cases here. */
130 if (disk
->dev
->id
!= GRUB_DISK_DEVICE_RAID_ID
)
133 return ((struct grub_raid_array
*) disk
->data
)->level
;
136 /* Since OF path names can have "," characters in them, and GRUB
137 internally uses "," to indicate partitions (unlike OF which uses
138 ":" for this purpose) we escape such commas. */
140 escape_of_path (const char *orig_path
)
142 char *new_path
, *d
, c
;
145 if (!strchr (orig_path
, ','))
146 return (char *) orig_path
;
148 new_path
= xmalloc (strlen (orig_path
) * 2 + sizeof ("ieee1275/"));
151 grub_strcpy (new_path
, "ieee1275/");
152 d
= new_path
+ sizeof ("ieee1275/") - 1;
153 while ((c
= *p
++) != '\0')
161 free ((char *) orig_path
);
167 guess_bios_drive (const char *orig_path
)
171 canon
= canonicalize_file_name (orig_path
);
174 ptr
= strrchr (orig_path
, '/');
179 if ((ptr
[0] == 's' || ptr
[0] == 'h') && ptr
[1] == 'd')
181 int num
= ptr
[2] - 'a';
183 return xasprintf ("hd%d", num
);
185 if (ptr
[0] == 'f' && ptr
[1] == 'd')
187 int num
= atoi (ptr
+ 2);
189 return xasprintf ("fd%d", num
);
196 guess_efi_drive (const char *orig_path
)
200 canon
= canonicalize_file_name (orig_path
);
203 ptr
= strrchr (orig_path
, '/');
208 if ((ptr
[0] == 's' || ptr
[0] == 'h') && ptr
[1] == 'd')
210 int num
= ptr
[2] - 'a';
212 return xasprintf ("hd%d", num
);
214 if (ptr
[0] == 'f' && ptr
[1] == 'd')
216 int num
= atoi (ptr
+ 2);
218 return xasprintf ("fd%d", num
);
225 guess_baremetal_drive (const char *orig_path
)
229 canon
= canonicalize_file_name (orig_path
);
232 ptr
= strrchr (orig_path
, '/');
237 if (ptr
[0] == 'h' && ptr
[1] == 'd')
239 int num
= ptr
[2] - 'a';
241 return xasprintf ("ata%d", num
);
243 if (ptr
[0] == 's' && ptr
[1] == 'd')
245 int num
= ptr
[2] - 'a';
247 return xasprintf ("ahci%d", num
);
254 print_full_name (const char *drive
, grub_device_t dev
)
256 if (dev
->disk
->partition
)
258 char *pname
= grub_partition_get_name (dev
->disk
->partition
);
259 printf ("%s,%s", drive
, pname
);
263 printf ("%s", drive
);
267 probe_abstraction (grub_disk_t disk
)
269 grub_disk_memberlist_t list
= NULL
, tmp
;
272 if (disk
->dev
->memberlist
)
273 list
= disk
->dev
->memberlist (disk
);
276 probe_abstraction (list
->disk
);
283 if (disk
->dev
->id
== GRUB_DISK_DEVICE_LVM_ID
)
286 if (disk
->dev
->id
== GRUB_DISK_DEVICE_CRYPTODISK_ID
)
287 grub_util_cryptodisk_print_abstraction (disk
);
289 raid_level
= probe_raid_level (disk
);
293 if (disk
->dev
->raidname
)
294 printf ("%s ", disk
->dev
->raidname (disk
));
297 printf ("raid5rec ");
299 printf ("raid6rec ");
303 probe (const char *path
, char *device_name
)
305 char *drive_name
= NULL
;
306 char *grub_path
= NULL
;
307 char *filebuf_via_grub
= NULL
, *filebuf_via_sys
= NULL
;
308 grub_device_t dev
= NULL
;
313 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__sun__)
314 if (! grub_util_check_char_device (device_name
))
315 grub_util_error (_("%s is not a character device"), device_name
);
317 if (! grub_util_check_block_device (device_name
))
318 grub_util_error (_("%s is not a block device"), device_name
);
323 grub_path
= canonicalize_file_name (path
);
324 device_name
= grub_guess_root_device (grub_path
);
328 grub_util_error (_("cannot find a device for %s (is /dev mounted?)"), path
);
330 if (print
== PRINT_DEVICE
)
332 printf ("%s\n", device_name
);
336 drive_name
= grub_util_get_grub_dev (device_name
);
338 grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"),
341 if (print
== PRINT_DRIVE
)
343 printf ("(%s)\n", drive_name
);
347 grub_util_info ("opening %s", drive_name
);
348 dev
= grub_device_open (drive_name
);
350 grub_util_error ("%s", _(grub_errmsg
));
352 if (print
== PRINT_HINT_STR
)
354 const char *osdev
= grub_util_biosdisk_get_osdev (dev
->disk
);
355 const char *orig_path
= grub_util_devname_to_ofpath (osdev
);
356 char *biosname
, *bare
, *efi
;
361 char *ofpath
= escape_of_path (orig_path
);
362 printf ("--hint-ieee1275='");
363 print_full_name (ofpath
, dev
);
368 biosname
= guess_bios_drive (device_name
);
371 printf ("--hint-bios=");
372 print_full_name (biosname
, dev
);
377 efi
= guess_efi_drive (device_name
);
380 printf ("--hint-efi=");
381 print_full_name (efi
, dev
);
386 bare
= guess_baremetal_drive (device_name
);
389 printf ("--hint-baremetal=");
390 print_full_name (bare
, dev
);
395 /* FIXME: Add ARC hint. */
397 map
= grub_util_biosdisk_get_compatibility_hint (dev
->disk
);
401 print_full_name (map
, dev
);
409 if (print
== PRINT_COMPATIBILITY_HINT
)
413 map
= grub_util_biosdisk_get_compatibility_hint (dev
->disk
);
416 print_full_name (map
, dev
);
420 biosname
= guess_bios_drive (device_name
);
422 print_full_name (biosname
, dev
);
428 if (print
== PRINT_BIOS_HINT
)
431 biosname
= guess_bios_drive (device_name
);
433 print_full_name (biosname
, dev
);
438 if (print
== PRINT_IEEE1275_HINT
)
440 const char *osdev
= grub_util_biosdisk_get_osdev (dev
->disk
);
441 const char *orig_path
= grub_util_devname_to_ofpath (osdev
);
442 char *ofpath
= escape_of_path (orig_path
);
445 map
= grub_util_biosdisk_get_compatibility_hint (dev
->disk
);
449 print_full_name (map
, dev
);
453 print_full_name (ofpath
, dev
);
459 if (print
== PRINT_EFI_HINT
)
464 biosname
= guess_efi_drive (device_name
);
466 map
= grub_util_biosdisk_get_compatibility_hint (dev
->disk
);
470 print_full_name (map
, dev
);
475 print_full_name (biosname
, dev
);
483 if (print
== PRINT_BAREMETAL_HINT
)
489 biosname
= guess_baremetal_drive (device_name
);
491 map
= grub_util_biosdisk_get_compatibility_hint (dev
->disk
);
495 print_full_name (map
, dev
);
500 print_full_name (biosname
, dev
);
508 if (print
== PRINT_ARC_HINT
)
512 map
= grub_util_biosdisk_get_compatibility_hint (dev
->disk
);
516 print_full_name (map
, dev
);
525 if (print
== PRINT_ABSTRACTION
)
527 probe_abstraction (dev
->disk
);
532 if (print
== PRINT_CRYPTODISK_UUID
)
534 probe_cryptodisk_uuid (dev
->disk
);
539 if (print
== PRINT_PARTMAP
)
541 /* Check if dev->disk itself is contained in a partmap. */
542 probe_partmap (dev
->disk
);
547 fs
= grub_fs_probe (dev
);
549 grub_util_error ("%s", _(grub_errmsg
));
551 if (print
== PRINT_FS
)
553 printf ("%s\n", fs
->name
);
555 else if (print
== PRINT_FS_UUID
)
559 grub_util_error (_("%s does not support UUIDs"), fs
->name
);
561 if (fs
->uuid (dev
, &uuid
) != GRUB_ERR_NONE
)
562 grub_util_error ("%s", grub_errmsg
);
564 printf ("%s\n", uuid
);
566 else if (print
== PRINT_FS_LABEL
)
570 grub_util_error (_("%s does not support labels"), fs
->name
);
572 if (fs
->label (dev
, &label
) != GRUB_ERR_NONE
)
573 grub_util_error ("%s", _(grub_errmsg
));
575 printf ("%s\n", label
);
580 grub_device_close (dev
);
582 free (filebuf_via_grub
);
583 free (filebuf_via_sys
);
587 static struct option options
[] =
589 {"device", no_argument
, 0, 'd'},
590 {"device-map", required_argument
, 0, 'm'},
591 {"target", required_argument
, 0, 't'},
592 {"help", no_argument
, 0, 'h'},
593 {"version", no_argument
, 0, 'V'},
594 {"verbose", no_argument
, 0, 'v'},
603 _("Try `%s --help' for more information.\n"), program_name
);
606 Usage: %s [OPTION]... [PATH|DEVICE]\n\
608 Probe device information for a given path (or device, if the -d option is given).\n\
610 -d, --device given argument is a system device, not a path\n\
611 -m, --device-map=FILE use FILE as the device map [default=%s]\n\
612 -t, --target=(fs|fs_uuid|fs_label|drive|device|partmap|abstraction|cryptodisk_uuid)\n\
613 print filesystem module, GRUB drive, system device, partition map module, abstraction module or CRYPTO UUID [default=fs]\n\
614 -h, --help display this message and exit\n\
615 -V, --version print version information and exit\n\
616 -v, --verbose print verbose messages\n\
618 Report bugs to <%s>.\n\
620 DEFAULT_DEVICE_MAP
, PACKAGE_BUGREPORT
);
626 main (int argc
, char *argv
[])
631 set_program_name (argv
[0]);
633 grub_util_init_nls ();
635 /* Check for options. */
638 int c
= getopt_long (argc
, argv
, "dm:t:hVv", options
, 0);
646 argument_is_device
= 1;
653 dev_map
= xstrdup (optarg
);
657 if (!strcmp (optarg
, "fs"))
659 else if (!strcmp (optarg
, "fs_uuid"))
660 print
= PRINT_FS_UUID
;
661 else if (!strcmp (optarg
, "fs_label"))
662 print
= PRINT_FS_LABEL
;
663 else if (!strcmp (optarg
, "drive"))
665 else if (!strcmp (optarg
, "device"))
666 print
= PRINT_DEVICE
;
667 else if (!strcmp (optarg
, "partmap"))
668 print
= PRINT_PARTMAP
;
669 else if (!strcmp (optarg
, "abstraction"))
670 print
= PRINT_ABSTRACTION
;
671 else if (!strcmp (optarg
, "cryptodisk_uuid"))
672 print
= PRINT_CRYPTODISK_UUID
;
673 else if (!strcmp (optarg
, "hints_string"))
674 print
= PRINT_HINT_STR
;
675 else if (!strcmp (optarg
, "bios_hints"))
676 print
= PRINT_BIOS_HINT
;
677 else if (!strcmp (optarg
, "ieee1275_hints"))
678 print
= PRINT_IEEE1275_HINT
;
679 else if (!strcmp (optarg
, "baremetal_hints"))
680 print
= PRINT_BAREMETAL_HINT
;
681 else if (!strcmp (optarg
, "efi_hints"))
682 print
= PRINT_EFI_HINT
;
683 else if (!strcmp (optarg
, "arc_hints"))
684 print
= PRINT_ARC_HINT
;
685 else if (!strcmp (optarg
, "compatibility_hint"))
686 print
= PRINT_COMPATIBILITY_HINT
;
696 printf ("%s (%s) %s\n", program_name
, PACKAGE_NAME
, PACKAGE_VERSION
);
710 grub_env_set ("debug", "all");
712 /* Obtain ARGUMENT. */
715 fprintf (stderr
, _("No path or device is specified.\n"));
719 if (optind
+ 1 != argc
)
721 fprintf (stderr
, _("Unknown extra argument `%s'.\n"), argv
[optind
+ 1]);
725 argument
= argv
[optind
];
727 /* Initialize the emulated biosdisk driver. */
728 grub_util_biosdisk_init (dev_map
? : DEFAULT_DEVICE_MAP
);
730 /* Initialize all modules. */
732 grub_gcry_init_all ();
735 grub_mdraid09_fini ();
736 grub_mdraid1x_fini ();
739 grub_mdraid09_init ();
740 grub_mdraid1x_init ();
744 if (argument_is_device
)
745 probe (NULL
, argument
);
747 probe (argument
, NULL
);
749 /* Free resources. */
750 grub_gcry_fini_all ();
752 grub_util_biosdisk_fini ();