grub-devel.gnu.org archive mirror
 help / color / mirror / Atom feed
From: Ram Pai <linuxram@us.ibm.com>
To: grub-devel@gnu.org
Cc: tlfalcon@linux.vnet.ibm.com, tbberry@us.ibm.com,
	anton@au1.ibm.com, linuxram@us.ibm.com, tonyb@au1.ibm.com,
	Anton Blanchard <anton@samba.org>
Subject: [RFC PATCH 15/23] Add ppc64 relocations
Date: Wed, 26 Feb 2014 10:31:14 -0800	[thread overview]
Message-ID: <1393439482-20341-16-git-send-email-linuxram@us.ibm.com> (raw)
In-Reply-To: <1393439482-20341-1-git-send-email-linuxram@us.ibm.com>

From: Anton Blanchard <anton@samba.org>

 Add ppc64 relocations

Signed-off-by: Ram Pai <linuxram@us.ibm.com>
From:    Anton Blanchard <anton@samba.org>
---
 grub-core/kern/powerpc/dl.c | 179 +++++++++++++++++++++++++++++++++++++++++---
 include/grub/elf.h          |   3 +
 2 files changed, 172 insertions(+), 10 deletions(-)

diff --git a/grub-core/kern/powerpc/dl.c b/grub-core/kern/powerpc/dl.c
index 7677e5a..2a3b022 100644
--- a/grub-core/kern/powerpc/dl.c
+++ b/grub-core/kern/powerpc/dl.c
@@ -23,6 +23,20 @@
 #include <grub/err.h>
 #include <grub/i18n.h>
 
+#if defined( __powerpc64__ ) || defined( __powerpc64le__ )
+#define ELFCLASSXX ELFCLASS64
+#define ELFMACHINEXX EM_PPC64
+#else
+#define ELFCLASSXX ELFCLASS32
+#define ELFMACHINEXX EM_PPC32
+#endif
+
+#if defined( __powerpc64le__ )
+#define ELFDATA2XSB ELFDATA2LSB
+#else
+#define ELFDATA2XSB ELFDATA2MSB
+#endif
+
 /* Check if EHDR is a valid ELF header.  */
 grub_err_t
 grub_arch_dl_check_header (void *ehdr)
@@ -30,14 +44,77 @@ grub_arch_dl_check_header (void *ehdr)
   Elf_Ehdr *e = ehdr;
 
   /* Check the magic numbers.  */
-  if (e->e_ident[EI_CLASS] != ELFCLASS32
-      || e->e_ident[EI_DATA] != ELFDATA2MSB
-      || e->e_machine != EM_PPC)
+  if (e->e_ident[EI_CLASS] != ELFCLASSXX
+      || e->e_ident[EI_DATA] != ELFDATA2XSB
+      || e->e_machine != ELFMACHINEXX)
     return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic"));
 
   return GRUB_ERR_NONE;
 }
 
+
+
+
+#if defined( __powerpc64le__ )
+struct trampoline
+{
+  grub_uint32_t std;
+  grub_uint32_t addis;
+  grub_uint32_t addi; 
+  grub_uint32_t mtctr;
+  grub_uint32_t bctr;
+};
+
+static const struct trampoline trampoline_template = 
+  {
+       0xf8410018,       /* std     r2,24(r1) */
+       0x3d800000,       /* addis   r12,0,0 */
+       0x398c0000,       /* addi    r12,r12,0 */
+       0x7d8903a6,       /* mtctr   r12 */
+       0x4e800420,       /* bctr */
+  };
+
+#define PPC_NOP 0x60000000
+#define	RESTORE_TOC 0xe8410018       /* ld      r2,24(r1) */
+
+#define STO_PPC64_LOCAL_BIT             5
+#define STO_PPC64_LOCAL_MASK            (7 << STO_PPC64_LOCAL_BIT)
+
+static inline unsigned int
+ppc64_decode_local_entry(unsigned int other)
+{
+  return ((1 << other) >> 2) << 2;
+}
+
+#define PPC64_LOCAL_ENTRY_OFFSET(other)                         \
+  ppc64_decode_local_entry (((other) & STO_PPC64_LOCAL_MASK)    \
+                            >> STO_PPC64_LOCAL_BIT)
+
+
+
+#elif defined( __powerpc64__ )
+
+#error "NOT SUPPORTED YET"
+
+static int grub_arch_dl_is_in_opd (grub_dl_t mod, void *ehdr, unsigned long addr)
+{
+  unsigned long start, end;
+  Elf_Shdr *s = grub_dl_find_section(ehdr, ".opd");
+
+  if (!s)
+	return 0;
+
+  start = (unsigned long)grub_dl_find_section_addr(mod, ehdr, ".opd");
+  end = start + s->sh_size;
+
+  if ((start <= addr) && (addr < end))
+    return 1;
+  else
+    return 0;
+}
+
+#else
+
 /* For low-endian reverse lis and addr_high as well as ori and addr_low. */
 struct trampoline
 {
@@ -55,8 +132,20 @@ static const struct trampoline trampoline_template =
     0x4e800420,
   };
 
