grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

PPC relocator


From: Marco Gerards
Subject: PPC relocator
Date: Tue, 14 Dec 2004 19:37:46 +0000
User-agent: Gnus/5.1006 (Gnus v5.10.6) Emacs/21.3 (gnu/linux)

Hi,

Here is the relocator for the PPC including a few changes to the build
script so modules can be used.  This will not give module support,
some other things still need to be done before that is possible.  this
is just the first step towards that.

I've tried this and Hollis' patch to add modules to grubof.  Hollis'
patch worked perfectly AFAIK, but for some reason grubof crashes.  I
think the crash is caused because the heap is not executable.  I could
test this again using the address we use to load linux to, of course
the load address of GRUB has to be changed too otherwise the REL24
relocation won't work anymore.

The relocation code for REL24 was "stolen" from glibc with a minor
modification to make it work for us.  I think that won't be a problem
because glibc is copyrighted by the FSF and it's just 5 lines.  Okuji,
am I right about this?

I assume it would be ok to check in this code if I don't hear
objections before Friday.

Thanks,
Marco



2004-12-14  Marco Gerards  <address@hidden>

        * conf/powerpc-ieee1275.rmk (MOSTLYCLEANFILES): Remove
        `symlist.c', add `grubof_symlist.c'.
        (symlist.c): Variable removed.
        (grubof_HEADERS): Variable added.
        (grubof_symlist.c): New target.
        (kernel_syms.lst): Use `grubof_HEADERS' instead of
        `kernel_img_HEADERS'.
        (grubof_SOURCES): Add `kern/powerpc/dl.c' and `grubof_symlist.c'.
        * kern/powerpc/dl.c: New file.
        * kern/powerpc/ieee1275/init.c (grub_arch_dl_check_header):
        Function removed.
        (grub_arch_dl_relocate_symbols): Likewise.
        (grub_register_exported_symbols): Likewise.


===================================================================
RCS file: /cvsroot/grub/grub2/conf/powerpc-ieee1275.rmk,v
retrieving revision 1.15
diff -u -p -r1.15 powerpc-ieee1275.rmk
--- conf/powerpc-ieee1275.rmk   4 Dec 2004 18:45:45 -0000       1.15
+++ conf/powerpc-ieee1275.rmk   14 Dec 2004 19:34:29 -0000
@@ -6,13 +6,18 @@ COMMON_CFLAGS = -ffreestanding -msoft-fl
 
 # Images.
 
-MOSTLYCLEANFILES += symlist.c kernel_syms.lst
+MOSTLYCLEANFILES += grubof_symlist.c kernel_syms.lst
 DEFSYMFILES += kernel_syms.lst
 
-symlist.c: $(addprefix include/grub/,$(kernel_img_HEADERS)) gensymlist.sh
+grubof_HEADERS = arg.h boot.h device.h disk.h dl.h elf.h env.h err.h \
+       file.h fs.h kernel.h misc.h mm.h net.h rescue.h symbol.h \
+       term.h types.h machine/biosdisk.h  \
+       partition.h pc_partition.h machine/time.h machine/ieee1275.h
+
+grubof_symlist.c: $(addprefix include/grub/,$(grubof_HEADERS)) gensymlist.sh
        sh $(srcdir)/gensymlist.sh $(filter %.h,$^) > $@
 
-kernel_syms.lst: $(addprefix include/grub/,$(kernel_img_HEADERS)) 
genkernsyms.sh
+kernel_syms.lst: $(addprefix include/grub/,$(grubof_HEADERS)) genkernsyms.sh
        sh $(srcdir)/genkernsyms.sh $(filter %h,$^) > $@
 
 # Utilities.
@@ -45,7 +50,7 @@ grubof_SOURCES = boot/powerpc/ieee1275/c
        partmap/apple.c kern/partition.c \
        kern/env.c normal/arg.c loader/powerpc/ieee1275/linux.c \
        loader/powerpc/ieee1275/linux_normal.c commands/boot.c \
-       normal/powerpc/setjmp.S
+       normal/powerpc/setjmp.S kern/powerpc/dl.c grubof_symlist.c
 grubof_HEADERS = grub/powerpc/ieee1275/ieee1275.h
 grubof_CFLAGS = $(COMMON_CFLAGS) -DGRUBOF
 grubof_ASFLAGS = $(COMMON_ASFLAGS)
