All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hollis Blanchard <hollis@penguinppc.org>
To: grub-devel@gnu.org
Subject: Re: grub-mkimage and module loading
Date: Sun, 2 Jan 2005 21:12:09 -0600	[thread overview]
Message-ID: <20050103031209.GA28369@miracle> (raw)

This is the updated version of the mkimage patch for PPC. It has been
tested on PowerPC, but only compile-tested on x86.

The interesting parts are in grub_load_modules(), where we no longer use
grub_end_addr and grub_get_end_addr() as the bounds of our modules.
Instead we call an arch-specific grub_arch_modules_addr(), and at that
location we find a struct grub_module_info, telling us the size of the
in-memory modules.

Note that now, grub_load_modules() is the only code that knows how large
the modules are. There were two other users of that information:
grub_add_unused_region() and i386/pc grub_machine_init(), and both are doing
the same thing: adding the module memory to the heap allocator.
grub_add_unused_region() was easily folded into grub_load_modules().
I believe the grub_machine_init use is unnecessary because the memory is
now given to the heap in grub_load_modules(). I have not confirmed this.

I know the common grub_load_modules() code works, but the corresponding i386
grub-mkimage additions need testing.

-Hollis

2004-01-02  Hollis Blanchard  <hollis@penguinppc.org>
	* TODO: Add note about endianness in grub-mkimage.
	* boot/powerpc/ieee1275/crt0.S (note): Remove unused .note
	section.
	* conf/powerpc-ieee1275.rmk (bin_UTILITIES): Add grub-mkimage.
	(grub_mkimage_SOURCES): New target.
	* include/grub/kernel.h (grub_start_addr): Remove variable.
	(grub_end_addr): Likewise.
	(grub_total_module_size): Likewise.
	(grub_kernel_image_size): Likewise.
	(GRUB_MODULE_MAGIC): New constant.
	(grub_module_info): New structure.
	(grub_arch_modules_addr): New prototype.
	(grub_get_end_addr): Remove prototype.
	* include/grub/i386/pc/kernel.h (grub_end_addr): New prototype.
	* include/grub/powerpc/ieee1275/kernel.h: New file.
	* include/grub/util/misc.h (grub_util_get_fp_size): New
	prototype.
	(grub_util_read_at): Likewise.
	(grub_util_write_image_at): Likewise.
	* kern/main.c (grub_get_end_addr): Remove function.
	(grub_load_modules): Call grub_arch_modules_addr instead of
	using grub_end_addr. Look for a grub_module_info struct in
	memory. Use the grub_module_info fields instead of calling
	grub_get_end_addr as loop conditions. Move
	grub_add_unused_region code here.
	(grub_add_unused_region): Remove function.
	* kern/i386/pc/init.c: Include grub/cache.h.
	(grub_machine_init): Remove call to grub_get_end_addr. Remove
	one call to add_mem_region.
	(grub_arch_modules_addr): New function.
	* kern/powerpc/ieee1275/init.c (grub_end_addr): Remove variable.
	(grub_total_module_size): Likewise.
	Include grub/machine/kernel.h.
	(grub_arch_modules_addr): New function.
	* util/grub-emu.c (grub_end_addr): Remove variable.
	(grub_total_module_size): Likewise.
	(grub_arch_modules_addr): New function.
	* util/misc.c: Include unistd.h.
	(grub_util_get_fp_size): New function.
	(grub_util_read_at): Likewise.
	(grub_util_write_image_at): Likewise.
	(grub_util_read_image): Call grub_util_read_at.
	(grub_util_write_image): Call grub_util_write_image_at.
	* util/i386/pc/grub-mkimage.c (generate_image): Allocate
	additional memory in kernel_img for a struct grub_module_info.
	Fill in that grub_module_info.
	* util/powerpc/ieee1275/grub-mkimage.c: New file.

Index: TODO
===================================================================
RCS file: /cvsroot/grub/grub2/TODO,v
retrieving revision 1.7
diff -u -p -r1.7 TODO
--- TODO	1 Aug 2004 13:19:38 -0000	1.7
+++ TODO	3 Jan 2005 02:56:55 -0000
@@ -39,3 +39,5 @@ Priorities:
 * Add a fancy menu interface which utilizes the graphics mode
   extensively with many eye-candies. This is important to beat
   GRUB legacy. :)
