All of lore.kernel.org
 help / color / mirror / Atom feed
* [ppc patch] grub-mkimage
@ 2004-12-03  5:36 Hollis Blanchard
  2004-12-03 12:50 ` Marco Gerards
                   ` (2 more replies)
  0 siblings, 3 replies; 16+ messages in thread
From: Hollis Blanchard @ 2004-12-03  5:36 UTC (permalink / raw)
  To: grub-devel

I'm going to be on vacation next week, so I wanted to get this out so
others could continue progress on PPC module loading... this is not
ready for inclusion, but it is functional. Comments are welcome.

Open Firmware loads GRUB as an ELF file (rather than a binary image like
x86 BIOS). So we can't just concatenate modules to the end of the grubof
ELF file; we need to put them in an ELF LOAD segment. That's what this
grub-mkimage does.

Right now there's still a manual step or two involved. You must build
a binary "note" segment (in the proper endianness). I *thought* we could
get the toolchain to build this for us with the right combination of
gcc/ld/objcopy options, but now I'm not so sure. Anyways, for now from a
PPC host:
  gcc -c note.S
  objcopy -O binary note.o note

Use the -n/--note switch to add the CHRP NOTE segment on CHRP platforms
(e.g. briQ and Pegasos). NEVER use this switch on Power Macintosh. I
guess that should be documented better in the help text, but anyways...

The endian-swapping code in grub-mkimage has not been tested, but
may work.

Right now grub-mkimage arbitrarily loads the modules starting at 3MB,
and grubof must look for them there at runtime. It's a bit awkward to
tell the grubof runtime about where the modules are loaded, since we
would need to parse the ELF file and edit it on disk (not as easy as
just hacking a binary file at reserved offsets). That same difficulty
makes it impossible right now to tell grubof runtime about the total
size of the modules loaded. One possible solution there is to end the
module area with a (0, 0) grub_module_header.

It may be possible to place module variables into their own section
containing nothing else, yet still in a LOAD segment.  Then grub-mkimage
could parse the *section* table (right now it only does segments) and
overwrite the contents of this section to inform the runtime of the
module location. I'm not convinced it's worth the effort.

