]> git.proxmox.com Git - grub2.git/blame - util/grub-probe.c
* grub-core/genmod.sh.in: Strip before converting to ELF as strip
[grub2.git] / util / grub-probe.c
CommitLineData
ddd5cee9 1/* grub-probe.c - probe device information for a given path */
8b5f3938 2/*
3 * GRUB -- GRand Unified Bootloader
2f1a3acf 4 * Copyright (C) 2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
8b5f3938 5 *
5a79f472 6 * GRUB is free software: you can redistribute it and/or modify
8b5f3938 7 * it under the terms of the GNU General Public License as published by
5a79f472 8 * the Free Software Foundation, either version 3 of the License, or
8b5f3938 9 * (at your option) any later version.
10 *
5a79f472 11 * GRUB is distributed in the hope that it will be useful,
8b5f3938 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.
15 *
16 * You should have received a copy of the GNU General Public License
5a79f472 17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
8b5f3938 18 */
19
20#include <config.h>
21#include <grub/types.h>
8c411768 22#include <grub/emu/misc.h>
8b5f3938 23#include <grub/util/misc.h>
24#include <grub/device.h>
25#include <grub/disk.h>
2a9525e6 26#include <grub/file.h>
8b5f3938 27#include <grub/fs.h>
28#include <grub/partition.h>
71acf5e5 29#include <grub/msdos_partition.h>
39cfdaa9 30#include <grub/gpt_partition.h>
8c411768
BC
31#include <grub/emu/hostdisk.h>
32#include <grub/emu/getroot.h>
9cacaa17 33#include <grub/term.h>
0bf6d401 34#include <grub/env.h>
076e7c0f 35#include <grub/diskfilter.h>
8a4c07fd 36#include <grub/i18n.h>
6babad5e
VS
37#include <grub/emu/misc.h>
38#include <grub/util/ofpath.h>
50ad7d9c 39#include <grub/crypto.h>
8585e54b 40#include <grub/cryptodisk.h>
8b5f3938 41
42#include <stdio.h>
43#include <unistd.h>
44#include <string.h>
45#include <stdlib.h>
8e1e4e39 46#include <assert.h>
8b5f3938 47
48#define _GNU_SOURCE 1
8e1e4e39 49#include <argp.h>
8b5f3938 50
8a4c07fd
RM
51#include "progname.h"
52
1eb8c802 53enum {
54 PRINT_FS,
62191274 55 PRINT_FS_UUID,
0806b63c 56 PRINT_FS_LABEL,
1eb8c802 57 PRINT_DRIVE,
58 PRINT_DEVICE,
59 PRINT_PARTMAP,
60 PRINT_ABSTRACTION,
17785932 61 PRINT_CRYPTODISK_UUID,
6babad5e
VS
62 PRINT_HINT_STR,
63 PRINT_BIOS_HINT,
64 PRINT_IEEE1275_HINT,
65 PRINT_BAREMETAL_HINT,
66 PRINT_EFI_HINT,
67 PRINT_ARC_HINT,
66832792 68 PRINT_COMPATIBILITY_HINT,
8be63f2e 69 PRINT_MSDOS_PARTTYPE,
39cfdaa9 70 PRINT_GPT_PARTTYPE,
fe8c2f11 71 PRINT_ZERO_CHECK,
8be63f2e 72 PRINT_DISK
1eb8c802 73};
ddd5cee9 74
29805028 75static int print = PRINT_FS;
79ca2d78 76static unsigned int argument_is_device = 0;
ddd5cee9 77
bf25f879
VS
78static void
79do_print (const char *x)
80{
81 grub_printf ("%s ", x);
82}
83
b92f0c18 84static void
85probe_partmap (grub_disk_t disk)
86{
15cb7d43 87 grub_partition_t part;
50ad7d9c 88 grub_disk_memberlist_t list = NULL, tmp;
15cb7d43 89
b92f0c18 90 if (disk->partition == NULL)
91 {
70a14d3d 92 grub_util_info ("no partition map found for %s", disk->name);
b92f0c18 93 }
b39f9d20 94
15cb7d43 95 for (part = disk->partition; part; part = part->parent)
50ad7d9c
VS
96 printf ("%s ", part->partmap->name);
97
4786a90f 98 if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID)
bf25f879 99 grub_diskfilter_get_partmap (disk, do_print);
4786a90f 100
50ad7d9c
VS
101 /* In case of LVM/RAID, check the member devices as well. */
102 if (disk->dev->memberlist)
103 {
104 list = disk->dev->memberlist (disk);
105 }
106 while (list)
107 {
108 probe_partmap (list->disk);
109 tmp = list->next;
110 free (list);
111 list = tmp;
112 }
b92f0c18 113}
114
9d647e4e 115static void
20a40940 116probe_cryptodisk_uuid (grub_disk_t disk)
9d647e4e
VS
117{
118 grub_disk_memberlist_t list = NULL, tmp;
119
120 /* In case of LVM/RAID, check the member devices as well. */
121 if (disk->dev->memberlist)
122 {
123 list = disk->dev->memberlist (disk);
124 }
125 while (list)
126 {
20a40940 127 probe_cryptodisk_uuid (list->disk);
9d647e4e
VS
128 tmp = list->next;
129 free (list);
130 list = tmp;
131 }
8585e54b 132 if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
bf25f879
VS
133 {
134 const char *uu = grub_util_cryptodisk_get_uuid (disk);
135 grub_printf ("%s ", uu);
136 }
b92f0c18 137}
138
f45d6cfc 139static int
140probe_raid_level (grub_disk_t disk)
141{
917dd370
CW
142 /* disk might be NULL in the case of a LVM physical volume with no LVM
143 signature. Ignore such cases here. */
144 if (!disk)
145 return -1;
146
076e7c0f 147 if (disk->dev->id != GRUB_DISK_DEVICE_DISKFILTER_ID)
f45d6cfc 148 return -1;
149
076e7c0f
VS
150 if (disk->name[0] != 'm' || disk->name[1] != 'd')
151 return -1;
152
153 if (!((struct grub_diskfilter_lv *) disk->data)->segments)
154 return -1;
155 return ((struct grub_diskfilter_lv *) disk->data)->segments->type;
f45d6cfc 156}
157
50ad7d9c
VS
158static void
159probe_abstraction (grub_disk_t disk)
160{
161 grub_disk_memberlist_t list = NULL, tmp;
162 int raid_level;
163
164 if (disk->dev->memberlist)
165 list = disk->dev->memberlist (disk);
166 while (list)
167 {
168 probe_abstraction (list->disk);
169
170 tmp = list->next;
171 free (list);
172 list = tmp;
173 }
174
076e7c0f 175 if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID
775b284d
AB
176 && (grub_memcmp (disk->name, "lvm/", sizeof ("lvm/") - 1) == 0 ||
177 grub_memcmp (disk->name, "lvmid/", sizeof ("lvmid/") - 1) == 0))
50ad7d9c
VS
178 printf ("lvm ");
179
076e7c0f
VS
180 if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID
181 && grub_memcmp (disk->name, "ldm/", sizeof ("ldm/") - 1) == 0)
182 printf ("ldm ");
183
8585e54b 184 if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
bf25f879 185 grub_util_cryptodisk_get_abstraction (disk, do_print);
50ad7d9c
VS
186
187 raid_level = probe_raid_level (disk);
188 if (raid_level >= 0)
189 {
4786a90f 190 printf ("diskfilter ");
50ad7d9c
VS
191 if (disk->dev->raidname)
192 printf ("%s ", disk->dev->raidname (disk));
193 }
194 if (raid_level == 5)
195 printf ("raid5rec ");
196 if (raid_level == 6)
197 printf ("raid6rec ");
198}
199
8b5f3938 200static void
cf5f7ee7 201probe (const char *path, char **device_names, char delim)
8b5f3938 202{
cf5f7ee7
VS
203 char **drives_names = NULL;
204 char **curdev, **curdrive;
2a9525e6 205 char *grub_path = NULL;
cf5f7ee7 206 int ndev = 0;
b39f9d20 207
cf5f7ee7 208 if (path != NULL)
828bc390
ML
209 {
210 grub_path = canonicalize_file_name (path);
65f08dbf 211 if (! grub_path)
22099030 212 grub_util_error (_("failed to get canonical path of `%s'"), path);
cf5f7ee7
VS
213 device_names = grub_guess_root_devices (grub_path);
214 free (grub_path);
828bc390 215 }
79ca2d78 216
cf5f7ee7 217 if (! device_names)
10f0117b 218 grub_util_error (_("cannot find a device for %s (is /dev mounted?)"), path);
ddd5cee9 219
220 if (print == PRINT_DEVICE)
221 {
cf5f7ee7
VS
222 for (curdev = device_names; *curdev; curdev++)
223 {
224 printf ("%s", *curdev);
225 putchar (delim);
226 }
227 return;
ddd5cee9 228 }
229
8be63f2e
VS
230 if (print == PRINT_DISK)
231 {
232 for (curdev = device_names; *curdev; curdev++)
233 {
234 char *disk;
235 disk = grub_util_get_os_disk (*curdev);
236 if (!disk)
237 {
238 grub_print_error ();
239 continue;
240 }
241 printf ("%s", disk);
242 putchar (delim);
243 }
244 return;
245 }
246
cf5f7ee7 247 for (curdev = device_names; *curdev; curdev++)
ddd5cee9 248 {
cf5f7ee7
VS
249 grub_util_pull_device (*curdev);
250 ndev++;
8b5f3938 251 }
cf5f7ee7
VS
252
253 drives_names = xmalloc (sizeof (drives_names[0]) * (ndev + 1));
8b5f3938 254
cf5f7ee7
VS
255 for (curdev = device_names, curdrive = drives_names; *curdev; curdev++,
256 curdrive++)
257 {
258 *curdrive = grub_util_get_grub_dev (*curdev);
259 if (! *curdrive)
260 grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"),
261 *curdev);
262 }
263 *curdrive = 0;
8b5f3938 264
65f08dbf
RL
265 if (print == PRINT_DRIVE)
266 {
267 for (curdrive = drives_names; *curdrive; curdrive++)
268 {
269 printf ("(%s)", *curdrive);
270 putchar (delim);
271 }
272 goto end;
273 }
274
fe8c2f11
VS
275 if (print == PRINT_ZERO_CHECK)
276 {
277 for (curdev = drives_names; *curdev; curdev++)
278 {
279 grub_device_t dev = NULL;
280 grub_uint32_t buffer[32768];
281 grub_disk_addr_t addr;
282 grub_disk_addr_t dsize;
283
284 grub_util_info ("opening %s", *curdev);
285 dev = grub_device_open (*curdev);
286 if (! dev || !dev->disk)
287 grub_util_error ("%s", grub_errmsg);
288
289 dsize = grub_disk_get_size (dev->disk);
290 for (addr = 0; addr < dsize;
291 addr += sizeof (buffer) / GRUB_DISK_SECTOR_SIZE)
292 {
293 grub_size_t sz = sizeof (buffer);
294 grub_uint32_t *ptr;
295
296 if (sizeof (buffer) / GRUB_DISK_SECTOR_SIZE > dsize - addr)
297 sz = (dsize - addr) * GRUB_DISK_SECTOR_SIZE;
298 grub_disk_read (dev->disk, addr, 0, sz, buffer);
299
300 for (ptr = buffer; ptr < buffer + sz / sizeof (*buffer); ptr++)
301 if (*ptr)
302 {
303 grub_printf ("false\n");
304 grub_device_close (dev);
305 goto end;
306 }
307 }
308
309 grub_device_close (dev);
310 }
311 grub_printf ("true\n");
312 }
313
cf5f7ee7
VS
314 if (print == PRINT_FS || print == PRINT_FS_UUID
315 || print == PRINT_FS_LABEL)
6babad5e 316 {
cf5f7ee7
VS
317 grub_device_t dev = NULL;
318 grub_fs_t fs;
6babad5e 319
cf5f7ee7
VS
320 grub_util_info ("opening %s", drives_names[0]);
321 dev = grub_device_open (drives_names[0]);
322 if (! dev)
36eb7379 323 grub_util_error ("%s", grub_errmsg);
cf5f7ee7
VS
324
325 fs = grub_fs_probe (dev);
326 if (! fs)
36eb7379 327 grub_util_error ("%s", grub_errmsg);
6babad5e 328
cf5f7ee7 329 if (print == PRINT_FS)
6babad5e 330 {
cf5f7ee7
VS
331 printf ("%s", fs->name);
332 putchar (delim);
6babad5e 333 }
cf5f7ee7 334 else if (print == PRINT_FS_UUID)
6babad5e 335 {
cf5f7ee7
VS
336 char *uuid;
337 if (! fs->uuid)
338 grub_util_error (_("%s does not support UUIDs"), fs->name);
6babad5e 339
cf5f7ee7
VS
340 if (fs->uuid (dev, &uuid) != GRUB_ERR_NONE)
341 grub_util_error ("%s", grub_errmsg);
342
343 printf ("%s", uuid);
344 putchar (delim);
6babad5e 345 }
cf5f7ee7
VS
346 else if (print == PRINT_FS_LABEL)
347 {
348 char *label;
349 if (! fs->label)
9c4b5c13
VS
350 grub_util_error (_("filesystem `%s' does not support labels"),
351 fs->name);
6babad5e 352
cf5f7ee7 353 if (fs->label (dev, &label) != GRUB_ERR_NONE)
36eb7379 354 grub_util_error ("%s", grub_errmsg);
6babad5e 355
cf5f7ee7
VS
356 printf ("%s", label);
357 putchar (delim);
6babad5e 358 }
592fd0e4 359 grub_device_close (dev);
6babad5e
VS
360 goto end;
361 }
362
cf5f7ee7
VS
363 for (curdrive = drives_names, curdev = device_names; *curdrive;
364 curdrive++, curdev++)
63fe43f3 365 {
cf5f7ee7 366 grub_device_t dev = NULL;
63fe43f3 367
cf5f7ee7
VS
368 grub_util_info ("opening %s", *curdrive);
369 dev = grub_device_open (*curdrive);
370 if (! dev)
36eb7379 371 grub_util_error ("%s", grub_errmsg);
cf5f7ee7
VS
372
373 if (print == PRINT_HINT_STR)
6babad5e 374 {
cf5f7ee7
VS
375 const char *osdev = grub_util_biosdisk_get_osdev (dev->disk);
376 const char *ofpath = osdev ? grub_util_devname_to_ofpath (osdev) : 0;
377 char *biosname, *bare, *efi;
378 const char *map;
379
380 if (ofpath)
381 {
1c715b5a
VS
382 char *tmp = xmalloc (strlen (ofpath) + sizeof ("ieee1275/"));
383 char *p;
ba44ca6d 384 p = grub_stpcpy (tmp, "ieee1275/");
1c715b5a 385 strcpy (p, ofpath);
cf5f7ee7 386 printf ("--hint-ieee1275='");
cd46aa6c 387 grub_util_fprint_full_disk_name (stdout, tmp, dev);
cf5f7ee7 388 printf ("' ");
1c715b5a 389 free (tmp);
cf5f7ee7
VS
390 }
391
cd46aa6c 392 biosname = grub_util_guess_bios_drive (*curdev);
cf5f7ee7
VS
393 if (biosname)
394 {
395 printf ("--hint-bios=");
cd46aa6c 396 grub_util_fprint_full_disk_name (stdout, biosname, dev);
cf5f7ee7
VS
397 printf (" ");
398 }
399 free (biosname);
400
cd46aa6c 401 efi = grub_util_guess_efi_drive (*curdev);
cf5f7ee7
VS
402 if (efi)
403 {
404 printf ("--hint-efi=");
cd46aa6c 405 grub_util_fprint_full_disk_name (stdout, efi, dev);
cf5f7ee7
VS
406 printf (" ");
407 }
408 free (efi);
409
cd46aa6c 410 bare = grub_util_guess_baremetal_drive (*curdev);
cf5f7ee7
VS
411 if (bare)
412 {
413 printf ("--hint-baremetal=");
cd46aa6c 414 grub_util_fprint_full_disk_name (stdout, bare, dev);
cf5f7ee7
VS
415 printf (" ");
416 }
417 free (bare);
418
419 /* FIXME: Add ARC hint. */
420
421 map = grub_util_biosdisk_get_compatibility_hint (dev->disk);
422 if (map)
423 {
424 printf ("--hint='");
cd46aa6c 425 grub_util_fprint_full_disk_name (stdout, map, dev);
cf5f7ee7
VS
426 printf ("' ");
427 }
588744d0
VS
428 if (curdrive[1])
429 printf (" ");
430 else
431 printf ("\n");
6babad5e 432
cf5f7ee7
VS
433 grub_device_close (dev);
434 continue;
435 }
436
437 if ((print == PRINT_COMPATIBILITY_HINT || print == PRINT_BIOS_HINT
438 || print == PRINT_IEEE1275_HINT || print == PRINT_BAREMETAL_HINT
439 || print == PRINT_EFI_HINT || print == PRINT_ARC_HINT)
440 && dev->disk->dev->id != GRUB_DISK_DEVICE_HOSTDISK_ID)
6babad5e 441 {
cd46aa6c 442 grub_util_fprint_full_disk_name (stdout, dev->disk->name, dev);
cf5f7ee7
VS
443 putchar (delim);
444 continue;
6babad5e
VS
445 }
446
cf5f7ee7 447 if (print == PRINT_COMPATIBILITY_HINT)
63fe43f3 448 {
cf5f7ee7
VS
449 const char *map;
450 char *biosname;
451 map = grub_util_biosdisk_get_compatibility_hint (dev->disk);
452 if (map)
453 {
cd46aa6c 454 grub_util_fprint_full_disk_name (stdout, map, dev);
cf5f7ee7
VS
455 putchar (delim);
456 grub_device_close (dev);
457 /* Compatibility hint is one device only. */
458 break;
459 }
cd46aa6c 460 biosname = grub_util_guess_bios_drive (*curdev);
cf5f7ee7
VS
461 if (biosname)
462 {
cd46aa6c 463 grub_util_fprint_full_disk_name (stdout, biosname, dev);
cf5f7ee7
VS
464 putchar (delim);
465 }
466 free (biosname);
467 grub_device_close (dev);
468 /* Compatibility hint is one device only. */
469 if (biosname)
470 break;
471 continue;
63fe43f3 472 }
6babad5e 473
cf5f7ee7 474 if (print == PRINT_BIOS_HINT)
6babad5e 475 {
cf5f7ee7 476 char *biosname;
cd46aa6c 477 biosname = grub_util_guess_bios_drive (*curdev);
cf5f7ee7
VS
478 if (biosname)
479 {
cd46aa6c 480 grub_util_fprint_full_disk_name (stdout, biosname, dev);
cf5f7ee7
VS
481 putchar (delim);
482 }
483 free (biosname);
484 grub_device_close (dev);
485 continue;
6babad5e 486 }
cf5f7ee7 487 if (print == PRINT_IEEE1275_HINT)
6babad5e 488 {
cf5f7ee7
VS
489 const char *osdev = grub_util_biosdisk_get_osdev (dev->disk);
490 const char *ofpath = grub_util_devname_to_ofpath (osdev);
491 const char *map;
492
493 map = grub_util_biosdisk_get_compatibility_hint (dev->disk);
494 if (map)
495 {
cd46aa6c 496 grub_util_fprint_full_disk_name (stdout, map, dev);
cf5f7ee7
VS
497 putchar (delim);
498 }
499
500 if (ofpath)
501 {
1c715b5a
VS
502 char *tmp = xmalloc (strlen (ofpath) + sizeof ("ieee1275/"));
503 char *p;
ba44ca6d 504 p = grub_stpcpy (tmp, "ieee1275/");
1c715b5a 505 strcpy (p, ofpath);
cd46aa6c 506 grub_util_fprint_full_disk_name (stdout, tmp, dev);
1c715b5a 507 free (tmp);
cf5f7ee7
VS
508 putchar (delim);
509 }
510
511 grub_device_close (dev);
512 continue;
6babad5e 513 }
cf5f7ee7 514 if (print == PRINT_EFI_HINT)
6babad5e 515 {
cf5f7ee7 516 char *biosname;
cf5f7ee7 517 const char *map;
cd46aa6c 518 biosname = grub_util_guess_efi_drive (*curdev);
cf5f7ee7
VS
519
520 map = grub_util_biosdisk_get_compatibility_hint (dev->disk);
521 if (map)
522 {
cd46aa6c 523 grub_util_fprint_full_disk_name (stdout, map, dev);
cf5f7ee7
VS
524 putchar (delim);
525 }
526 if (biosname)
527 {
cd46aa6c 528 grub_util_fprint_full_disk_name (stdout, biosname, dev);
cf5f7ee7
VS
529 putchar (delim);
530 }
531
532 free (biosname);
533 grub_device_close (dev);
534 continue;
6babad5e 535 }
cf5f7ee7
VS
536
537 if (print == PRINT_BAREMETAL_HINT)
6babad5e 538 {
cf5f7ee7 539 char *biosname;
cf5f7ee7
VS
540 const char *map;
541
cd46aa6c 542 biosname = grub_util_guess_baremetal_drive (*curdev);
cf5f7ee7
VS
543
544 map = grub_util_biosdisk_get_compatibility_hint (dev->disk);
545 if (map)
546 {
cd46aa6c 547 grub_util_fprint_full_disk_name (stdout, map, dev);
cf5f7ee7
VS
548 putchar (delim);
549 }
550 if (biosname)
551 {
cd46aa6c 552 grub_util_fprint_full_disk_name (stdout, biosname, dev);
cf5f7ee7
VS
553 putchar (delim);
554 }
555
556 free (biosname);
557 grub_device_close (dev);
558 continue;
6babad5e
VS
559 }
560
cf5f7ee7 561 if (print == PRINT_ARC_HINT)
6babad5e 562 {
cf5f7ee7
VS
563 const char *map;
564
565 map = grub_util_biosdisk_get_compatibility_hint (dev->disk);
566 if (map)
567 {
cd46aa6c 568 grub_util_fprint_full_disk_name (stdout, map, dev);
cf5f7ee7
VS
569 putchar (delim);
570 }
571
572 /* FIXME */
573 grub_device_close (dev);
574 continue;
6babad5e 575 }
75f396cc 576
cf5f7ee7
VS
577 if (print == PRINT_ABSTRACTION)
578 {
579 probe_abstraction (dev->disk);
580 putchar (delim);
581 grub_device_close (dev);
582 continue;
583 }
62191274 584
cf5f7ee7
VS
585 if (print == PRINT_CRYPTODISK_UUID)
586 {
587 probe_cryptodisk_uuid (dev->disk);
588 putchar (delim);
589 grub_device_close (dev);
590 continue;
591 }
62191274 592
cf5f7ee7
VS
593 if (print == PRINT_PARTMAP)
594 {
595 /* Check if dev->disk itself is contained in a partmap. */
596 probe_partmap (dev->disk);
597 putchar (delim);
598 grub_device_close (dev);
599 continue;
600 }
0806b63c 601
cf5f7ee7
VS
602 if (print == PRINT_MSDOS_PARTTYPE)
603 {
604 if (dev->disk->partition
605 && strcmp(dev->disk->partition->partmap->name, "msdos") == 0)
606 printf ("%02x", dev->disk->partition->msdostype);
0806b63c 607
cf5f7ee7
VS
608 putchar (delim);
609 grub_device_close (dev);
610 continue;
611 }
39cfdaa9
PFS
612
613 if (print == PRINT_GPT_PARTTYPE)
614 {
615 if (dev->disk->partition
616 && strcmp (dev->disk->partition->partmap->name, "gpt") == 0)
617 {
618 struct grub_gpt_partentry gptdata;
619 grub_partition_t p = dev->disk->partition;
620 dev->disk->partition = dev->disk->partition->parent;
621
622 if (grub_disk_read (dev->disk, p->offset, p->index,
623 sizeof (gptdata), &gptdata) == 0)
624 {
625 grub_gpt_part_type_t gpttype;
626 gpttype.data1 = grub_le_to_cpu32 (gptdata.type.data1);
627 gpttype.data2 = grub_le_to_cpu16 (gptdata.type.data2);
628 gpttype.data3 = grub_le_to_cpu16 (gptdata.type.data3);
629 grub_memcpy (gpttype.data4, gptdata.type.data4, 8);
630
631 grub_printf ("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
632 gpttype.data1, gpttype.data2,
633 gpttype.data3, gpttype.data4[0],
634 gpttype.data4[1], gpttype.data4[2],
635 gpttype.data4[3], gpttype.data4[4],
636 gpttype.data4[5], gpttype.data4[6],
637 gpttype.data4[7]);
638 }
639 dev->disk->partition = p;
640 }
641 putchar (delim);
642 grub_device_close (dev);
643 continue;
644 }
0806b63c 645 }
62191274 646
e0994b8b 647 end:
cf5f7ee7
VS
648 for (curdrive = drives_names; *curdrive; curdrive++)
649 free (*curdrive);
650 free (drives_names);
8b5f3938 651}
652
8e1e4e39
VS
653static struct argp_option options[] = {
654 {"device", 'd', 0, 0,
655 N_("given argument is a system device, not a path"), 0},
656 {"device-map", 'm', N_("FILE"), 0,
657 N_("use FILE as the device map [default=%s]"), 0},
658 {"target", 't', "(fs|fs_uuid|fs_label|drive|device|partmap|abstraction|cryptodisk_uuid|msdos_parttype)", 0,
9c4b5c13 659 N_("print filesystem module, GRUB drive, system device, partition map module, abstraction module or cryptographic container UUID [default=fs]"), 0},
b525fd83 660 {"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
8e1e4e39
VS
661 { 0, 0, 0, 0, 0, 0 }
662};
8b5f3938 663
8e1e4e39
VS
664static char *
665help_filter (int key, const char *text, void *input __attribute__ ((unused)))
8b5f3938 666{
8e1e4e39
VS
667 switch (key)
668 {
669 case 'm':
670 return xasprintf (text, DEFAULT_DEVICE_MAP);
671
672 default:
673 return (char *) text;
674 }
8b5f3938 675}
676
8e1e4e39 677struct arguments
8b5f3938 678{
8e1e4e39
VS
679 char **devices;
680 size_t device_max;
681 size_t ndevices;
682 char *dev_map;
683 int zero_delim;
684};
b39f9d20 685
8e1e4e39
VS
686static error_t
687argp_parser (int key, char *arg, struct argp_state *state)
688{
689 /* Get the input argument from argp_parse, which we
690 know is a pointer to our arguments structure. */
691 struct arguments *arguments = state->input;
2f1a3acf 692
8e1e4e39 693 switch (key)
8b5f3938 694 {
8e1e4e39
VS
695 case 'd':
696 argument_is_device = 1;
697 break;
698
699 case 'm':
700 if (arguments->dev_map)
701 free (arguments->dev_map);
702
703 arguments->dev_map = xstrdup (arg);
704 break;
705
706 case 't':
707 if (!strcmp (arg, "fs"))
708 print = PRINT_FS;
709 else if (!strcmp (arg, "fs_uuid"))
710 print = PRINT_FS_UUID;
711 else if (!strcmp (arg, "fs_label"))
712 print = PRINT_FS_LABEL;
713 else if (!strcmp (arg, "drive"))
714 print = PRINT_DRIVE;
715 else if (!strcmp (arg, "device"))
716 print = PRINT_DEVICE;
717 else if (!strcmp (arg, "partmap"))
718 print = PRINT_PARTMAP;
719 else if (!strcmp (arg, "abstraction"))
720 print = PRINT_ABSTRACTION;
721 else if (!strcmp (arg, "cryptodisk_uuid"))
722 print = PRINT_CRYPTODISK_UUID;
723 else if (!strcmp (arg, "msdos_parttype"))
724 print = PRINT_MSDOS_PARTTYPE;
39cfdaa9
PFS
725 else if (!strcmp (arg, "gpt_parttype"))
726 print = PRINT_GPT_PARTTYPE;
8e1e4e39
VS
727 else if (!strcmp (arg, "hints_string"))
728 print = PRINT_HINT_STR;
729 else if (!strcmp (arg, "bios_hints"))
730 print = PRINT_BIOS_HINT;
731 else if (!strcmp (arg, "ieee1275_hints"))
732 print = PRINT_IEEE1275_HINT;
733 else if (!strcmp (arg, "baremetal_hints"))
734 print = PRINT_BAREMETAL_HINT;
735 else if (!strcmp (arg, "efi_hints"))
736 print = PRINT_EFI_HINT;
737 else if (!strcmp (arg, "arc_hints"))
738 print = PRINT_ARC_HINT;
739 else if (!strcmp (arg, "compatibility_hint"))
740 print = PRINT_COMPATIBILITY_HINT;
fe8c2f11
VS
741 else if (strcmp (arg, "zero_check") == 0)
742 print = PRINT_ZERO_CHECK;
8be63f2e
VS
743 else if (!strcmp (arg, "disk"))
744 print = PRINT_DISK;
8b5f3938 745 else
8e1e4e39
VS
746 argp_usage (state);
747 break;
79ca2d78 748
8e1e4e39
VS
749 case '0':
750 arguments->zero_delim = 1;
751 break;
8b5f3938 752
8e1e4e39
VS
753 case 'v':
754 verbosity++;
755 break;
8b5f3938 756
8e1e4e39
VS
757 case ARGP_KEY_NO_ARGS:
758 fprintf (stderr, "%s", _("No path or device is specified.\n"));
759 argp_usage (state);
760 break;
ddd5cee9 761
8e1e4e39
VS
762 case ARGP_KEY_ARG:
763 assert (arguments->ndevices < arguments->device_max);
764 arguments->devices[arguments->ndevices++] = xstrdup(arg);
765 break;
8b5f3938 766
8e1e4e39
VS
767 default:
768 return ARGP_ERR_UNKNOWN;
769 }
770 return 0;
771}
cf5f7ee7 772
8e1e4e39
VS
773static struct argp argp = {
774 options, argp_parser, N_("[OPTION]... [PATH|DEVICE]"),
775 N_("\
776Probe device information for a given path (or device, if the -d option is given)."),
777 NULL, help_filter, NULL
778};
8b5f3938 779
8e1e4e39
VS
780int
781main (int argc, char *argv[])
782{
783 char delim;
784 struct arguments arguments;
8b5f3938 785
ae5540d3 786 grub_util_host_init (&argc, &argv);
8e1e4e39
VS
787
788 memset (&arguments, 0, sizeof (struct arguments));
789 arguments.device_max = argc + 1;
790 arguments.devices = xmalloc ((arguments.device_max + 1)
791 * sizeof (arguments.devices[0]));
792 memset (arguments.devices, 0, (arguments.device_max + 1)
793 * sizeof (arguments.devices[0]));
794
795 /* Parse our arguments */
796 if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0)
797 {
798 fprintf (stderr, "%s", _("Error in parsing command line arguments\n"));
799 exit(1);
8b5f3938 800 }
801
91a4bf68 802 if (verbosity > 1)
803 grub_env_set ("debug", "all");
804
79ca2d78 805 /* Obtain ARGUMENT. */
8e1e4e39 806 if (arguments.ndevices != 1 && !argument_is_device)
8b5f3938 807 {
8e1e4e39 808 char *program = xstrdup(program_name);
67093bc0
VS
809 fprintf (stderr, _("Unknown extra argument `%s'."), arguments.devices[1]);
810 fprintf (stderr, "\n");
8e1e4e39
VS
811 argp_help (&argp, stderr, ARGP_HELP_STD_USAGE, program);
812 free (program);
813 exit(1);
8b5f3938 814 }
815
8b5f3938 816 /* Initialize the emulated biosdisk driver. */
8e1e4e39 817 grub_util_biosdisk_init (arguments.dev_map ? : DEFAULT_DEVICE_MAP);
b39f9d20 818
daf0f0ba 819 /* Initialize all modules. */
820 grub_init_all ();
dcd73ec0 821 grub_gcry_init_all ();
8b5f3938 822
88b87c93 823 grub_lvm_fini ();
1e8d555b
VS
824 grub_mdraid09_fini ();
825 grub_mdraid1x_fini ();
076e7c0f
VS
826 grub_diskfilter_fini ();
827 grub_diskfilter_init ();
1e8d555b
VS
828 grub_mdraid09_init ();
829 grub_mdraid1x_init ();
88b87c93
VS
830 grub_lvm_init ();
831
0a1e473c 832 if (print == PRINT_BIOS_HINT
cf5f7ee7
VS
833 || print == PRINT_IEEE1275_HINT || print == PRINT_BAREMETAL_HINT
834 || print == PRINT_EFI_HINT || print == PRINT_ARC_HINT)
835 delim = ' ';
836 else
837 delim = '\n';
838
8e1e4e39 839 if (arguments.zero_delim)
cf5f7ee7
VS
840 delim = '\0';
841
8b5f3938 842 /* Do it. */
79ca2d78 843 if (argument_is_device)
8e1e4e39 844 probe (NULL, arguments.devices, delim);
79ca2d78 845 else
8e1e4e39
VS
846 probe (arguments.devices[0], NULL, delim);
847
0a1e473c 848 if (!arguments.zero_delim && (print == PRINT_BIOS_HINT
8e1e4e39
VS
849 || print == PRINT_IEEE1275_HINT
850 || print == PRINT_BAREMETAL_HINT
851 || print == PRINT_EFI_HINT
852 || print == PRINT_ARC_HINT))
cf5f7ee7 853 putchar ('\n');
b39f9d20 854
8b5f3938 855 /* Free resources. */
dcd73ec0 856 grub_gcry_fini_all ();
daf0f0ba 857 grub_fini_all ();
8b5f3938 858 grub_util_biosdisk_fini ();
b39f9d20 859
8e1e4e39
VS
860 {
861 size_t i;
862 for (i = 0; i < arguments.ndevices; i++)
863 free (arguments.devices[i]);
864 }
865 free (arguments.devices);
866
867 free (arguments.dev_map);
b39f9d20 868
8b5f3938 869 return 0;
870}