+
+* Audit util/powerpc/ieee1275/grub-mkimage.c for endianness fixes.
Index: boot/powerpc/ieee1275/crt0.S
===================================================================
RCS file: /cvsroot/grub/grub2/boot/powerpc/ieee1275/crt0.S,v
retrieving revision 1.4
diff -u -p -r1.4 crt0.S
--- boot/powerpc/ieee1275/crt0.S	28 Dec 2004 22:43:37 -0000	1.4
+++ boot/powerpc/ieee1275/crt0.S	3 Jan 2005 02:56:55 -0000
@@ -18,21 +18,6 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-	.section ".note"
-	.align	2
-.note_section_header:
-	.long	8
-	.long	24
-	.long	0x1275
-	.string	"PowerPC"
-.note_descriptor:
-	.long   0x0             /* real-mode */
-	.long   0xffffffff      /* real-base */
-	.long   0xffffffff      /* real-size */
-	.long   0xffffffff      /* virt-base */
-	.long   0xffffffff      /* virt-size */
-	.long   0x00030000      /* load-base */
-
 .extern __bss_start
 .extern _end
 
Index: conf/powerpc-ieee1275.rmk
===================================================================
RCS file: /cvsroot/grub/grub2/conf/powerpc-ieee1275.rmk,v
retrieving revision 1.18
diff -u -p -r1.18 powerpc-ieee1275.rmk
--- conf/powerpc-ieee1275.rmk	28 Dec 2004 22:43:37 -0000	1.18
+++ conf/powerpc-ieee1275.rmk	3 Jan 2005 02:56:57 -0000
@@ -24,9 +24,13 @@ kernel_syms.lst: $(addprefix include/gru
 pkgdata_PROGRAMS = grubof
 
 # Utilities.
-bin_UTILITIES = grub-emu
+bin_UTILITIES = grub-emu grub-mkimage
 noinst_UTILITIES = genmoddep
 
+# For grub-mkimage.
+grub_mkimage_SOURCES = util/powerpc/ieee1275/grub-mkimage.c util/misc.c \
+        util/resolve.c 
+
 # For grub-emu
 grub_emu_SOURCES = kern/main.c kern/device.c				\
 	kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c		\
Index: include/grub/kernel.h
===================================================================
RCS file: /cvsroot/grub/grub2/include/grub/kernel.h,v
retrieving revision 1.4
diff -u -p -r1.4 kernel.h
--- include/grub/kernel.h	4 Apr 2004 13:46:00 -0000	1.4
+++ include/grub/kernel.h	3 Jan 2005 02:56:57 -0000
@@ -31,17 +31,18 @@ struct grub_module_header
   grub_size_t size;
 };
 
-/* The start address of the kernel.  */
-extern grub_addr_t grub_start_addr;
+#define GRUB_MODULE_MAGIC 0x676d696d /* "gmim" (GRUB Module Info Magic).  */
 
-/* The end address of the kernel.  */
-extern grub_addr_t grub_end_addr;
+struct grub_module_info {
+  /* Magic number so we know we have modules present.  */
+  grub_uint32_t magic;
+  /* The offset of the modules.  */
+  grub_off_t offset;
+  /* The size of all modules plus this header.  */
+  grub_size_t size;
+};
 
-/* The total size of modules including their headers.  */
-extern grub_size_t grub_total_module_size;
-
-/* The size of the kernel image.  */
-extern grub_size_t grub_kernel_image_size;
+extern grub_addr_t grub_arch_modules_addr (void);
 
 /* The start point of the C code.  */
 void grub_main (void);
@@ -49,9 +50,6 @@ void grub_main (void);
 /* The machine-specific initialization. This must initialize memory.  */
 void grub_machine_init (void);
 
-/* Return the end address of the core image.  */
-grub_addr_t grub_get_end_addr (void);
-
 /* Register all the exported symbols. This is automatically generated.  */
 void grub_register_exported_symbols (void);
 
Index: include/grub/i386/pc/kernel.h
===================================================================
RCS file: /cvsroot/grub/grub2/include/grub/i386/pc/kernel.h,v
retrieving revision 1.5
diff -u -p -r1.5 kernel.h
--- include/grub/i386/pc/kernel.h	4 Apr 2004 13:46:01 -0000	1.5
+++ include/grub/i386/pc/kernel.h	3 Jan 2005 02:56:57 -0000
@@ -58,6 +58,9 @@ extern char grub_prefix[];
 /* The boot BIOS drive number.  */
 extern grub_int32_t grub_boot_drive;
 