I'm firmly convinced that grub_load_modules(), currently in kern/main.c,
will need to be changed to a more generic interface. For example, each
arch could provide its own grub_module_start() and grub_module_end()
functions. It is no longer a valid assumption that the modules begin
immediately after grub_end_addr in memory. But for now I will leave that
to someone (Marco?) doing the real module loading; grub-mkimage just
needs to get it into memory (which I've verified it does).

-Hollis

P.S. -o is a mandatory switch for this grub-mkimage. ELF rewriting
involves a lot of seeking, which you can't do with stdout...

Index: boot/powerpc/ieee1275/crt0.S
===================================================================
RCS file: /cvsroot/grub/grub2/boot/powerpc/ieee1275/crt0.S,v
retrieving revision 1.3
diff -u -p -r1.3 crt0.S
--- boot/powerpc/ieee1275/crt0.S	12 Oct 2004 03:56:10 -0000	1.3
+++ boot/powerpc/ieee1275/crt0.S	3 Dec 2004 05:26:48 -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.14
diff -u -p -r1.14 powerpc-ieee1275.rmk
--- conf/powerpc-ieee1275.rmk	16 Nov 2004 23:34:44 -0000	1.14
+++ conf/powerpc-ieee1275.rmk	3 Dec 2004 05:26:49 -0000
@@ -17,9 +17,13 @@ kernel_syms.lst: $(addprefix include/gru
 
 # Utilities.
 sbin_UTILITIES = grubof
-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/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 Dec 2004 05:26:49 -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: util/misc.c
===================================================================
RCS file: /cvsroot/grub/grub2/util/misc.c,v
retrieving revision 1.8
diff -u -p -r1.8 misc.c
--- util/misc.c	4 Apr 2004 13:46:03 -0000	1.8
+++ util/misc.c	3 Dec 2004 05:26:49 -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,6 +188,15 @@ grub_util_load_image (const char *path, 
 }
 
 void
+grub_util_write_image_at (const void *img, size_t size, off_t offset, FILE *out)
+{
+  grub_util_info ("writing 0x%x bytes at offset 0x%x", size, offset);
+  if (fseek (out, offset, SEEK_SET) == -1)
+    grub_util_error ("write failed");
+  grub_util_write_image (img, size, out);
+}
+
+void
 grub_util_write_image (const char *img, size_t size, FILE *out)
 {
   grub_util_info ("writing 0x%x bytes", size);
--- /dev/null	2004-09-05 22:56:24.000000000 -0500
+++ util/powerpc/ieee1275/grub-mkimage.c	2004-12-02 23:06:42.309752560 -0600
@@ -0,0 +1,334 @@
+/*
+ *  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 <getopt.h>
+#include <string.h>
+#include <grub/elf.h>
+#include <grub/util/misc.h>
+#include <grub/util/resolve.h>
+#include <grub/kernel.h>
+
+#define ALIGN_UP(addr, align) ((long)((char *)addr + align - 1) & ~(align - 1))
+
+#define MODULE_BASE 0x00300000
+
+static char *kernel_path = "grubof";
+static char *note_path = "note";
+
+void swap_ehdr (const Elf32_Ehdr *ehdr, Elf32_Ehdr *swapped)
+{
+  memcpy (swapped->e_ident, ehdr->e_ident, EI_NIDENT);
+  swapped->e_type = grub_cpu_to_be16 (ehdr->e_type);
+  swapped->e_machine = grub_cpu_to_be16 (ehdr->e_machine);
+  swapped->e_version = grub_cpu_to_be32 (ehdr->e_version);
+  swapped->e_entry = grub_cpu_to_be32 (ehdr->e_entry);
+  swapped->e_phoff = grub_cpu_to_be32 (ehdr->e_phoff);
+  swapped->e_shoff = grub_cpu_to_be32 (ehdr->e_shoff);
+  swapped->e_flags = grub_cpu_to_be32 (ehdr->e_flags);
+  swapped->e_ehsize = grub_cpu_to_be16 (ehdr->e_ehsize);
+  swapped->e_phentsize = grub_cpu_to_be16 (ehdr->e_phentsize);
+  swapped->e_phnum = grub_cpu_to_be16 (ehdr->e_phnum);
+  swapped->e_shentsize = grub_cpu_to_be16 (ehdr->e_shentsize);
+  swapped->e_shnum = grub_cpu_to_be16 (ehdr->e_shnum);
+  swapped->e_shstrndx = grub_cpu_to_be16 (ehdr->e_shstrndx);
+}
+
+void swap_phdrs (Elf32_Phdr *phdr, Elf32_Phdr *swapped, int count)
+{
+  int i;
+
+  for (i = 0; i < count; i++)
+    {
+      swapped->p_type = grub_cpu_to_be32 (phdr->p_type);
+      swapped->p_offset = grub_cpu_to_be32 (phdr->p_offset);
+      swapped->p_vaddr = grub_cpu_to_be32 (phdr->p_vaddr);
+      swapped->p_paddr = grub_cpu_to_be32 (phdr->p_paddr);
+      swapped->p_filesz = grub_cpu_to_be32 (phdr->p_filesz);
+      swapped->p_memsz = grub_cpu_to_be32 (phdr->p_memsz);
+      swapped->p_flags = grub_cpu_to_be32 (phdr->p_flags);
+      swapped->p_align = grub_cpu_to_be32 (phdr->p_align);
+    }
+}
+
+#ifdef GRUB_CPU_WORDS_BIGENDIAN
+#define grub_cpu_to_be_ehdr(x, y)
+#define grub_be_to_cpu_ehdr(x, y)
+#define grub_cpu_to_be_phdrs(x, y, z)
+#define grub_be_to_cpu_phdrs(x, y, z)
+#else /* ! WORDS_BIGENDIAN */
+#define grub_cpu_to_be_ehdr(x, y) swap_ehdr(x, y)
+#define grub_be_to_cpu_ehdr(x, y) swap_ehdr(x, y)
+#define grub_cpu_to_be_phdrs(x, y, z) swap_phdrs(x, y, z)
+#define grub_be_to_cpu_phdrs(x, y, z) swap_phdrs(x, y, z)
+#endif
+
+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, *p;
+  size_t offset = 0;
+  size_t total_module_size;
+
+  path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods);
+
+  total_module_size = 0;
+  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);
+
+  /* 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);
+  grub_be_to_cpu_ehdr (&ehdr, &ehdr);
+
+  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_be_to_cpu_phdrs (phdr, phdr, 1);
+
+      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_cpu_to_be_phdrs (phdrs, phdrs, ehdr.e_phnum);
+  grub_util_write_image_at (phdrs, ehdr.e_phentsize * ehdr.e_phnum,
+			    phdroff, out);
+
+  /* Write ELF header.  */
+  ehdr.e_phoff = phdroff;
+  grub_cpu_to_be_ehdr (&ehdr, &ehdr);
+  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;
+}
--- /dev/null	2004-09-05 22:56:24.000000000 -0500
+++ note.S	2004-11-08 21:30:09.000000000 -0600
@@ -0,0 +1,17 @@
+/* PT_NOTE segment for IEEE1275 CHRP binding.
+   !!! NOT for use on Power Macs!!!
+ */
+
+.note_section_header:
+	.long	8
+	.long	.note_end - .note_section_header
+	.long	0x1275
+	.string	"PowerPC"
+.note_descriptor:
+	.long   0xffffffff      /* real-mode */
+	.long   0x00c00000      /* real-base */
+	.long   0xffffffff      /* real-size */
+	.long   0xffffffff      /* virt-base */
+	.long   0xffffffff      /* virt-size */
+	.long   0x00004000      /* load-base */
+.note_end:



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [ppc patch] grub-mkimage
  2004-12-03  5:36 [ppc patch] grub-mkimage Hollis Blanchard
