]>
Commit | Line | Data |
---|---|---|
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 | 53 | enum { |
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 | 75 | static int print = PRINT_FS; |
79ca2d78 | 76 | static unsigned int argument_is_device = 0; |
ddd5cee9 | 77 | |
bf25f879 VS |
78 | static void |
79 | do_print (const char *x) | |
80 | { | |
81 | grub_printf ("%s ", x); | |
82 | } | |
83 | ||
b92f0c18 | 84 | static void |
85 | probe_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 | 115 | static void |
20a40940 | 116 | probe_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 | 139 | static int |
140 | probe_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 |
158 | static void |
159 | probe_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 | 200 | static void |
cf5f7ee7 | 201 | probe (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 |
653 | static 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 |
664 | static char * |
665 | help_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 | 677 | struct 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 |
686 | static error_t |
687 | argp_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 |
773 | static struct argp argp = { |
774 | options, argp_parser, N_("[OPTION]... [PATH|DEVICE]"), | |
775 | N_("\ | |
776 | Probe device information for a given path (or device, if the -d option is given)."), | |
777 | NULL, help_filter, NULL | |
778 | }; | |
8b5f3938 | 779 | |
8e1e4e39 VS |
780 | int |
781 | main (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 | } |