Because the binutils of the loongarch architecture adds relaxation support [1],
the next version of binutils will not be able to build grub.

So we added the R_LARCH_B16, R_LARCH_B21 and R_LARCH_RELAX [2] relocations to
enhance grub compatibility.

[1]: 
https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=56576f4a722b7398d35802ecf7d4185c27d6d69b
[2]: 
https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc#relocations

Signed-off-by: Xiaotian Wu <wuxiaot...@loongson.cn>
---
 grub-core/kern/loongarch64/dl.c        | 17 +++++++++++
 grub-core/kern/loongarch64/dl_helper.c | 39 ++++++++++++++++++++++++++
 include/grub/elf.h                     |  3 ++
 include/grub/loongarch64/reloc.h       |  2 ++
 util/grub-mkimagexx.c                  | 22 +++++++++++++++
 util/grub-module-verifier.c            |  3 ++
 6 files changed, 86 insertions(+)

diff --git a/grub-core/kern/loongarch64/dl.c b/grub-core/kern/loongarch64/dl.c
index 7f923b415..c22d2bd52 100644
--- a/grub-core/kern/loongarch64/dl.c
+++ b/grub-core/kern/loongarch64/dl.c
@@ -87,11 +87,28 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
          }
          break;
        case R_LARCH_MARK_LA:
+       case R_LARCH_RELAX:
          break;
        case R_LARCH_SOP_PUSH_PCREL:
        case R_LARCH_SOP_PUSH_PLT_PCREL:
          grub_loongarch64_sop_push (&stack, sym_addr - (grub_uint64_t)place);
          break;