@ 2004-12-03 12:50 ` Marco Gerards
  2004-12-03 13:49   ` Johan Rydberg
  2004-12-03 15:18   ` Hollis Blanchard
  2004-12-03 17:18 ` Yoshinori K. Okuji
  2005-01-01 22:42 ` [ppc patch] grub-mkimage and module loading Hollis Blanchard
  2 siblings, 2 replies; 16+ messages in thread
From: Marco Gerards @ 2004-12-03 12:50 UTC (permalink / raw)
  To: The development of GRUB 2

Hollis Blanchard <hollis@penguinppc.org> writes:

> I'm going to be on vacation next week, so I wanted to get this out so
> others could continue progress on PPC module loading... this is not
> ready for inclusion, but it is functional. Comments are welcome.

Nice!  Enjoy your vacation.

> Use the -n/--note switch to add the CHRP NOTE segment on CHRP platforms
> (e.g. briQ and Pegasos). NEVER use this switch on Power Macintosh. I
> guess that should be documented better in the help text, but anyways...

Oh, weird.  For me grubof worked on the PegasosII without doing this.

> It may be possible to place module variables into their own section
> containing nothing else, yet still in a LOAD segment.  Then grub-mkimage
> could parse the *section* table (right now it only does segments) and
> overwrite the contents of this section to inform the runtime of the
> module location. I'm not convinced it's worth the effort.

Whatever is the most flexible seems the best to me...

> I'm firmly convinced that grub_load_modules(), currently in kern/main.c,
> will need to be changed to a more generic interface. For example, each
> arch could provide its own grub_module_start() and grub_module_end()
> functions. It is no longer a valid assumption that the modules begin
> immediately after grub_end_addr in memory. But for now I will leave that
> to someone (Marco?) doing the real module loading; grub-mkimage just
> needs to get it into memory (which I've verified it does).

Right, I agree.

AS Hollis said, I'm working on the relocator for PPC at the moment.
It is quite easy, but PPC_REL24 is a bit more complex.  It is used for
relative jumps.  That means the module should be loaded close to
grubof, which IMHO really sucks...

For some reason my REL24 code does not work, when it does I will send
in a patch.  But there are 3 options we should consider:

- Making sure REL24 should not be used.  This can be done using the
  -mlongcall option.  Still, after using this the module will not work
  when it uses libraries, this is a gcc bug that has been fixed last
  week.  The library that we use is libgcc.  If we choose for
  eliminating all calls to libgcc and if we use -mlongcall the
  relocator will work.  The disadvantage of this solution is that the
  modules will get a bit bigger.

- It is possible to fix the relocator just to use PPC_REL24, but in
  that case the module should be loaded near grubof.

- What linux uses is jumping to some code near the module and that
  code does a long jump into grubof.  This is the hardest solution and
  I don't yet have enough knowledge to do this.

I am now trying to get option 2 to work first (by using black magic to
get everything loaded at the right address ;)) and when module loading
works for me I will try to make 3 work.  Does someone else think I
try to do something else, or can someone help a bit somehow?  As you
might have noticed I really suck at this stuff and doing it just
because no one else does. ;)

Thanks,
Marco





^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [ppc patch] grub-mkimage
  2004-12-03 12:50 ` Marco Gerards
