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_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
:
78 case GRUB_DISK_DEVICE_ATA_ID
:
79 case GRUB_DISK_DEVICE_SCSI_ID
:
80 case GRUB_DISK_DEVICE_XEN
:
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",
96 grub_device_close (dev
);
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
:
106 fs
= grub_fs_probe (dev
);
109 grub_device_close (dev
);
112 if (!fs
->fs_uuid
|| fs
->fs_uuid (dev
, uuid
) || !*uuid
)
114 grub_device_close (dev
);
117 grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET
,
118 N_("%s does not support UUIDs"), fs
->name
);
122 grub_device_close (dev
);
123 return GRUB_ERR_NONE
;
130 const char *prefix_path
;
131 int prefix_found
, root_found
;
135 iterate_device (const char *name
, void *data
)
137 struct search_ctx
*ctx
= data
;
140 if (get_uuid (name
, &cur_uuid
, 1))
142 if (grub_errno
== GRUB_ERR_UNKNOWN_FS
)
148 grub_dprintf ("nativedisk", "checking %s: %s\n", name
,
150 if (ctx
->prefix_uuid
&& grub_strcasecmp (cur_uuid
, ctx
->prefix_uuid
) == 0)
153 prefix
= grub_xasprintf ("(%s)/%s", name
, ctx
->prefix_path
);
154 grub_env_set ("prefix", prefix
);
156 ctx
->prefix_found
= 1;
158 if (ctx
->root_uuid
&& grub_strcasecmp (cur_uuid
, ctx
->root_uuid
) == 0)
160 grub_env_set ("root", name
);
163 return ctx
->prefix_found
&& ctx
->root_found
;
167 grub_cmd_nativedisk (grub_command_t cmd
__attribute__ ((unused
)),
168 int argc
, char **args_in
)
170 char *uuid_root
= 0, *uuid_prefix
, *prefdev
= 0;
171 const char *prefix
= 0;
172 const char *path_prefix
= 0;
180 argc
= ARRAY_SIZE (modnames_def
);
184 args
= (const char **) args_in
;
186 prefix
= grub_env_get ("prefix");
189 return grub_error (GRUB_ERR_FILE_NOT_FOUND
, N_("variable `%s' isn't set"), "prefix");
192 path_prefix
= (prefix
[0] == '(') ? grub_strchr (prefix
, ')') : NULL
;
196 path_prefix
= prefix
;
198 mods
= grub_malloc (argc
* sizeof (mods
[0]));
202 if (get_uuid (NULL
, &uuid_root
, 0))
208 prefdev
= grub_file_get_device_name (prefix
);
215 if (get_uuid (prefdev
, &uuid_prefix
, 0))
217 grub_free (uuid_root
);
223 grub_dprintf ("nativedisk", "uuid_prefix = %s, uuid_root = %s\n",
224 uuid_prefix
, uuid_root
);
226 for (mods_loaded
= 0; mods_loaded
< argc
; mods_loaded
++)
230 grub_file_t file
= NULL
;
234 mod
= grub_dl_get (args
[mods_loaded
]);
237 mods
[mods_loaded
] = 0;
241 filename
= grub_xasprintf ("%s/" GRUB_TARGET_CPU
"-" GRUB_PLATFORM
"/%s.mod",
242 prefix
, args
[mods_loaded
]);
246 file
= grub_file_open (filename
,
247 GRUB_FILE_TYPE_GRUB_MODULE
);
248 grub_free (filename
);
252 size
= grub_file_size (file
);
253 core
= grub_malloc (size
);
256 grub_file_close (file
);
260 if (grub_file_read (file
, core
, size
) != (grub_ssize_t
) size
)
262 grub_file_close (file
);
267 grub_file_close (file
);
269 mods
[mods_loaded
] = grub_dl_load_core_noinit (core
, size
);
270 if (! mods
[mods_loaded
])
274 for (i
= 0; i
< argc
; i
++)
276 grub_dl_init (mods
[i
]);
278 if (uuid_prefix
|| uuid_root
)
280 struct search_ctx ctx
;
281 grub_fs_autoload_hook_t saved_autoload
;
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;
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
;
293 /* FIXME: try to guess the correct values. */
294 grub_device_iterate (iterate_device
, &ctx
);
296 grub_fs_autoload_hook
= saved_autoload
;
298 grub_free (uuid_root
);
299 grub_free (uuid_prefix
);
303 return GRUB_ERR_NONE
;
306 grub_free (uuid_root
);
307 grub_free (uuid_prefix
);
310 for (i
= 0; i
< mods_loaded
; i
++)
314 grub_dl_unload (mods
[i
]);
321 static grub_command_t cmd
;
323 GRUB_MOD_INIT(nativedisk
)
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"));
329 GRUB_MOD_FINI(nativedisk
)
331 grub_unregister_command (cmd
);