New patch.  Also enable it for ELF platforms (coreboot, ieee1275).

-- 
Robert Millan

  The DRM opt-in fallacy: "Your data belongs to us. We will decide when (and
  how) you may access your data; but nobody's threatening your freedom: we
  still allow you to remove your data and not access it at all."
2008-07-31  Robert Millan  <[EMAIL PROTECTED]>

	* 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/mm.h>'.
	(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 <grub/kernel.h>
 #include <grub/misc.h>
-#include <grub/mm.h>
 #include <grub/symbol.h>
 #include <grub/dl.h>
 #include <grub/term.h>
@@ -28,9 +27,8 @@
 #include <grub/device.h>
 #include <grub/env.h>
 
-/* 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);
 
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to