@ 2004-12-03 13:49   ` Johan Rydberg
  2004-12-03 14:14     ` Marco Gerards
  2004-12-03 15:18   ` Hollis Blanchard
  1 sibling, 1 reply; 16+ messages in thread
From: Johan Rydberg @ 2004-12-03 13:49 UTC (permalink / raw)
  To: The development of GRUB 2

Marco Gerards <metgerards@student.han.nl> writes:

> For some reason my REL24 code does not work, when it does I will send
> in a patch.  But there are 3 options we should consider:
>
> - Making sure REL24 should not be used.  This can be done using the
>   -mlongcall option.  Still, after using this the module will not work
>   when it uses libraries, this is a gcc bug that has been fixed last
>   week.  The library that we use is libgcc.  If we choose for
>   eliminating all calls to libgcc and if we use -mlongcall the
>   relocator will work.  The disadvantage of this solution is that the
>   modules will get a bit bigger.
>
> - It is possible to fix the relocator just to use PPC_REL24, but in
>   that case the module should be loaded near grubof.
>
> - What linux uses is jumping to some code near the module and that
>   code does a long jump into grubof.  This is the hardest solution and
>   I don't yet have enough knowledge to do this.
>
> I am now trying to get option 2 to work first (by using black magic to
> get everything loaded at the right address ;)) and when module loading
> works for me I will try to make 3 work.  Does someone else think I
> try to do something else, or can someone help a bit somehow?  As you
> might have noticed I really suck at this stuff and doing it just
> because no one else does. ;)

If I'm not mistaken, you're using the regular SVR4 ABI for PPC.  It
might be a good idea to take a look at the EABI (Embedded ABI) [1]

I'm not sure if you have to re-configure GCC to make it EABI-compat,
or if there's a configuration switch for this.  Anyway, as I said,
it might be worth looking into.

Cheers,
Johan.

 [1] ftp://sources.redhat.com/pub/binutils/ppc-docs/ppc-eabi-1995-01.pdf






^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [ppc patch] grub-mkimage
  2004-12-03 13:49   ` Johan Rydberg
@ 2004-12-03 14:14     ` Marco Gerards
  2004-12-03 15:13       ` Johan Rydberg
  0 siblings, 1 reply; 16+ messages in thread
From: Marco Gerards @ 2004-12-03 14:14 UTC (permalink / raw)
  To: Johan Rydberg; +Cc: The development of GRUB 2

Johan Rydberg <jrydberg@night.trouble.net> writes:

>> For some reason my REL24 code does not work, when it does I will send
>> in a patch.  But there are 3 options we should consider:

[...]

> If I'm not mistaken, you're using the regular SVR4 ABI for PPC.  It
> might be a good idea to take a look at the EABI (Embedded ABI) [1]

You are right about that.  Thanks a lot for the suggestion.

> I'm not sure if you have to re-configure GCC to make it EABI-compat,
> or if there's a configuration switch for this.  Anyway, as I said,
> it might be worth looking into.

What I did is using the following options:

-memb -meabi -msdata=eabi

After that the R_PPC_REL24 relocation was still there.  In addition to
that the R_PPC_EMB_SDA21 relocation was added.  So the relative
relocation is still there and things got even more complex... Did I do
something wrong here?

Thanks,
Marco




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [ppc patch] grub-mkimage
  2004-12-03 14:14     ` Marco Gerards
@ 2004-12-03 15:13       ` Johan Rydberg
  2004-12-03 15:20         ` Marco Gerards
  0 siblings, 1 reply; 16+ messages in thread
From: Johan Rydberg @ 2004-12-03 15:13 UTC (permalink / raw)
  To: Marco Gerards; +Cc: The development of GRUB 2

Marco Gerards <metgerards@student.han.nl> writes:

>> I'm not sure if you have to re-configure GCC to make it EABI-compat,
>> or if there's a configuration switch for this.  Anyway, as I said,
>> it might be worth looking into.
>
> What I did is using the following options:
>
> -memb -meabi -msdata=eabi
>
> After that the R_PPC_REL24 relocation was still there.  In addition to
> that the R_PPC_EMB_SDA21 relocation was added.  So the relative
> relocation is still there and things got even more complex... Did I do
> something wrong here?

No idea.  I thought that it would eliminate the REL24 relocations, but
I was clearly wrong.  See if you can get GCC to generate code that uses
a GOT/TOC.

~j





^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [ppc patch] grub-mkimage
  2004-12-03 12:50 ` Marco Gerards
  2004-12-03 13:49   ` Johan Rydberg
@ 2004-12-03 15:18   ` Hollis Blanchard
  2004-12-03 16:10     ` Marco Gerards
  1 sibling, 1 reply; 16+ messages in thread
From: Hollis Blanchard @ 2004-12-03 15:18 UTC (permalink / raw)
  To: The development of GRUB 2

On Dec 3, 2004, at 6:50 AM, Marco Gerards wrote:

> Hollis Blanchard <hollis@penguinppc.org> writes:
>
>> Use the -n/--note switch to add the CHRP NOTE segment on CHRP 
>> platforms
>> (e.g. briQ and Pegasos). NEVER use this switch on Power Macintosh. I
>> guess that should be documented better in the help text, but 
>> anyways...
>
> Oh, weird.  For me grubof worked on the PegasosII without doing this.

Ah, my mistake then, good to know. The NOTE segment is still needed on 
briQ, RS/6000, and pSeries of course.

>> It may be possible to place module variables into their own section
>> containing nothing else, yet still in a LOAD segment.  Then 
>> grub-mkimage
>> could parse the *section* table (right now it only does segments) and
>> overwrite the contents of this section to inform the runtime of the
>> module location. I'm not convinced it's worth the effort.
>
> Whatever is the most flexible seems the best to me...

I was aiming for simplicity really... What's the simplest possible way 
we can inform grubof of the location of its modules? :)

> AS Hollis said, I'm working on the relocator for PPC at the moment.
> It is quite easy, but PPC_REL24 is a bit more complex.  It is used for
> relative jumps.  That means the module should be loaded close to
> grubof, which IMHO really sucks...

24-bit offsets give you a 16 MiB range, is that really a problem?

> I am now trying to get option 2 to work first (by using black magic to
> get everything loaded at the right address ;)) and when module loading
> works for me I will try to make 3 work.

I agree this makes sense. I'm not sure that option 3 will end up being 
necessary, but option 2 is obviously needed.

> Does someone else think I
> try to do something else, or can someone help a bit somehow?  As you
> might have noticed I really suck at this stuff and doing it just
> because no one else does. ;)

I've never seen relocation code before, but if it's still not working 
when I get back I'd be happy to take a look...

-Hollis




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [ppc patch] grub-mkimage
  2004-12-03 15:13       ` Johan Rydberg
