grub2/grub-2.00-for-ppc-include-all-modules-in-the-core-image.patch
2012-10-18 13:47:39 -04:00

333 lines
10 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 4613775aee8b413ba89bfb7233d49a4288e13390 Mon Sep 17 00:00:00 2001
From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
Date: Mon, 15 Oct 2012 17:21:01 -0300
Subject: [PATCH] for ppc, include all modules in the core image
This patch implements the solution suggested by Gustavo Luiz Duarte
<gustavold@linux.vnet.ibm.com>:
Adding more modules to be built-in to the grub core ELF is easy. It is a
parameter passed by grub2-install to grub2-mkimage. However, there is a downside
on adding many modules to the core ELF: they are fully initialized in the grub's
first stage. It means you could hit a bug on a module you don't need and end up
with a non-bootable system.
Another downside is that you wouldn't get updates for these built-in modules, as
updating the grub2 package only updates the modules residing in /boot and not
the grub core ELF in the PReP partition.
A proper solution would be to add to grub the ability of having built-in
*inactive* modules which would be loaded and initialized only on demand (i.e.
explicitly calling the insmod command).
This patch fix this bugzilla:
https://bugzilla.redhat.com/show_bug.cgi?id=866559
---
grub-core/kern/corecmd.c | 3 ++
grub-core/kern/dl.c | 67 ++++++++++++++++++++++++++++++++++++++++---
include/grub/dl.h | 1 +
include/grub/kernel.h | 1 +
include/grub/util/resolve.h | 5 ++++
util/grub-mkimage.c | 37 +++++++++++++++++++++++-
util/resolve.c | 57 ++++++++++++++++++++++++++++++++++++
7 files changed, 166 insertions(+), 5 deletions(-)
diff --git a/grub-core/kern/corecmd.c b/grub-core/kern/corecmd.c
index 16c03df..8684139 100644
--- a/grub-core/kern/corecmd.c
+++ b/grub-core/kern/corecmd.c
@@ -100,6 +100,9 @@ grub_core_cmd_insmod (struct grub_command *cmd __attribute__ ((unused)),
else
mod = grub_dl_load (argv[0]);
+ if (!mod)
+ grub_dl_load_core_by_name (argv[0]);
+
if (mod)
grub_dl_ref (mod);
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
index 5b0aa65..a498682 100644
--- a/grub-core/kern/dl.c
+++ b/grub-core/kern/dl.c
@@ -32,6 +32,7 @@
#include <grub/env.h>
#include <grub/cache.h>
#include <grub/i18n.h>
+#include <grub/kernel.h>
/* Platforms where modules are in a readonly area of memory. */
#if defined(GRUB_MACHINE_QEMU)
@@ -47,6 +48,7 @@
#pragma GCC diagnostic ignored "-Wcast-align"
grub_dl_t grub_dl_head = 0;
+char grub_use_stale_modules = 0;
grub_err_t
grub_dl_add (grub_dl_t mod);
@@ -659,6 +661,57 @@ grub_dl_load_core (void *addr, grub_size_t size)
return mod;
}
+/* Load a module from core using a symbolic name. */
+grub_dl_t
+grub_dl_load_core_by_name (const char *name)
+{
+ struct grub_module_header *header;
+ grub_dl_t mod;
+ char *module_addr;
+
+ mod = (grub_dl_t) grub_zalloc (sizeof (*mod));
+ if (! mod)
+ return 0;
+
+ grub_use_stale_modules = 1;
+
+ FOR_MODULES (header)
+ {
+ /* Not an ELF module, skip. */
+ if ((header->type != OBJ_TYPE_ELF) &&
+ (header->type != OBJ_TYPE_ELF_STALE))
+ continue;
+
+ module_addr = (char *) header + sizeof (struct grub_module_header);
+ grub_dl_resolve_name (mod, (Elf_Ehdr *) module_addr);
+
+ if (grub_strcmp(name, mod->name) == 0)
+ {
+ grub_printf ("WARNING: You are using the built-in '%s' module!\n", name);
+
+ mod = grub_dl_load_core ((char *) header + sizeof (struct grub_module_header),
+ (header->size - sizeof (struct grub_module_header)));
+
+ break;
+ }
+ else
+ mod = 0;
+ }
+
+ if (! mod)
+ return 0;
+ else
+ {
+ if (grub_errno == GRUB_ERR_IO)
+ grub_errno = GRUB_ERR_NONE;
+ }
+
+ if (grub_strcmp (mod->name, name) != 0)
+ grub_error (GRUB_ERR_BAD_MODULE, "mismatched names");
+
+ return mod;
+}
+
/* Load a module from the file FILENAME. */
grub_dl_t
grub_dl_load_file (const char *filename)
@@ -718,13 +771,19 @@ grub_dl_load (const char *name)
return 0;
}
+ /* First, try to load module from the grub directory */
filename = grub_xasprintf ("%s/" GRUB_TARGET_CPU "-" GRUB_PLATFORM "/%s.mod",
grub_dl_dir, name);
- if (! filename)
- return 0;
+ if (filename)
+ {
+ mod = grub_dl_load_file (filename);
+ grub_free (filename);
+ }
- mod = grub_dl_load_file (filename);
- grub_free (filename);
+ /* If the module isn't loaded, check if there is a stale module available and
+ * use it*/
+ if (! mod && grub_use_stale_modules)
+ mod = grub_dl_load_core_by_name (name);
if (! mod)
return 0;
diff --git a/include/grub/dl.h b/include/grub/dl.h
index 3119978..30f12f9 100644
--- a/include/grub/dl.h
+++ b/include/grub/dl.h
@@ -181,6 +181,7 @@ 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 grub_dl_load_core_by_name (const char *name);
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);
diff --git a/include/grub/kernel.h b/include/grub/kernel.h
index eef4c3f..4cd2cb0 100644
--- a/include/grub/kernel.h
+++ b/include/grub/kernel.h
@@ -25,6 +25,7 @@
enum
{
OBJ_TYPE_ELF,
+ OBJ_TYPE_ELF_STALE,
OBJ_TYPE_MEMDISK,
OBJ_TYPE_CONFIG,
OBJ_TYPE_PREFIX
diff --git a/include/grub/util/resolve.h b/include/grub/util/resolve.h
index f42df32..1d0252c 100644
--- a/include/grub/util/resolve.h
+++ b/include/grub/util/resolve.h
@@ -32,4 +32,9 @@ grub_util_resolve_dependencies (const char *prefix,
const char *dep_list_file,
char *modules[]);
+struct grub_util_path_list *
+grub_util_create_complementary_module_list (const char *prefix,
+ const char *dep_list_file,
+ struct grub_util_path_list *path_list);
+
#endif /* ! GRUB_UTIL_RESOLVE_HEADER */
diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
index a551bbb..b06f37a 100644
--- a/util/grub-mkimage.c
+++ b/util/grub-mkimage.c
@@ -711,7 +711,7 @@ generate_image (const char *dir, const char *prefix,
size_t prefix_size = 0;
char *kernel_path;
size_t offset;
- struct grub_util_path_list *path_list, *p, *next;
+ struct grub_util_path_list *path_list, *path_list_comp = 0, *p, *next;
grub_size_t bss_size;
grub_uint64_t start_address;
void *rel_section = 0;
@@ -727,6 +727,10 @@ generate_image (const char *dir, const char *prefix,
path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
+ if (image_target->id == IMAGE_PPC)
+ path_list_comp = grub_util_create_complementary_module_list (dir,
+ "moddep.lst", path_list);
+
kernel_path = grub_util_get_path (dir, "kernel.img");
if (image_target->voidp_sizeof == 8)
@@ -761,6 +765,10 @@ generate_image (const char *dir, const char *prefix,
total_module_size += (ALIGN_ADDR (grub_util_get_image_size (p->name))
+ sizeof (struct grub_module_header));
+ for (p = path_list_comp; p; p = p->next)
+ total_module_size += (ALIGN_ADDR (grub_util_get_image_size (p->name))
+ + sizeof (struct grub_module_header));
+
grub_util_info ("the total module size is 0x%llx",
(unsigned long long) total_module_size);
@@ -835,6 +843,25 @@ generate_image (const char *dir, const char *prefix,
offset += mod_size;
}
+ for (p = path_list_comp; p; p = p->next)
+ {
+ struct grub_module_header *header;
+ size_t mod_size, orig_size;
+
+ orig_size = grub_util_get_image_size (p->name);
+ mod_size = ALIGN_ADDR (orig_size);
+
+ header = (struct grub_module_header *) (kernel_img + offset);
+ memset (header, 0, sizeof (struct grub_module_header));
+ header->type = grub_host_to_target32 (OBJ_TYPE_ELF_STALE);
+ header->size = grub_host_to_target32 (mod_size + sizeof (*header));
+ offset += sizeof (*header);
+ memset (kernel_img + offset + orig_size, 0, mod_size - orig_size);
+
+ grub_util_load_image (p->name, kernel_img + offset);
+ offset += mod_size;
+ }
+
if (memdisk_path)
{
struct grub_module_header *header;
@@ -1639,6 +1666,14 @@ generate_image (const char *dir, const char *prefix,
free (path_list);
path_list = next;
}
+
+ while (path_list_comp)
+ {
+ next = path_list_comp->next;
+ free ((void *) path_list_comp->name);
+ free (path_list_comp);
+ path_list_comp = next;
+ }
}
diff --git a/util/resolve.c b/util/resolve.c
index 1af24e6..997db99 100644
--- a/util/resolve.c
+++ b/util/resolve.c
@@ -271,3 +271,60 @@ grub_util_resolve_dependencies (const char *prefix,
return prev;
}
}
+
+struct grub_util_path_list *
+grub_util_create_complementary_module_list (const char *prefix,
+ const char *dep_list_file,
+ struct grub_util_path_list *path_list)
+{
+ char *path;
+ FILE *fp;
+ struct grub_util_path_list *path_list_comp = 0;
+ struct grub_util_path_list *new_path;
+ char skip;
+
+ path = grub_util_get_path (prefix, dep_list_file);
+ fp = fopen (path, "r");
+ if (! fp)
+ grub_util_error (_("cannot open `%s': %s"), path, strerror (errno));
+
+ while (fgets (buf, sizeof (buf), fp))
+ {
+ char *p;
+ struct grub_util_path_list *pl;
+
+ skip = 0;
+
+ /* Get the target name. */
+ p = strchr (buf, ':');
+ if (! p)
+ grub_util_error (_("invalid line format: %s"), buf);
+
+ *p++ = '\0';
+
+ /* kernel is not a module */
+ if (strcmp(buf, "kernel") == 0)
+ continue;
+
+ /* Check if the module is already in the core. */
+ for (pl = path_list; pl; pl = pl->next)
+ {
+ if (strcmp(buf, get_module_name(pl->name)) == 0)
+ {
+ skip = 1;
+ break;
+ }
+ }
+
+ if (skip)
+ continue;
+
+ /* Add the new path. */
+ new_path = (struct grub_util_path_list *) xmalloc (sizeof (*new_path));
+ new_path->name = get_module_path (prefix, buf);
+ new_path->next = path_list_comp;
+ path_list_comp = new_path;
+ }
+
+ return path_list_comp;
+}
--
1.7.10.4