]> git.proxmox.com Git - grub2.git/blame - grub-core/commands/nativedisk.c
Import grub2_2.04.orig.tar.xz
[grub2.git] / grub-core / commands / nativedisk.c
CommitLineData
7cd0df84
VS
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
32GRUB_MOD_LICENSE ("GPLv3+");
33
ef9d8cd5
VS
34static 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 };
7cd0df84
VS
44
45static grub_err_t
ef9d8cd5 46get_uuid (const char *name, char **uuid, int getnative)
7cd0df84
VS
47{
48 grub_device_t dev;
49 grub_fs_t fs = 0;
50
ef9d8cd5
VS
51 *uuid = 0;
52
7cd0df84
VS
53 dev = grub_device_open (name);
54 if (!dev)
55 return grub_errno;
ef9d8cd5
VS
56
57 if (!dev->disk)
58 {
59 grub_dprintf ("nativedisk", "Skipping non-disk\n");
bd50aa32 60 grub_device_close (dev);
ef9d8cd5
VS
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:
3434ddec 69 case GRUB_DISK_DEVICE_OBDISK_ID:
ef9d8cd5
VS
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:
d65be02b 74 case GRUB_DISK_DEVICE_UBOOTDISK_ID:
ef9d8cd5
VS
75 break;
76
77 /* Native disks. */
78 case GRUB_DISK_DEVICE_ATA_ID:
79 case GRUB_DISK_DEVICE_SCSI_ID:
9612ebc0 80 case GRUB_DISK_DEVICE_XEN:
ef9d8cd5
VS
81 if (getnative)
82 break;
4bd4a887 83 /* FALLTHROUGH */
ef9d8cd5
VS
84
85 /* Virtual disks. */
5027af38 86 /* GRUB dynamically generated files. */
ef9d8cd5 87 case GRUB_DISK_DEVICE_PROCFS_ID:
5027af38 88 /* To access through host OS routines (grub-emu only). */
ef9d8cd5 89 case GRUB_DISK_DEVICE_HOST_ID:
5027af38
VS
90 /* To access coreboot roms. */
91 case GRUB_DISK_DEVICE_CBFSDISK_ID:
ef9d8cd5
VS
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);
bd50aa32 96 grub_device_close (dev);
ef9d8cd5
VS
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 }
7cd0df84
VS
105 if (dev)
106 fs = grub_fs_probe (dev);
107 if (!fs)
108 {
109 grub_device_close (dev);
110 return grub_errno;
111 }
ad4bfeec 112 if (!fs->fs_uuid || fs->fs_uuid (dev, uuid) || !*uuid)
7cd0df84
VS
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
126struct search_ctx
127{
128 char *root_uuid;
129 char *prefix_uuid;
130 const char *prefix_path;
131 int prefix_found, root_found;
132};
133
134static int
135iterate_device (const char *name, void *data)
136{
137 struct search_ctx *ctx = data;
138 char *cur_uuid;
139
ef9d8cd5 140 if (get_uuid (name, &cur_uuid, 1))
7cd0df84 141 {
adb7d667
VS
142 if (grub_errno == GRUB_ERR_UNKNOWN_FS)
143 grub_errno = 0;
7cd0df84
VS
144 grub_print_error ();
145 return 0;
146 }
ef9d8cd5
VS
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)
7cd0df84
VS
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 }
ef9d8cd5 158 if (ctx->root_uuid && grub_strcasecmp (cur_uuid, ctx->root_uuid) == 0)
7cd0df84
VS
159 {
160 grub_env_set ("root", name);
161 ctx->root_found = 1;
162 }
163 return ctx->prefix_found && ctx->root_found;
164}
165
166static grub_err_t
167grub_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;
7cd0df84 175 const char **args;
7cd0df84
VS
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
ef9d8cd5 202 if (get_uuid (NULL, &uuid_root, 0))
1bff60e5
AB
203 {
204 grub_free (mods);
205 return grub_errno;
206 }
7cd0df84
VS
207
208 prefdev = grub_file_get_device_name (prefix);
209 if (grub_errno)
210 {
211 grub_print_error ();
212 prefdev = 0;
213 }
214
ef9d8cd5 215 if (get_uuid (prefdev, &uuid_prefix, 0))
7cd0df84
VS
216 {
217 grub_free (uuid_root);
1bff60e5
AB
218 grub_free (prefdev);
219 grub_free (mods);
7cd0df84
VS
220 return grub_errno;
221 }
222
ef9d8cd5
VS
223 grub_dprintf ("nativedisk", "uuid_prefix = %s, uuid_root = %s\n",
224 uuid_prefix, uuid_root);
225
7cd0df84
VS
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
ca0a4f68
VS
246 file = grub_file_open (filename,
247 GRUB_FILE_TYPE_GRUB_MODULE);
7cd0df84
VS
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
ef9d8cd5
VS
278 if (uuid_prefix || uuid_root)
279 {
280 struct search_ctx ctx;
281 grub_fs_autoload_hook_t saved_autoload;
7cd0df84 282
ef9d8cd5
VS
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;
7cd0df84 286
ef9d8cd5
VS
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;
7cd0df84 292
ef9d8cd5
VS
293 /* FIXME: try to guess the correct values. */
294 grub_device_iterate (iterate_device, &ctx);
7cd0df84 295
ef9d8cd5
VS
296 grub_fs_autoload_hook = saved_autoload;
297 }
7cd0df84
VS
298 grub_free (uuid_root);
299 grub_free (uuid_prefix);
1bff60e5
AB
300 grub_free (prefdev);
301 grub_free (mods);
7cd0df84
VS
302
303 return GRUB_ERR_NONE;
304
305 fail:
306 grub_free (uuid_root);
307 grub_free (uuid_prefix);
1bff60e5 308 grub_free (prefdev);
7cd0df84
VS
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 }
1bff60e5
AB
316 grub_free (mods);
317
7cd0df84
VS
318 return grub_errno;
319}
320
321static grub_command_t cmd;
322
323GRUB_MOD_INIT(nativedisk)
324{
d22840ec 325 cmd = grub_register_command ("nativedisk", grub_cmd_nativedisk, N_("[MODULE1 MODULE2 ...]"),
7cd0df84
VS
326 N_("Switch to native disk drivers. If no modules are specified default set (pata,ahci,usbms,ohci,uhci,ehci) is used"));
327}
328
329GRUB_MOD_FINI(nativedisk)
330{
331 grub_unregister_command (cmd);
332}