+#endif
+
 #pragma GCC diagnostic ignored "-Wcast-align"
 
+static unsigned long grub_arch_dl_get_toc (grub_dl_t mod, void *ehdr)
+{
+  unsigned long i = (unsigned long)grub_dl_find_section_addr(mod, ehdr, ".toc");
+  if (!i)
+    return 0;
+
+  return i;
+}
+
+
 grub_err_t
 grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
 				 grub_size_t *got)
@@ -89,12 +178,15 @@ grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
   return GRUB_ERR_NONE;
 }
 
+#define PPC_LO(v) ((v) & 0xffff)
+#define PPC_HI(v) (((v) >> 16) & 0xffff)
+#define PPC_HA(v) PPC_HI ((v) + 0x8000)
+
 /* Relocate symbols.  */
 grub_err_t
 grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
 			       Elf_Shdr *s, grub_dl_segment_t seg)
 {
-#ifdef powerpc
   Elf_Rela *rel, *max;
 
   for (rel = (Elf_Rela *) ((char *) ehdr + s->sh_offset),
@@ -104,7 +196,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
     {
       Elf_Word *addr;
       Elf_Sym *sym;
-      grub_uint32_t value;
+      Elf_Addr value;
 
       if (seg->size < rel->r_offset)
 	return grub_error (GRUB_ERR_BAD_MODULE,
@@ -119,6 +211,76 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
       value = sym->st_value + rel->r_addend;
       switch (ELF_R_TYPE (rel->r_info))
 	{
+#ifdef __powerpc64le__
+	case GRUB_ELF_R_PPC_REL24:
+	  {
+	    struct trampoline *tptr = mod->trampptr;
+	    Elf_Sword delta;
+	    if (sym->st_shndx == SHN_UNDEF)
+	    {
+	      	grub_memcpy (tptr, &trampoline_template, sizeof (*tptr));
+
+		tptr->addis |= PPC_HA(value);
+		tptr->addi |= PPC_LO(value);
+
+	        mod->trampptr = tptr + 1;
+	        delta = (grub_uint8_t *) tptr - (grub_uint8_t *) addr;
+
+	        if (*(addr+1) != PPC_NOP)
+	               return grub_error (GRUB_ERR_BAD_MODULE,
+			     "Missing NOP after PPC_REL24 got %x", *(addr+1));
+	        *(addr+1) = RESTORE_TOC;
+	    } else
+	        delta = (grub_uint8_t *)value - (grub_uint8_t *) addr + 
+                     PPC64_LOCAL_ENTRY_OFFSET(sym->st_other);
+
+
+            if (delta << 6 >> 6 != delta)
+		      return grub_error (GRUB_ERR_BAD_MODULE,
+					 "relocation overflow");
+
+	    *(Elf_Word *) (addr) = (*addr & ~0x03fffffc) | (delta & 0x03fffffc);
+	  }
+	  break;
+
+	case GRUB_ELF_R_PPC64_ADDR64:
+	  *(Elf_Xword *) addr = value;
+	  break;
+
+	case GRUB_ELF_R_PPC64_TOC:
+	  *(Elf_Xword *) addr = grub_arch_dl_get_toc(mod, ehdr);
+	  break;
+
+	case GRUB_ELF_R_PPC64_TOC16_HA:
+          value -= grub_arch_dl_get_toc(mod, ehdr);
+          *(Elf_Half *) addr = PPC_HA(value);
+	  break;
+
+	case GRUB_ELF_R_PPC64_TOC16_LO:
+          value -= grub_arch_dl_get_toc(mod, ehdr);
+	  *(Elf_Half *) addr = PPC_LO(value);
+	  break;
+
+	case GRUB_ELF_R_PPC64_TOC16_LO_DS:
+	   value -= grub_arch_dl_get_toc(mod, ehdr);
+	   if (value & 3)
+	    return grub_error (GRUB_ERR_BAD_MODULE,
+			       "bad TOC16_LO_DS relocation");
+	
+	  *(Elf_Half *) addr = ((*(Elf_Half *) addr) & ~0xfffc) | (value & 0xfffc);
+	  break;
+
+	case GRUB_ELF_R_PPC64_REL16_HA:
+	  value -=  (unsigned long) addr;
+	  *(Elf_Half *) addr = PPC_HA(value);
+	  break;
+
+	case GRUB_ELF_R_PPC64_REL16_LO:
+	  value -=  (unsigned long) addr;
+	  *(Elf_Half *) addr = PPC_LO(value);
+	  break;
+#else
+
 	case GRUB_ELF_R_PPC_ADDR16_LO:
 	  *(Elf_Half *) addr = value;
 	  break;
@@ -156,6 +318,8 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
 	case GRUB_ELF_R_PPC_REL32:
 	  *addr = value - (Elf_Word) addr;
 	  break;
+#endif
+
 	default:
 	  return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
 			     N_("relocation 0x%x is not implemented yet"),
@@ -164,9 +328,4 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
     }
 
   return GRUB_ERR_NONE;
-#else
-  return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
-     N_("relocation is not implemented yet for module=%llx ehdr=%llx Elf_Shdr=%llx seg=%llx"), 
-     mod, ehdr, s, seg);
-#endif
 }
diff --git a/include/grub/elf.h b/include/grub/elf.h
index bee7583..224d164 100644
--- a/include/grub/elf.h
+++ b/include/grub/elf.h
@@ -1998,6 +1998,9 @@ typedef Elf32_Addr Elf32_Conflict;
 #define GRUB_ELF_R_PPC_DIAB_RELSDA_HI	184	/* like EMB_RELSDA, but high 16 bit */
 #define GRUB_ELF_R_PPC_DIAB_RELSDA_HA	185	/* like EMB_RELSDA, adjusted high 16 */
 
+#define GRUB_ELF_R_PPC64_REL16_LO       250
+#define GRUB_ELF_R_PPC64_REL16_HA       252
+
 /* This is a phony reloc to handle any old fashioned TOC16 references
    that may still be in object files.  */
 #define GRUB_ELF_R_PPC_TOC16		255
-- 
1.8.5.3



  parent reply	other threads:[~2014-02-26 18:32 UTC|newest]

Thread overview: 68+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-02-26 18:30 [RFC PATCH 00/23] grub 64bit little-endian on power Ram Pai
2014-02-26 18:31 ` [RFC PATCH 01/23] Add a new architecture to the build process Ram Pai
2014-02-26 18:31 ` [RFC PATCH 02/23] Build LE grub as O1 Ram Pai
2014-02-26 18:31 ` [RFC PATCH 03/23] ignore .TOC. symbol Ram Pai
2014-04-01 16:52   ` Andrey Borzenkov
2014-02-26 18:31 ` [RFC PATCH 04/23] grub-install can now recognize and install a LE grub boot loader Ram Pai
2014-02-26 18:31 ` [RFC PATCH 05/23] set ABI version in e_flag of the PPC64LE ELF image Ram Pai
2014-02-26 18:31 ` [RFC PATCH 06/23] Add IEEE1275_ADDR helper Ram Pai
2014-04-01 17:11   ` Andrey Borzenkov
2014-02-26 18:31 ` [RFC PATCH 07/23] Fix some more warnings when casting Ram Pai
2014-02-26 18:31 ` [RFC PATCH 08/23] Add powerpc64 types Ram Pai
2014-04-01 17:15   ` Andrey Borzenkov
2014-04-02 17:02     ` Ram Pai
2014-02-26 18:31 ` [RFC PATCH 09/23] Fix warnings when building powerpc linux loader 64bit Ram Pai
2014-04-01 17:21   ` Andrey Borzenkov
2014-04-02 17:03     ` Ram Pai
2014-02-26 18:31 ` [RFC PATCH 10/23] GRUB_ELF_R_PPC_* processing is applicable only for 32 bit bootloader Ram Pai
2014-02-26 18:31 ` [RFC PATCH 11/23] Fix powerpc setjmp/longjmp 64bit issues Ram Pai
2014-04-01 17:27   ` Andrey Borzenkov
2014-04-02 17:06     ` Ram Pai
2014-04-02 17:19       ` Andrey Borzenkov
2014-04-02 17:48         ` Ram Pai
2014-04-02 17:56           ` Andrey Borzenkov
2014-04-02 18:55             ` Ram Pai
2014-02-26 18:31 ` [RFC PATCH 12/23] Add powerpc64 ieee1275 trampoline Ram Pai
2014-02-26 18:31 ` [RFC PATCH 13/23] Add 64bit support to powerpc startup code Ram Pai
2014-02-26 18:31 ` [RFC PATCH 14/23] Add grub_dl_find_section_addr Ram Pai
2014-02-26 18:31 ` Ram Pai [this message]
2014-02-26 18:31 ` [RFC PATCH 16/23] ppc64 doesn't need libgcc routines Ram Pai
2014-02-26 18:31 ` [RFC PATCH 17/23] Use FUNC_START/FUNC_END for powerpc function definitions Ram Pai
2014-02-26 18:31 ` [RFC PATCH 18/23] .TOC. symbol is special in ppc64le Ram Pai
2014-02-26 18:31 ` [RFC PATCH 19/23] align .toc section on 4byte boundary Ram Pai
2014-02-26 18:31 ` [RFC PATCH 20/23] fix parameter to firmware calls Ram Pai
2014-04-01 17:45   ` Andrey Borzenkov
2014-04-02 17:08     ` Ram Pai
2014-04-02 17:16       ` Andrey Borzenkov
2014-02-26 18:31 ` [RFC PATCH 21/23] powerpc64 is not necessarily BigEndian anymore! :) Ram Pai
2014-04-01 17:49   ` Andrey Borzenkov
2014-04-01 20:22     ` Vladimir 'φ-coder/phcoder' Serbinenko
2014-04-03 17:33       ` Ram Pai
2014-04-03 17:53         ` Andrey Borzenkov
2014-04-03 18:37           ` Ram Pai
2014-04-03 19:03             ` Andrey Borzenkov
2014-04-03 19:26               ` Ram Pai
2014-04-03 19:42                 ` Vladimir 'φ-coder/phcoder' Serbinenko
2014-04-03 20:23                   ` Ram Pai
2014-04-03 19:54                 ` Andrey Borzenkov
2014-04-03 20:32                   ` Ram Pai
2014-04-03 21:41                     ` Vladimir 'phcoder' Serbinenko
2014-04-04  2:28                     ` Andrey Borzenkov
2014-04-04 17:47                       ` Ram Pai
2014-04-04 18:17                         ` Andrey Borzenkov
2014-04-04 18:24                           ` Dinar Valeev
2014-04-04 19:12                             ` Andrey Borzenkov
2014-04-04 20:29                               ` Dinar Valeev
2014-04-04 22:19                                 ` Ram Pai
     [not found]                                   ` <CAEaD8JN9SkqU9+BkU2MYub=aC3Wb143nMPgRWjVbFvgit90yBQ@mail.gmail.com>
2014-04-05  0:04                                     ` Fwd: " Vladimir 'phcoder' Serbinenko
2014-09-27  5:42                             ` Andrei Borzenkov
2014-09-28  6:33                               ` Andrei Borzenkov
2014-04-04  6:37                   ` Vladimir 'φ-coder/phcoder' Serbinenko
2014-04-04 17:08                     ` Andrey Borzenkov
2014-04-05 15:45                       ` Vladimir 'φ-coder/phcoder' Serbinenko
2014-04-05 16:49                         ` Andrey Borzenkov
2014-04-05 18:29                           ` Vladimir 'φ-coder/phcoder' Serbinenko
2014-04-05 18:48                             ` Andrey Borzenkov
2014-04-02 17:09     ` Ram Pai
2014-02-26 18:31 ` [RFC PATCH 22/23] fix segfaults if initrd Ram Pai
2014-02-26 18:31 ` [RFC PATCH 23/23] Optional: Power7 VSX instructions workaround Ram Pai

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=1393439482-20341-16-git-send-email-linuxram@us.ibm.com \
    --to=linuxram@us.ibm.com \
    --cc=anton@au1.ibm.com \
    --cc=anton@samba.org \
    --cc=grub-devel@gnu.org \
    --cc=tbberry@us.ibm.com \
    --cc=tlfalcon@linux.vnet.ibm.com \
    --cc=tonyb@au1.ibm.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).