2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2013 Free Software Foundation, Inc.
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.
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.
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/>.
19 #include <grub/types.h>
20 #include <grub/misc.h>
24 #include <grub/command.h>
25 #include <grub/i18n.h>
26 #include <grub/device.h>
30 #include <grub/file.h>
32 GRUB_MOD_LICENSE ("GPLv3+");
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)
46 get_uuid (const char *name
, char **uuid
, int getnative
)
53 dev
= grub_device_open (name
);
59 grub_dprintf ("nativedisk", "Skipping non-disk\n");
60 grub_device_close (dev
);
64 switch (dev
->disk
->dev
->id
)
67 case GRUB_DISK_DEVICE_BIOSDISK_ID
:
68 case GRUB_DISK_DEVICE_OFDISK_ID
:
69 case GRUB_DISK_DEVICE_EFIDISK_ID
:
70 case GRUB_DISK_DEVICE_NAND_ID
:
71 case GRUB_DISK_DEVICE_ARCDISK_ID
:
72 case GRUB_DISK_DEVICE_HOSTDISK_ID
:
73 case GRUB_DISK_DEVICE_UBOOTDISK_ID
:
77 case GRUB_DISK_DEVICE_ATA_ID
:
78 case GRUB_DISK_DEVICE_SCSI_ID
:
79 case GRUB_DISK_DEVICE_XEN
:
84 /* GRUB dynamically generated files. */
85 case GRUB_DISK_DEVICE_PROCFS_ID
:
86 /* To access through host OS routines (grub-emu only). */
87 case GRUB_DISK_DEVICE_HOST_ID
:
88 /* To access coreboot roms. */
89 case GRUB_DISK_DEVICE_CBFSDISK_ID
:
90 /* GRUB-only memdisk. Can't match any of firmware devices. */
91 case GRUB_DISK_DEVICE_MEMDISK_ID
:
92 grub_dprintf ("nativedisk", "Skipping native disk %s\n",
94 grub_device_close (dev
);
97 /* FIXME: those probably need special handling. */
98 case GRUB_DISK_DEVICE_LOOPBACK_ID
:
99 case GRUB_DISK_DEVICE_DISKFILTER_ID
:
100 case GRUB_DISK_DEVICE_CRYPTODISK_ID
:
104 fs
= grub_fs_probe (dev
);
107 grub_device_close (dev
);
110 if (!fs
->uuid
|| fs
->uuid (dev
, uuid
) || !*uuid
)
112 grub_device_close (dev
);
115 grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET
,
116 N_("%s does not support UUIDs"), fs
->name
);
120 grub_device_close (dev
);
121 return GRUB_ERR_NONE
;
128 const char *prefix_path
;
129 int prefix_found
, root_found
;
133 iterate_device (const char *name
, void *data
)
135 struct search_ctx
*ctx
= data
;
138 if (get_uuid (name
, &cur_uuid
, 1))
140 if (grub_errno
== GRUB_ERR_UNKNOWN_FS
)
146 grub_dprintf ("nativedisk", "checking %s: %s\n", name
,
148 if (ctx
->prefix_uuid
&& grub_strcasecmp (cur_uuid
, ctx
->prefix_uuid
) == 0)
151 prefix
= grub_xasprintf ("(%s)/%s", name
, ctx
->prefix_path
);
152 grub_env_set ("prefix", prefix
);
154 ctx
->prefix_found
= 1;
156 if (ctx
->root_uuid
&& grub_strcasecmp (cur_uuid
, ctx
->root_uuid
) == 0)
158 grub_env_set ("root", name
);
161 return ctx
->prefix_found
&& ctx
->root_found
;
165 grub_cmd_nativedisk (grub_command_t cmd
__attribute__ ((unused
)),
166 int argc
, char **args_in
)
168 char *uuid_root
= 0, *uuid_prefix
, *prefdev
= 0;
169 const char *prefix
= 0;
170 const char *path_prefix
= 0;
178 argc
= ARRAY_SIZE (modnames_def
);
182 args
= (const char **) args_in
;
184 prefix
= grub_env_get ("prefix");
187 return grub_error (GRUB_ERR_FILE_NOT_FOUND
, N_("variable `%s' isn't set"), "prefix");
190 path_prefix
= (prefix
[0] == '(') ? grub_strchr (prefix
, ')') : NULL
;
194 path_prefix
= prefix
;
196 mods
= grub_malloc (argc
* sizeof (mods
[0]));
200 if (get_uuid (NULL
, &uuid_root
, 0))
203 prefdev
= grub_file_get_device_name (prefix
);
210 if (get_uuid (prefdev
, &uuid_prefix
, 0))
212 grub_free (uuid_root
);
216 grub_dprintf ("nativedisk", "uuid_prefix = %s, uuid_root = %s\n",
217 uuid_prefix
, uuid_root
);
219 for (mods_loaded
= 0; mods_loaded
< argc
; mods_loaded
++)
223 grub_file_t file
= NULL
;
227 mod
= grub_dl_get (args
[mods_loaded
]);
230 mods
[mods_loaded
] = 0;
234 filename
= grub_xasprintf ("%s/" GRUB_TARGET_CPU
"-" GRUB_PLATFORM
"/%s.mod",
235 prefix
, args
[mods_loaded
]);
239 file
= grub_file_open (filename
);
240 grub_free (filename
);
244 size
= grub_file_size (file
);
245 core
= grub_malloc (size
);
248 grub_file_close (file
);
252 if (grub_file_read (file
, core
, size
) != (grub_ssize_t
) size
)
254 grub_file_close (file
);
259 grub_file_close (file
);
261 mods
[mods_loaded
] = grub_dl_load_core_noinit (core
, size
);
262 if (! mods
[mods_loaded
])
266 for (i
= 0; i
< argc
; i
++)
268 grub_dl_init (mods
[i
]);
270 if (uuid_prefix
|| uuid_root
)
272 struct search_ctx ctx
;
273 grub_fs_autoload_hook_t saved_autoload
;
275 /* No need to autoload FS since obviously we already have the necessary fs modules. */
276 saved_autoload
= grub_fs_autoload_hook
;
277 grub_fs_autoload_hook
= 0;
279 ctx
.root_uuid
= uuid_root
;
280 ctx
.prefix_uuid
= uuid_prefix
;
281 ctx
.prefix_path
= path_prefix
;
282 ctx
.prefix_found
= !uuid_prefix
;
283 ctx
.root_found
= !uuid_root
;
285 /* FIXME: try to guess the correct values. */
286 grub_device_iterate (iterate_device
, &ctx
);
288 grub_fs_autoload_hook
= saved_autoload
;
290 grub_free (uuid_root
);
291 grub_free (uuid_prefix
);
293 return GRUB_ERR_NONE
;
296 grub_free (uuid_root
);
297 grub_free (uuid_prefix
);
299 for (i
= 0; i
< mods_loaded
; i
++)
303 grub_dl_unload (mods
[i
]);
308 static grub_command_t cmd
;
310 GRUB_MOD_INIT(nativedisk
)
312 cmd
= grub_register_command ("nativedisk", grub_cmd_nativedisk
, N_("[MODULE1 MODULE2 ...]"),
313 N_("Switch to native disk drivers. If no modules are specified default set (pata,ahci,usbms,ohci,uhci,ehci) is used"));
316 GRUB_MOD_FINI(nativedisk
)
318 grub_unregister_command (cmd
);