+       case R_LARCH_B16:
+         {
+           grub_uint32_t *abs_place = place;
+           grub_ssize_t off = sym_addr - (grub_addr_t) place;
+
+           grub_loongarch64_b16 (abs_place, off);
+         }
+         break;
+       case R_LARCH_B21:
+         {
+           grub_uint32_t *abs_place = place;
+           grub_ssize_t off = sym_addr - (grub_addr_t) place;
+
+           grub_loongarch64_b21 (abs_place, off);
+         }
+         break;
        case R_LARCH_B26:
          {
            grub_uint32_t *abs_place = place;
diff --git a/grub-core/kern/loongarch64/dl_helper.c 
b/grub-core/kern/loongarch64/dl_helper.c
index b5d39b282..a3569b1e5 100644
--- a/grub-core/kern/loongarch64/dl_helper.c
+++ b/grub-core/kern/loongarch64/dl_helper.c
@@ -204,6 +204,45 @@ grub_loongarch64_sop_32_s_0_10_10_16_s2 
(grub_loongarch64_stack_t stack,
   *place =(*place) | ((a >> 18) & 0x3ff);
 }
 
+/*
+ * B16 relocation for the 18-bit PC-relative jump
+ * (*(uint32_t *) PC) [25 ... 10] = (S+A-PC) [17 ... 2]
+ */
+void grub_loongarch64_b16 (grub_uint32_t *place, grub_int64_t offset)
+{
+  grub_uint32_t val;
+  const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfc0003ff);
+
+  grub_dprintf ("dl", "  reloc_b16 %p %c= 0x%" PRIxGRUB_INT64_T "\n",
+               place, offset > 0 ? '+' : '-',
+               offset < 0 ? -offset : offset);
+
+  val = ((offset >> 2) & 0xffff) << 10;
+
+  *place &= insmask;
+  *place |= grub_cpu_to_le32 (val) & ~insmask;
+}
+
+/*
+ * B21 relocation for the 23-bit PC-relative jump
+ * (*(uint32_t *) PC) [4 ... 0] = (S+A-PC) [22 ... 18]
+ * (*(uint32_t *) PC) [25 ... 10] = (S+A-PC) [17 ... 2]
+ */
+void grub_loongarch64_b21 (grub_uint32_t *place, grub_int64_t offset)
+{
+  grub_uint32_t val;
+  const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfc0003e0);
+
+  grub_dprintf ("dl", "  reloc_b21 %p %c= 0x%" PRIxGRUB_INT64_T "\n",
+               place, offset > 0 ? '+' : '-',
+               offset < 0 ? -offset : offset);
+
+  val = ((offset >> 18) & 0x1f) | (((offset >> 2) & 0xffff) << 10);
+
+  *place &= insmask;
+  *place |= grub_cpu_to_le32 (val) & ~insmask;
+}
+
 /*
  * B26 relocation for the 28-bit PC-relative jump
  * (*(uint32_t *) PC) [9 ... 0] = (S+A-PC) [27 ... 18]
diff --git a/include/grub/elf.h b/include/grub/elf.h
index bd313a70b..12349c9e4 100644
--- a/include/grub/elf.h
+++ b/include/grub/elf.h
@@ -2558,6 +2558,8 @@ typedef Elf32_Addr Elf32_Conflict;
 #define R_LARCH_SOP_POP_32_S_5_20            43
 #define R_LARCH_SOP_POP_32_S_0_5_10_16_S2     44
 #define R_LARCH_SOP_POP_32_S_0_10_10_16_S2    45
+#define R_LARCH_B16                          64
+#define R_LARCH_B21                          65
 #define R_LARCH_B26                          66
 #define R_LARCH_ABS_HI20                     67
 #define R_LARCH_ABS_LO12                     68
@@ -2565,6 +2567,7 @@ typedef Elf32_Addr Elf32_Conflict;
 #define R_LARCH_ABS64_HI12                   70
 #define R_LARCH_PCALA_HI20                   71
 #define R_LARCH_PCALA_LO12                   72
+#define R_LARCH_RELAX                        100
 
 extern grub_err_t grub_elf32_get_shnum (Elf32_Ehdr *e, Elf32_Shnum *shnum);
 extern grub_err_t grub_elf32_get_shstrndx (Elf32_Ehdr *e, Elf32_Word 
*shstrndx);
diff --git a/include/grub/loongarch64/reloc.h b/include/grub/loongarch64/reloc.h
index 8ba355385..01d4f6831 100644
--- a/include/grub/loongarch64/reloc.h
+++ b/include/grub/loongarch64/reloc.h
@@ -57,6 +57,8 @@ void grub_loongarch64_sop_32_s_0_5_10_16_s2  
(grub_loongarch64_stack_t stack,
 void grub_loongarch64_sop_32_s_0_10_10_16_s2 (grub_loongarch64_stack_t stack,
                                              grub_uint64_t *place);
 
+void grub_loongarch64_b16        (grub_uint32_t *place, grub_int64_t offset);
+void grub_loongarch64_b21        (grub_uint32_t *place, grub_int64_t offset);
 void grub_loongarch64_b26        (grub_uint32_t *place, grub_int64_t offset);
 void grub_loongarch64_xxx_hi20   (grub_uint32_t *place, grub_int64_t offset);
 void grub_loongarch64_xxx_lo12   (grub_uint32_t *place, grub_int64_t offset);
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
index e50b29533..04c74d226 100644
--- a/util/grub-mkimagexx.c
+++ b/util/grub-mkimagexx.c
@@ -1144,6 +1144,7 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct 
section_metadata *smd,
                     }
                     break;
                   case R_LARCH_MARK_LA:
+                  case R_LARCH_RELAX:
                     break;
                   case R_LARCH_SOP_PUSH_PCREL:
                   case R_LARCH_SOP_PUSH_PLT_PCREL:
@@ -1152,6 +1153,24 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct 
section_metadata *smd,
                                                  +offset
                                                  +image_target->vaddr_offset));
                     break;
+                  case R_LARCH_B16:
+                    {
+                      grub_int64_t off;
+
+                      off = sym_addr - pc;
+
+                      grub_loongarch64_b16 (t32, off);
+                    }
+                    break;
+                  case R_LARCH_B21:
+                    {
+                      grub_int64_t off;
+
+                      off = sym_addr - pc;
+
+                      grub_loongarch64_b21 (t32, off);
+                    }
+                    break;
                   case R_LARCH_B26:
                     {
                       grub_int64_t off;
@@ -1777,6 +1796,8 @@ translate_relocation_pe (struct translate_context *ctx,
        case R_LARCH_SOP_POP_32_S_5_20:
        case R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
        case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
+       case R_LARCH_B16:
+       case R_LARCH_B21:
        case R_LARCH_B26:
        case R_LARCH_ABS_HI20:
        case R_LARCH_ABS_LO12:
@@ -1784,6 +1805,7 @@ translate_relocation_pe (struct translate_context *ctx,
        case R_LARCH_ABS64_HI12:
        case R_LARCH_PCALA_HI20:
        case R_LARCH_PCALA_LO12:
+       case R_LARCH_RELAX:
          grub_util_info ("  %s:  not adding fixup: 0x%08x : 0x%08x",
                          __FUNCTION__,
                          (unsigned int) addr,
diff --git a/util/grub-module-verifier.c b/util/grub-module-verifier.c
index 91d9e8f88..3d4c9a14b 100644
--- a/util/grub-module-verifier.c
+++ b/util/grub-module-verifier.c
@@ -140,6 +140,8 @@ struct grub_module_verifier_arch archs[] = {
       R_LARCH_SOP_POP_32_S_5_20,
       R_LARCH_SOP_POP_32_S_0_5_10_16_S2,
       R_LARCH_SOP_POP_32_S_0_10_10_16_S2,
+      R_LARCH_B16,
+      R_LARCH_B21,
       R_LARCH_B26,
       R_LARCH_ABS_HI20,
       R_LARCH_ABS_LO12,
@@ -147,6 +149,7 @@ struct grub_module_verifier_arch archs[] = {
       R_LARCH_ABS64_HI12,
       R_LARCH_PCALA_HI20,
       R_LARCH_PCALA_LO12,
+      R_LARCH_RELAX,
       -1
     }, (int[]){
       -1
-- 
2.20.1


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to