grub2/0380-New-command-nativedisk.patch
2013-06-07 14:03:56 -04:00

500 lines
13 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 97f30af3b3b4bbfe51efa1f8bb0cd344280a028e Mon Sep 17 00:00:00 2001
From: Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Date: Sun, 28 Apr 2013 15:31:33 +0200
Subject: [PATCH 380/471] New command `nativedisk'.
---
ChangeLog | 4 +
docs/grub.texi | 8 ++
grub-core/Makefile.core.def | 5 +
grub-core/commands/nativedisk.c | 250 ++++++++++++++++++++++++++++++++++++++++
grub-core/kern/dl.c | 46 +++-----
grub-core/normal/main.c | 3 +-
include/grub/dl.h | 29 ++++-
7 files changed, 316 insertions(+), 29 deletions(-)
create mode 100644 grub-core/commands/nativedisk.c
diff --git a/ChangeLog b/ChangeLog
index 835895b..69c7839 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2013-04-28 Vladimir Serbinenko <phcoder@gmail.com>
+ New command `nativedisk'.
+
+2013-04-28 Vladimir Serbinenko <phcoder@gmail.com>
+
* grub-core/io/lzopio.c: Use GRUB_PROPERLY_ALIGNED_ARRAY.
* grub-core/loader/i386/bsd.c: Likewise.
diff --git a/docs/grub.texi b/docs/grub.texi
index 754e191..587c64e 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -3411,6 +3411,7 @@ you forget a command, you can run the command @command{help}
* lsfonts:: List loaded fonts
* lsmod:: Show loaded modules
* md5sum:: Compute or check MD5 hash
+* nativedisk:: Switch to native disk drivers
* normal:: Enter normal mode
* normal_exit:: Exit from normal mode
* parttool:: Modify partition table entries
@@ -4035,6 +4036,13 @@ Alias for @code{hashsum --hash md5 arg @dots{}}. See command @command{hashsum}
@end deffn
+@node nativedisk
+@subsection nativedisk
+
+@deffn Command nativedisk
+Switch from firmware disk drivers to native ones.
+@end deffn
+
@node normal
@subsection normal
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 7f93723..2e73d89 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -508,6 +508,11 @@ module = {
};
module = {
+ name = nativedisk;
+ common = commands/nativedisk.c;
+};
+
+module = {
name = emupci;
common = bus/emu/pci.c;
common = commands/lspci.c;
diff --git a/grub-core/commands/nativedisk.c b/grub-core/commands/nativedisk.c
new file mode 100644
index 0000000..adb4043
--- /dev/null
+++ b/grub-core/commands/nativedisk.c
@@ -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);
+}
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
index 641146d..6c086ad 100644
--- a/grub-core/kern/dl.c
+++ b/grub-core/kern/dl.c
@@ -51,6 +51,7 @@ grub_dl_t grub_dl_head = 0;
grub_err_t
grub_dl_add (grub_dl_t mod);
+/* Keep global so that GDB scripts work. */
grub_err_t
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,
"`%s' is already loaded", mod->name);
- mod->next = grub_dl_head;
- grub_dl_head = mod;
-
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
@@ -447,13 +433,6 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
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
GNU module policy. Note that this license check is informative only.
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. */
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;
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", "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))
{
grub_dl_unload (mod);
@@ -664,6 +639,23 @@ grub_dl_load_core (void *addr, grub_size_t size)
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. */
grub_dl_t
grub_dl_load_file (const char *filename)
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index 2f203dd..759e0a4 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -506,7 +506,8 @@ static void (*grub_xputs_saved) (const char *str);
static const char *features[] = {
"feature_chainloader_bpb", "feature_ntldr", "feature_platform_search_hint",
"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)
diff --git a/include/grub/dl.h b/include/grub/dl.h
index 3119978..f34b5a1 100644
--- a/include/grub/dl.h
+++ b/include/grub/dl.h
@@ -25,6 +25,7 @@
#include <grub/err.h>
#include <grub/types.h>
#include <grub/elf.h>
+#include <grub/list.h>
#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 EXPORT_FUNC(grub_dl_load) (const char *name);
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);
void grub_dl_unload_unneeded (void);
int EXPORT_FUNC(grub_dl_ref) (grub_dl_t mod);
int EXPORT_FUNC(grub_dl_unref) (grub_dl_t mod);
extern grub_dl_t EXPORT_VAR(grub_dl_head);
+#ifndef GRUB_UTIL
+
#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,
int isfunc, grub_dl_t mod);
--
1.8.2.1