2008-07-31 Robert Millan
* disk/memdisk.c (memdisk_size): Don't initialize.
(GRUB_MOD_INIT(memdisk)): Find memdisk using grub_module_iterate().
* include/grub/i386/pc/kernel.h
(GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE): Remove macro.
(GRUB_KERNEL_MACHINE_PREFIX, GRUB_KERNEL_MACHINE_DATA_END): Shift.
(grub_memdisk_image_size, grub_arch_memdisk_addr)
(grub_arch_memdisk_size): Remove.
* include/grub/kernel.h (struct grub_module_header): Remove `offset'
field (was only used to transfer a constant). Add `type' field to
support multiple module types.
(grub_module_iterate): New function.
* kern/device.c (grub_device_open): Do not hide error messages
when grub_disk_open() fails. Use grub_print_error() instead.
* kern/i386/pc/init.c (grub_arch_modules_addr)
(grub_arch_memdisk_size): Remove functions.
(grub_arch_modules_addr): Return the module address in high memory
(now that it isn't copied anymore).
* kern/i386/pc/startup.S (grub_memdisk_image_size): Remove variable.
(codestart): Don't add grub_memdisk_image_size to %ecx in LZMA
decompression routine (grub_total_module_size already includes that
now). Don't copy modules back to low memory.
* kern/main.c: Include `'.
(grub_load_modules): Split out (and use) ...
(grub_module_iterate): ... this function, which iterates through
module objects and runs a hook.
Comment out grub_mm_init_region() call, as it would cause non-ELF
modules to be overwritten.
* util/i386/pc/grub-mkimage.c (generate_image): Instead of appending
the memdisk image in its own region, make it part of the module list.
* util/elf/grub-mkimage.c (options): Add "memdisk"|'m' option.
(main): Parse --memdisk|-m option, and pass user-provided path as
parameter to generate_image().
(add_segments): Pass `memdisk_path' down to load_modules().
(load_modules): Embed memdisk image in module section when requested.
* conf/powerpc-ieee1275.rmk (pkglib_MODULES): Add `memdisk.mod'.
(memdisk_mod_SOURCES, memdisk_mod_CFLAGS)
(memdisk_mod_LDFLAGS): New variables.
* conf/i386-coreboot.rmk: Likewise.
* conf/i386-ieee1275.rmk: Likewise.
Index: conf/i386-coreboot.rmk
===================================================================
--- conf/i386-coreboot.rmk (revision 1754)
+++ conf/i386-coreboot.rmk (working copy)
@@ -94,7 +94,7 @@
# Modules.
pkglib_MODULES = _linux.mod linux.mod normal.mod \
_multiboot.mod multiboot.mod aout.mod \
- play.mod cpuid.mod serial.mod ata.mod
+ play.mod cpuid.mod serial.mod ata.mod memdisk.mod
# For _linux.mod.
_linux_mod_SOURCES = loader/i386/pc/linux.c
@@ -154,4 +154,9 @@
ata_mod_CFLAGS = $(COMMON_CFLAGS)
ata_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For memdisk.mod.
+memdisk_mod_SOURCES = disk/memdisk.c
+memdisk_mod_CFLAGS = $(COMMON_CFLAGS)
+memdisk_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
Index: conf/powerpc-ieee1275.rmk
===================================================================
--- conf/powerpc-ieee1275.rmk (revision 1754)
+++ conf/powerpc-ieee1275.rmk (working copy)
@@ -110,7 +110,8 @@
reboot.mod \
suspend.mod \
_multiboot.mod \
- multiboot.mod
+ multiboot.mod \
+ memdisk.mod
# For _linux.mod.
_linux_mod_SOURCES = loader/powerpc/ieee1275/linux.c
@@ -159,6 +160,10 @@
multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For memdisk.mod.
+memdisk_mod_SOURCES = disk/memdisk.c
+memdisk_mod_CFLAGS = $(COMMON_CFLAGS)
+memdisk_mod_LDFLAGS = $(COMMON_LDFLAGS)
include $(srcdir)/conf/common.mk
Index: conf/i386-ieee1275.rmk
===================================================================
--- conf/i386-ieee1275.rmk (revision 1754)
+++ conf/i386-ieee1275.rmk (working copy)
@@ -102,7 +102,7 @@
# Modules.
pkglib_MODULES = normal.mod halt.mod reboot.mod suspend.mod cpuid.mod \
multiboot.mod _multiboot.mod aout.mod serial.mod linux.mod \
- _linux.mod nand.mod
+ _linux.mod nand.mod memdisk.mod
# For normal.mod.
normal_mod_SOURCES = normal/arg.c normal/cmdline.c normal/command.c \
@@ -171,4 +171,9 @@
nand_mod_CFLAGS = $(COMMON_CFLAGS)
nand_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For memdisk.mod.
+memdisk_mod_SOURCES = disk/memdisk.c
+memdisk_mod_CFLAGS = $(COMMON_CFLAGS)
+memdisk_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/common.mk
Index: disk/memdisk.c
===================================================================
--- disk/memdisk.c (revision 1754)
+++ disk/memdisk.c (working copy)
@@ -82,21 +82,30 @@
GRUB_MOD_INIT(memdisk)
{
- char *memdisk_orig_addr;
+ auto int hook (struct grub_module_header *);
+ int hook (struct grub_module_header *header)
+ {
+ if (header->type == OBJ_TYPE_MEMDISK)
+ {
+ char *memdisk_orig_addr;
+ memdisk_orig_addr = (char *) header + sizeof (struct grub_module_header);
- memdisk_size = grub_arch_memdisk_size ();
- if (! memdisk_size)
- return;
+ grub_dprintf ("memdisk", "Found memdisk image at %p\n", memdisk_orig_addr);
- memdisk_orig_addr = (char *) grub_arch_memdisk_addr ();
- grub_dprintf ("memdisk", "Found memdisk image at %p\n", memdisk_orig_addr);
+ memdisk_size = header->size - sizeof (struct grub_module_header);
+ memdisk_addr = grub_malloc (memdisk_size);
- memdisk_addr = grub_malloc (memdisk_size);
+ grub_dprintf ("memdisk", "Copying memdisk image to dynamic memory\n");
+ grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size);
- grub_dprintf ("memdisk", "Copying memdisk image to dynamic memory\n");
- grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size);
+ grub_disk_dev_register (&grub_memdisk_dev);
+ return 1;
+ }
- grub_disk_dev_register (&grub_memdisk_dev);
+ return 0;
+ }
+
+ grub_module_iterate (hook);
}
GRUB_MOD_FINI(memdisk)
Index: kern/device.c
===================================================================
--- kern/device.c (revision 1754)
+++ kern/device.c (working copy)
@@ -50,7 +50,8 @@
disk = grub_disk_open (name);
if (! disk)
{
- grub_error (GRUB_ERR_BAD_DEVICE, "unknown device %s", name);
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
goto fail;
}
Index: kern/i386/pc/startup.S
===================================================================
--- kern/i386/pc/startup.S (revision 1754)
+++ kern/i386/pc/startup.S (working copy)
@@ -96,8 +96,6 @@
.long 0xFFFFFFFF
VARIABLE(grub_install_bsd_part)
.long 0xFFFFFFFF
-VARIABLE(grub_memdisk_image_size)
- .long 0
VARIABLE(grub_prefix)
/* to be filled by grub-mkimage */
@@ -211,7 +209,6 @@
call lzo1x_decompress
addl $12, %esp
- /* copy back the decompressed part */
movl %eax, %ecx
cld
#elif defined(ENABLE_LZMA)
@@ -221,19 +218,22 @@
pushl %esi
movl EXT_C(grub_kernel_image_size), %ecx
addl EXT_C(grub_total_module_size), %ecx
- addl EXT_C(grub_memdisk_image_size), %ecx
subl $GRUB_KERNEL_MACHINE_RAW_SIZE, %ecx
pushl %ecx
leal (%edi, %ecx), %ebx
call _LzmaDecodeA
+ /* _LzmaDecodeA clears DF, so no need to run cld */
popl %ecx
popl %edi
popl %esi
#endif
+ /* copy back the decompressed part (except the modules) */
+ subl EXT_C(grub_total_module_size), %ecx
rep
movsb
+#if 0
/* copy modules before cleaning out the bss */
movl EXT_C(grub_total_module_size), %ecx
movl EXT_C(grub_kernel_image_size), %esi
@@ -246,6 +246,7 @@
std
rep
movsb
+#endif
/* clean out the bss */
movl $BSS_START_SYMBOL, %edi
Index: kern/i386/pc/init.c
===================================================================
--- kern/i386/pc/init.c (revision 1754)
+++ kern/i386/pc/init.c (working copy)
@@ -250,21 +250,6 @@
grub_addr_t
grub_arch_modules_addr (void)
{
- return grub_end_addr;
-}
-
-/* Return the start of the memdisk image. */
-grub_addr_t
-grub_arch_memdisk_addr (void)
-{
return GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR
- + (grub_kernel_image_size - GRUB_KERNEL_MACHINE_RAW_SIZE)
- + grub_total_module_size;
+ + (grub_kernel_image_size - GRUB_KERNEL_MACHINE_RAW_SIZE);
}
-
-/* Return the size of the memdisk image. */
-grub_off_t
-grub_arch_memdisk_size (void)
-{
- return grub_memdisk_image_size;
-}
Index: kern/main.c
===================================================================
--- kern/main.c (revision 1754)
+++ kern/main.c (working copy)
@@ -19,7 +19,6 @@
#include
#include
-#include
#include
#include
#include
@@ -28,9 +27,8 @@
#include
#include
-/* Load all modules in core. */
-static void
-grub_load_modules (void)
+void
+grub_module_iterate (int (*hook) (struct grub_module_header *header))
{
struct grub_module_info *modinfo;
struct grub_module_header *header;
@@ -47,13 +45,30 @@
header < (struct grub_module_header *) (modbase + modinfo->size);
header = (struct grub_module_header *) ((char *) header + header->size))
{
- if (! grub_dl_load_core ((char *) header + header->offset,
- (header->size - header->offset)))
+ if (hook (header))
+ break;
+ }
+}
+
+/* Load all modules in core. */
+static void
+grub_load_modules (void)
+{
+ auto int hook (struct grub_module_header *);
+ int hook (struct grub_module_header *header)
+ {
+ /* Not an ELF module, skip. */
+ if (header->type != OBJ_TYPE_ELF)
+ return 0;
+
+ if (! grub_dl_load_core ((char *) header + sizeof (struct grub_module_header),
+ (header->size - sizeof (struct grub_module_header))))
grub_fatal ("%s", grub_errmsg);
+
+ return 0;
}
- /* Add the region where modules reside into dynamic memory. */
- grub_mm_init_region ((void *) modinfo, modinfo->size);
+ grub_module_iterate (hook);
}
/* Write hook for the environment variables of root. Remove surrounding
Index: include/grub/kernel.h
===================================================================
--- include/grub/kernel.h (revision 1754)
+++ include/grub/kernel.h (working copy)
@@ -25,9 +25,15 @@
/* The module header. */
struct grub_module_header
{
- /* The offset of object code. */
- grub_target_off_t offset;
- /* The size of object code plus this header. */
+ /* The type of object. */
+ grub_int8_t type;
+ enum
+ {
+ OBJ_TYPE_ELF,
+ OBJ_TYPE_MEMDISK,
+ } grub_module_header_types;
+
+ /* The size of object (including this header). */
grub_target_size_t size;
};
@@ -49,6 +55,8 @@
extern grub_addr_t grub_arch_modules_addr (void);
+extern void EXPORT_FUNC(grub_module_iterate) (int (*hook) (struct grub_module_header *));
+
/* The start point of the C code. */
void grub_main (void);
Index: include/grub/i386/pc/kernel.h
===================================================================
--- include/grub/i386/pc/kernel.h (revision 1754)
+++ include/grub/i386/pc/kernel.h (working copy)
@@ -34,14 +34,11 @@
/* The offset of GRUB_INSTALL_BSD_PART. */
#define GRUB_KERNEL_MACHINE_INSTALL_BSD_PART 0x18
-/* The offset of GRUB_MEMDISK_IMAGE_SIZE. */
-#define GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE 0x1c
-
/* The offset of GRUB_PREFIX. */
-#define GRUB_KERNEL_MACHINE_PREFIX 0x20
+#define GRUB_KERNEL_MACHINE_PREFIX 0x1c
/* End of the data section. */
-#define GRUB_KERNEL_MACHINE_DATA_END 0x60
+#define GRUB_KERNEL_MACHINE_DATA_END 0x5c
/* The size of the first region which won't be compressed. */
#if defined(ENABLE_LZO)
@@ -67,9 +64,6 @@
/* The BSD partition number of the installed partition. */
extern grub_int32_t grub_install_bsd_part;
-/* The size of memory disk image, if present. */
-extern grub_int32_t grub_memdisk_image_size;
-
/* The prefix which points to the directory where GRUB modules and its
configuration file are located. */
extern char grub_prefix[];
@@ -83,9 +77,6 @@
/* The end address of the kernel. */
extern grub_addr_t grub_end_addr;
-extern grub_addr_t EXPORT_FUNC(grub_arch_memdisk_addr) (void);
-extern grub_off_t EXPORT_FUNC(grub_arch_memdisk_size) (void);
-
#endif /* ! ASM_FILE */
#endif /* ! KERNEL_MACHINE_HEADER */
Index: util/i386/pc/grub-mkimage.c
===================================================================
--- util/i386/pc/grub-mkimage.c (revision 1754)
+++ util/i386/pc/grub-mkimage.c (working copy)
@@ -146,19 +146,21 @@
kernel_size = grub_util_get_image_size (kernel_path);
total_module_size = sizeof (struct grub_module_info);
- for (p = path_list; p; p = p->next)
- total_module_size += (grub_util_get_image_size (p->name)
- + sizeof (struct grub_module_header));
- grub_util_info ("the total module size is 0x%x", total_module_size);
-
if (memdisk_path)
{
memdisk_size = ALIGN_UP(grub_util_get_image_size (memdisk_path), 512);
grub_util_info ("the size of memory disk is 0x%x", memdisk_size);
+ total_module_size += memdisk_size + sizeof (struct grub_module_header);
}
- kernel_img = xmalloc (kernel_size + total_module_size + memdisk_size);
+ for (p = path_list; p; p = p->next)
+ total_module_size += (grub_util_get_image_size (p->name)
+ + sizeof (struct grub_module_header));
+
+ grub_util_info ("the total module size is 0x%x", total_module_size);
+
+ kernel_img = xmalloc (kernel_size + total_module_size);
grub_util_load_image (kernel_path, kernel_img);
if (GRUB_KERNEL_MACHINE_PREFIX + strlen (prefix) + 1 > GRUB_KERNEL_MACHINE_DATA_END)
@@ -180,7 +182,7 @@
mod_size = grub_util_get_image_size (p->name);
header = (struct grub_module_header *) (kernel_img + offset);
- header->offset = grub_cpu_to_le32 (sizeof (*header));
+ header->type = grub_cpu_to_le32 (OBJ_TYPE_ELF);
header->size = grub_cpu_to_le32 (mod_size + sizeof (*header));
offset += sizeof (*header);
@@ -190,11 +192,18 @@
if (memdisk_path)
{
+ struct grub_module_header *header;
+
+ header = (struct grub_module_header *) (kernel_img + offset);
+ header->type = grub_cpu_to_le32 (OBJ_TYPE_MEMDISK);
+ header->size = grub_cpu_to_le32 (memdisk_size + sizeof (*header));
+ offset += sizeof (*header);
+
grub_util_load_image (memdisk_path, kernel_img + offset);
offset += memdisk_size;
}
- compress_kernel (kernel_img, kernel_size + total_module_size + memdisk_size,
+ compress_kernel (kernel_img, kernel_size + total_module_size,
&core_img, &core_size);
grub_util_info ("the core size is 0x%x", core_size);
@@ -229,8 +238,6 @@
= grub_cpu_to_le32 (total_module_size);
*((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE))
= grub_cpu_to_le32 (kernel_size);
- *((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE))
- = grub_cpu_to_le32 (memdisk_size);
*((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE))
= grub_cpu_to_le32 (core_size - GRUB_KERNEL_MACHINE_RAW_SIZE);
Index: util/elf/grub-mkimage.c
===================================================================
--- util/elf/grub-mkimage.c (revision 1754)
+++ util/elf/grub-mkimage.c (working copy)
@@ -97,19 +97,26 @@
void
load_modules (grub_addr_t modbase, Elf32_Phdr *phdr, const char *dir,
- char *mods[], FILE *out)
+ char *mods[], FILE *out, char *memdisk_path)
{
char *module_img;
struct grub_util_path_list *path_list;
struct grub_util_path_list *p;
struct grub_module_info *modinfo;
- size_t offset;
- size_t total_module_size;
+ size_t offset, total_module_size, memdisk_size;
path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
offset = sizeof (struct grub_module_info);
total_module_size = sizeof (struct grub_module_info);
+
+ if (memdisk_path)
+ {
+ memdisk_size = ALIGN_UP(grub_util_get_image_size (memdisk_path), 512);
+ grub_util_info ("the size of memory disk is 0x%x", memdisk_size);
+ total_module_size += memdisk_size + sizeof (struct grub_module_header);
+ }
+
for (p = path_list; p; p = p->next)
{
total_module_size += (grub_util_get_image_size (p->name)
@@ -135,7 +142,7 @@
mod_size = grub_util_get_image_size (p->name);
header = (struct grub_module_header *) (module_img + offset);
- header->offset = grub_host_to_target32 (sizeof (*header));
+ header->type = grub_host_to_target32 (OBJ_TYPE_ELF);
header->size = grub_host_to_target32 (mod_size + sizeof (*header));
grub_util_load_image (p->name, module_img + offset + sizeof (*header));
@@ -143,6 +150,20 @@
offset += sizeof (*header) + mod_size;
}
+ if (memdisk_path)
+ {
+ struct grub_module_header *header;
+
+ header = (struct grub_module_header *) (module_img + offset);
+ header->type = grub_cpu_to_le32 (OBJ_TYPE_MEMDISK);
+ header->size = grub_cpu_to_le32 (memdisk_size + sizeof (*header));
+ offset += sizeof (*header);
+
+ grub_util_load_image (memdisk_path, module_img + offset);
+ offset += memdisk_size;
+ }
+
+
/* Write the module data to the new segment. */
grub_util_write_image_at (module_img, total_module_size,
grub_host_to_target32 (phdr->p_offset), out);
@@ -158,7 +179,7 @@
}
void
-add_segments (char *dir, char *prefix, FILE *out, int chrp, char *mods[])
+add_segments (char *dir, char *prefix, FILE *out, int chrp, char *mods[], char *memdisk_path)
{
Elf32_Ehdr ehdr;
Elf32_Phdr *phdrs = NULL;
@@ -247,7 +268,7 @@
phdr->p_offset = grub_host_to_target32 (ALIGN_UP (grub_util_get_fp_size (out),
GRUB_TARGET_SIZEOF_LONG));
- load_modules (modbase, phdr, dir, mods, out);
+ load_modules (modbase, phdr, dir, mods, out, memdisk_path);
}
if (chrp)
@@ -289,6 +310,7 @@
{
{"directory", required_argument, 0, 'd'},
{"prefix", required_argument, 0, 'p'},
+ {"memdisk", required_argument, 0, 'm'},
{"output", required_argument, 0, 'o'},
{"help", no_argument, 0, 'h'},
{"note", no_argument, 0, 'n'},
@@ -310,6 +332,7 @@
\n\
-d, --directory=DIR use images and modules under DIR [default=%s]\n\
-p, --prefix=DIR set grub_prefix directory\n\
+-m, --memdisk=FILE embed FILE as a memdisk image\n\
-o, --output=FILE output a generated image to FILE\n\
-h, --help display this message and exit\n\
-n, --note add NOTE segment for CHRP Open Firmware\n\
@@ -329,13 +352,14 @@
char *output = NULL;
char *dir = NULL;
char *prefix = NULL;
+ char *memdisk = NULL;
int chrp = 0;
progname = "grub-mkimage";
while (1)
{
- int c = getopt_long (argc, argv, "d:p:o:hVvn", options, 0);
+ int c = getopt_long (argc, argv, "d:p:m:o:hVvn", options, 0);
if (c == -1)
break;
@@ -351,6 +375,16 @@
free (prefix);
prefix = xstrdup (optarg);
break;
+ case 'm':
+ if (memdisk)
+ free (memdisk);
+ memdisk = xstrdup (optarg);
+
+ if (prefix)
+ free (prefix);
+ prefix = xstrdup ("(memdisk)/boot/grub");
+
+ break;
case 'h':
usage (0);
break;
@@ -381,7 +415,7 @@
if (! fp)
grub_util_error ("cannot open %s", output);
- add_segments (dir ? : GRUB_LIBDIR, prefix, fp, chrp, argv + optind);
+ add_segments (dir ? : GRUB_LIBDIR, prefix, fp, chrp, argv + optind, memdisk);
fclose (fp);