New command `nativedisk'.

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2013-04-28 15:31:33 +02:00
parent 02adbb932d
commit 7cd0df84f1
7 changed files with 316 additions and 29 deletions

View file

@ -1,3 +1,7 @@
2013-04-28 Vladimir Serbinenko <phcoder@gmail.com>
New command `nativedisk'.
2013-04-28 Vladimir Serbinenko <phcoder@gmail.com> 2013-04-28 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/io/lzopio.c: Use GRUB_PROPERLY_ALIGNED_ARRAY. * grub-core/io/lzopio.c: Use GRUB_PROPERLY_ALIGNED_ARRAY.

View file

@ -3411,6 +3411,7 @@ you forget a command, you can run the command @command{help}
* lsfonts:: List loaded fonts * lsfonts:: List loaded fonts
* lsmod:: Show loaded modules * lsmod:: Show loaded modules
* md5sum:: Compute or check MD5 hash * md5sum:: Compute or check MD5 hash
* nativedisk:: Switch to native disk drivers
* normal:: Enter normal mode * normal:: Enter normal mode
* normal_exit:: Exit from normal mode * normal_exit:: Exit from normal mode
* parttool:: Modify partition table entries * parttool:: Modify partition table entries
@ -4035,6 +4036,13 @@ Alias for @code{hashsum --hash md5 arg @dots{}}. See command @command{hashsum}
@end deffn @end deffn
@node nativedisk
@subsection nativedisk
@deffn Command nativedisk
Switch from firmware disk drivers to native ones.
@end deffn
@node normal @node normal
@subsection normal @subsection normal

View file

@ -507,6 +507,11 @@ module = {
enable = i386_multiboot; enable = i386_multiboot;
}; };
module = {
name = nativedisk;
common = commands/nativedisk.c;
};
module = { module = {
name = emupci; name = emupci;
common = bus/emu/pci.c; common = bus/emu/pci.c;

View file

@ -0,0 +1,250 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/types.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/command.h>
#include <grub/i18n.h>
#include <grub/device.h>
#include <grub/mm.h>
#include <grub/fs.h>
#include <grub/env.h>
#include <grub/file.h>
GRUB_MOD_LICENSE ("GPLv3+");
static const char *modnames_def[] = { "pata", "ahci", "usbms", "ohci", "uhci", "ehci" };
static grub_err_t
get_uuid (const char *name, char **uuid)
{
grub_device_t dev;
grub_fs_t fs = 0;
dev = grub_device_open (name);
if (!dev)
return grub_errno;
if (dev)
fs = grub_fs_probe (dev);
if (!fs)
{
grub_device_close (dev);
return grub_errno;
}
if (!fs->uuid || fs->uuid (dev, uuid))
{
grub_device_close (dev);
if (!grub_errno)
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
N_("%s does not support UUIDs"), fs->name);
return grub_errno;
}
grub_device_close (dev);
return GRUB_ERR_NONE;
}
struct search_ctx
{
char *root_uuid;
char *prefix_uuid;
const char *prefix_path;
int prefix_found, root_found;
};
static int
iterate_device (const char *name, void *data)
{
struct search_ctx *ctx = data;
char *cur_uuid;
if (get_uuid (name, &cur_uuid))
{
grub_print_error ();
return 0;
}
if (grub_strcasecmp (cur_uuid, ctx->prefix_uuid) == 0)
{
char *prefix;
prefix = grub_xasprintf ("(%s)/%s", name, ctx->prefix_path);
grub_env_set ("prefix", prefix);
grub_free (prefix);
ctx->prefix_found = 1;
}
if (grub_strcasecmp (cur_uuid, ctx->root_uuid) == 0)
{
grub_env_set ("root", name);
ctx->root_found = 1;
}
return ctx->prefix_found && ctx->root_found;
}
static grub_err_t
grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)),
int argc, char **args_in)
{
char *uuid_root = 0, *uuid_prefix, *prefdev = 0;
const char *prefix = 0;
const char *path_prefix = 0;
int mods_loaded = 0;
grub_dl_t *mods;
struct search_ctx ctx;
const char **args;
grub_fs_autoload_hook_t saved_autoload;
int i;
if (argc == 0)
{
argc = ARRAY_SIZE (modnames_def);
args = modnames_def;
}
else
args = (const char **) args_in;
prefix = grub_env_get ("prefix");
if (! prefix)
return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix");
if (prefix)
path_prefix = (prefix[0] == '(') ? grub_strchr (prefix, ')') : NULL;
if (path_prefix)
path_prefix++;
else
path_prefix = prefix;
mods = grub_malloc (argc * sizeof (mods[0]));
if (!mods)
return grub_errno;
if (get_uuid (NULL, &uuid_root))
return grub_errno;
prefdev = grub_file_get_device_name (prefix);
if (grub_errno)
{
grub_print_error ();
prefdev = 0;
}
if (get_uuid (prefdev, &uuid_prefix))
{
grub_free (uuid_root);
return grub_errno;
}
for (mods_loaded = 0; mods_loaded < argc; mods_loaded++)
{
char *filename;
grub_dl_t mod;
grub_file_t file = NULL;
grub_ssize_t size;
void *core = 0;
mod = grub_dl_get (args[mods_loaded]);
if (mod)
{
mods[mods_loaded] = 0;
continue;
}
filename = grub_xasprintf ("%s/" GRUB_TARGET_CPU "-" GRUB_PLATFORM "/%s.mod",
prefix, args[mods_loaded]);
if (! filename)
goto fail;
file = grub_file_open (filename);
grub_free (filename);
if (! file)
goto fail;
size = grub_file_size (file);
core = grub_malloc (size);
if (! core)
{
grub_file_close (file);
goto fail;
}
if (grub_file_read (file, core, size) != (grub_ssize_t) size)
{
grub_file_close (file);
grub_free (core);
goto fail;
}
grub_file_close (file);
mods[mods_loaded] = grub_dl_load_core_noinit (core, size);
if (! mods[mods_loaded])
goto fail;
}
for (i = 0; i < argc; i++)
if (mods[i])
grub_dl_init (mods[i]);
/* No need to autoload FS since obviously we already have the necessary fs modules. */
saved_autoload = grub_fs_autoload_hook;
grub_fs_autoload_hook = 0;
ctx.root_uuid = uuid_root;
ctx.prefix_uuid = uuid_prefix;
ctx.prefix_path = path_prefix;
ctx.prefix_found = 0;
ctx.root_found = 0;
/* FIXME: try to guess the correct values. */
grub_device_iterate (iterate_device, &ctx);
grub_fs_autoload_hook = saved_autoload;
grub_free (uuid_root);
grub_free (uuid_prefix);
return GRUB_ERR_NONE;
fail:
grub_free (uuid_root);
grub_free (uuid_prefix);
for (i = 0; i < mods_loaded; i++)
if (mods[i])
{
mods[i]->fini = 0;
grub_dl_unload (mods[i]);
}
return grub_errno;
}
static grub_command_t cmd;
GRUB_MOD_INIT(nativedisk)
{
cmd = grub_register_command ("nativedisk", grub_cmd_nativedisk, "[MODULE1 MODULE2 ...]",
N_("Switch to native disk drivers. If no modules are specified default set (pata,ahci,usbms,ohci,uhci,ehci) is used"));
}
GRUB_MOD_FINI(nativedisk)
{
grub_unregister_command (cmd);
}

