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