On Wed, Jul 30, 2008 at 08:51:57PM +0200, Robert Millan wrote:
> 
> This patch makes memdisk much less dependant on i386-pc specific structures
> and therefore easier to port.

Here we go again, after some suggestions from Bean on IRC.

It does now stop copiing the module section to low memory.  Instead, we just
make sure memdisk grabs its own copy of the data (as is done with ELF modules),
and use the module section at GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR for the
whole dance.

Ah, and it saves 40 bytes in kernel, and 48 bytes in memdisk :-)

-- 
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-30  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.

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);
 
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to