View file

@ -51,6 +51,7 @@ grub_dl_t grub_dl_head = 0;
grub_err_t grub_err_t
grub_dl_add (grub_dl_t mod); grub_dl_add (grub_dl_t mod);
/* Keep global so that GDB scripts work. */
grub_err_t grub_err_t
grub_dl_add (grub_dl_t mod) grub_dl_add (grub_dl_t mod)
{ {
@ -58,9 +59,6 @@ grub_dl_add (grub_dl_t mod)
return grub_error (GRUB_ERR_BAD_MODULE, return grub_error (GRUB_ERR_BAD_MODULE,
"`%s' is already loaded", mod->name); "`%s' is already loaded", mod->name);
mod->next = grub_dl_head;
grub_dl_head = mod;
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
@ -77,18 +75,6 @@ grub_dl_remove (grub_dl_t mod)
} }
} }
grub_dl_t
grub_dl_get (const char *name)
{
grub_dl_t l;
for (l = grub_dl_head; l; l = l->next)
if (grub_strcmp (name, l->name) == 0)
return l;
return 0;
}
struct grub_symbol struct grub_symbol
@ -447,13 +433,6 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
static void
grub_dl_call_init (grub_dl_t mod)
{
if (mod->init)
(mod->init) (mod);
}
/* Me, Vladimir Serbinenko, hereby I add this module check as per new /* Me, Vladimir Serbinenko, hereby I add this module check as per new
GNU module policy. Note that this license check is informative only. GNU module policy. Note that this license check is informative only.
Modules have to be licensed under GPLv3 or GPLv3+ (optionally Modules have to be licensed under GPLv3 or GPLv3+ (optionally
@ -595,7 +574,7 @@ grub_dl_flush_cache (grub_dl_t mod)
/* Load a module from core memory. */ /* Load a module from core memory. */
grub_dl_t grub_dl_t
grub_dl_load_core (void *addr, grub_size_t size) grub_dl_load_core_noinit (void *addr, grub_size_t size)
{ {
Elf_Ehdr *e; Elf_Ehdr *e;
grub_dl_t mod; grub_dl_t mod;
@ -651,10 +630,6 @@ grub_dl_load_core (void *addr, grub_size_t size)
grub_dprintf ("modules", "module name: %s\n", mod->name); grub_dprintf ("modules", "module name: %s\n", mod->name);
grub_dprintf ("modules", "init function: %p\n", mod->init); grub_dprintf ("modules", "init function: %p\n", mod->init);
grub_boot_time ("Initing module %s", mod->name);
grub_dl_call_init (mod);
grub_boot_time ("Module %s inited", mod->name);
if (grub_dl_add (mod)) if (grub_dl_add (mod))
{ {
grub_dl_unload (mod); grub_dl_unload (mod);
@ -664,6 +639,23 @@ grub_dl_load_core (void *addr, grub_size_t size)
return mod; return mod;
} }
grub_dl_t
grub_dl_load_core (void *addr, grub_size_t size)
{
grub_dl_t mod;
mod = grub_dl_load_core_noinit (addr, size);
if (!mod)
return NULL;
grub_boot_time ("Initing module %s", mod->name);
grub_dl_init (mod);
grub_boot_time ("Module %s inited", mod->name);
return mod;
}
/* Load a module from the file FILENAME. */ /* Load a module from the file FILENAME. */
grub_dl_t grub_dl_t
grub_dl_load_file (const char *filename) grub_dl_load_file (const char *filename)

View file

@ -506,7 +506,8 @@ static void (*grub_xputs_saved) (const char *str);
static const char *features[] = { static const char *features[] = {
"feature_chainloader_bpb", "feature_ntldr", "feature_platform_search_hint", "feature_chainloader_bpb", "feature_ntldr", "feature_platform_search_hint",
"feature_default_font_path", "feature_all_video_module", "feature_default_font_path", "feature_all_video_module",
"feature_menuentry_id", "feature_menuentry_options", "feature_200_final" "feature_menuentry_id", "feature_menuentry_options", "feature_200_final",
"feature_nativedisk_cmd"
}; };
GRUB_MOD_INIT(normal) GRUB_MOD_INIT(normal)

View file

@ -25,6 +25,7 @@
#include <grub/err.h> #include <grub/err.h>
#include <grub/types.h> #include <grub/types.h>
#include <grub/elf.h> #include <grub/elf.h>
#include <grub/list.h>
#endif #endif
/* /*
@ -181,15 +182,41 @@ typedef struct grub_dl *grub_dl_t;
grub_dl_t grub_dl_load_file (const char *filename); grub_dl_t grub_dl_load_file (const char *filename);
grub_dl_t EXPORT_FUNC(grub_dl_load) (const char *name); grub_dl_t EXPORT_FUNC(grub_dl_load) (const char *name);
grub_dl_t grub_dl_load_core (void *addr, grub_size_t size); grub_dl_t grub_dl_load_core (void *addr, grub_size_t size);
grub_dl_t EXPORT_FUNC(grub_dl_load_core_noinit) (void *addr, grub_size_t size);
int EXPORT_FUNC(grub_dl_unload) (grub_dl_t mod); int EXPORT_FUNC(grub_dl_unload) (grub_dl_t mod);
void grub_dl_unload_unneeded (void); void grub_dl_unload_unneeded (void);
int EXPORT_FUNC(grub_dl_ref) (grub_dl_t mod); int EXPORT_FUNC(grub_dl_ref) (grub_dl_t mod);
int EXPORT_FUNC(grub_dl_unref) (grub_dl_t mod); int EXPORT_FUNC(grub_dl_unref) (grub_dl_t mod);
extern grub_dl_t EXPORT_VAR(grub_dl_head); extern grub_dl_t EXPORT_VAR(grub_dl_head);
#ifndef GRUB_UTIL
#define FOR_DL_MODULES(var) FOR_LIST_ELEMENTS ((var), (grub_dl_head)) #define FOR_DL_MODULES(var) FOR_LIST_ELEMENTS ((var), (grub_dl_head))
grub_dl_t EXPORT_FUNC(grub_dl_get) (const char *name); static inline void
grub_dl_init (grub_dl_t mod)
{
if (mod->init)
(mod->init) (mod);
mod->next = grub_dl_head;
grub_dl_head = mod;
}
static inline grub_dl_t
grub_dl_get (const char *name)
{
grub_dl_t l;
FOR_DL_MODULES(l)
if (grub_strcmp (name, l->name) == 0)
return l;
return 0;
}
#endif
grub_err_t grub_dl_register_symbol (const char *name, void *addr, grub_err_t grub_dl_register_symbol (const char *name, void *addr,
int isfunc, grub_dl_t mod); int isfunc, grub_dl_t mod);