From aebda5e118748d819291f21fc11d5cc8f20de2bb Mon Sep 17 00:00:00 2001
From: sunway_fw <sunway_fw@wxiat.com>
Date: Tue, 18 Feb 2025 15:13:24 +0800
Subject: [PATCH 3/5] sw64: Add awareness for SW64 reloations

This patch adds awareness of SW64 relocations throughout the grub tools
as well as dynamic linkage and elf->PE relocation conversion support.

Signed-off-by: sunway_fw <sunway_fw@wxiat.com>
---
 grub-core/kern/sw64/dl.c    | 214 ++++++++++++++++++++++++++++++++++++
 include/grub/dl.h           |  16 ++-
 include/grub/elf.h          |  39 +++++++
 util/grub-mkimagexx.c       | 146 +++++++++++++++++++++++-
 util/grub-module-verifier.c |  18 +++
 5 files changed, 430 insertions(+), 3 deletions(-)
 create mode 100644 grub-core/kern/sw64/dl.c

diff --git a/grub-core/kern/sw64/dl.c b/grub-core/kern/sw64/dl.c
new file mode 100644
index 0000000..8e3cac2
--- /dev/null
+++ b/grub-core/kern/sw64/dl.c
@@ -0,0 +1,214 @@
+/* dl.c - arch-dependent part of loadable module support */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2018  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 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/elf.h>
+#include <grub/misc.h>
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <grub/i18n.h>
+#include <grub/elf.h>
+
+/*
+ * Check if EHDR is a valid ELF header.
+ */
+grub_err_t
+grub_arch_dl_check_header (void *ehdr)
+{
+  Elf_Ehdr *e = ehdr;
+
+  /* Check the magic numbers.  */
+  if (e->e_ident[EI_DATA] != ELFDATA2LSB || e->e_machine != EM_SW_64)
+    return grub_error (GRUB_ERR_BAD_OS,
+		       N_("invalid arch-dependent ELF magic"));
+
+  return GRUB_ERR_NONE;
+}
+
+#pragma GCC diagnostic ignored "-Wcast-align"
+
+/* Relocate symbols. */
+grub_err_t
+grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
+                               Elf_Shdr *s, grub_dl_segment_t seg)
+{
+  Elf_Rela *rel, *max;
+  grub_uint64_t *gpptr, *gotptr;
+
+  gotptr = (grub_uint64_t *) mod->got;
+  gpptr = (grub_uint64_t *) ((grub_uint64_t) mod->got + 0x8000);
+
+  for (rel = (Elf_Rela *) ((char *) ehdr + s->sh_offset),
+         max = (Elf_Rela *) ((char *) rel + s->sh_size);
+       rel < max;
+       rel = (Elf_Rela *) ((char *) rel + s->sh_entsize))
+    {
+      grub_addr_t addr;
+      Elf_Sym *sym;
+      grub_uint64_t value;
+
+      if (seg->size < (rel->r_offset & ~3))
+              return grub_error (GRUB_ERR_BAD_MODULE,
+                              "reloc offset is out of the segment");
+
+      addr = (grub_addr_t) seg->addr + rel->r_offset;
+      sym = (Elf_Sym *) ((char *) mod->symtab
+                      + mod->symsize * ELF_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 (ELF_R_TYPE (rel->r_info))
+        {
+        case R_SW64_NONE:
+          break;
+        case R_SW64_REFLONG:
+          *(grub_uint32_t *)addr = value;
+          break;
+        case R_SW64_REFQUAD:
+          {
+            *(grub_uint32_t *)addr = value;
+            *((grub_uint32_t *)addr + 1) = value >> 32;
+            break;
+          }
+        case R_SW64_GPREL32:
+          {
+            value -= (grub_uint64_t)gpptr;
+            if ((grub_int32_t)value != value)
+                    return grub_error (GRUB_ERR_BAD_MODULE,
+                                    "R_SW64_GPREL32 relocation out of range");
+            *(grub_uint32_t *) addr = value;
+            break;
+          }
+        case R_SW64_LITERAL:
+          {
+            grub_uint64_t li_hi;
+            grub_uint64_t li_lo;
+
+            li_hi = (grub_uint64_t) gotptr + (((grub_uint64_t)ELF_R_TYPE(rel->r_info)) >> 8 );
+            li_lo = li_hi - ((grub_uint64_t) gpptr);
+            if ((grub_int16_t)li_lo != li_lo)
+                    return grub_error (GRUB_ERR_BAD_MODULE,
+                                    "R_SW64_LITERAL relocation out of range");
+
+            *(grub_uint16_t *) addr = (li_lo & 0xffff);
+            *(grub_uint64_t *) (li_hi) = value;
+            gotptr++;
+            break;
+          }
+        case R_SW64_LITERAL_GOT:
+          break;
+        case R_SW64_LITUSE:
+          break;
+        case R_SW64_GPDISP:
+          {
+            grub_uint64_t hi;
+            grub_uint64_t lo;
+            grub_uint64_t gpoffset = (grub_int64_t)gpptr - addr;
+            lo = (grub_int16_t) gpoffset;
+            hi = (grub_int32_t) (gpoffset - lo);
+            if (hi + lo != gpoffset)
+                    return grub_error (GRUB_ERR_BAD_MODULE,
+                                    "R_SW64_GPDISP relocation out of range");
+
+            if (gpoffset & 0x8000) {
+                    hi = ((gpoffset + 0x8000) >> 16) & 0xffff;
+                    lo = gpoffset & 0xffff;
+            } else {
+                    hi = (gpoffset >> 16) & 0xffff;
+                    lo = gpoffset & 0xffff;
+            }
+
+            *(grub_uint32_t *) addr = ( *(grub_uint32_t *)addr & 0xffff0000) | (hi & 0xffff);
+            *(grub_uint32_t *) ((unsigned long)addr + rel->r_addend) =
+                    (((*(grub_uint32_t *)((unsigned long)addr + rel->r_addend)) & 0xffff0000) | (lo & 0xffff));
+            break;
+          }
+        case R_SW64_BRADDR:
+          {
+            grub_uint64_t braddr = (*(grub_uint64_t *)addr) + value - ((grub_uint64_t)addr + 4);
+            braddr = (grub_int64_t)braddr >> 2;
+            if (braddr + (1<<21) >= 1<<21)
+                    return grub_error (GRUB_ERR_BAD_MODULE,
+                                    "R_SW64_BRADDR relocation out of range");
+
+            *(grub_uint32_t *) addr = (*(grub_uint32_t *)addr & (~0x1fffff)) | (braddr & 0x1fffff);
+            break;
+          }
+        case R_SW64_HINT:
+          break;
+        case R_SW64_SREL32:
+          {
+            value -= (grub_uint64_t)addr;
+            if ((grub_int32_t)value != value)
+                    return grub_error (GRUB_ERR_BAD_MODULE,
+                                    "R_SW64_SREL32 relocation out of range");
+
+            *(grub_uint32_t *) addr = value;
+            break;
+          }
+        case R_SW64_SREL64:
+          {
+            grub_uint64_t srel64 = *(grub_uint64_t *)addr + value;;
+            srel64 -= (grub_uint64_t)addr;
+            *(grub_uint64_t *) addr = srel64;
+            break;
+          }
+        case R_SW64_GPRELHIGH:
+          {
+            grub_uint64_t gprel_hi = (grub_int64_t)(value - (grub_uint64_t)gpptr);
+
+            if (gprel_hi & 0x8000)
+                    gprel_hi = (grub_int64_t)(((grub_int64_t)gprel_hi + 0x8000) >> 16);
+            else
+                    gprel_hi = (grub_int64_t)gprel_hi >> 16;
+
+            if ((grub_int16_t)gprel_hi != gprel_hi)
+                    return grub_error (GRUB_ERR_BAD_MODULE,
+                                    "GPRELHIGH out of range\n");
+
+            *(grub_uint32_t *) addr = (*(grub_uint32_t *)addr & 0xffff0000) | (gprel_hi & 0xffff);
+            break;
+          }
+        case R_SW64_GPRELLOW:
+          {
+            grub_uint64_t gprel_lo = value - (grub_uint64_t)gpptr;
+            *(grub_uint32_t *) addr = (*(grub_uint32_t *)addr & 0xffff0000) | (gprel_lo & 0xffff);
+            break;
+          }
+        case R_SW64_GPREL16:
+          {
+            grub_uint64_t gprel16 = (*(grub_uint64_t *)addr + value);
+            gprel16 = (grub_uint64_t)(gprel16 - (grub_uint64_t)gpptr);
+            if ((grub_int16_t)gprel16 != gprel16)
+                    return grub_error (GRUB_ERR_BAD_MODULE,
+                                    "R_SW64_GPREL16 relocation out of range");
+            *(grub_uint16_t *) addr = gprel16;
+            break;
+          }
+        default:
+          return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+                          N_("relocation 0x%lx is not implemented yet"),
+                          ELF_R_TYPE (rel->r_info));
+        }
+    }
+
+  return GRUB_ERR_NONE;
+}
diff --git a/include/grub/dl.h b/include/grub/dl.h
index c5ab18c..a4cb287 100644
--- a/include/grub/dl.h
+++ b/include/grub/dl.h
@@ -292,17 +292,31 @@ grub_err_t
 grub_arm64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
 				  grub_size_t *got);
 