@ 2004-12-03 15:20         ` Marco Gerards
  2004-12-03 16:04           ` Johan Rydberg
  0 siblings, 1 reply; 16+ messages in thread
From: Marco Gerards @ 2004-12-03 15:20 UTC (permalink / raw)
  To: Johan Rydberg; +Cc: The development of GRUB 2

Johan Rydberg <jrydberg@night.trouble.net> writes:

> Marco Gerards <metgerards@student.han.nl> writes:
>
>>> I'm not sure if you have to re-configure GCC to make it EABI-compat,
>>> or if there's a configuration switch for this.  Anyway, as I said,
>>> it might be worth looking into.
>>
>> What I did is using the following options:
>>
>> -memb -meabi -msdata=eabi
>>
>> After that the R_PPC_REL24 relocation was still there.  In addition to
>> that the R_PPC_EMB_SDA21 relocation was added.  So the relative
>> relocation is still there and things got even more complex... Did I do
>> something wrong here?
>
> No idea.  I thought that it would eliminate the REL24 relocations, but
> I was clearly wrong.  See if you can get GCC to generate code that uses
> a GOT/TOC.

Isn't that impossible because GRUB has its own GOT?  I mean: GRUB has
to lookup all symbols itself, etc.  If I am wrong, I have no idea how
to do it.

I hope to finish module loading so it at least works this weekend
using the method that can still cause overflows.  Can you have a look
at the code when I send it in and explain it using the GRUB code?

Thanks,
Marco




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [ppc patch] grub-mkimage
  2004-12-03 15:20         ` Marco Gerards
@ 2004-12-03 16:04           ` Johan Rydberg
  2004-12-03 16:13             ` Marco Gerards
  0 siblings, 1 reply; 16+ messages in thread
From: Johan Rydberg @ 2004-12-03 16:04 UTC (permalink / raw)
  To: Marco Gerards; +Cc: The development of GRUB 2

Marco Gerards <metgerards@student.han.nl> writes:

> Isn't that impossible because GRUB has its own GOT?  I mean: GRUB has
> to lookup all symbols itself, etc.  If I am wrong, I have no idea how
> to do it.

As I said to you off-line, the GOT-track might not be worth even
exploring.  Instead, at least in my opinion, move the modules within
the calling range of the "b" insn ; thus eliminating chances of
overflows.

> I hope to finish module loading so it at least works this weekend
> using the method that can still cause overflows.  Can you have a look
> at the code when I send it in and explain it using the GRUB code?

I could take a look at it, Yes.

~j






^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [ppc patch] grub-mkimage
  2004-12-03 15:18   ` Hollis Blanchard
