Skip to contentSkip to conversation

make memdisk portable

PATCH In review Robert Millan 1 participant 4 messages Jul 30, 2008 – Aug 2, 2008

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 make memdisk portable

This patch makes memdisk much less dependant on i386-pc specific structures and therefore easier to port.

Signature · 5 lines
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.

* 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).

* kern/main.c (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.

memdisk.c +15 -14
Index: disk/memdisk.c
===================================================================
@@ -26,7 +26,7 @@
 #include <grub/machine/kernel.h>
 
 static char *memdisk_addr;
-static grub_off_t memdisk_size = 0;
+static grub_off_t memdisk_size;
 
 static int
 grub_memdisk_iterate (int (*hook) (const char *name))
@@ -82,21 +82,22 @@
 
 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)
+	{
+	  memdisk_addr = (char *) header + sizeof (struct grub_module_header);
+	  memdisk_size = header->size - sizeof (struct grub_module_header);
+	  grub_dprintf ("memdisk", "Found memdisk image at %p\n", memdisk_addr);
+	  grub_disk_dev_register (&grub_memdisk_dev);
+	  return 1;
+	}
 
-  memdisk_size = grub_arch_memdisk_size ();
-  if (! memdisk_size)
-    return;
+      return 0;
+    }
 
-  memdisk_orig_addr = (char *) grub_arch_memdisk_addr ();
-  grub_dprintf ("memdisk", "Found memdisk image at %p\n", memdisk_orig_addr);
-
-  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_disk_dev_register (&grub_memdisk_dev);
+  grub_module_iterate (hook);
 }
 
 GRUB_MOD_FINI(memdisk)
device.c +2 -1
Index: kern/device.c
===================================================================
@@ -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;
     }
 
i386/pc/startup.S +0 -3
Index: kern/i386/pc/startup.S
===================================================================
@@ -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 */
 
@@ -221,7 +219,6 @@
 	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
i386/pc/init.c +0 -16
Index: kern/i386/pc/init.c
===================================================================
@@ -252,19 +252,3 @@
 {
   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;
-}
-
-/* Return the size of the memdisk image.  */
-grub_off_t
-grub_arch_memdisk_size (void)
-{
-  return grub_memdisk_image_size;
-}
main.c +29 -5
Index: kern/main.c
===================================================================
@@ -28,9 +28,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 +46,38 @@
        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))
+	return 1;
+    }
+
+  return 0;
+}
+
+/* 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;
     }
 
+  grub_module_iterate (hook);
+
+/* FIXME: This would destroy memdisk.  */
+#if 0
   /* Add the region where modules reside into dynamic memory.  */
   grub_mm_init_region ((void *) modinfo, modinfo->size);
+#endif
 }
 
 /* Write hook for the environment variables of root. Remove surrounding
grub/kernel.h +11 -3
Index: include/grub/kernel.h
===================================================================
@@ -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.  */
+  int 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);
 
grub/i386/pc/kernel.h +2 -11
Index: include/grub/i386/pc/kernel.h
===================================================================
@@ -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 */
i386/pc/grub-mkimage.c +13 -7
Index: util/i386/pc/grub-mkimage.c
===================================================================
@@ -150,15 +150,16 @@
     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;
     }
 
-  kernel_img = xmalloc (kernel_size + total_module_size + memdisk_size);
+  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 +181,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 +191,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 +237,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);
 
#1 lore raw
Quoted 3 lines · Robert Millan

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 :-)

Signature · 5 lines
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.

memdisk.c +19 -10
Index: disk/memdisk.c
===================================================================
@@ -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)
device.c +2 -1
Index: kern/device.c
===================================================================
@@ -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;
     }
 
i386/pc/startup.S +5 -4
Index: kern/i386/pc/startup.S
===================================================================
@@ -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
i386/pc/init.c +1 -16
Index: kern/i386/pc/init.c
===================================================================
@@ -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;
-}
main.c +23 -8
Index: kern/main.c
===================================================================
@@ -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
grub/kernel.h +11 -3
Index: include/grub/kernel.h
===================================================================
@@ -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);
 
grub/i386/pc/kernel.h +2 -11
Index: include/grub/i386/pc/kernel.h
===================================================================
@@ -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 */
i386/pc/grub-mkimage.c +17 -10
Index: util/i386/pc/grub-mkimage.c
===================================================================
@@ -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);
 
#2 lore raw

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

Signature · 5 lines
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.

i386-coreboot.rmk +6 -1
Index: conf/i386-coreboot.rmk
===================================================================
@@ -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
powerpc-ieee1275.rmk +6 -1
Index: conf/powerpc-ieee1275.rmk
===================================================================
@@ -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
 
i386-ieee1275.rmk +6 -1
Index: conf/i386-ieee1275.rmk
===================================================================
@@ -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
memdisk.c +19 -10
Index: disk/memdisk.c
===================================================================
@@ -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)
device.c +2 -1
Index: kern/device.c
===================================================================
@@ -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;
     }
 
i386/pc/startup.S +5 -4
Index: kern/i386/pc/startup.S
===================================================================
@@ -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
i386/pc/init.c +1 -16
Index: kern/i386/pc/init.c
===================================================================
@@ -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;
-}
main.c +23 -8
Index: kern/main.c
===================================================================
@@ -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
grub/kernel.h +11 -3
Index: include/grub/kernel.h
===================================================================
@@ -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);
 
grub/i386/pc/kernel.h +2 -11
Index: include/grub/i386/pc/kernel.h
===================================================================
@@ -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 */
i386/pc/grub-mkimage.c +17 -10
Index: util/i386/pc/grub-mkimage.c
===================================================================
@@ -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);
 
elf/grub-mkimage.c +42 -8

126 lines not on this page · raw message

#3 lore raw

Committed.

Signature · 5 lines
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."