Index: kern/powerpc/dl.c
===================================================================
RCS file: kern/powerpc/dl.c
diff -N kern/powerpc/dl.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ kern/powerpc/dl.c   14 Dec 2004 19:34:29 -0000
@@ -0,0 +1,144 @@
+/* dl.c - arch-dependent part of loadable module support */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002, 2004  Free Software Foundation, Inc.
+ *
+ *  GRUB 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 GRUB; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/dl.h>
+#include <grub/elf.h>
+#include <grub/misc.h>
+#include <grub/err.h>
+
+/* Check if EHDR is a valid ELF header.  */
+int
+grub_arch_dl_check_header (void *ehdr, unsigned size)
+{
+  Elf32_Ehdr *e = ehdr;
+
+  /* Check the header size.  */
+  if (size < sizeof (Elf32_Ehdr))
+    return 0;
+
+  /* Check the magic numbers.  */
+  if (!((e->e_ident[EI_MAG0] == ELFMAG0) 
+       && (e->e_ident[EI_MAG1] == ELFMAG1)
+       && (e->e_ident[EI_MAG2] == ELFMAG2) 
+       && (e->e_ident[EI_MAG3] == ELFMAG3)
+       && (e->e_ident[EI_CLASS] == ELFCLASS32) 
+       && (e->e_ident[EI_DATA] == ELFDATA2MSB)
+       && (e->e_ident[EI_VERSION] == EV_CURRENT) 
+       && (e->e_type == ET_REL) && (e->e_machine == EM_PPC) 
+       && (e->e_version == EV_CURRENT)))
+    return 0;
+  
+  /* Make sure that every section is within the core.  */
+  if (size < e->e_shoff + e->e_shentsize * e->e_shnum)
+    return 0;
+
+  return 1;
+}
+
+
+/* Relocate symbols.  */
+grub_err_t
+grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
+{
+  Elf32_Ehdr *e = ehdr;
+  Elf32_Shdr *s;
+  Elf32_Sym *symtab;
+  Elf32_Word entsize;
+  unsigned i;
+  
+  /* Find a symbol table.  */
+  for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf32_Shdr *) ((char *) s + e->e_shentsize))
+    if (s->sh_type == SHT_SYMTAB)
+      break;
+
+  if (i == e->e_shnum)
+    return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found");
+  
+  symtab = (Elf32_Sym *) ((char *) e + s->sh_offset);
+  entsize = s->sh_entsize;
+  
+  for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf32_Shdr *) ((char *) s + e->e_shentsize))
+    if (s->sh_type == SHT_RELA)
+      {
+       grub_dl_segment_t seg;
+
+       /* Find the target segment.  */
+       for (seg = mod->segment; seg; seg = seg->next)
+         if (seg->section == s->sh_info)
+           break;
+
+       if (seg)
+         {
+           Elf32_Rela *rel, *max;
+           
+           for (rel = (Elf32_Rela *) ((char *) e + s->sh_offset),
+                  max = rel + s->sh_size / s->sh_entsize;
+                rel < max;
+                rel++)
+             {
+               Elf32_Word *addr;
+               Elf32_Sym *sym;
+               grub_uint32_t value;
+               
+               if (seg->size < rel->r_offset)
+                 return grub_error (GRUB_ERR_BAD_MODULE,
+                                    "reloc offset is out of the segment");
+               
+               addr = (Elf32_Word *) ((char *) seg->addr + rel->r_offset);
+               sym = (Elf32_Sym *) ((char *) symtab
+                                    + entsize * ELF32_R_SYM (rel->r_info));
+               
+               /* On the PPC the value does not have an explicit
+                  addend, add it.  */
+               value = sym->st_value + rel->r_addend;
+               switch (ELF32_R_TYPE (rel->r_info))
+                 {
+                 case R_PPC_ADDR16_LO:
+                   *(Elf32_Half *) addr = value;
+                   break;
+                   
+                 case R_PPC_REL24:
+                   {
+                     Elf32_Sword delta = value - (Elf32_Word) addr;
+                     
+                     if (delta << 6 >> 6 != delta)
+                       return grub_error (GRUB_ERR_BAD_MODULE, "Relocation 
overflow");
+                     *addr = (*addr & 0xfc000003) | (delta & 0x3fffffc);
+                     break;
+                   }
+                   
+                 case R_PPC_ADDR16_HA:
+                   *(Elf32_Half *) addr = (value + 0x8000) >> 16;
+                   break;
+                   
+                 case R_PPC_ADDR32:
+                   *addr = value;
+                   break;
+                 }
+             }
+         }
+      }
+  
+  return GRUB_ERR_NONE;
+}
Index: kern/powerpc/ieee1275/init.c
===================================================================
RCS file: /cvsroot/grub/grub2/kern/powerpc/ieee1275/init.c,v
retrieving revision 1.9
diff -u -p -r1.9 init.c
--- kern/powerpc/ieee1275/init.c        4 Dec 2004 18:45:45 -0000       1.9
+++ kern/powerpc/ieee1275/init.c        14 Dec 2004 19:34:31 -0000
@@ -84,31 +84,12 @@ grub_machine_init (void)
   grub_ofdisk_init ();
 }
 
-int
-grub_arch_dl_check_header (void *ehdr __attribute ((unused)),
-                          grub_size_t size __attribute ((unused)))
-{
-  return 0;
-}
-
-grub_err_t
-grub_arch_dl_relocate_symbols (grub_dl_t mod __attribute ((unused)),
-                              void *ehdr __attribute ((unused)))
-{
-  return 0;
-}
-
 void
 grub_stop (void)
 {
   for (;;);
 }
 
-void
-grub_register_exported_symbols (void)
-{
-}
-
 grub_uint32_t
 grub_get_rtc (void)
 {





reply via email to

[Prev in Thread] Current Thread [Next in Thread]