@ 2004-12-03 16:10     ` Marco Gerards
  2004-12-03 16:45       ` Hollis Blanchard
  2004-12-03 17:12       ` Yoshinori K. Okuji
  0 siblings, 2 replies; 16+ messages in thread
From: Marco Gerards @ 2004-12-03 16:10 UTC (permalink / raw)
  To: The development of GRUB 2

Hollis Blanchard <hollis@penguinppc.org> writes:

>>> It may be possible to place module variables into their own section
>>> containing nothing else, yet still in a LOAD segment.  Then
>>> grub-mkimage
>>> could parse the *section* table (right now it only does segments) and
>>> overwrite the contents of this section to inform the runtime of the
>>> module location. I'm not convinced it's worth the effort.
>>
>> Whatever is the most flexible seems the best to me...
>
> I was aiming for simplicity really... What's the simplest possible way
> we can inform grubof of the location of its modules? :)

The solution with the other LOAD segment sounded the cleanest to me.
The one that assumed it would follow immediately after the rest of GRUB
sounded a bit hard to me.  I mean, can you really rely on such
assumptions?

>> AS Hollis said, I'm working on the relocator for PPC at the moment.
>> It is quite easy, but PPC_REL24 is a bit more complex.  It is used for
>> relative jumps.  That means the module should be loaded close to
>> grubof, which IMHO really sucks...
>
> 24-bit offsets give you a 16 MiB range, is that really a problem?

The modules are loaded into the free memory of grubof.  And grubof is
loaded to where it is linked, IIRC.  So I think that would cause
problems. :)

>> I am now trying to get option 2 to work first (by using black magic to
>> get everything loaded at the right address ;)) and when module loading
>> works for me I will try to make 3 work.
>
> I agree this makes sense. I'm not sure that option 3 will end up being
> necessary, but option 2 is obviously needed.

Right, and it is finished now.  I am quite sure it is required, but we
can test it.

>> Does someone else think I
>> try to do something else, or can someone help a bit somehow?  As you
>> might have noticed I really suck at this stuff and doing it just
>> because no one else does. ;)
>
> I've never seen relocation code before, but if it's still not working
> when I get back I'd be happy to take a look...

Cool.

Thanks,
Marco




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [ppc patch] grub-mkimage
  2004-12-03 16:04           ` Johan Rydberg
@ 2004-12-03 16:13             ` Marco Gerards
  0 siblings, 0 replies; 16+ messages in thread
From: Marco Gerards @ 2004-12-03 16:13 UTC (permalink / raw)
  To: Johan Rydberg; +Cc: The development of GRUB 2

Johan Rydberg <jrydberg@night.trouble.net> writes:

> Marco Gerards <metgerards@student.han.nl> writes:
>
>> Isn't that impossible because GRUB has its own GOT?  I mean: GRUB has
>> to lookup all symbols itself, etc.  If I am wrong, I have no idea how
>> to do it.
>
> As I said to you off-line, the GOT-track might not be worth even
> exploring.  Instead, at least in my opinion, move the modules within
> the calling range of the "b" insn ; thus eliminating chances of
> overflows.

Right, but that is quite difficult.

grubof is loaded by open firmware.  The module is loaded to malloc'ed
memory which can be completely somewhere else.  But I will think about
how to get those in each other's reach.

Thanks,
Marco




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [ppc patch] grub-mkimage
  2004-12-03 16:10     ` Marco Gerards
@ 2004-12-03 16:45       ` Hollis Blanchard
  2004-12-03 16:58         ` Marco Gerards
  2004-12-03 17:12       ` Yoshinori K. Okuji
  1 sibling, 1 reply; 16+ messages in thread
From: Hollis Blanchard @ 2004-12-03 16:45 UTC (permalink / raw)
  To: The development of GRUB 2

On Dec 3, 2004, at 10:10 AM, Marco Gerards wrote:
>
>>> AS Hollis said, I'm working on the relocator for PPC at the moment.
>>> It is quite easy, but PPC_REL24 is a bit more complex.  It is used 
>>> for
>>> relative jumps.  That means the module should be loaded close to
>>> grubof, which IMHO really sucks...
>>
>> 24-bit offsets give you a 16 MiB range, is that really a problem?
>
> The modules are loaded into the free memory of grubof.  And grubof is
> loaded to where it is linked, IIRC.  So I think that would cause
> problems. :)

I don't understand this. By "free memory of grubof" do you mean the 
heap? Right now, grubof is linked and loaded at 0x200000 (size is 
~100KiB right now), and uses memory from 0x4000 to 0x200000 as heap 
space. That means the heap is well within the 16MiB 24-bit offset 
range.

Above grubof, we don't have much to worry about (on any system I know 
of) until 0x400000, which leaves about 1.5 MiB of totally unused space 
just above us. That space also falls well within the 24-bit offset 
range.

So why is there a problem finding a place to put modules that's close 
to grubof?

-Hollis




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [ppc patch] grub-mkimage
  2004-12-03 16:45       ` Hollis Blanchard