+#if defined (__sw_64__)
+#define GRUB_SW64_DL_TRAMP_ALIGN 16
+#define GRUB_SW64_DL_GOT_ALIGN 16
+
+grub_err_t
+grub_sw64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
+				 grub_size_t *got);
+#endif
+
 #if defined (__ia64__)
 #define GRUB_ARCH_DL_TRAMP_ALIGN GRUB_IA64_DL_TRAMP_ALIGN
 #define GRUB_ARCH_DL_GOT_ALIGN GRUB_IA64_DL_GOT_ALIGN
 #define grub_arch_dl_get_tramp_got_size grub_ia64_dl_get_tramp_got_size
 #elif defined (__aarch64__)
 #define grub_arch_dl_get_tramp_got_size grub_arm64_dl_get_tramp_got_size
+#elif defined (__sw_64__)
+#define GRUB_ARCH_DL_TRAMP_ALIGN GRUB_SW64_DL_TRAMP_ALIGN
+#define GRUB_ARCH_DL_GOT_ALIGN GRUB_SW64_DL_GOT_ALIGN
+#define grub_arch_dl_get_tramp_got_size grub_sw64_dl_get_tramp_got_size
 #else
 grub_err_t
 grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
 				 grub_size_t *got);
 #endif
+#endif
 
 #if defined (__powerpc__) || defined (__mips__) || defined (__arm__) || \
     (defined(__riscv) && (__riscv_xlen == 32))