+/* The end address of the kernel.  */
+extern grub_addr_t grub_end_addr;
+
 #endif /* ! ASM_FILE */
 
 #endif /* ! KERNEL_MACHINE_HEADER */
Index: include/grub/powerpc/ieee1275/kernel.h
===================================================================
RCS file: include/grub/powerpc/ieee1275/kernel.h
diff -N include/grub/powerpc/ieee1275/kernel.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ include/grub/powerpc/ieee1275/kernel.h	3 Jan 2005 02:56:57 -0000
@@ -0,0 +1,26 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef GRUB_KERNEL_MACHINE_HEADER
+#define GRUB_KERNEL_MACHINE_HEADER	1
+
+/* Where grub-mkimage places the core modules in memory.  */
+#define MODULE_BASE 0x00300000
+
+#endif
Index: include/grub/util/misc.h
===================================================================
RCS file: /cvsroot/grub/grub2/include/grub/util/misc.h,v
retrieving revision 1.5
diff -u -p -r1.5 misc.h
--- include/grub/util/misc.h	4 Apr 2004 13:46:01 -0000	1.5
+++ include/grub/util/misc.h	3 Jan 2005 02:56:57 -0000
@@ -34,9 +34,13 @@ void *xrealloc (void *ptr, size_t size);
 char *xstrdup (const char *str);
 
 char *grub_util_get_path (const char *dir, const char *file);
+size_t grub_util_get_fp_size (FILE *fp);
 size_t grub_util_get_image_size (const char *path);
+void grub_util_read_at (void *img, size_t len, off_t offset, FILE *fp);
 char *grub_util_read_image (const char *path);
 void grub_util_load_image (const char *path, char *buf);
 void grub_util_write_image (const char *img, size_t size, FILE *out);
+void grub_util_write_image_at (const void *img, size_t size, off_t offset,
+			       FILE *out);
 
 #endif /* ! GRUB_UTIL_MISC_HEADER */
Index: kern/main.c
===================================================================
RCS file: /cvsroot/grub/grub2/kern/main.c,v
retrieving revision 1.8
diff -u -p -r1.8 main.c
--- kern/main.c	4 Apr 2004 13:46:01 -0000	1.8
+++ kern/main.c	3 Jan 2005 02:56:57 -0000
@@ -29,35 +29,31 @@
 #include <grub/device.h>
 #include <grub/env.h>
 
-/* Return the end of the core image.  */
-grub_addr_t
-grub_get_end_addr (void)
-{
-  return grub_total_module_size + grub_end_addr;
-}
-
 /* Load all modules in core.  */
 static void
 grub_load_modules (void)
 {
+  struct grub_module_info *modinfo;
   struct grub_module_header *header;
+  grub_addr_t modbase;
+
+  modbase = grub_arch_modules_addr ();
+  modinfo = (struct grub_module_info *) modbase;
+  if ((modinfo == 0) || modinfo->magic != GRUB_MODULE_MAGIC)
+    /* No modules.  */
+    return;
 
-  for (header = (struct grub_module_header *) grub_end_addr;
-       header < (struct grub_module_header *) grub_get_end_addr ();
+  for (header = (struct grub_module_header *) (modbase + modinfo->offset);
+       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)))
 	grub_fatal ("%s", grub_errmsg);
     }
-}
 
-/* Add the region where modules reside into dynamic memory.  */
-static void
-grub_add_unused_region (void)
-{
-  if (grub_total_module_size)
-    grub_mm_init_region ((void *) grub_end_addr, grub_total_module_size);
+  /* Add the region where modules reside into dynamic memory.  */
+  grub_mm_init_region ((void *) modinfo, modinfo->size);
 }
 
 /* Set the root device according to the dl prefix.  */
@@ -111,7 +107,6 @@ grub_main (void)
   /* Load pre-loaded modules and free the space.  */
   grub_register_exported_symbols ();
   grub_load_modules ();
-  grub_add_unused_region ();
 
   /* Load the normal mode module.  */
   grub_load_normal_mode ();