@ 2004-12-03 16:58         ` Marco Gerards
  0 siblings, 0 replies; 16+ messages in thread
From: Marco Gerards @ 2004-12-03 16:58 UTC (permalink / raw)
  To: The development of GRUB 2

Hollis Blanchard <hollis@penguinppc.org> writes:

> On Dec 3, 2004, at 10:10 AM, Marco Gerards wrote:
>>
>>>> AS Hollis said, I'm working on the relocator for PPC at the moment.
>>>> It is quite easy, but PPC_REL24 is a bit more complex.  It is used
>>>> for
>>>> relative jumps.  That means the module should be loaded close to
>>>> grubof, which IMHO really sucks...
>>>
>>> 24-bit offsets give you a 16 MiB range, is that really a problem?
>>
>> The modules are loaded into the free memory of grubof.  And grubof is
>> loaded to where it is linked, IIRC.  So I think that would cause
>> problems. :)
>
> I don't understand this. By "free memory of grubof" do you mean the
> heap? Right now, grubof is linked and loaded at 0x200000 (size is
> ~100KiB right now), and uses memory from 0x4000 to 0x200000 as heap
> space. That means the heap is well within the 16MiB 24-bit offset
> range.

Ok, cool.  In that case there is no problem.  I thought that you
changed init.c so it adds all free memory.  In that case it could
cause problems if you have a few hundreds of megs of memory.  Perhaps
we just discussed this and the change was never made.

Thanks,
Marco




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [ppc patch] grub-mkimage
  2004-12-03 16:10     ` Marco Gerards
  2004-12-03 16:45       ` Hollis Blanchard
@ 2004-12-03 17:12       ` Yoshinori K. Okuji
  1 sibling, 0 replies; 16+ messages in thread
From: Yoshinori K. Okuji @ 2004-12-03 17:12 UTC (permalink / raw)
  To: grub-devel

On Friday 03 December 2004 17:10, Marco Gerards wrote:
> > 24-bit offsets give you a 16 MiB range, is that really a problem?
>
> The modules are loaded into the free memory of grubof.  And grubof is
> loaded to where it is linked, IIRC.  So I think that would cause
> problems. :)

A quite obvious solution would be to limit the max amount of dynamic 
memory to 16MB. For me, this sounds big enough...

On i386-pc, GRUB runs with 4MB memory.