@@ -317,6 +331,4 @@ grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
 #define GRUB_ARCH_DL_GOT_ALIGN 8
 #endif
 
-#endif
-
 #endif /* ! GRUB_DL_H */
diff --git a/include/grub/elf.h b/include/grub/elf.h
index bd313a7..2af59fe 100644
--- a/include/grub/elf.h
+++ b/include/grub/elf.h
@@ -259,6 +259,7 @@ typedef struct
    chances of collision with official or non-GNU unofficial values.  */
 
 #define EM_ALPHA	0x9026
+#define EM_SW_64        0x9916
 
 /* Legal values for e_version (version).  */
 
@@ -2537,6 +2538,44 @@ typedef Elf32_Addr Elf32_Conflict;
 #define R_RISCV_SET32           56
 #define R_RISCV_32_PCREL        57
 
+/*
+ * SW-64 ELF relocation types
+ */
+#define R_SW64_NONE            0       /* No reloc */
+#define R_SW64_REFLONG         1       /* Direct 32 bit */
+#define R_SW64_REFQUAD         2       /* Direct 64 bit */
+#define R_SW64_GPREL32         3       /* GP relative 32 bit */
+#define R_SW64_LITERAL         4       /* GP relative 16 bit w/optimization */
+#define R_SW64_LITUSE          5       /* Optimization hint for LITERAL */
+#define R_SW64_GPDISP          6       /* Add displacement to GP */
+#define R_SW64_BRADDR          7       /* PC+4 relative 23 bit shifted */
+#define R_SW64_HINT            8       /* PC+4 relative 16 bit shifted */
+#define R_SW64_SREL16          9       /* PC relative 16 bit */
+#define R_SW64_SREL32          10      /* PC relative 32 bit */
+#define R_SW64_SREL64          11      /* PC relative 64 bit */
+#define R_SW64_GPRELHIGH       17      /* GP relative 32 bit, high 16 bits */
+#define R_SW64_GPRELLOW        18      /* GP relative 32 bit, low 16 bits */
+#define R_SW64_GPREL16         19      /* GP relative 16 bit */
+#define R_SW64_COPY            24      /* Copy symbol at runtime */
+#define R_SW64_GLOB_DAT        25      /* Create GOT entry */
+#define R_SW64_JMP_SLOT        26      /* Create PLT entry */
+#define R_SW64_RELATIVE        27      /* Adjust by program base */
+#define R_SW64_BRSGP           28
+#define R_SW64_TLSGD           29
+#define R_SW64_TLS_LDM         30
+#define R_SW64_DTPMOD64        31
+#define R_SW64_GOTDTPREL       32
+#define R_SW64_DTPREL64        33
+#define R_SW64_DTPRELHI        34
+#define R_SW64_DTPRELLO        35
+#define R_SW64_DTPREL16        36
+#define R_SW64_GOTTPREL        37
+#define R_SW64_TPREL64         38
+#define R_SW64_TPRELHI         39
+#define R_SW64_TPRELLO         40
+#define R_SW64_TPREL16         41
+#define R_SW64_LITERAL_GOT     43
+
 /* LoongArch relocations */
 #define R_LARCH_NONE			      0
 #define R_LARCH_64			      2
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
index 9488f05..f327e26 100644
--- a/util/grub-mkimagexx.c
+++ b/util/grub-mkimagexx.c
@@ -819,8 +819,14 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd,
   Elf_Half i;
   Elf_Shdr *s;
 #ifdef MKIMAGE_ELF64
