]> git.proxmox.com Git - grub2.git/blob - grub-core/commands/probe.c
probe: Support probing for partition UUID with --part-uuid
[grub2.git] / grub-core / commands / probe.c
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2009 Free Software Foundation, Inc.
4 *
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <grub/types.h>
20 #include <grub/misc.h>
21 #include <grub/mm.h>
22 #include <grub/err.h>
23 #include <grub/dl.h>
24 #include <grub/device.h>
25 #include <grub/disk.h>
26 #include <grub/partition.h>
27 #include <grub/gpt_partition.h>
28 #include <grub/net.h>
29 #include <grub/fs.h>
30 #include <grub/file.h>
31 #include <grub/misc.h>
32 #include <grub/env.h>
33 #include <grub/extcmd.h>
34 #include <grub/i18n.h>
35
36 GRUB_MOD_LICENSE ("GPLv3+");
37
38 static const struct grub_arg_option options[] =
39 {
40 {"set", 's', 0,
41 N_("Set a variable to return value."), N_("VARNAME"), ARG_TYPE_STRING},
42 /* TRANSLATORS: It's a driver that is currently in use to access
43 the diven disk. */
44 {"driver", 'd', 0, N_("Determine driver."), 0, 0},
45 {"partmap", 'p', 0, N_("Determine partition map type."), 0, 0},
46 {"fs", 'f', 0, N_("Determine filesystem type."), 0, 0},
47 {"fs-uuid", 'u', 0, N_("Determine filesystem UUID."), 0, 0},
48 {"label", 'l', 0, N_("Determine filesystem label."), 0, 0},
49 {"part-uuid", 0, 0, N_("Determine partition UUID."), 0, 0},
50 {0, 0, 0, 0, 0, 0}
51 };
52
53 static grub_err_t
54 grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args)
55 {
56 struct grub_arg_list *state = ctxt->state;
57 grub_device_t dev;
58 grub_fs_t fs;
59 char *ptr;
60 grub_err_t err;
61
62 if (argc < 1)
63 return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
64
65 ptr = args[0] + grub_strlen (args[0]) - 1;
66 if (args[0][0] == '(' && *ptr == ')')
67 {
68 *ptr = 0;
69 dev = grub_device_open (args[0] + 1);
70 *ptr = ')';
71 }
72 else
73 dev = grub_device_open (args[0]);
74 if (! dev)
75 return grub_errno;
76
77 if (state[1].set)
78 {
79 const char *val = "none";
80 if (dev->net)
81 val = dev->net->protocol->name;
82 if (dev->disk)
83 val = dev->disk->dev->name;
84 if (state[0].set)
85 grub_env_set (state[0].arg, val);
86 else
87 grub_printf ("%s", val);
88 grub_device_close (dev);
89 return GRUB_ERR_NONE;
90 }
91 if (state[2].set)
92 {
93 const char *val = "none";
94 if (dev->disk && dev->disk->partition)
95 val = dev->disk->partition->partmap->name;
96 if (state[0].set)
97 grub_env_set (state[0].arg, val);
98 else
99 grub_printf ("%s", val);
100 grub_device_close (dev);
101 return GRUB_ERR_NONE;
102 }
103 if (state[6].set)
104 {
105 /* AAAABBBB-CCCC-DDDD-EEEE-FFFFFFFFFFFF + null terminator */
106 char val[37] = "none";
107 if (dev->disk && dev->disk->partition &&
108 grub_strcmp(dev->disk->partition->partmap->name, "gpt") == 0)
109 {
110 struct grub_gpt_partentry entry;
111 struct grub_partition *p = dev->disk->partition;
112 grub_disk_t disk = grub_disk_open(dev->disk->name);
113 if (!disk)
114 return grub_errno;
115 if (grub_disk_read(disk, p->offset, p->index, sizeof(entry), &entry))
116 return grub_errno;
117 grub_disk_close(disk);
118 grub_gpt_part_guid_t *guid = &entry.guid;
119 grub_snprintf (val, sizeof(val),
120 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
121 grub_le_to_cpu32 (guid->data1),
122 grub_le_to_cpu16 (guid->data2),
123 grub_le_to_cpu16 (guid->data3),
124 guid->data4[0], guid->data4[1], guid->data4[2],
125 guid->data4[3], guid->data4[4], guid->data4[5],
126 guid->data4[6], guid->data4[7]);
127 }
128 if (state[0].set)
129 grub_env_set (state[0].arg, val);
130 else
131 grub_printf ("%s", val);
132 grub_device_close (dev);
133 return GRUB_ERR_NONE;
134 }
135 fs = grub_fs_probe (dev);
136 if (! fs)
137 return grub_errno;
138 if (state[3].set)
139 {
140 if (state[0].set)
141 grub_env_set (state[0].arg, fs->name);
142 else
143 grub_printf ("%s", fs->name);
144 grub_device_close (dev);
145 return GRUB_ERR_NONE;
146 }
147 if (state[4].set)
148 {
149 char *uuid;
150 if (! fs->fs_uuid)
151 return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
152 N_("%s does not support UUIDs"), fs->name);
153 err = fs->fs_uuid (dev, &uuid);
154 if (err)
155 return err;
156 if (! uuid)
157 return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
158 N_("%s does not support UUIDs"), fs->name);
159
160 if (state[0].set)
161 grub_env_set (state[0].arg, uuid);
162 else
163 grub_printf ("%s", uuid);
164 grub_free (uuid);
165 grub_device_close (dev);
166 return GRUB_ERR_NONE;
167 }
168 if (state[5].set)
169 {
170 char *label;
171 if (! fs->fs_label)
172 return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
173 N_("filesystem `%s' does not support labels"),
174 fs->name);
175 err = fs->fs_label (dev, &label);
176 if (err)
177 return err;
178 if (! label)
179 return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
180 N_("filesystem `%s' does not support labels"),
181 fs->name);
182
183 if (state[0].set)
184 grub_env_set (state[0].arg, label);
185 else
186 grub_printf ("%s", label);
187 grub_free (label);
188 grub_device_close (dev);
189 return GRUB_ERR_NONE;
190 }
191 grub_device_close (dev);
192 return grub_error (GRUB_ERR_BAD_ARGUMENT, "unrecognised target");
193 }
194
195 static grub_extcmd_t cmd;
196
197 GRUB_MOD_INIT (probe)
198 {
199 cmd = grub_register_extcmd ("probe", grub_cmd_probe, 0, N_("DEVICE"),
200 N_("Retrieve device info."), options);
201 }
202
203 GRUB_MOD_FINI (probe)
204 {
205 grub_unregister_extcmd (cmd);
206 }