Okuji



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [ppc patch] grub-mkimage
  2004-12-03  5:36 [ppc patch] grub-mkimage Hollis Blanchard
  2004-12-03 12:50 ` Marco Gerards
@ 2004-12-03 17:18 ` Yoshinori K. Okuji
  2005-01-01 22:42 ` [ppc patch] grub-mkimage and module loading Hollis Blanchard
  2 siblings, 0 replies; 16+ messages in thread
From: Yoshinori K. Okuji @ 2004-12-03 17:18 UTC (permalink / raw)
  To: The development of GRUB 2

On Friday 03 December 2004 06:36, Hollis Blanchard wrote:
> I'm firmly convinced that grub_load_modules(), currently in
> kern/main.c, will need to be changed to a more generic interface. For
> example, each arch could provide its own grub_module_start() and
> grub_module_end() functions. It is no longer a valid assumption that
> the modules begin immediately after grub_end_addr in memory. But for
> now I will leave that to someone (Marco?) doing the real module
> loading; grub-mkimage just needs to get it into memory (which I've
> verified it does).

I agree.

Okuji



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [ppc patch] grub-mkimage and module loading
  2004-12-03  5:36 [ppc patch] grub-mkimage Hollis Blanchard
  2004-12-03 12:50 ` Marco Gerards
  2004-12-03 17:18 ` Yoshinori K. Okuji
@ 2005-01-01 22:42 ` Hollis Blanchard
  2005-01-02 13:47   ` Marco Gerards
  2 siblings, 1 reply; 16+ messages in thread
From: Hollis Blanchard @ 2005-01-01 22:42 UTC (permalink / raw)
  To: The development of GRUB 2

On Dec 2, 2004, at 11:36 PM, Hollis Blanchard wrote:
>
> I'm firmly convinced that grub_load_modules(), currently in 
> kern/main.c,
> will need to be changed to a more generic interface. For example, each
> arch could provide its own grub_module_start() and grub_module_end()
> functions. It is no longer a valid assumption that the modules begin
> immediately after grub_end_addr in memory. But for now I will leave 
> that
> to someone (Marco?) doing the real module loading; grub-mkimage just
> needs to get it into memory (which I've verified it does).

On PPC, it is difficult to inform runtime grub of its modules that were 
added post-compile. There are two pieces of module information we need 
at runtime: the address and the length of the modules.

x86 grub uses a binary format so grub_total_module_size can be placed 
at a known location at compile time, to be overwritten at install time. 
The address is known because the modules are appended directly after 
the executable.

PPC grub is an ELF executable. That makes it very difficult to 
overwrite a variable at install time, as the variable lives in a 
section at some offset inside the file. We can use a constant location 
for the module base address, but we still need to communicate the 
module size somehow. Here are some options:

1) create a very small special-purpose section (e.g. ".moduleinfo") to 
hold the address and size of the post-compile modules. Cons: would 
require more ELF header parsing in grub-mkimage; wouldn't work if we 
need to go XCOFF or binary on Old World Macintosh (we might need to, 
due to firmware limitations).
1.5) a variation of 1), embed the information inside a normal section 
like .text. That might be easier to work with when using non-ELF 
formats.
2) Store the number of modules in memory just before the first 
grub_module_header. This is very simple, and I have implemented a 
working example already:
3) Run the object through ld several times (used in Linux to get the 
ramdisk location). This would require running ld at install time 
though, and I believe we don't want to require users have a toolchain 
present.

#define MODULE_BASE 0x00300000 /* where grub-mkimage puts them */
void
grub_load_modules (void)
{
   struct grub_modules {
     int num_modules;
     struct grub_module_header first_header;
   } *module_base = (struct grub_modules *) MODULE_BASE;
   struct grub_module_header *header = &module_base->first_header;
   int i;

   for (i = 0; i < module_base->num_modules; i++)
     {
       if (! grub_dl_load_core ((char *) header + header->offset,
                                (header->size - header->offset)))
         grub_fatal ("%s", grub_errmsg);
       header = (struct grub_module_header *) ((char *) header + 
header->size);
     }
}

I am in favor of option 2. This approach could also be used for the 
i386 port, but I guess there are other reasons we need to overwrite 
fixed-location variables there, so maybe it wouldn't simplify much. 
(I'm looking at the VARIABLE() macros in kern/i386/pc/startup.S) So it 
would also be easy to move the existing grub_load_modules() into 
arch-specific code, and use something like the above function for the 
PPC port.

Comments?

-Hollis




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [ppc patch] grub-mkimage and module loading
  2005-01-01 22:42 ` [ppc patch] grub-mkimage and module loading Hollis Blanchard
@ 2005-01-02 13:47   ` Marco Gerards
  0 siblings, 0 replies; 16+ messages in thread
From: Marco Gerards @ 2005-01-02 13:47 UTC (permalink / raw)
  To: The development of GRUB 2

Hollis Blanchard <hollis@penguinppc.org> writes:

> I am in favor of option 2. This approach could also be used for the
> i386 port, but I guess there are other reasons we need to overwrite
> fixed-location variables there, so maybe it wouldn't simplify
> much. (I'm looking at the VARIABLE() macros in kern/i386/pc/startup.S)
> So it would also be easy to move the existing grub_load_modules() into
> arch-specific code, and use something like the above function for the
> PPC port.

I completely agree.  Before the modules there should be a header and
it can and IMHO it should be something that is portable.  I can't come
up with a reason why such header would make things harder instead of
easier.

It would be nice if we can get rid of `grub_get_end_addr'.  The best
thing we can do is renaming it to `grub_get_dl_modules_adrr' or
something like that.  It should be moved to a machine specific place.
After doing that you can use that new function, parse the header and
initialize the modules.

Thanks,
Marco




^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2005-01-02 14:00 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-12-03  5:36 [ppc patch] grub-mkimage Hollis Blanchard
2004-12-03 12:50 ` Marco Gerards
2004-12-03 13:49   ` Johan Rydberg
2004-12-03 14:14     ` Marco Gerards
2004-12-03 15:13       ` Johan Rydberg
2004-12-03 15:20         ` Marco Gerards
2004-12-03 16:04           ` Johan Rydberg
2004-12-03 16:13             ` Marco Gerards
2004-12-03 15:18   ` Hollis Blanchard
2004-12-03 16:10     ` Marco Gerards
2004-12-03 16:45       ` Hollis Blanchard
2004-12-03 16:58         ` Marco Gerards
2004-12-03 17:12       ` Yoshinori K. Okuji
2004-12-03 17:18 ` Yoshinori K. Okuji
2005-01-01 22:42 ` [ppc patch] grub-mkimage and module loading Hollis Blanchard
2005-01-02 13:47   ` Marco Gerards

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.