+  grub_uint64_t got_offset = 0;
+
   struct grub_ia64_trampoline *tr = (void *) (pe_target + tramp_off);
   grub_uint64_t *gpptr = (void *) (pe_target + got_off);
+  if (image_target->elf_target == EM_SW_64) {
+    got_offset = got_off;
+    gpptr = (void *) (pe_target + got_offset + 0x8000);
+  }
   unsigned unmatched_adr_got_page = 0;
   struct grub_loongarch64_stack stack;
   grub_loongarch64_stack_init (&stack);
@@ -1163,6 +1169,119 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd,
 		   }
 	       break;
 	       }
+             case EM_SW_64:
+              {
+               sym_addr += addend;
+               switch (ELF_R_TYPE (info))
+                 {
+                 case R_SW64_NONE:
+                   break;
+                 case R_SW64_REFLONG:
+                   *(grub_uint32_t *)target = grub_host_to_target32 (sym_addr);
+                   break;
+                 case R_SW64_REFQUAD:
+                   {
+                     *(grub_uint32_t *)target = grub_host_to_target32(sym_addr);
+                     *((grub_uint32_t *)target + 1) = grub_host_to_target32(sym_addr >> 32);
+                     break;
+                   }
+                 case R_SW64_GPREL32:
+                   {
+                     *(grub_uint32_t *) target = (grub_host_to_target64 (sym_addr) -
+                                     ((char *) gpptr - (char *)pe_target + image_target->vaddr_offset )) & 0xffffffff;
+                     break;
+                   }
+                 case R_SW64_LITERAL:
+                   {
+                     grub_uint64_t li_hi;
+                     grub_uint64_t li_lo;
+
+                     li_hi = (grub_uint64_t)pe_target + got_offset + (((grub_uint64_t)ELF_R_TYPE(r->r_info)) >> 8 );
+                     li_lo = li_hi - ((grub_uint64_t) gpptr);
+                     *(grub_uint16_t *) target = (li_lo & 0xffff);
+                     *(grub_uint64_t *) (li_hi) = grub_host_to_target64(grub_host_to_target64 (sym_addr));
+                     got_offset += 8;
+                     break;
+                   }
+                 case R_SW64_LITERAL_GOT:
+                   break;
+                 case R_SW64_LITUSE:
+                   break;
+                 case R_SW64_GPDISP:
+                   {
+                     grub_uint64_t hi;
+                     grub_uint64_t lo;
+                     grub_int64_t gpoffset = (((char *) gpptr - (char *) pe_target + image_target->vaddr_offset))
+                             - ((offset + target_section_addr + image_target->vaddr_offset));
+                     if (gpoffset & 0x8000) {
+                             hi = ((gpoffset + 0x8000) >> 16) & 0xffff;
+                             lo = gpoffset & 0xffff;
+                     } else {
+                             hi = (gpoffset >> 16) & 0xffff;
+                             lo = gpoffset & 0xffff;
+                     }
+                     *(grub_uint32_t *) target = grub_host_to_target32 ((grub_target_to_host32 (*target) & 0xffff0000) | (hi & 0xffff));
+                     *(grub_uint32_t *) ((unsigned long)target + addend) =
+                             grub_host_to_target32 ((grub_target_to_host32 (*(grub_uint32_t *)
+                                                             ((unsigned long)target + addend)) & 0xffff0000) | (lo & 0xffff));
+                     break;
+
+                   }
+                 case R_SW64_BRADDR:
+                   {
+                     grub_uint64_t braddr = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr) - ((grub_uint64_t)target + 4);
+                     braddr = braddr >> 2;
+                     *(grub_uint32_t *) target = (*(grub_uint32_t *)target & (~0x1fffff)) | (braddr & 0x1fffff);
+                     break;
+                   }
+                 case R_SW64_HINT:
+                   break;
+                 case R_SW64_SREL32:
+                   {
+                     grub_uint64_t srel32 = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr);
+                     srel32 -= (grub_uint64_t)target;
+                     *(grub_uint32_t *) target = srel32;
+                     break;
+                   }
+                 case R_SW64_SREL64:
+                   {
+                     grub_uint64_t srel64 = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr);
+                     srel64 -= (grub_uint64_t)target;
+                     *(grub_uint64_t *) target = srel64;
+                     break;
+                   }
+                 case R_SW64_GPRELHIGH:
+                   {
+                     grub_uint64_t gprel_hi = ((grub_host_to_target64 (sym_addr) - (((char *) gpptr - (char *)pe_target + image_target->vaddr_offset) + 0x0)));
+
+                     if (gprel_hi & 0x8000)
+                             gprel_hi = ((gprel_hi + 0x8000) >> 16) & 0xffff;
+                     else
+                             gprel_hi = (gprel_hi >> 16) & 0xffff;
+
+                     *(grub_uint32_t *) target = grub_host_to_target32 ((grub_target_to_host32 (*target) & 0xffff0000) | (gprel_hi & 0xffff));
+                     break;
+                   }
+                 case R_SW64_GPRELLOW:
+                   {
+                     grub_uint64_t gprel_lo = (grub_host_to_target64 (sym_addr) - ((char *) gpptr - (char *)pe_target + image_target->vaddr_offset));
+                     *(grub_uint32_t *) target = grub_host_to_target32 ((grub_target_to_host32 (*target) & 0xffff0000) | (gprel_lo & 0xffff));
+                     break;
+                   }
+                 case R_SW64_GPREL16:
+                   {
+                     grub_uint64_t gprel16 = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr);
+                     gprel16 = (grub_uint64_t)(gprel16 - (grub_uint64_t)gpptr);
+                     *(grub_uint16_t *) target = gprel16;
+                     break;
+                   }
+                 default:
+                   grub_util_error (_("relocation 0x%lx is not implemented yet"),
+                                   ELF_R_TYPE (info));
+                   break;
+                 }
+               break;
+              }
 	     case EM_LOONGARCH:
 	       {
 		 grub_int64_t pc;
@@ -1700,6 +1819,19 @@ translate_relocation_pe (struct translate_context *ctx,
 			       image_target);
 	}
       break;