Index: kern/i386/pc/init.c
===================================================================
RCS file: /cvsroot/grub/grub2/kern/i386/pc/init.c,v
retrieving revision 1.9
diff -u -p -r1.9 init.c
--- kern/i386/pc/init.c	27 Dec 2004 13:46:20 -0000	1.9
+++ kern/i386/pc/init.c	3 Jan 2005 02:56:57 -0000
@@ -30,6 +30,7 @@
 #include <grub/misc.h>
 #include <grub/loader.h>
 #include <grub/env.h>
+#include <grub/cache.h>
 
 struct mem_region
 {
@@ -126,7 +127,6 @@ grub_machine_init (void)
   grub_uint32_t cont;
   struct grub_machine_mmap_entry *entry
     = (struct grub_machine_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
-  grub_addr_t end_addr = grub_get_end_addr ();
   int i;
   
   /* Initialize the console as early as possible.  */
@@ -148,8 +148,6 @@ grub_machine_init (void)
     add_mem_region (GRUB_MEMORY_MACHINE_RESERVED_END,
 		    grub_lower_mem - GRUB_MEMORY_MACHINE_RESERVED_END);
   
-  add_mem_region (end_addr, GRUB_MEMORY_MACHINE_RESERVED_START - end_addr);
-
   /* Check if grub_get_mmap_entry works.  */
   cont = grub_get_mmap_entry (entry, 0);
 
@@ -233,3 +231,10 @@ grub_machine_init (void)
   /* Initialize the prefix.  */
   grub_env_set ("prefix", make_install_device ());
 }
+
+/* Return the end of the core image.  */
+grub_addr_t
+grub_arch_modules_addr (void)
+{
+  return grub_end_addr;
+}
Index: kern/powerpc/ieee1275/init.c
===================================================================
RCS file: /cvsroot/grub/grub2/kern/powerpc/ieee1275/init.c,v
retrieving revision 1.11
diff -u -p -r1.11 init.c
--- kern/powerpc/ieee1275/init.c	27 Dec 2004 13:46:20 -0000	1.11
+++ kern/powerpc/ieee1275/init.c	3 Jan 2005 02:56:57 -0000
@@ -31,10 +31,7 @@
 #include <grub/misc.h>
 #include <grub/machine/init.h>
 #include <grub/machine/time.h>
-
-/* XXX: Modules are not yet supported.  */
-grub_addr_t grub_end_addr = -1;
-grub_addr_t grub_total_module_size = 0;
+#include <grub/machine/kernel.h>
 
 void
 abort (void)
@@ -84,3 +81,9 @@ grub_get_rtc (void)
 {
   return 0;
 }
+
+grub_addr_t
+grub_arch_modules_addr (void)
+{
+  return MODULE_BASE;
+}
Index: util/grub-emu.c
===================================================================
RCS file: /cvsroot/grub/grub2/util/grub-emu.c,v
retrieving revision 1.9
diff -u -p -r1.9 grub-emu.c
--- util/grub-emu.c	4 Dec 2004 18:45:45 -0000	1.9
+++ util/grub-emu.c	3 Jan 2005 02:56:58 -0000
@@ -45,9 +45,11 @@
 
 #define DEFAULT_DEVICE_MAP	DEFAULT_DIRECTORY "/device.map"
 
-/* XXX.  */
-grub_addr_t grub_end_addr = -1;
-grub_addr_t grub_total_module_size = 0;
+grub_addr_t
+grub_arch_modules_addr (void)
+{
+  return 0;
+}
 
 int
 grub_arch_dl_check_header (void *ehdr, grub_size_t size)
Index: util/misc.c
===================================================================
RCS file: /cvsroot/grub/grub2/util/misc.c,v
retrieving revision 1.9
diff -u -p -r1.9 misc.c
--- util/misc.c	27 Dec 2004 13:46:20 -0000	1.9
+++ util/misc.c	3 Jan 2005 02:56:58 -0000
@@ -25,6 +25,7 @@
 #include <sys/stat.h>
 #include <sys/times.h>
 #include <malloc.h>
+#include <unistd.h>
 
 #include <grub/util/misc.h>
 #include <grub/mm.h>
@@ -107,6 +108,20 @@ grub_util_get_path (const char *dir, con
 }
 
 size_t
+grub_util_get_fp_size (FILE *fp)
+{
+  struct stat st;
+  
+  if (fflush (fp) == EOF)
+    grub_util_error ("fflush failed");
+
+  if (fstat (fileno (fp), &st) == -1)
+    grub_util_error ("fstat failed");
+  
+  return st.st_size;
+}
+
+size_t
 grub_util_get_image_size (const char *path)
 {
   struct stat st;
@@ -119,6 +134,16 @@ grub_util_get_image_size (const char *pa
   return st.st_size;
 }
 
+void
+grub_util_read_at (void *img, size_t size, off_t offset, FILE *fp)
+{
+  if (fseek (fp, offset, SEEK_SET) == -1)
+    grub_util_error ("fseek failed");
+
+  if (fread (img, 1, size, fp) != size)
+    grub_util_error ("read failed");
+}
+
 char *
 grub_util_read_image (const char *path)
 {
@@ -134,9 +159,8 @@ grub_util_read_image (const char *path)
   fp = fopen (path, "rb");
   if (! fp)
     grub_util_error ("cannot open %s", path);
-  
-  if (fread (img, 1, size, fp) != size)
-    grub_util_error ("cannot read %s", path);
+
+  grub_util_read_at (img, size, 0, fp);
 
   fclose (fp);
   
@@ -164,13 +188,21 @@ grub_util_load_image (const char *path, 
 }
 
 void
-grub_util_write_image (const char *img, size_t size, FILE *out)
+grub_util_write_image_at (const void *img, size_t size, off_t offset, FILE *out)
 {
-  grub_util_info ("writing 0x%x bytes", size);
+  grub_util_info ("writing 0x%x bytes at offset 0x%x", size, offset);
+  if (fseek (out, offset, SEEK_SET) == -1)
+    grub_util_error ("seek failed");
   if (fwrite (img, 1, size, out) != size)
     grub_util_error ("write failed");
 }
 
+void
+grub_util_write_image (const char *img, size_t size, FILE *out)
+{
+  grub_util_write_image_at (img, size, 0, out);
+}
+
 void *
 grub_malloc (unsigned size)
 {
Index: util/i386/pc/grub-mkimage.c
===================================================================
RCS file: /cvsroot/grub/grub2/util/i386/pc/grub-mkimage.c,v
retrieving revision 1.6
diff -u -p -r1.6 grub-mkimage.c
--- util/i386/pc/grub-mkimage.c	4 Apr 2004 13:46:03 -0000	1.6
+++ util/i386/pc/grub-mkimage.c	3 Jan 2005 02:56:58 -0000
@@ -79,13 +79,14 @@ generate_image (const char *dir, FILE *o
   unsigned num;
   size_t offset;
   struct grub_util_path_list *path_list, *p, *next;
+  struct grub_module_info *modinfo;
 
   path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
 
   kernel_path = grub_util_get_path (dir, "kernel.img");
   kernel_size = grub_util_get_image_size (kernel_path);
 
-  total_module_size = 0;
+  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));
@@ -94,7 +95,14 @@ generate_image (const char *dir, FILE *o
 
   kernel_img = xmalloc (kernel_size + total_module_size);
   grub_util_load_image (kernel_path, kernel_img);
-  offset = kernel_size;
+
+  /* Fill in the grub_module_info structure.  */
+  modinfo = (struct grub_module_info *) (kernel_img + kernel_size);
+  modinfo->magic = GRUB_MODULE_MAGIC;
+  modinfo->offset = sizeof (struct grub_module_info);
+  modinfo->size = total_module_size;
+
+  offset = kernel_size + sizeof (struct grub_module_info);
   for (p = path_list; p; p = p->next)
     {
       struct grub_module_header *header;
Index: util/powerpc/ieee1275/grub-mkimage.c
===================================================================
RCS file: util/powerpc/ieee1275/grub-mkimage.c
diff -N util/powerpc/ieee1275/grub-mkimage.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ util/powerpc/ieee1275/grub-mkimage.c	3 Jan 2005 02:56:58 -0000
@@ -0,0 +1,298 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2004  Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <grub/elf.h>
+#include <grub/util/misc.h>
+#include <grub/util/resolve.h>
+#include <grub/kernel.h>
+#include <grub/machine/kernel.h>
+
+#define ALIGN_UP(addr, align) ((long)((char *)addr + align - 1) & ~(align - 1))
+
+static char *kernel_path = "grubof";
+static char *note_path = "note";
+
+
+void
+load_note (Elf32_Phdr *phdr, const char *dir, FILE *out)
+{
+  char *note_img;
+  char *path;
+  int note_size;
+
+  grub_util_info ("adding CHRP NOTE segment");
+
+  path = grub_util_get_path (dir, note_path);
+  note_size = grub_util_get_image_size (path);
+  note_img = xmalloc (note_size);
+  grub_util_load_image (path, note_img);
+  free (path);
+
+  /* Write the note data to the new segment.  */
+  grub_util_write_image_at (note_img, note_size, phdr->p_offset, out);
+
+  /* Fill in the rest of the segment header.  */
+  phdr->p_type = PT_NOTE;
+  phdr->p_flags = PF_R;
+  phdr->p_align = sizeof (long);
+  phdr->p_vaddr = 0;
+  phdr->p_paddr = 0;
+  phdr->p_filesz = note_size;
+  phdr->p_memsz = 0;
+}
+
+void
+load_modules (Elf32_Phdr *phdr, const char *dir, char *mods[], FILE *out)
+{
+  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;
+
+  path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
+
+  offset = sizeof (struct grub_module_info);
+  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);
+
+  module_img = xmalloc (total_module_size);
+  modinfo = (struct grub_module_info *) module_img;
+  modinfo->magic = GRUB_MODULE_MAGIC;
+  modinfo->offset = sizeof (struct grub_module_info);
+  modinfo->size = total_module_size;
+
+  /* Load all the modules, with headers, into module_img.  */
+  for (p = path_list; p; p = p->next)
+    {
+      struct grub_module_header *header;
+      size_t mod_size;
+
+      grub_util_info ("adding module %s", p->name);
+
+      mod_size = grub_util_get_image_size (p->name);
+
+      header = (struct grub_module_header *) (module_img + offset);
+      header->offset = grub_cpu_to_be32 (sizeof (*header));
+      header->size = grub_cpu_to_be32 (mod_size + sizeof (*header));
+
+      grub_util_load_image (p->name, module_img + offset + sizeof (*header));
+
+      offset += sizeof (*header) + mod_size;
+    }
+
+  /* Write the module data to the new segment.  */
+  grub_util_write_image_at (module_img, total_module_size, phdr->p_offset, out);
+
+  /* Fill in the rest of the segment header.  */
+  phdr->p_type = PT_LOAD;
+  phdr->p_flags = PF_R | PF_W | PF_X;
+  phdr->p_align = sizeof (long);
+  phdr->p_vaddr = MODULE_BASE;
+  phdr->p_paddr = MODULE_BASE;
+  phdr->p_filesz = total_module_size;
+  phdr->p_memsz = total_module_size;
+}
+
+void
+add_segments (char *dir, FILE *out, int chrp, char *mods[])
+{
+  Elf32_Ehdr ehdr;
+  Elf32_Phdr *phdrs = NULL;
+  Elf32_Phdr *phdr;
+  FILE *in;
+  off_t phdroff;
+  int i;
+
+  /* Read ELF header.  */
+  in = fopen (kernel_path, "rb");
+  if (! in)
+    grub_util_error ("cannot open %s", kernel_path);
+  grub_util_read_at (&ehdr, sizeof (ehdr), 0, in);
+
+  phdrs = xmalloc (ehdr.e_phentsize * (ehdr.e_phnum + 2));
+
+  /* Copy all existing segments.  */
+  for (i = 0; i < ehdr.e_phnum; i++)
+    {
+      char *segment_img;
+
+      phdr = phdrs + i;
+
+      /* Read segment header.  */
+      grub_util_read_at (phdr, sizeof (Elf32_Phdr), ehdr.e_phoff
+			 + (i * ehdr.e_phentsize), in);
+      grub_util_info ("copying segment %d, type %d", i, phdr->p_type);
+
+      /* Read segment data and write it to new file.  */
+      segment_img = xmalloc (phdr->p_filesz);
+      grub_util_read_at (segment_img, phdr->p_filesz, phdr->p_offset, in);
+      grub_util_write_image_at (segment_img, phdr->p_filesz, phdr->p_offset, out);
+
+      free (segment_img);
+    }
+
+  if (mods[0] != NULL)
+    {
+      /* Construct new segment header for modules.  */
+      phdr = phdrs + ehdr.e_phnum;
+      ehdr.e_phnum++;
+
+      /* Fill in p_offset so the callees know where to write.  */
+      phdr->p_offset = ALIGN_UP (grub_util_get_fp_size (out), sizeof (long));
+
+      load_modules (phdr, dir, mods, out);
+    }
+
+  if (chrp)
+    {
+      /* Construct new segment header for the CHRP note.  */
+      phdr = phdrs + ehdr.e_phnum;
+      ehdr.e_phnum++;
+
+      /* Fill in p_offset so the callees know where to write.  */
+      phdr->p_offset = ALIGN_UP (grub_util_get_fp_size (out), sizeof (long));
+
+      load_note (phdr, dir, out);
+    }
+
+  /* Don't bother preserving the section headers.  */
+  ehdr.e_shoff = 0;
+  ehdr.e_shnum = 0;
+  ehdr.e_shstrndx = 0;
+
+  /* Append entire segment table to the file.  */
+  phdroff = ALIGN_UP (grub_util_get_fp_size (out), sizeof (long));
+  grub_util_write_image_at (phdrs, ehdr.e_phentsize * ehdr.e_phnum, phdroff,
+			    out);
+
+  /* Write ELF header.  */
+  ehdr.e_phoff = phdroff;
+  grub_util_write_image_at (&ehdr, sizeof (ehdr), 0, out);
+
+  free (phdrs);
+}
+
+static struct option options[] =
+  {
+    {"directory", required_argument, 0, 'd'},
+    {"output", required_argument, 0, 'o'},
+    {"help", no_argument, 0, 'h'},
+    {"note", no_argument, 0, 'n'},
+    {"version", no_argument, 0, 'V'},
+    {"verbose", no_argument, 0, 'v'},
+    { 0, 0, 0, 0 },
+  };
+
+static void
+usage (int status)
+{
+  if (status)
+    fprintf (stderr, "Try ``grub-mkimage --help'' for more information.\n");
+  else
+    printf ("\
+Usage: grub-mkimage -o FILE [OPTION]... [MODULES]\n\
+\n\
+Make a bootable image of GRUB.\n\
+\n\
+-d, --directory=DIR     use images and modules under DIR [default=%s]\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\
+-V, --version           print version information and exit\n\
+-v, --verbose           print verbose messages\n\
+\n\
+Report bugs to <%s>.\n\
+", GRUB_DATADIR, PACKAGE_BUGREPORT);
+
+  exit (status);
+}
+
+int
+main (int argc, char *argv[])
+{
+  FILE *fp;
+  char *output = NULL;
+  char *dir = NULL;
+  int chrp = 0;
+
+  progname = "grub-mkimage";
+
+  while (1)
+    {
+      int c = getopt_long (argc, argv, "d:o:hVvn", options, 0);
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	  case 'd':
+	    if (dir)
+	      free (dir);
+	    dir = xstrdup (optarg);
+	    break;
+	  case 'h':
+	    usage (0);
+	    break;
+	  case 'n':
+	    chrp = 1;
+	    break;
+	  case 'o':
+	    if (output)
+	      free (output);
+	    output = xstrdup (optarg);
+	    break;
+	  case 'V':
+	    printf ("grub-mkimage (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+	    return 0;
+	  case 'v':
+	    verbosity++;
+	    break;
+	  default:
+	    usage (1);
+	    break;
+	}
+  }
+
+  if (!output)
+    usage (1);
+
+  fp = fopen (output, "wb");
+  if (! fp)
+    grub_util_error ("cannot open %s", output);
+
+  add_segments (dir ? : GRUB_DATADIR, fp, chrp, argv + optind);
+
+  fclose (fp);
+
+  return 0;
+}



             reply	other threads:[~2005-01-03  3:42 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-01-03  3:12 Hollis Blanchard [this message]
2005-01-03 13:10 ` grub-mkimage and module loading Marco Gerards
2005-01-04 14:09   ` Marco Gerards
2005-01-05 13:36   ` Marco Gerards
  -- strict thread matches above, loose matches on Subject: below --
2005-01-02 19:02 Hollis Blanchard
2005-01-02 21:05 ` Marco Gerards
2005-01-02 22:23   ` Hollis Blanchard
2005-01-02 22:45     ` Marco Gerards

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20050103031209.GA28369@miracle \
    --to=hollis@penguinppc.org \
    --cc=grub-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.