]> git.proxmox.com Git - grub2.git/blob - grub-core/commands/nativedisk.c
Import grub2_2.04.orig.tar.xz
[grub2.git] / grub-core / commands / nativedisk.c
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2013 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/command.h>
25 #include <grub/i18n.h>
26 #include <grub/device.h>
27 #include <grub/mm.h>
28 #include <grub/fs.h>
29 #include <grub/env.h>
30 #include <grub/file.h>
31
32 GRUB_MOD_LICENSE ("GPLv3+");
33
34 static const char *modnames_def[] = {
35 /* FIXME: autogenerate this. */
36 #if defined (__i386__) || defined (__x86_64__) || defined (GRUB_MACHINE_MIPS_LOONGSON)
37 "pata", "ahci", "usbms", "ohci", "uhci", "ehci"
38 #elif defined (GRUB_MACHINE_MIPS_QEMU_MIPS)
39 "pata"
40 #else
41 #error "Fill this"
42 #endif
43 };
44
45 static grub_err_t
46 get_uuid (const char *name, char **uuid, int getnative)
47 {
48 grub_device_t dev;
49 grub_fs_t fs = 0;
50
51 *uuid = 0;
52
53 dev = grub_device_open (name);
54 if (!dev)
55 return grub_errno;
56
57 if (!dev->disk)
58 {
59 grub_dprintf ("nativedisk", "Skipping non-disk\n");
60 grub_device_close (dev);
61 return 0;
62 }
63
64 switch (dev->disk->dev->id)
65 {
66 /* Firmware disks. */
67 case GRUB_DISK_DEVICE_BIOSDISK_ID:
68 case GRUB_DISK_DEVICE_OFDISK_ID:
69 case GRUB_DISK_DEVICE_OBDISK_ID:
70 case GRUB_DISK_DEVICE_EFIDISK_ID:
71 case GRUB_DISK_DEVICE_NAND_ID:
72 case GRUB_DISK_DEVICE_ARCDISK_ID:
73 case GRUB_DISK_DEVICE_HOSTDISK_ID:
74 case GRUB_DISK_DEVICE_UBOOTDISK_ID:
75 break;
76
77 /* Native disks. */
78 case GRUB_DISK_DEVICE_ATA_ID:
79 case GRUB_DISK_DEVICE_SCSI_ID:
80 case GRUB_DISK_DEVICE_XEN:
81 if (getnative)
82 break;
83 /* FALLTHROUGH */
84
85 /* Virtual disks. */
86 /* GRUB dynamically generated files. */
87 case GRUB_DISK_DEVICE_PROCFS_ID:
88 /* To access through host OS routines (grub-emu only). */
89 case GRUB_DISK_DEVICE_HOST_ID:
90 /* To access coreboot roms. */
91 case GRUB_DISK_DEVICE_CBFSDISK_ID:
92 /* GRUB-only memdisk. Can't match any of firmware devices. */
93 case GRUB_DISK_DEVICE_MEMDISK_ID:
94 grub_dprintf ("nativedisk", "Skipping native disk %s\n",
95 dev->disk->name);
96 grub_device_close (dev);
97 return 0;
98
99 /* FIXME: those probably need special handling. */
100 case GRUB_DISK_DEVICE_LOOPBACK_ID:
101 case GRUB_DISK_DEVICE_DISKFILTER_ID:
102 case GRUB_DISK_DEVICE_CRYPTODISK_ID:
103 break;
104 }
105 if (dev)
106 fs = grub_fs_probe (dev);
107 if (!fs)
108 {
109 grub_device_close (dev);
110 return grub_errno;
111 }
112 if (!fs->fs_uuid || fs->fs_uuid (dev, uuid) || !*uuid)
113 {
114 grub_device_close (dev);
115
116 if (!grub_errno)
117 grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
118 N_("%s does not support UUIDs"), fs->name);
119
120 return grub_errno;
121 }
122 grub_device_close (dev);
123 return GRUB_ERR_NONE;
124 }
125
126 struct search_ctx
127 {
128 char *root_uuid;
129 char *prefix_uuid;
130 const char *prefix_path;
131 int prefix_found, root_found;
132 };
133
134 static int
135 iterate_device (const char *name, void *data)
136 {
137 struct search_ctx *ctx = data;
138 char *cur_uuid;
139
140 if (get_uuid (name, &cur_uuid, 1))
141 {
142 if (grub_errno == GRUB_ERR_UNKNOWN_FS)
143 grub_errno = 0;
144 grub_print_error ();
145 return 0;
146 }
147
148 grub_dprintf ("nativedisk", "checking %s: %s\n", name,
149 cur_uuid);
150 if (ctx->prefix_uuid && grub_strcasecmp (cur_uuid, ctx->prefix_uuid) == 0)
151 {
152 char *prefix;
153 prefix = grub_xasprintf ("(%s)/%s", name, ctx->prefix_path);
154 grub_env_set ("prefix", prefix);
155 grub_free (prefix);
156 ctx->prefix_found = 1;
157 }
158 if (ctx->root_uuid && grub_strcasecmp (cur_uuid, ctx->root_uuid) == 0)
159 {
160 grub_env_set ("root", name);
161 ctx->root_found = 1;
162 }
163 return ctx->prefix_found && ctx->root_found;
164 }
165
166 static grub_err_t
167 grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)),
168 int argc, char **args_in)
169 {
170 char *uuid_root = 0, *uuid_prefix, *prefdev = 0;
171 const char *prefix = 0;
172 const char *path_prefix = 0;
173 int mods_loaded = 0;
174 grub_dl_t *mods;
175 const char **args;
176 int i;
177
178 if (argc == 0)
179 {
180 argc = ARRAY_SIZE (modnames_def);
181 args = modnames_def;
182 }
183 else
184 args = (const char **) args_in;
185
186 prefix = grub_env_get ("prefix");
187
188 if (! prefix)
189 return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix");
190
191 if (prefix)
192 path_prefix = (prefix[0] == '(') ? grub_strchr (prefix, ')') : NULL;
193 if (path_prefix)
194 path_prefix++;
195 else
196 path_prefix = prefix;
197
198 mods = grub_malloc (argc * sizeof (mods[0]));
199 if (!mods)
200 return grub_errno;
201
202 if (get_uuid (NULL, &uuid_root, 0))
203 {
204 grub_free (mods);
205 return grub_errno;
206 }
207
208 prefdev = grub_file_get_device_name (prefix);
209 if (grub_errno)
210 {
211 grub_print_error ();
212 prefdev = 0;
213 }
214
215 if (get_uuid (prefdev, &uuid_prefix, 0))
216 {
217 grub_free (uuid_root);
218 grub_free (prefdev);
219 grub_free (mods);
220 return grub_errno;
221 }
222
223 grub_dprintf ("nativedisk", "uuid_prefix = %s, uuid_root = %s\n",
224 uuid_prefix, uuid_root);
225
226 for (mods_loaded = 0; mods_loaded < argc; mods_loaded++)
227 {
228 char *filename;
229 grub_dl_t mod;
230 grub_file_t file = NULL;
231 grub_ssize_t size;
232 void *core = 0;
233
234 mod = grub_dl_get (args[mods_loaded]);
235 if (mod)
236 {
237 mods[mods_loaded] = 0;
238 continue;
239 }
240
241 filename = grub_xasprintf ("%s/" GRUB_TARGET_CPU "-" GRUB_PLATFORM "/%s.mod",
242 prefix, args[mods_loaded]);
243 if (! filename)
244 goto fail;
245
246 file = grub_file_open (filename,
247 GRUB_FILE_TYPE_GRUB_MODULE);
248 grub_free (filename);
249 if (! file)
250 goto fail;
251
252 size = grub_file_size (file);
253 core = grub_malloc (size);
254 if (! core)
255 {
256 grub_file_close (file);
257 goto fail;
258 }
259
260 if (grub_file_read (file, core, size) != (grub_ssize_t) size)
261 {
262 grub_file_close (file);
263 grub_free (core);
264 goto fail;
265 }
266
267 grub_file_close (file);
268
269 mods[mods_loaded] = grub_dl_load_core_noinit (core, size);
270 if (! mods[mods_loaded])
271 goto fail;
272 }
273
274 for (i = 0; i < argc; i++)
275 if (mods[i])
276 grub_dl_init (mods[i]);
277
278 if (uuid_prefix || uuid_root)
279 {
280 struct search_ctx ctx;
281 grub_fs_autoload_hook_t saved_autoload;
282
283 /* No need to autoload FS since obviously we already have the necessary fs modules. */
284 saved_autoload = grub_fs_autoload_hook;
285 grub_fs_autoload_hook = 0;
286
287 ctx.root_uuid = uuid_root;
288 ctx.prefix_uuid = uuid_prefix;
289 ctx.prefix_path = path_prefix;
290 ctx.prefix_found = !uuid_prefix;
291 ctx.root_found = !uuid_root;
292
293 /* FIXME: try to guess the correct values. */
294 grub_device_iterate (iterate_device, &ctx);
295
296 grub_fs_autoload_hook = saved_autoload;
297 }
298 grub_free (uuid_root);
299 grub_free (uuid_prefix);
300 grub_free (prefdev);
301 grub_free (mods);
302
303 return GRUB_ERR_NONE;
304
305 fail:
306 grub_free (uuid_root);
307 grub_free (uuid_prefix);
308 grub_free (prefdev);
309
310 for (i = 0; i < mods_loaded; i++)
311 if (mods[i])
312 {
313 mods[i]->fini = 0;
314 grub_dl_unload (mods[i]);
315 }
316 grub_free (mods);
317
318 return grub_errno;
319 }
320
321 static grub_command_t cmd;
322
323 GRUB_MOD_INIT(nativedisk)
324 {
325 cmd = grub_register_command ("nativedisk", grub_cmd_nativedisk, N_("[MODULE1 MODULE2 ...]"),
326 N_("Switch to native disk drivers. If no modules are specified default set (pata,ahci,usbms,ohci,uhci,ehci) is used"));
327 }
328
329 GRUB_MOD_FINI(nativedisk)
330 {
331 grub_unregister_command (cmd);
332 }