+    case EM_SW_64:
+      if (ELF_R_TYPE (info) == R_SW64_REFQUAD)
+        {
+         grub_util_info ("adding a relocation entry for 0x%llx",
+                         (unsigned long long) addr);
+         ctx->current_address
+           = add_fixup_entry (&ctx->lst,
+                              GRUB_PE32_REL_BASED_DIR64,
+                              addr,
+                              0, ctx->current_address,
+                              image_target);
+       }
+      break;
     case EM_IA_64:
       switch (ELF_R_TYPE (info))
 	{
@@ -2181,7 +2313,8 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout,
 		       + image_target->vaddr_offset,
 		       2 * layout->ia64jmpnum,
 		       image_target);
-  if (image_target->elf_target == EM_IA_64 || image_target->elf_target == EM_AARCH64)
+  if (image_target->elf_target == EM_IA_64 || image_target->elf_target == EM_AARCH64 ||
+      image_target->elf_target == EM_SW_64)
     create_u64_fixups (&ctx,
 		       layout->got_off
 		       + image_target->vaddr_offset,
@@ -2550,6 +2683,17 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
 
 	  grub_arm64_dl_get_tramp_got_size (e, &tramp, &layout->got_size);
 
+          layout->got_off = layout->kernel_size;
+          layout->kernel_size += ALIGN_UP (layout->got_size, 16);
+        }
+      else if (image_target->elf_target == EM_SW_64)
+        {
+          grub_size_t tramp;
+
+          layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
+
+          grub_sw64_dl_get_tramp_got_size (e, &tramp, &layout->got_size);
+
 	  layout->got_off = layout->kernel_size;
 	  layout->kernel_size += ALIGN_UP (layout->got_size, 16);
 	}
diff --git a/util/grub-module-verifier.c b/util/grub-module-verifier.c
index 91d9e8f..37fd0f6 100644
--- a/util/grub-module-verifier.c
+++ b/util/grub-module-verifier.c
@@ -209,6 +209,24 @@ struct grub_module_verifier_arch archs[] = {
       -1
     }
   },
+  { "sw64", 8, 0, EM_SW_64, GRUB_MODULE_VERIFY_SUPPORTS_REL | GRUB_MODULE_VERIFY_SUPPORTS_RELA, (int[]){
+      R_SW64_NONE,
+      R_SW64_REFQUAD,
+      R_SW64_GPREL32,
+      R_SW64_LITERAL,
+      R_SW64_LITERAL_GOT,
+      R_SW64_LITUSE,
+      R_SW64_GPDISP,
+      R_SW64_BRSGP,
+      R_SW64_BRADDR,
+      R_SW64_HINT,
+      R_SW64_SREL32,
+      R_SW64_SREL64,
+      R_SW64_GPRELHIGH,
+      R_SW64_GPRELLOW,
+      R_SW64_GPREL16,
+      -1
+    } },
 };
 
 struct platform_whitelist {
-- 
2.33.0

