All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Vladimir 'φ-coder/phcoder' Serbinenko" <phcoder@gmail.com>
To: The development of GRUB 2 <grub-devel@gnu.org>,
	Leif Lindholm <leif.lindholm@linaro.org>,
	Ian Campbell <Ian.Campbell@citrix.com>
Subject: [PATCH] U-Boot self-relocatable images
Date: Tue, 23 Feb 2016 11:35:02 +0100	[thread overview]
Message-ID: <56CC35D6.4010108@gmail.com> (raw)


[-- Attachment #1.1: Type: text/plain, Size: 263 bytes --]

Currently to compile arm-uboot port for a different platform you need to
relink it at new address with modifying source code. This set of patches
changes to U-boot in-place loading and images that relocate themselves.
I'd be interested in opinion of ARM guys

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: 0001-mkimage.c-Split-into-separate-files.patch --]
[-- Type: text/x-diff; name="0001-mkimage.c-Split-into-separate-files.patch", Size: 28427 bytes --]

From 80f8cfe29ace49167c1ad6439ddd15519b0a5455 Mon Sep 17 00:00:00 2001
From: Vladimir Serbinenko <phcoder@gmail.com>
Date: Thu, 18 Feb 2016 20:26:44 +0100
Subject: [PATCH 1/6] mkimage.c: Split into separate files.

util/grub-mkimagexx.c is included in a special way into mkimage.c.
Interoperation between defines makes this very tricky. Instead
just have a clean interface and compile util/grub-mkimage*.c separately
from mkimage.c
---
 Makefile.util.def           |  10 ++
 include/grub/util/mkimage.h | 170 +++++++++++++++++++++++++++
 util/grub-mkimage32.c       |  22 ++++
 util/grub-mkimage64.c       |  22 ++++
 util/grub-mkimagexx.c       | 246 +++++++++++++++++++++++++++------------
 util/mkimage.c              | 273 ++------------------------------------------
 6 files changed, 405 insertions(+), 338 deletions(-)
 create mode 100644 include/grub/util/mkimage.h
 create mode 100644 util/grub-mkimage32.c
 create mode 100644 util/grub-mkimage64.c

diff --git a/Makefile.util.def b/Makefile.util.def
index db7e8ec..ed9b4c6 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -172,6 +172,8 @@ program = {
 
   common = util/grub-mkimage.c;
   common = util/mkimage.c;
+  common = util/grub-mkimage32.c;
+  common = util/grub-mkimage64.c;
   common = util/resolve.c;
   common = grub-core/kern/emu/argp_common.c;
   common = grub-core/osdep/init.c;
@@ -510,6 +512,8 @@ program = {
   common = util/render-label.c;
   common = util/glue-efi.c;
   common = util/mkimage.c;
+  common = util/grub-mkimage32.c;
+  common = util/grub-mkimage64.c;
   common = util/grub-install-common.c;
   common = util/setup_bios.c;
   common = util/setup_sparc.c;
@@ -552,6 +556,8 @@ program = {
   common = util/render-label.c;
   common = util/glue-efi.c;
   common = util/mkimage.c;
+  common = util/grub-mkimage32.c;
+  common = util/grub-mkimage64.c;
   common = util/grub-install-common.c;
   common = util/setup_bios.c;
   common = util/setup_sparc.c;
@@ -595,6 +601,8 @@ program = {
   common = util/grub-install.c;
   common = util/probe.c;
   common = util/mkimage.c;
+  common = util/grub-mkimage32.c;
+  common = util/grub-mkimage64.c;
   common = util/grub-install-common.c;
   common = util/setup_bios.c;
   common = util/setup_sparc.c;
@@ -632,6 +640,8 @@ program = {
   common = util/grub-mknetdir.c;
 
   common = util/mkimage.c;
+  common = util/grub-mkimage32.c;
+  common = util/grub-mkimage64.c;
   common = util/grub-install-common.c;
   common = util/setup_bios.c;
   common = util/setup_sparc.c;
diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h
new file mode 100644
index 0000000..564adbc
--- /dev/null
+++ b/include/grub/util/mkimage.h
@@ -0,0 +1,170 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2013  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/>.
+ */
+
+#ifndef GRUB_UTIL_MKIMAGE_HEADER
+#define GRUB_UTIL_MKIMAGE_HEADER	1
+
+/* Private header. Use only in mkimage-related sources.  */
+char *
+grub_mkimage_load_image32 (const char *kernel_path, size_t *exec_size, 
+			   size_t *kernel_sz, size_t *bss_size,
+			   size_t total_module_size, grub_uint64_t *start,
+			   void **reloc_section, size_t *reloc_size,
+			   size_t *align,
+			   const struct grub_install_image_target_desc *image_target);
+char *
+grub_mkimage_load_image64 (const char *kernel_path, size_t *exec_size, 
+			   size_t *kernel_sz, size_t *bss_size,
+			   size_t total_module_size, grub_uint64_t *start,
+			   void **reloc_section, size_t *reloc_size,
+			   size_t *align,
+			   const struct grub_install_image_target_desc *image_target);
+void
+grub_mkimage_generate_elf32 (const struct grub_install_image_target_desc *image_target,
+			     int note, char **core_img, size_t *core_size,
+			     Elf32_Addr target_addr, grub_size_t align,
+			     size_t kernel_size, size_t bss_size);
+void
+grub_mkimage_generate_elf64 (const struct grub_install_image_target_desc *image_target,
+			     int note, char **core_img, size_t *core_size,
+			     Elf64_Addr target_addr, grub_size_t align,
+			     size_t kernel_size, size_t bss_size);
+
+struct grub_install_image_target_desc
+{
+  const char *dirname;
+  const char *names[6];
+  grub_size_t voidp_sizeof;
+  int bigendian;
+  enum {
+    IMAGE_I386_PC, IMAGE_EFI, IMAGE_COREBOOT,
+    IMAGE_SPARC64_AOUT, IMAGE_SPARC64_RAW, IMAGE_SPARC64_CDCORE,
+    IMAGE_I386_IEEE1275,
+    IMAGE_LOONGSON_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH,
+    IMAGE_FULOONG2F_FLASH, IMAGE_I386_PC_PXE, IMAGE_MIPS_ARC,
+    IMAGE_QEMU_MIPS_FLASH, IMAGE_UBOOT, IMAGE_XEN, IMAGE_I386_PC_ELTORITO
+  } id;
+  enum
+    {
+      PLATFORM_FLAGS_NONE = 0,
+      PLATFORM_FLAGS_DECOMPRESSORS = 2,
+      PLATFORM_FLAGS_MODULES_BEFORE_KERNEL = 4,
+    } flags;
+  unsigned total_module_size;
+  unsigned decompressor_compressed_size;
+  unsigned decompressor_uncompressed_size;
+  unsigned decompressor_uncompressed_addr;
+  unsigned link_align;
+  grub_uint16_t elf_target;
+  unsigned section_align;
+  signed vaddr_offset;
+  grub_uint64_t link_addr;
+  unsigned mod_gap, mod_align;
+  grub_compression_t default_compression;
+  grub_uint16_t pe_target;
+};
+
+#define grub_target_to_host32(x) (grub_target_to_host32_real (image_target, (x)))
+#define grub_host_to_target32(x) (grub_host_to_target32_real (image_target, (x)))
+#define grub_target_to_host64(x) (grub_target_to_host64_real (image_target, (x)))
+#define grub_host_to_target64(x) (grub_host_to_target64_real (image_target, (x)))
+#define grub_host_to_target_addr(x) (grub_host_to_target_addr_real (image_target, (x)))
+#define grub_target_to_host16(x) (grub_target_to_host16_real (image_target, (x)))
+#define grub_host_to_target16(x) (grub_host_to_target16_real (image_target, (x)))
+
+static inline grub_uint32_t
+grub_target_to_host32_real (const struct grub_install_image_target_desc *image_target,
+			    grub_uint32_t in)
+{
+  if (image_target->bigendian)
+    return grub_be_to_cpu32 (in);
+  else
+    return grub_le_to_cpu32 (in);
+}
+
+static inline grub_uint64_t
+grub_target_to_host64_real (const struct grub_install_image_target_desc *image_target,
+			    grub_uint64_t in)
+{
+  if (image_target->bigendian)
+    return grub_be_to_cpu64 (in);
+  else
+    return grub_le_to_cpu64 (in);
+}
+
+static inline grub_uint64_t
+grub_host_to_target64_real (const struct grub_install_image_target_desc *image_target,
+			    grub_uint64_t in)
+{
+  if (image_target->bigendian)
+    return grub_cpu_to_be64 (in);
+  else
+    return grub_cpu_to_le64 (in);
+}
+
+static inline grub_uint32_t
+grub_host_to_target32_real (const struct grub_install_image_target_desc *image_target,
+			    grub_uint32_t in)
+{
+  if (image_target->bigendian)
+    return grub_cpu_to_be32 (in);
+  else
+    return grub_cpu_to_le32 (in);
+}
+
+static inline grub_uint16_t
+grub_target_to_host16_real (const struct grub_install_image_target_desc *image_target,
+			    grub_uint16_t in)
+{
+  if (image_target->bigendian)
+    return grub_be_to_cpu16 (in);
+  else
+    return grub_le_to_cpu16 (in);
+}
+
+static inline grub_uint16_t
+grub_host_to_target16_real (const struct grub_install_image_target_desc *image_target,
+			    grub_uint16_t in)
+{
+  if (image_target->bigendian)
+    return grub_cpu_to_be16 (in);
+  else
+    return grub_cpu_to_le16 (in);
+}
+
+static inline grub_uint64_t
+grub_host_to_target_addr_real (const struct grub_install_image_target_desc *image_target, grub_uint64_t in)
+{
+  if (image_target->voidp_sizeof == 8)
+    return grub_host_to_target64_real (image_target, in);
+  else
+    return grub_host_to_target32_real (image_target, in);
+}
+
+static inline grub_uint64_t
+grub_target_to_host_real (const struct grub_install_image_target_desc *image_target, grub_uint64_t in)
+{
+  if (image_target->voidp_sizeof == 8)
+    return grub_target_to_host64_real (image_target, in);
+  else
+    return grub_target_to_host32_real (image_target, in);
+}
+
+#define grub_target_to_host(val) grub_target_to_host_real(image_target, (val))
+
+#endif
diff --git a/util/grub-mkimage32.c b/util/grub-mkimage32.c
new file mode 100644
index 0000000..9b31397
--- /dev/null
+++ b/util/grub-mkimage32.c
@@ -0,0 +1,22 @@
+#define MKIMAGE_ELF32 1
+
+# define SUFFIX(x)	x ## 32
+# define ELFCLASSXX	ELFCLASS32
+# define Elf_Ehdr	Elf32_Ehdr
+# define Elf_Phdr	Elf32_Phdr
+# define Elf_Nhdr	Elf32_Nhdr
+# define Elf_Addr	Elf32_Addr
+# define Elf_Sym	Elf32_Sym
+# define Elf_Off	Elf32_Off
+# define Elf_Shdr	Elf32_Shdr
+# define Elf_Rela       Elf32_Rela
+# define Elf_Rel        Elf32_Rel
+# define Elf_Word       Elf32_Word
+# define Elf_Half       Elf32_Half
+# define Elf_Section    Elf32_Section
+# define ELF_R_SYM(val)		ELF32_R_SYM(val)
+# define ELF_R_TYPE(val)		ELF32_R_TYPE(val)
+# define ELF_ST_TYPE(val)		ELF32_ST_TYPE(val)
+#define XEN_NOTE_SIZE 132
+
+#include "grub-mkimagexx.c"
diff --git a/util/grub-mkimage64.c b/util/grub-mkimage64.c
new file mode 100644
index 0000000..d833459
--- /dev/null
+++ b/util/grub-mkimage64.c
@@ -0,0 +1,22 @@
+#define MKIMAGE_ELF64 1
+
+# define SUFFIX(x)	x ## 64
+# define ELFCLASSXX	ELFCLASS64
+# define Elf_Ehdr	Elf64_Ehdr
+# define Elf_Phdr	Elf64_Phdr
+# define Elf_Nhdr	Elf64_Nhdr
+# define Elf_Addr	Elf64_Addr
+# define Elf_Sym	Elf64_Sym
+# define Elf_Off	Elf64_Off
+# define Elf_Shdr	Elf64_Shdr
+# define Elf_Rela       Elf64_Rela
+# define Elf_Rel        Elf64_Rel
+# define Elf_Word       Elf64_Word
+# define Elf_Half       Elf64_Half
+# define Elf_Section    Elf64_Section
+# define ELF_R_SYM(val)		ELF64_R_SYM(val)
+# define ELF_R_TYPE(val)		ELF64_R_TYPE(val)
+# define ELF_ST_TYPE(val)		ELF64_ST_TYPE(val)
+#define XEN_NOTE_SIZE 120
+
+#include "grub-mkimagexx.c"
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
index 06b6a72..03874be 100644
--- a/util/grub-mkimagexx.c
+++ b/util/grub-mkimagexx.c
@@ -17,58 +17,172 @@
  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#undef ELF_R_SYM
-#undef ELF_R_TYPE
-
-#if defined(MKIMAGE_ELF32)
-# define SUFFIX(x)	x ## 32
-# define ELFCLASSXX	ELFCLASS32
-# define Elf_Ehdr	Elf32_Ehdr
-# define Elf_Phdr	Elf32_Phdr
-# define Elf_Nhdr	Elf32_Nhdr
-# define Elf_Addr	Elf32_Addr
-# define Elf_Sym	Elf32_Sym
-# define Elf_Off	Elf32_Off
-# define Elf_Shdr	Elf32_Shdr
-# define Elf_Rela       Elf32_Rela
-# define Elf_Rel        Elf32_Rel
-# define Elf_Word       Elf32_Word
-# define Elf_Half       Elf32_Half
-# define Elf_Section    Elf32_Section
-# define ELF_R_SYM(val)		ELF32_R_SYM(val)
-# define ELF_R_TYPE(val)		ELF32_R_TYPE(val)
-# define ELF_ST_TYPE(val)		ELF32_ST_TYPE(val)
-#define XEN_NOTE_SIZE 132
-#elif defined(MKIMAGE_ELF64)
-# define SUFFIX(x)	x ## 64
-# define ELFCLASSXX	ELFCLASS64
-# define Elf_Ehdr	Elf64_Ehdr
-# define Elf_Phdr	Elf64_Phdr
-# define Elf_Nhdr	Elf64_Nhdr
-# define Elf_Addr	Elf64_Addr
-# define Elf_Sym	Elf64_Sym
-# define Elf_Off	Elf64_Off
-# define Elf_Shdr	Elf64_Shdr
-# define Elf_Rela       Elf64_Rela
-# define Elf_Rel        Elf64_Rel
-# define Elf_Word       Elf64_Word
-# define Elf_Half       Elf64_Half
-# define Elf_Section    Elf64_Section
-# define ELF_R_SYM(val)		ELF64_R_SYM(val)
-# define ELF_R_TYPE(val)		ELF64_R_TYPE(val)
-# define ELF_ST_TYPE(val)		ELF64_ST_TYPE(val)
-#define XEN_NOTE_SIZE 120
-#else
-#error "I'm confused"
-#endif
+#include <config.h>
+#include <grub/types.h>
+#include <grub/elf.h>
+#include <grub/aout.h>
+#include <grub/i18n.h>
+#include <grub/kernel.h>
+#include <grub/disk.h>
+#include <grub/emu/misc.h>
+#include <grub/util/misc.h>
+#include <grub/util/resolve.h>
+#include <grub/misc.h>
+#include <grub/offsets.h>
+#include <grub/crypto.h>
+#include <grub/dl.h>
+#include <time.h>
+#include <multiboot.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <grub/efi/pe32.h>
+#include <grub/uboot/image.h>
+#include <grub/arm/reloc.h>
+#include <grub/arm64/reloc.h>
+#include <grub/ia64/reloc.h>
+#include <grub/osdep/hostfile.h>
+#include <grub/util/install.h>
+#include <grub/util/mkimage.h>
+
+#pragma GCC diagnostic ignored "-Wcast-align"
 
 static Elf_Addr SUFFIX (entry_point);
 
-static void
-SUFFIX (generate_elf) (const struct grub_install_image_target_desc *image_target,
-		       int note, char **core_img, size_t *core_size,
-		       Elf_Addr target_addr, grub_size_t align,
-		       size_t kernel_size, size_t bss_size)
+/* These structures are defined according to the CHRP binding to IEEE1275,
+   "Client Program Format" section.  */
+
+struct grub_ieee1275_note_desc
+{
+  grub_uint32_t real_mode;
+  grub_uint32_t real_base;
+  grub_uint32_t real_size;
+  grub_uint32_t virt_base;
+  grub_uint32_t virt_size;
+  grub_uint32_t load_base;
+};
+
+#define GRUB_IEEE1275_NOTE_NAME "PowerPC"
+#define GRUB_IEEE1275_NOTE_TYPE 0x1275
+
+struct grub_ieee1275_note
+{
+  Elf32_Nhdr header;
+  char name[ALIGN_UP(sizeof (GRUB_IEEE1275_NOTE_NAME), 4)];
+  struct grub_ieee1275_note_desc descriptor;
+};
+
+#define GRUB_XEN_NOTE_NAME "Xen"
+
+struct fixup_block_list
+{
+  struct fixup_block_list *next;
+  int state;
+  struct grub_pe32_fixup_block b;
+};
+
+#define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof))
+
+#ifdef MKIMAGE_ELF32
+
+/*
+ * R_ARM_THM_CALL/THM_JUMP24
+ *
+ * Relocate Thumb (T32) instruction set relative branches:
+ *   B.W, BL and BLX
+ */
+static grub_err_t
+grub_arm_reloc_thm_call (grub_uint16_t *target, Elf32_Addr sym_addr)
+{
+  grub_int32_t offset;
+
+  offset = grub_arm_thm_call_get_offset (target);
+
+  grub_dprintf ("dl", "    sym_addr = 0x%08x", sym_addr);
+
+  offset += sym_addr;
+
+  grub_dprintf("dl", " BL*: target=%p, sym_addr=0x%08x, offset=%d\n",
+	       target, sym_addr, offset);
+
+  /* Keep traditional (pre-Thumb2) limits on blx. In any case if the kernel
+     is bigger than 2M  (currently under 150K) then we probably have a problem
+     somewhere else.  */
+  if (offset < -0x200000 || offset >= 0x200000)
+    return grub_error (GRUB_ERR_BAD_MODULE,
+		       "THM_CALL Relocation out of range.");
+
+  grub_dprintf ("dl", "    relative destination = %p",
+		(char *) target + offset);
+
+  return grub_arm_thm_call_set_offset (target, offset);
+}
+
+/*
+ * R_ARM_THM_JUMP19
+ *
+ * Relocate conditional Thumb (T32) B<c>.W
+ */
+static grub_err_t
+grub_arm_reloc_thm_jump19 (grub_uint16_t *target, Elf32_Addr sym_addr)
+{
+  grub_int32_t offset;
+
+  if (!(sym_addr & 1))
+    return grub_error (GRUB_ERR_BAD_MODULE,
+		       "Relocation targeting wrong execution state");
+
+  offset = grub_arm_thm_jump19_get_offset (target);
+
+  /* Adjust and re-truncate offset */
+  offset += sym_addr;
+
+  if (!grub_arm_thm_jump19_check_offset (offset))
+    return grub_error (GRUB_ERR_BAD_MODULE,
+		       "THM_JUMP19 Relocation out of range.");
+
+  grub_arm_thm_jump19_set_offset (target, offset);
+
+  return GRUB_ERR_NONE;
+}
+
+/*
+ * R_ARM_JUMP24
+ *
+ * Relocate ARM (A32) B
+ */
+static grub_err_t
+grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr)
+{
+  grub_int32_t offset;
+
+  if (sym_addr & 1)
+    return grub_error (GRUB_ERR_BAD_MODULE,
+		       "Relocation targeting wrong execution state");
+
+  offset = grub_arm_jump24_get_offset (target);
+  offset += sym_addr;
+
+  if (!grub_arm_jump24_check_offset (offset))
+    return grub_error (GRUB_ERR_BAD_MODULE,
+		       "JUMP24 Relocation out of range.");
+
+
+  grub_arm_jump24_set_offset (target, offset);
+
+  return GRUB_ERR_NONE;
+}
+
+#endif
+
+void
+SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc *image_target,
+				    int note, char **core_img, size_t *core_size,
+				    Elf_Addr target_addr, grub_size_t align,
+				    size_t kernel_size, size_t bss_size)
 {
   char *elf_img;
   size_t program_size;
@@ -1457,13 +1571,13 @@ SUFFIX (locate_sections) (const char *kernel_path,
   return section_addresses;
 }
 
-static char *
-SUFFIX (load_image) (const char *kernel_path, size_t *exec_size, 
-		     size_t *kernel_sz, size_t *bss_size,
-		     size_t total_module_size, grub_uint64_t *start,
-		     void **reloc_section, size_t *reloc_size,
-		     size_t *align,
-		     const struct grub_install_image_target_desc *image_target)
+char *
+SUFFIX (grub_mkimage_load_image) (const char *kernel_path, size_t *exec_size, 
+				  size_t *kernel_sz, size_t *bss_size,
+				  size_t total_module_size, grub_uint64_t *start,
+				  void **reloc_section, size_t *reloc_size,
+				  size_t *align,
+				  const struct grub_install_image_target_desc *image_target)
 {
   char *kernel_img, *out_img;
   const char *strtab;
@@ -1671,23 +1785,3 @@ SUFFIX (load_image) (const char *kernel_path, size_t *exec_size,
 
   return out_img;
 }
-
-
-#undef SUFFIX
-#undef ELFCLASSXX
-#undef Elf_Ehdr
-#undef Elf_Phdr
-#undef Elf_Nhdr
-#undef Elf_Shdr
-#undef Elf_Addr
-#undef Elf_Sym
-#undef Elf_Off
-#undef Elf_Rela
-#undef Elf_Rel
-#undef ELF_R_TYPE
-#undef ELF_R_SYM
-#undef Elf_Word
-#undef Elf_Half
-#undef Elf_Section
-#undef ELF_ST_TYPE
-#undef XEN_NOTE_SIZE
diff --git a/util/mkimage.c b/util/mkimage.c
index c3365bb..678b221 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -46,6 +46,7 @@
 #include <grub/ia64/reloc.h>
 #include <grub/osdep/hostfile.h>
 #include <grub/util/install.h>
+#include <grub/util/mkimage.h>
 
 #define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof))
 
@@ -58,40 +59,6 @@
 /* use 2015-01-01T00:00:00+0000 as a stock timestamp */
 #define STABLE_EMBEDDING_TIMESTAMP 1420070400
 
-struct grub_install_image_target_desc
-{
-  const char *dirname;
-  const char *names[6];
-  grub_size_t voidp_sizeof;
-  int bigendian;
-  enum {
-    IMAGE_I386_PC, IMAGE_EFI, IMAGE_COREBOOT,
-    IMAGE_SPARC64_AOUT, IMAGE_SPARC64_RAW, IMAGE_SPARC64_CDCORE,
-    IMAGE_I386_IEEE1275,
-    IMAGE_LOONGSON_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH,
-    IMAGE_FULOONG2F_FLASH, IMAGE_I386_PC_PXE, IMAGE_MIPS_ARC,
-    IMAGE_QEMU_MIPS_FLASH, IMAGE_UBOOT, IMAGE_XEN, IMAGE_I386_PC_ELTORITO
-  } id;
-  enum
-    {
-      PLATFORM_FLAGS_NONE = 0,
-      PLATFORM_FLAGS_DECOMPRESSORS = 2,
-      PLATFORM_FLAGS_MODULES_BEFORE_KERNEL = 4,
-    } flags;
-  unsigned total_module_size;
-  unsigned decompressor_compressed_size;
-  unsigned decompressor_uncompressed_size;
-  unsigned decompressor_uncompressed_addr;
-  unsigned link_align;
-  grub_uint16_t elf_target;
-  unsigned section_align;
-  signed vaddr_offset;
-  grub_uint64_t link_addr;
-  unsigned mod_gap, mod_align;
-  grub_compression_t default_compression;
-  grub_uint16_t pe_target;
-};
-
 #define EFI32_HEADER_SIZE ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE		\
 				    + GRUB_PE32_SIGNATURE_SIZE		\
 				    + sizeof (struct grub_pe32_coff_header) \
@@ -603,119 +570,6 @@ static const struct grub_install_image_target_desc image_targets[] =
     },
   };
 
-#define grub_target_to_host32(x) (grub_target_to_host32_real (image_target, (x)))
-#define grub_host_to_target32(x) (grub_host_to_target32_real (image_target, (x)))
-#define grub_target_to_host64(x) (grub_target_to_host64_real (image_target, (x)))
-#define grub_host_to_target64(x) (grub_host_to_target64_real (image_target, (x)))
-#define grub_host_to_target_addr(x) (grub_host_to_target_addr_real (image_target, (x)))
-#define grub_target_to_host16(x) (grub_target_to_host16_real (image_target, (x)))
-#define grub_host_to_target16(x) (grub_host_to_target16_real (image_target, (x)))
-
-static inline grub_uint32_t
-grub_target_to_host32_real (const struct grub_install_image_target_desc *image_target,
-			    grub_uint32_t in)
-{
-  if (image_target->bigendian)
-    return grub_be_to_cpu32 (in);
-  else
-    return grub_le_to_cpu32 (in);
-}
-
-static inline grub_uint64_t
-grub_target_to_host64_real (const struct grub_install_image_target_desc *image_target,
-			    grub_uint64_t in)
-{
-  if (image_target->bigendian)
-    return grub_be_to_cpu64 (in);
-  else
-    return grub_le_to_cpu64 (in);
-}
-
-static inline grub_uint64_t
-grub_host_to_target64_real (const struct grub_install_image_target_desc *image_target,
-			    grub_uint64_t in)
-{
-  if (image_target->bigendian)
-    return grub_cpu_to_be64 (in);
-  else
-    return grub_cpu_to_le64 (in);
-}
-
-static inline grub_uint32_t
-grub_host_to_target32_real (const struct grub_install_image_target_desc *image_target,
-			    grub_uint32_t in)
-{
-  if (image_target->bigendian)
-    return grub_cpu_to_be32 (in);
-  else
-    return grub_cpu_to_le32 (in);
-}
-
-static inline grub_uint16_t
-grub_target_to_host16_real (const struct grub_install_image_target_desc *image_target,
-			    grub_uint16_t in)
-{
-  if (image_target->bigendian)
-    return grub_be_to_cpu16 (in);
-  else
-    return grub_le_to_cpu16 (in);
-}
-
-static inline grub_uint16_t
-grub_host_to_target16_real (const struct grub_install_image_target_desc *image_target,
-			    grub_uint16_t in)
-{
-  if (image_target->bigendian)
-    return grub_cpu_to_be16 (in);
-  else
-    return grub_cpu_to_le16 (in);
-}
-
-static inline grub_uint64_t
-grub_host_to_target_addr_real (const struct grub_install_image_target_desc *image_target, grub_uint64_t in)
-{
-  if (image_target->voidp_sizeof == 8)
-    return grub_host_to_target64_real (image_target, in);
-  else
-    return grub_host_to_target32_real (image_target, in);
-}
-
-static inline grub_uint64_t
-grub_target_to_host_real (const struct grub_install_image_target_desc *image_target, grub_uint64_t in)
-{
-  if (image_target->voidp_sizeof == 8)
-    return grub_target_to_host64_real (image_target, in);
-  else
-    return grub_target_to_host32_real (image_target, in);
-}
-
-#define GRUB_IEEE1275_NOTE_NAME "PowerPC"
-#define GRUB_IEEE1275_NOTE_TYPE 0x1275
-
-/* These structures are defined according to the CHRP binding to IEEE1275,
-   "Client Program Format" section.  */
-
-struct grub_ieee1275_note_desc
-{
-  grub_uint32_t real_mode;
-  grub_uint32_t real_base;
-  grub_uint32_t real_size;
-  grub_uint32_t virt_base;
-  grub_uint32_t virt_size;
-  grub_uint32_t load_base;
-};
-
-struct grub_ieee1275_note
-{
-  Elf32_Nhdr header;
-  char name[ALIGN_UP(sizeof (GRUB_IEEE1275_NOTE_NAME), 4)];
-  struct grub_ieee1275_note_desc descriptor;
-};
-
-#define GRUB_XEN_NOTE_NAME "Xen"
-
-#define grub_target_to_host(val) grub_target_to_host_real(image_target, (val))
-
 #include <grub/lib/LzmaEnc.h>
 
 static void *SzAlloc(void *p __attribute__ ((unused)), size_t size) { return xmalloc(size); }
@@ -830,111 +684,6 @@ compress_kernel (const struct grub_install_image_target_desc *image_target, char
   *core_size = kernel_size;
 }
 
-struct fixup_block_list
-{
-  struct fixup_block_list *next;
-  int state;
-  struct grub_pe32_fixup_block b;
-};
-
-/*
- * R_ARM_THM_CALL/THM_JUMP24
- *
- * Relocate Thumb (T32) instruction set relative branches:
- *   B.W, BL and BLX
- */
-static grub_err_t
-grub_arm_reloc_thm_call (grub_uint16_t *target, Elf32_Addr sym_addr)
-{
-  grub_int32_t offset;
-
-  offset = grub_arm_thm_call_get_offset (target);
-
-  grub_dprintf ("dl", "    sym_addr = 0x%08x", sym_addr);
-
-  offset += sym_addr;
-
-  grub_dprintf("dl", " BL*: target=%p, sym_addr=0x%08x, offset=%d\n",
-	       target, sym_addr, offset);
-
-  /* Keep traditional (pre-Thumb2) limits on blx. In any case if the kernel
-     is bigger than 2M  (currently under 150K) then we probably have a problem
-     somewhere else.  */
-  if (offset < -0x200000 || offset >= 0x200000)
-    return grub_error (GRUB_ERR_BAD_MODULE,
-		       "THM_CALL Relocation out of range.");
-
-  grub_dprintf ("dl", "    relative destination = %p",
-		(char *) target + offset);
-
-  return grub_arm_thm_call_set_offset (target, offset);
-}
-
-/*
- * R_ARM_THM_JUMP19
- *
- * Relocate conditional Thumb (T32) B<c>.W
- */
-static grub_err_t
-grub_arm_reloc_thm_jump19 (grub_uint16_t *target, Elf32_Addr sym_addr)
-{
-  grub_int32_t offset;
-
-  if (!(sym_addr & 1))
-    return grub_error (GRUB_ERR_BAD_MODULE,
-		       "Relocation targeting wrong execution state");
-
-  offset = grub_arm_thm_jump19_get_offset (target);
-
-  /* Adjust and re-truncate offset */
-  offset += sym_addr;
-
-  if (!grub_arm_thm_jump19_check_offset (offset))
-    return grub_error (GRUB_ERR_BAD_MODULE,
-		       "THM_JUMP19 Relocation out of range.");
-
-  grub_arm_thm_jump19_set_offset (target, offset);
-
-  return GRUB_ERR_NONE;
-}
-
-/*
- * R_ARM_JUMP24
- *
- * Relocate ARM (A32) B
- */
-static grub_err_t
-grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr)
-{
-  grub_int32_t offset;
-
-  if (sym_addr & 1)
-    return grub_error (GRUB_ERR_BAD_MODULE,
-		       "Relocation targeting wrong execution state");
-
-  offset = grub_arm_jump24_get_offset (target);
-  offset += sym_addr;
-
-  if (!grub_arm_jump24_check_offset (offset))
-    return grub_error (GRUB_ERR_BAD_MODULE,
-		       "JUMP24 Relocation out of range.");
-
-
-  grub_arm_jump24_set_offset (target, offset);
-
-  return GRUB_ERR_NONE;
-}
-
-#pragma GCC diagnostic ignored "-Wcast-align"
-
-#define MKIMAGE_ELF32 1
-#include "grub-mkimagexx.c"
-#undef MKIMAGE_ELF32
-
-#define MKIMAGE_ELF64 1
-#include "grub-mkimagexx.c"
-#undef MKIMAGE_ELF64
-
 const struct grub_install_image_target_desc *
 grub_install_get_image_target (const char *arg)
 {
@@ -1063,13 +812,13 @@ grub_install_generate_image (const char *dir, const char *prefix,
 		  (unsigned long long) total_module_size);
 
   if (image_target->voidp_sizeof == 4)
-    kernel_img = load_image32 (kernel_path, &exec_size, &kernel_size, &bss_size,
-			       total_module_size, &start_address, &rel_section,
-			       &reloc_size, &align, image_target);
+    kernel_img = grub_mkimage_load_image32 (kernel_path, &exec_size, &kernel_size, &bss_size,
+					    total_module_size, &start_address, &rel_section,
+					    &reloc_size, &align, image_target);
   else
-    kernel_img = load_image64 (kernel_path, &exec_size, &kernel_size, &bss_size,
-			       total_module_size, &start_address, &rel_section,
-			       &reloc_size, &align, image_target);
+    kernel_img = grub_mkimage_load_image64 (kernel_path, &exec_size, &kernel_size, &bss_size,
+					    total_module_size, &start_address, &rel_section,
+					    &reloc_size, &align, image_target);
   if (image_target->id == IMAGE_XEN && align < 4096)
     align = 4096;
 
@@ -1890,11 +1639,11 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	else
 	  target_addr = image_target->link_addr;
 	if (image_target->voidp_sizeof == 4)
-	  generate_elf32 (image_target, note, &core_img, &core_size,
-			  target_addr, align, kernel_size, bss_size);
+	  grub_mkimage_generate_elf32 (image_target, note, &core_img, &core_size,
+				       target_addr, align, kernel_size, bss_size);
 	else
-	  generate_elf64 (image_target, note, &core_img, &core_size,
-			  target_addr, align, kernel_size, bss_size);
+	  grub_mkimage_generate_elf64 (image_target, note, &core_img, &core_size,
+				       target_addr, align, kernel_size, bss_size);
       }
       break;
     }
-- 
2.7.0


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.3: 0002-mkimagexx-Split-PE-and-generic-part-for-relocations.patch --]
[-- Type: text/x-diff; name="0002-mkimagexx-Split-PE-and-generic-part-for-relocations.patch", Size: 14009 bytes --]

From 88091fb936a45f8dece352c5bec26e011f9573c3 Mon Sep 17 00:00:00 2001
From: Vladimir Serbinenko <phcoder@gmail.com>
Date: Thu, 18 Feb 2016 20:54:37 +0100
Subject: [PATCH 2/6] mkimagexx: Split PE and generic part for relocations.

As a preparation for U-Boot relocations, split emitting PE-relocations
from parsing source ELF-relocations.
---
 util/grub-mkimagexx.c | 415 ++++++++++++++++++++++++++------------------------
 1 file changed, 219 insertions(+), 196 deletions(-)

diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
index 03874be..a39803a 100644
--- a/util/grub-mkimagexx.c
+++ b/util/grub-mkimagexx.c
@@ -1095,9 +1095,9 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
 /* Add a PE32's fixup entry for a relocation. Return the resulting address
    after having written to the file OUT.  */
 static Elf_Addr
-SUFFIX (add_fixup_entry) (struct fixup_block_list **cblock, grub_uint16_t type,
-			  Elf_Addr addr, int flush, Elf_Addr current_address,
-			  const struct grub_install_image_target_desc *image_target)
+add_fixup_entry (struct fixup_block_list **cblock, grub_uint16_t type,
+		 Elf_Addr addr, int flush, Elf_Addr current_address,
+		 const struct grub_install_image_target_desc *image_target)
 {
   struct grub_pe32_fixup_block *b;
 
@@ -1187,22 +1187,222 @@ SUFFIX (add_fixup_entry) (struct fixup_block_list **cblock, grub_uint16_t type,
   return current_address;
 }
 
+struct translate_context
+{
+  struct fixup_block_list *lst, *lst0;
+  Elf_Addr current_address;
+};
+
+static void
+translate_reloc_start (struct translate_context *ctx)
+{
+  ctx->lst = ctx->lst0 = xmalloc (sizeof (*ctx->lst) + 2 * 0x1000);
+  memset (ctx->lst, 0, sizeof (*ctx->lst) + 2 * 0x1000);
+  ctx->current_address = 0;
+}
+
+static void
+translate_relocation (struct translate_context *ctx,
+		      Elf_Addr addr,
+		      Elf_Addr info,
+		      const struct grub_install_image_target_desc *image_target)
+{
+  /* Necessary to relocate only absolute addresses.  */
+  switch (image_target->elf_target)
+    {
+    case EM_386:
+      if (ELF_R_TYPE (info) == R_386_32)
+	{
+	  grub_util_info ("adding a relocation entry for 0x%"
+			  GRUB_HOST_PRIxLONG_LONG,
+			  (unsigned long long) addr);
+	  ctx->current_address
+	    = add_fixup_entry (&ctx->lst,
+			       GRUB_PE32_REL_BASED_HIGHLOW,
+			       addr, 0, ctx->current_address,
+			       image_target);
+	}
+      break;
+    case EM_X86_64:
+      if ((ELF_R_TYPE (info) == R_X86_64_32) ||
+	  (ELF_R_TYPE (info) == R_X86_64_32S))
+	{
+	  grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)");
+	}
+      else if (ELF_R_TYPE (info) == R_X86_64_64)
+	{
+	  grub_util_info ("adding a relocation entry for 0x%"
+			  GRUB_HOST_PRIxLONG_LONG,
+			  (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))
+	{
+	case R_IA64_PCREL64LSB:
+	case R_IA64_LDXMOV:
+	case R_IA64_PCREL21B:
+	case R_IA64_LTOFF_FPTR22:
+	case R_IA64_LTOFF22X:
+	case R_IA64_LTOFF22:
+	case R_IA64_GPREL22:
+	case R_IA64_SEGREL64LSB:
+	  break;
+
+	case R_IA64_FPTR64LSB:
+	case R_IA64_DIR64LSB:
+#if 1
+	  {
+	    grub_util_info ("adding a relocation entry for 0x%"
+			    GRUB_HOST_PRIxLONG_LONG,
+			    (unsigned long long) addr);
+	    ctx->current_address
+	      = add_fixup_entry (&ctx->lst,
+				 GRUB_PE32_REL_BASED_DIR64,
+				 addr,
+				 0, ctx->current_address,
+				 image_target);
+	  }
+#endif
+	  break;
+	default:
+	  grub_util_error (_("relocation 0x%x is not implemented yet"),
+			   (unsigned int) ELF_R_TYPE (info));
+	  break;
+	}
+      break;
+    case EM_AARCH64:
+      switch (ELF_R_TYPE (info))
+	{
+	case R_AARCH64_ABS64:
+	  {
+	    ctx->current_address
+	      = add_fixup_entry (&ctx->lst,
+				 GRUB_PE32_REL_BASED_DIR64,
+				 addr, 0, ctx->current_address,
+				 image_target);
+	  }
+	  break;
+	  /* Relative relocations do not require fixup entries. */
+	case R_AARCH64_CALL26:
+	case R_AARCH64_JUMP26:
+	  break;
+	  /* Page-relative relocations do not require fixup entries. */
+	case R_AARCH64_ADR_PREL_PG_HI21:
+	  /* We page-align the whole kernel, so no need
+	     for fixup entries.
+	  */
+	case R_AARCH64_ADD_ABS_LO12_NC:
+	case R_AARCH64_LDST64_ABS_LO12_NC:
+	  break;
+
+	default:
+	  grub_util_error (_("relocation 0x%x is not implemented yet"),
+			   (unsigned int) ELF_R_TYPE (info));
+	  break;
+	}
+      break;
+      break;
+#if defined(MKIMAGE_ELF32)
+    case EM_ARM:
+      switch (ELF_R_TYPE (info))
+	{
+	case R_ARM_V4BX:
+	  /* Relative relocations do not require fixup entries. */
+	case R_ARM_JUMP24:
+	case R_ARM_THM_CALL:
+	case R_ARM_THM_JUMP19:
+	case R_ARM_THM_JUMP24:
+	case R_ARM_CALL:
+	  {
+	    grub_util_info ("  %s:  not adding fixup: 0x%08x : 0x%08x", __FUNCTION__, (unsigned int) addr, (unsigned int) ctx->current_address);
+	  }
+	  break;
+	  /* Create fixup entry for PE/COFF loader */
+	case R_ARM_ABS32:
+	  {
+	    ctx->current_address
+	      = add_fixup_entry (&ctx->lst,
+				 GRUB_PE32_REL_BASED_HIGHLOW,
+				 addr, 0, ctx->current_address,
+				 image_target);
+	  }
+	  break;
+	default:
+	  grub_util_error (_("relocation 0x%x is not implemented yet"),
+			   (unsigned int) ELF_R_TYPE (info));
+	  break;
+	}
+      break;
+#endif /* defined(MKIMAGE_ELF32) */
+    default:
+      grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
+    }
+}
+
+static Elf_Addr
+finish_reloc_translation (struct translate_context *ctx, void **out,
+			  const struct grub_install_image_target_desc *image_target)
+{
+  ctx->current_address = add_fixup_entry (&ctx->lst, 0, 0, 1, ctx->current_address, image_target);
+
+  {
+    grub_uint8_t *ptr;
+    ptr = *out = xmalloc (ctx->current_address);
+    for (ctx->lst = ctx->lst0; ctx->lst; ctx->lst = ctx->lst->next)
+      if (ctx->lst->state)
+	{
+	  memcpy (ptr, &ctx->lst->b, grub_target_to_host32 (ctx->lst->b.block_size));
+	  ptr += grub_target_to_host32 (ctx->lst->b.block_size);
+	}
+    assert ((ctx->current_address + (grub_uint8_t *) *out) == ptr);
+  }
+
+  for (ctx->lst = ctx->lst0; ctx->lst; )
+    {
+      struct fixup_block_list *next;
+      next = ctx->lst->next;
+      free (ctx->lst);
+      ctx->lst = next;
+    }
+
+  return ctx->current_address;
+}
+
+static void
+translate_reloc_jumpers (struct translate_context *ctx,
+			 Elf_Addr jumpers, grub_size_t njumpers,
+			 const struct grub_install_image_target_desc *image_target)
+{
+  unsigned i;
+  for (i = 0; i < njumpers; i++)
+    ctx->current_address = add_fixup_entry (&ctx->lst,
+					    GRUB_PE32_REL_BASED_DIR64,
+					    jumpers + 8 * i,
+					    0, ctx->current_address,
+					    image_target);
+}
+
 /* Make a .reloc section.  */
 static Elf_Addr
-SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out,
-			     Elf_Addr *section_addresses, Elf_Shdr *sections,
-			     Elf_Half section_entsize, Elf_Half num_sections,
-			     const char *strtab,
-			     Elf_Addr jumpers, grub_size_t njumpers,
-			     const struct grub_install_image_target_desc *image_target)
+make_reloc_section (Elf_Ehdr *e, void **out,
+		    Elf_Addr *section_addresses, Elf_Shdr *sections,
+		    Elf_Half section_entsize, Elf_Half num_sections,
+		    const char *strtab,
+		    Elf_Addr jumpers, grub_size_t njumpers,
+		    const struct grub_install_image_target_desc *image_target)
 {
   unsigned i;
   Elf_Shdr *s;
-  struct fixup_block_list *lst, *lst0;
-  Elf_Addr current_address = 0;
+  struct translate_context ctx;
 
-  lst = lst0 = xmalloc (sizeof (*lst) + 2 * 0x1000);
-  memset (lst, 0, sizeof (*lst) + 2 * 0x1000);
+  translate_reloc_start (&ctx);
 
   for (i = 0, s = sections; i < num_sections;
        i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
@@ -1231,199 +1431,22 @@ SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out,
 	  {
 	    Elf_Addr info;
 	    Elf_Addr offset;
+	    Elf_Addr addr;
 
 	    offset = grub_target_to_host (r->r_offset);
 	    info = grub_target_to_host (r->r_info);
 
-	    /* Necessary to relocate only absolute addresses.  */
-	    switch (image_target->elf_target)
-	      {
-	      case EM_386:
-		if (ELF_R_TYPE (info) == R_386_32)
-		  {
-		    Elf_Addr addr;
+	    addr = section_address + offset;
 
-		    addr = section_address + offset;
-		    grub_util_info ("adding a relocation entry for 0x%"
-				    GRUB_HOST_PRIxLONG_LONG,
-				    (unsigned long long) addr);
-		    current_address
-		      = SUFFIX (add_fixup_entry) (&lst,
-						  GRUB_PE32_REL_BASED_HIGHLOW,
-						  addr, 0, current_address,
-						  image_target);
-		  }
-		break;
-	      case EM_X86_64:
-		if ((ELF_R_TYPE (info) == R_X86_64_32) ||
-		    (ELF_R_TYPE (info) == R_X86_64_32S))
-		  {
-		    grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)");
-		  }
-		else if (ELF_R_TYPE (info) == R_X86_64_64)
-		  {
-		    Elf_Addr addr;
-
-		    addr = section_address + offset;
-		    grub_util_info ("adding a relocation entry for 0x%"
-				    GRUB_HOST_PRIxLONG_LONG,
-				    (unsigned long long) addr);
-		    current_address
-		      = SUFFIX (add_fixup_entry) (&lst,
-						  GRUB_PE32_REL_BASED_DIR64,
-						  addr,
-						  0, current_address,
-						  image_target);
-		  }
-		break;
-	      case EM_IA_64:
-	      switch (ELF_R_TYPE (info))
-		{
-		case R_IA64_PCREL64LSB:
-		case R_IA64_LDXMOV:
-		case R_IA64_PCREL21B:
-		case R_IA64_LTOFF_FPTR22:
-		case R_IA64_LTOFF22X:
-		case R_IA64_LTOFF22:
-		case R_IA64_GPREL22:
-		case R_IA64_SEGREL64LSB:
-		  break;
-
-		case R_IA64_FPTR64LSB:
-		case R_IA64_DIR64LSB:
-#if 1
-		  {
-		    Elf_Addr addr;
-
-		    addr = section_address + offset;
-		    grub_util_info ("adding a relocation entry for 0x%"
-				    GRUB_HOST_PRIxLONG_LONG,
-				    (unsigned long long) addr);
-		    current_address
-		      = SUFFIX (add_fixup_entry) (&lst,
-						  GRUB_PE32_REL_BASED_DIR64,
-						  addr,
-						  0, current_address,
-						  image_target);
-		  }
-#endif
-		  break;
-		default:
-		  grub_util_error (_("relocation 0x%x is not implemented yet"),
-				   (unsigned int) ELF_R_TYPE (info));
-		  break;
-		}
-		break;
-	      case EM_AARCH64:
-		switch (ELF_R_TYPE (info))
-		  {
-		  case R_AARCH64_ABS64:
-		    {
-		      Elf_Addr addr;
-
-		      addr = section_address + offset;
-		      current_address
-			= SUFFIX (add_fixup_entry) (&lst,
-						    GRUB_PE32_REL_BASED_DIR64,
-						    addr, 0, current_address,
-						    image_target);
-		    }
-		    break;
-		    /* Relative relocations do not require fixup entries. */
-		  case R_AARCH64_CALL26:
-		  case R_AARCH64_JUMP26:
-		    break;
-		    /* Page-relative relocations do not require fixup entries. */
-		  case R_AARCH64_ADR_PREL_PG_HI21:
-		     /* We page-align the whole kernel, so no need
-			for fixup entries.
-		      */
-		  case R_AARCH64_ADD_ABS_LO12_NC:
-		  case R_AARCH64_LDST64_ABS_LO12_NC:
-		    break;
-
-		  default:
-		    grub_util_error (_("relocation 0x%x is not implemented yet"),
-				     (unsigned int) ELF_R_TYPE (info));
-		    break;
-		  }
-		break;
-		break;
-#if defined(MKIMAGE_ELF32)
-	      case EM_ARM:
-		switch (ELF_R_TYPE (info))
-		  {
-		  case R_ARM_V4BX:
-		    /* Relative relocations do not require fixup entries. */
-		  case R_ARM_JUMP24:
-		  case R_ARM_THM_CALL:
-		  case R_ARM_THM_JUMP19:
-		  case R_ARM_THM_JUMP24:
-		  case R_ARM_CALL:
-		    {
-		      Elf_Addr addr;
-
-		      addr = section_address + offset;
-		      grub_util_info ("  %s:  not adding fixup: 0x%08x : 0x%08x", __FUNCTION__, (unsigned int) addr, (unsigned int) current_address);
-		    }
-		    break;
-		    /* Create fixup entry for PE/COFF loader */
-		  case R_ARM_ABS32:
-		    {
-		      Elf_Addr addr;
-
-		      addr = section_address + offset;
-		      current_address
-			= SUFFIX (add_fixup_entry) (&lst,
-						    GRUB_PE32_REL_BASED_HIGHLOW,
-						    addr, 0, current_address,
-						    image_target);
-		    }
-		    break;
-		  default:
-		    grub_util_error (_("relocation 0x%x is not implemented yet"),
-				     (unsigned int) ELF_R_TYPE (info));
-		    break;
-		  }
-		break;
-#endif /* defined(MKIMAGE_ELF32) */
-	      default:
-		grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
-	      }
+	    translate_relocation (&ctx, addr, info, image_target);
 	  }
       }
 
   if (image_target->elf_target == EM_IA_64)
-    for (i = 0; i < njumpers; i++)
-      current_address = SUFFIX (add_fixup_entry) (&lst,
-						  GRUB_PE32_REL_BASED_DIR64,
-						  jumpers + 8 * i,
-						  0, current_address,
-						  image_target);
+    translate_reloc_jumpers (&ctx, jumpers, njumpers,
+			     image_target);
 
-  current_address = SUFFIX (add_fixup_entry) (&lst, 0, 0, 1, current_address, image_target);
-
-  {
-    grub_uint8_t *ptr;
-    ptr = *out = xmalloc (current_address);
-    for (lst = lst0; lst; lst = lst->next)
-      if (lst->state)
-	{
-	  memcpy (ptr, &lst->b, grub_target_to_host32 (lst->b.block_size));
-	  ptr += grub_target_to_host32 (lst->b.block_size);
-	}
-    assert ((current_address + (grub_uint8_t *) *out) == ptr);
-  }
-
-  for (lst = lst0; lst; )
-    {
-      struct fixup_block_list *next;
-      next = lst->next;
-      free (lst);
-      lst = next;
-    }
-
-  return current_address;
+  return finish_reloc_translation (&ctx, out, image_target);
 }
 
 /* Determine if this section is a text section. Return false if this
-- 
2.7.0


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.4: 0003-Encapsulate-image-layout-into-a-separate-structure.patch --]
[-- Type: text/x-diff; name="0003-Encapsulate-image-layout-into-a-separate-structure.patch", Size: 28377 bytes --]

From 7cfa8d4568b714b463e0ad4ac900017a538a5840 Mon Sep 17 00:00:00 2001
From: Vladimir Serbinenko <phcoder@gmail.com>
Date: Fri, 19 Feb 2016 01:49:53 +0100
Subject: [PATCH 3/6] Encapsulate image layout into a separate structure.

Currently we pass around a lot of pointer. Instead put all relevant data
into one structure.
---
 include/grub/util/mkimage.h |  32 ++++++++----
 util/grub-mkimagexx.c       | 116 ++++++++++++++++++++++----------------------
 util/mkimage.c              | 112 +++++++++++++++++++++---------------------
 3 files changed, 133 insertions(+), 127 deletions(-)

diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h
index 564adbc..8169939 100644
--- a/include/grub/util/mkimage.h
+++ b/include/grub/util/mkimage.h
@@ -19,20 +19,32 @@
 #ifndef GRUB_UTIL_MKIMAGE_HEADER
 #define GRUB_UTIL_MKIMAGE_HEADER	1
 
+struct grub_mkimage_layout
+{
+  size_t exec_size;
+  size_t kernel_size;
+  size_t bss_size;
+  grub_uint64_t start_address;
+  void *reloc_section;
+  size_t reloc_size;
+  size_t align;
+  grub_size_t ia64jmp_off;
+  grub_size_t tramp_off;
+  grub_size_t ia64_got_off;
+  grub_size_t got_size;
+  unsigned ia64jmpnum;
+};
+
 /* Private header. Use only in mkimage-related sources.  */
 char *
-grub_mkimage_load_image32 (const char *kernel_path, size_t *exec_size, 
-			   size_t *kernel_sz, size_t *bss_size,
-			   size_t total_module_size, grub_uint64_t *start,
-			   void **reloc_section, size_t *reloc_size,
-			   size_t *align,
+grub_mkimage_load_image32 (const char *kernel_path,
+			   size_t total_module_size,
+			   struct grub_mkimage_layout *layout,
 			   const struct grub_install_image_target_desc *image_target);
 char *
-grub_mkimage_load_image64 (const char *kernel_path, size_t *exec_size, 
-			   size_t *kernel_sz, size_t *bss_size,
-			   size_t total_module_size, grub_uint64_t *start,
-			   void **reloc_section, size_t *reloc_size,
-			   size_t *align,
+grub_mkimage_load_image64 (const char *kernel_path,
+			   size_t total_module_size,
+			   struct grub_mkimage_layout *layout,
 			   const struct grub_install_image_target_desc *image_target);
 void
 grub_mkimage_generate_elf32 (const struct grub_install_image_target_desc *image_target,
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
index a39803a..74f86f5 100644
--- a/util/grub-mkimagexx.c
+++ b/util/grub-mkimagexx.c
@@ -1346,22 +1346,23 @@ translate_relocation (struct translate_context *ctx,
     }
 }
 
-static Elf_Addr
-finish_reloc_translation (struct translate_context *ctx, void **out,
+static void
+finish_reloc_translation (struct translate_context *ctx,
+			  struct grub_mkimage_layout *layout,
 			  const struct grub_install_image_target_desc *image_target)
 {
   ctx->current_address = add_fixup_entry (&ctx->lst, 0, 0, 1, ctx->current_address, image_target);
 
   {
     grub_uint8_t *ptr;
-    ptr = *out = xmalloc (ctx->current_address);
+    layout->reloc_section = ptr = xmalloc (ctx->current_address);
     for (ctx->lst = ctx->lst0; ctx->lst; ctx->lst = ctx->lst->next)
       if (ctx->lst->state)
 	{
 	  memcpy (ptr, &ctx->lst->b, grub_target_to_host32 (ctx->lst->b.block_size));
 	  ptr += grub_target_to_host32 (ctx->lst->b.block_size);
 	}
-    assert ((ctx->current_address + (grub_uint8_t *) *out) == ptr);
+    assert ((ctx->current_address + (grub_uint8_t *) layout->reloc_section) == ptr);
   }
 
   for (ctx->lst = ctx->lst0; ctx->lst; )
@@ -1372,7 +1373,7 @@ finish_reloc_translation (struct translate_context *ctx, void **out,
       ctx->lst = next;
     }
 
-  return ctx->current_address;
+  layout->reloc_size = ctx->current_address;
 }
 
 static void
@@ -1390,8 +1391,8 @@ translate_reloc_jumpers (struct translate_context *ctx,
 }
 
 /* Make a .reloc section.  */
-static Elf_Addr
-make_reloc_section (Elf_Ehdr *e, void **out,
+static void
+make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout,
 		    Elf_Addr *section_addresses, Elf_Shdr *sections,
 		    Elf_Half section_entsize, Elf_Half num_sections,
 		    const char *strtab,
@@ -1446,7 +1447,7 @@ make_reloc_section (Elf_Ehdr *e, void **out,
     translate_reloc_jumpers (&ctx, jumpers, njumpers,
 			     image_target);
 
-  return finish_reloc_translation (&ctx, out, image_target);
+  finish_reloc_translation (&ctx, layout, image_target);
 }
 
 /* Determine if this section is a text section. Return false if this
@@ -1498,8 +1499,7 @@ static Elf_Addr *
 SUFFIX (locate_sections) (const char *kernel_path,
 			  Elf_Shdr *sections, Elf_Half section_entsize,
 			  Elf_Half num_sections, const char *strtab,
-			  size_t *exec_size, size_t *kernel_sz,
-			  size_t *all_align,
+			  struct grub_mkimage_layout *layout,
 			  const struct grub_install_image_target_desc *image_target)
 {
   int i;
@@ -1507,10 +1507,10 @@ SUFFIX (locate_sections) (const char *kernel_path,
   Elf_Addr *section_addresses;
   Elf_Shdr *s;
 
-  *all_align = 1;
+  layout->align = 1;
   /* Page-aligning simplifies relocation handling.  */
   if (image_target->elf_target == EM_AARCH64)
-    *all_align = 4096;
+    layout->align = 4096;
 
   section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
   memset (section_addresses, 0, sizeof (*section_addresses) * num_sections);
@@ -1521,8 +1521,8 @@ SUFFIX (locate_sections) (const char *kernel_path,
        i < num_sections;
        i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
     if ((grub_target_to_host (s->sh_flags) & SHF_ALLOC) 
-	&& grub_host_to_target32 (s->sh_addralign) > *all_align)
-      *all_align = grub_host_to_target32 (s->sh_addralign);
+	&& grub_host_to_target32 (s->sh_addralign) > layout->align)
+      layout->align = grub_host_to_target32 (s->sh_addralign);
 
 
   /* .text */
@@ -1562,7 +1562,7 @@ SUFFIX (locate_sections) (const char *kernel_path,
   current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
 			      image_target->section_align)
     - image_target->vaddr_offset;
-  *exec_size = current_address;
+  layout->exec_size = current_address;
 
   /* .data */
   for (i = 0, s = sections;
@@ -1590,16 +1590,14 @@ SUFFIX (locate_sections) (const char *kernel_path,
 
   current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
 			      image_target->section_align) - image_target->vaddr_offset;
-  *kernel_sz = current_address;
+  layout->kernel_size = current_address;
   return section_addresses;
 }
 
 char *
-SUFFIX (grub_mkimage_load_image) (const char *kernel_path, size_t *exec_size, 
-				  size_t *kernel_sz, size_t *bss_size,
-				  size_t total_module_size, grub_uint64_t *start,
-				  void **reloc_section, size_t *reloc_size,
-				  size_t *align,
+SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
+				  size_t total_module_size,
+				  struct grub_mkimage_layout *layout,
 				  const struct grub_install_image_target_desc *image_target)
 {
   char *kernel_img, *out_img;
@@ -1614,12 +1612,11 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path, size_t *exec_size,
   Elf_Off section_offset;
   Elf_Half section_entsize;
   grub_size_t kernel_size;
-  grub_size_t ia64jmp_off = 0, tramp_off = 0, ia64_got_off = 0;
-  unsigned ia64jmpnum = 0;
   Elf_Shdr *symtab_section = 0;
-  grub_size_t got = 0;
 
-  *start = 0;
+  grub_memset (layout, 0, sizeof (*layout));
+
+  layout->start_address = 0;
 
   kernel_size = grub_util_get_image_size (kernel_path);
   kernel_img = xmalloc (kernel_size);
@@ -1646,7 +1643,7 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path, size_t *exec_size,
   section_addresses = SUFFIX (locate_sections) (kernel_path,
 						sections, section_entsize,
 						num_sections, strtab,
-						exec_size, kernel_sz, align,
+						layout,
 						image_target);
 
   section_vaddresses = xmalloc (sizeof (*section_addresses) * num_sections);
@@ -1656,7 +1653,7 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path, size_t *exec_size,
 
   if (image_target->id != IMAGE_EFI)
     {
-      Elf_Addr current_address = *kernel_sz;
+      Elf_Addr current_address = layout->kernel_size;
 
       for (i = 0, s = sections;
 	   i < num_sections;
@@ -1686,15 +1683,15 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path, size_t *exec_size,
       current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
 				  image_target->section_align)
 	- image_target->vaddr_offset;
-      *bss_size = current_address - *kernel_sz;
+      layout->bss_size = current_address - layout->kernel_size;
     }
   else
-    *bss_size = 0;
+    layout->bss_size = 0;
 
   if (image_target->id == IMAGE_SPARC64_AOUT
       || image_target->id == IMAGE_SPARC64_RAW
       || image_target->id == IMAGE_SPARC64_CDCORE)
-    *kernel_sz = ALIGN_UP (*kernel_sz, image_target->mod_align);
+    layout->kernel_size = ALIGN_UP (layout->kernel_size, image_target->mod_align);
 
   if (image_target->id == IMAGE_EFI)
     {
@@ -1715,13 +1712,13 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path, size_t *exec_size,
 	{
 	  grub_size_t tramp;
 
-	  *kernel_sz = ALIGN_UP (*kernel_sz, 16);
+	  layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
 
 	  tramp = arm_get_trampoline_size (e, sections, section_entsize,
 					   num_sections, image_target);
 
-	  tramp_off = *kernel_sz;
-	  *kernel_sz += ALIGN_UP (tramp, 16);
+	  layout->tramp_off = layout->kernel_size;
+	  layout->kernel_size += ALIGN_UP (tramp, 16);
 	}
 #endif
 
@@ -1730,61 +1727,62 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path, size_t *exec_size,
 	{
 	  grub_size_t tramp;
 
-	  *kernel_sz = ALIGN_UP (*kernel_sz, 16);
+	  layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
 
-	  grub_ia64_dl_get_tramp_got_size (e, &tramp, &got);
+	  grub_ia64_dl_get_tramp_got_size (e, &tramp, &layout->got_size);
 
-	  tramp_off = *kernel_sz;
-	  *kernel_sz += ALIGN_UP (tramp, 16);
+	  layout->tramp_off = layout->kernel_size;
+	  layout->kernel_size += ALIGN_UP (tramp, 16);
 
-	  ia64jmp_off = *kernel_sz;
-	  ia64jmpnum = SUFFIX (count_funcs) (e, symtab_section,
+	  layout->ia64jmp_off = layout->kernel_size;
+	  layout->ia64jmpnum = SUFFIX (count_funcs) (e, symtab_section,
 					     image_target);
-	  *kernel_sz += 16 * ia64jmpnum;
+	  layout->kernel_size += 16 * layout->ia64jmpnum;
 
-	  ia64_got_off = *kernel_sz;
-	  *kernel_sz += ALIGN_UP (got, 16);
+	  layout->ia64_got_off = layout->kernel_size;
+	  layout->kernel_size += ALIGN_UP (layout->got_size, 16);
 	}
 #endif
 
     }
   else
     {
-      *reloc_size = 0;
-      *reloc_section = NULL;
+      layout->reloc_size = 0;
+      layout->reloc_section = NULL;
     }
 
-  out_img = xmalloc (*kernel_sz + total_module_size);
-  memset (out_img, 0, *kernel_sz + total_module_size);
+  out_img = xmalloc (layout->kernel_size + total_module_size);
+  memset (out_img, 0, layout->kernel_size + total_module_size);
 
   if (image_target->id == IMAGE_EFI)
     {
-      *start = SUFFIX (relocate_symbols) (e, sections, symtab_section,
+      layout->start_address = SUFFIX (relocate_symbols) (e, sections, symtab_section,
 					  section_vaddresses, section_entsize,
 					  num_sections, 
-					  (char *) out_img + ia64jmp_off, 
-					  ia64jmp_off 
+					  (char *) out_img + layout->ia64jmp_off, 
+					  layout->ia64jmp_off 
 					  + image_target->vaddr_offset,
 					  image_target);
-      if (*start == 0)
+      if (layout->start_address == 0)
 	grub_util_error ("start symbol is not defined");
 
-      SUFFIX (entry_point) = (Elf_Addr) *start;
+      SUFFIX (entry_point) = (Elf_Addr) layout->start_address;
 
       /* Resolve addresses in the virtual address space.  */
       SUFFIX (relocate_addresses) (e, sections, section_addresses, 
 				   section_entsize,
 				   num_sections, strtab,
-				   out_img, tramp_off, ia64_got_off,
+				   out_img, layout->tramp_off,
+				   layout->ia64_got_off,
 				   image_target);
 
-      *reloc_size = SUFFIX (make_reloc_section) (e, reloc_section,
-						 section_vaddresses, sections,
-						 section_entsize, num_sections,
-						 strtab, ia64jmp_off
-						 + image_target->vaddr_offset,
-						 2 * ia64jmpnum + (got / 8),
-						 image_target);
+      make_reloc_section (e, layout,
+			  section_vaddresses, sections,
+			  section_entsize, num_sections,
+			  strtab, layout->ia64jmp_off
+			  + image_target->vaddr_offset,
+			  2 * layout->ia64jmpnum + (layout->got_size / 8),
+			  image_target);
     }
 
   for (i = 0, s = sections;
diff --git a/util/mkimage.c b/util/mkimage.c
index 678b221..84b4823 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -740,17 +740,14 @@ grub_install_generate_image (const char *dir, const char *prefix,
 			     grub_compression_t comp)
 {
   char *kernel_img, *core_img;
-  size_t kernel_size, total_module_size, core_size, exec_size;
+  size_t total_module_size, core_size;
   size_t memdisk_size = 0, config_size = 0;
   size_t prefix_size = 0;
   char *kernel_path;
   size_t offset;
   struct grub_util_path_list *path_list, *p;
-  size_t bss_size;
-  grub_uint64_t start_address;
-  void *rel_section = 0;
-  size_t reloc_size = 0, align;
   size_t decompress_size = 0;
+  struct grub_mkimage_layout layout;
 
   if (comp == GRUB_COMPRESSION_AUTO)
     comp = image_target->default_compression;
@@ -812,15 +809,13 @@ grub_install_generate_image (const char *dir, const char *prefix,
 		  (unsigned long long) total_module_size);
 
   if (image_target->voidp_sizeof == 4)
-    kernel_img = grub_mkimage_load_image32 (kernel_path, &exec_size, &kernel_size, &bss_size,
-					    total_module_size, &start_address, &rel_section,
-					    &reloc_size, &align, image_target);
+    kernel_img = grub_mkimage_load_image32 (kernel_path, total_module_size,
+					    &layout, image_target);
   else
-    kernel_img = grub_mkimage_load_image64 (kernel_path, &exec_size, &kernel_size, &bss_size,
-					    total_module_size, &start_address, &rel_section,
-					    &reloc_size, &align, image_target);
-  if (image_target->id == IMAGE_XEN && align < 4096)
-    align = 4096;
+    kernel_img = grub_mkimage_load_image64 (kernel_path, total_module_size,
+					    &layout, image_target);
+  if (image_target->id == IMAGE_XEN && layout.align < 4096)
+    layout.align = 4096;
 
   if ((image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS)
       && (image_target->total_module_size != TARGET_NO_FIELD))
@@ -829,7 +824,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
 
   if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
     {
-      memmove (kernel_img + total_module_size, kernel_img, kernel_size);
+      memmove (kernel_img + total_module_size, kernel_img, layout.kernel_size);
       memset (kernel_img, 0, total_module_size);
     }
 
@@ -840,14 +835,14 @@ grub_install_generate_image (const char *dir, const char *prefix,
       if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
 	modinfo = (struct grub_module_info64 *) kernel_img;
       else
-	modinfo = (struct grub_module_info64 *) (kernel_img + kernel_size);
+	modinfo = (struct grub_module_info64 *) (kernel_img + layout.kernel_size);
       modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC);
       modinfo->offset = grub_host_to_target_addr (sizeof (struct grub_module_info64));
       modinfo->size = grub_host_to_target_addr (total_module_size);
       if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
 	offset = sizeof (struct grub_module_info64);
       else
-	offset = kernel_size + sizeof (struct grub_module_info64);
+	offset = layout.kernel_size + sizeof (struct grub_module_info64);
     }
   else
     {
@@ -856,14 +851,14 @@ grub_install_generate_image (const char *dir, const char *prefix,
       if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
 	modinfo = (struct grub_module_info32 *) kernel_img;
       else
-	modinfo = (struct grub_module_info32 *) (kernel_img + kernel_size);
+	modinfo = (struct grub_module_info32 *) (kernel_img + layout.kernel_size);
       modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC);
       modinfo->offset = grub_host_to_target_addr (sizeof (struct grub_module_info32));
       modinfo->size = grub_host_to_target_addr (total_module_size);
       if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
 	offset = sizeof (struct grub_module_info32);
       else
-	offset = kernel_size + sizeof (struct grub_module_info32);
+	offset = layout.kernel_size + sizeof (struct grub_module_info32);
     }
 
   for (p = path_list; p; p = p->next)
@@ -942,8 +937,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
 
   grub_util_info ("kernel_img=%p, kernel_size=0x%" GRUB_HOST_PRIxLONG_LONG,
 		  kernel_img,
-		  (unsigned long long) kernel_size);
-  compress_kernel (image_target, kernel_img, kernel_size + total_module_size,
+		  (unsigned long long) layout.kernel_size);
+  compress_kernel (image_target, kernel_img, layout.kernel_size + total_module_size,
 		   &core_img, &core_size, comp);
   free (kernel_img);
 
@@ -995,7 +990,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
       if (image_target->decompressor_uncompressed_size != TARGET_NO_FIELD)
 	*((grub_uint32_t *) (decompress_img
 			     + image_target->decompressor_uncompressed_size))
-	  = grub_host_to_target32 (kernel_size + total_module_size);
+	  = grub_host_to_target32 (layout.kernel_size + total_module_size);
 
       if (image_target->decompressor_uncompressed_addr != TARGET_NO_FIELD)
 	{
@@ -1028,16 +1023,17 @@ grub_install_generate_image (const char *dir, const char *prefix,
     case IMAGE_I386_PC_ELTORITO:
 	if (GRUB_KERNEL_I386_PC_LINK_ADDR + core_size > 0x78000
 	    || (core_size > (0xffff << GRUB_DISK_SECTOR_BITS))
-	    || (kernel_size + bss_size + GRUB_KERNEL_I386_PC_LINK_ADDR > 0x68000))
+	    || (layout.kernel_size + layout.bss_size
+		+ GRUB_KERNEL_I386_PC_LINK_ADDR > 0x68000))
 	  grub_util_error (_("core image is too big (0x%x > 0x%x)"),
 			   GRUB_KERNEL_I386_PC_LINK_ADDR + (unsigned) core_size,
 			   0x78000);
 	/* fallthrough */
     case IMAGE_COREBOOT:
     case IMAGE_QEMU:
-	if (kernel_size + bss_size + GRUB_KERNEL_I386_PC_LINK_ADDR > 0x68000)
+	if (layout.kernel_size + layout.bss_size + GRUB_KERNEL_I386_PC_LINK_ADDR > 0x68000)
 	  grub_util_error (_("kernel image is too big (0x%x > 0x%x)"),
-			   (unsigned) kernel_size + (unsigned) bss_size
+			   (unsigned) layout.kernel_size + (unsigned) layout.bss_size
 			   + GRUB_KERNEL_I386_PC_LINK_ADDR,
 			   0x68000);
 	break;
@@ -1159,13 +1155,13 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	reloc_addr = ALIGN_UP (header_size + core_size,
 			       image_target->section_align);
 
-	pe_size = ALIGN_UP (reloc_addr + reloc_size,
+	pe_size = ALIGN_UP (reloc_addr + layout.reloc_size,
 			    image_target->section_align);
-	pe_img = xmalloc (reloc_addr + reloc_size);
+	pe_img = xmalloc (reloc_addr + layout.reloc_size);
 	memset (pe_img, 0, header_size);
 	memcpy ((char *) pe_img + header_size, core_img, core_size);
 	memset ((char *) pe_img + header_size + core_size, 0, reloc_addr - (header_size + core_size));
-	memcpy ((char *) pe_img + reloc_addr, rel_section, reloc_size);
+	memcpy ((char *) pe_img + reloc_addr, layout.reloc_section, layout.reloc_size);
 	header = pe_img;
 
 	/* The magic.  */
@@ -1199,14 +1195,14 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	      (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE
 	       + sizeof (struct grub_pe32_coff_header));
 	    o->magic = grub_host_to_target16 (GRUB_PE32_PE32_MAGIC);
-	    o->code_size = grub_host_to_target32 (exec_size);
-	    o->data_size = grub_cpu_to_le32 (reloc_addr - exec_size
+	    o->code_size = grub_host_to_target32 (layout.exec_size);
+	    o->data_size = grub_cpu_to_le32 (reloc_addr - layout.exec_size
 					     - header_size);
-	    o->bss_size = grub_cpu_to_le32 (bss_size);
-	    o->entry_addr = grub_cpu_to_le32 (start_address);
+	    o->bss_size = grub_cpu_to_le32 (layout.bss_size);
+	    o->entry_addr = grub_cpu_to_le32 (layout.start_address);
 	    o->code_base = grub_cpu_to_le32 (header_size);
 
-	    o->data_base = grub_host_to_target32 (header_size + exec_size);
+	    o->data_base = grub_host_to_target32 (header_size + layout.exec_size);
 
 	    o->image_base = 0;
 	    o->section_alignment = grub_host_to_target32 (image_target->section_align);
@@ -1224,7 +1220,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	    o->num_data_directories = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
 
 	    o->base_relocation_table.rva = grub_host_to_target32 (reloc_addr);
-	    o->base_relocation_table.size = grub_host_to_target32 (reloc_size);
+	    o->base_relocation_table.size = grub_host_to_target32 (layout.reloc_size);
 	    sections = o + 1;
 	  }
 	else
@@ -1237,11 +1233,11 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	      (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE
 	       + sizeof (struct grub_pe32_coff_header));
 	    o->magic = grub_host_to_target16 (GRUB_PE32_PE64_MAGIC);
-	    o->code_size = grub_host_to_target32 (exec_size);
-	    o->data_size = grub_cpu_to_le32 (reloc_addr - exec_size
+	    o->code_size = grub_host_to_target32 (layout.exec_size);
+	    o->data_size = grub_cpu_to_le32 (reloc_addr - layout.exec_size
 					     - header_size);
-	    o->bss_size = grub_cpu_to_le32 (bss_size);
-	    o->entry_addr = grub_cpu_to_le32 (start_address);
+	    o->bss_size = grub_cpu_to_le32 (layout.bss_size);
+	    o->entry_addr = grub_cpu_to_le32 (layout.start_address);
 	    o->code_base = grub_cpu_to_le32 (header_size);
 	    o->image_base = 0;
 	    o->section_alignment = grub_host_to_target32 (image_target->section_align);
@@ -1260,15 +1256,15 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	      = grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES);
 
 	    o->base_relocation_table.rva = grub_host_to_target32 (reloc_addr);
-	    o->base_relocation_table.size = grub_host_to_target32 (reloc_size);
+	    o->base_relocation_table.size = grub_host_to_target32 (layout.reloc_size);
 	    sections = o + 1;
 	  }
 	/* The sections.  */
 	text_section = sections;
 	strcpy (text_section->name, ".text");
-	text_section->virtual_size = grub_cpu_to_le32 (exec_size);
+	text_section->virtual_size = grub_cpu_to_le32 (layout.exec_size);
 	text_section->virtual_address = grub_cpu_to_le32 (header_size);
-	text_section->raw_data_size = grub_cpu_to_le32 (exec_size);
+	text_section->raw_data_size = grub_cpu_to_le32 (layout.exec_size);
 	text_section->raw_data_offset = grub_cpu_to_le32 (header_size);
 	text_section->characteristics = grub_cpu_to_le32_compile_time (
 						  GRUB_PE32_SCN_CNT_CODE
@@ -1277,10 +1273,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
 
 	data_section = text_section + 1;
 	strcpy (data_section->name, ".data");
-	data_section->virtual_size = grub_cpu_to_le32 (kernel_size - exec_size);
-	data_section->virtual_address = grub_cpu_to_le32 (header_size + exec_size);
-	data_section->raw_data_size = grub_cpu_to_le32 (kernel_size - exec_size);
-	data_section->raw_data_offset = grub_cpu_to_le32 (header_size + exec_size);
+	data_section->virtual_size = grub_cpu_to_le32 (layout.kernel_size - layout.exec_size);
+	data_section->virtual_address = grub_cpu_to_le32 (header_size + layout.exec_size);
+	data_section->raw_data_size = grub_cpu_to_le32 (layout.kernel_size - layout.exec_size);
+	data_section->raw_data_offset = grub_cpu_to_le32 (header_size + layout.exec_size);
 	data_section->characteristics
 	  = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
 			      | GRUB_PE32_SCN_MEM_READ
@@ -1289,8 +1285,8 @@ grub_install_generate_image (const char *dir, const char *prefix,
 #if 0
 	bss_section = data_section + 1;
 	strcpy (bss_section->name, ".bss");
-	bss_section->virtual_size = grub_cpu_to_le32 (bss_size);
-	bss_section->virtual_address = grub_cpu_to_le32 (header_size + kernel_size);
+	bss_section->virtual_size = grub_cpu_to_le32 (layout.bss_size);
+	bss_section->virtual_address = grub_cpu_to_le32 (header_size + layout.kernel_size);
 	bss_section->raw_data_size = 0;
 	bss_section->raw_data_offset = 0;
 	bss_section->characteristics
@@ -1303,10 +1299,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
     
 	mods_section = data_section + 1;
 	strcpy (mods_section->name, "mods");
-	mods_section->virtual_size = grub_cpu_to_le32 (reloc_addr - kernel_size - header_size);
-	mods_section->virtual_address = grub_cpu_to_le32 (header_size + kernel_size + bss_size);
-	mods_section->raw_data_size = grub_cpu_to_le32 (reloc_addr - kernel_size - header_size);
-	mods_section->raw_data_offset = grub_cpu_to_le32 (header_size + kernel_size);
+	mods_section->virtual_size = grub_cpu_to_le32 (reloc_addr - layout.kernel_size - header_size);
+	mods_section->virtual_address = grub_cpu_to_le32 (header_size + layout.kernel_size + layout.bss_size);
+	mods_section->raw_data_size = grub_cpu_to_le32 (reloc_addr - layout.kernel_size - header_size);
+	mods_section->raw_data_offset = grub_cpu_to_le32 (header_size + layout.kernel_size);
 	mods_section->characteristics
 	  = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
 			      | GRUB_PE32_SCN_MEM_READ
@@ -1314,9 +1310,9 @@ grub_install_generate_image (const char *dir, const char *prefix,
 
 	reloc_section = mods_section + 1;
 	strcpy (reloc_section->name, ".reloc");
-	reloc_section->virtual_size = grub_cpu_to_le32 (reloc_size);
-	reloc_section->virtual_address = grub_cpu_to_le32 (reloc_addr + bss_size);
-	reloc_section->raw_data_size = grub_cpu_to_le32 (reloc_size);
+	reloc_section->virtual_size = grub_cpu_to_le32 (layout.reloc_size);
+	reloc_section->virtual_address = grub_cpu_to_le32 (reloc_addr + layout.bss_size);
+	reloc_section->raw_data_size = grub_cpu_to_le32 (layout.reloc_size);
 	reloc_section->raw_data_offset = grub_cpu_to_le32 (reloc_addr);
 	reloc_section->characteristics
 	  = grub_cpu_to_le32_compile_time (GRUB_PE32_SCN_CNT_INITIALIZED_DATA
@@ -1587,7 +1583,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	  target_addr = (image_target->link_addr - decompress_size);
 	else
 	  target_addr = ALIGN_UP (image_target->link_addr
-				  + kernel_size + total_module_size, 32);
+				  + layout.kernel_size + total_module_size, 32);
 
 	ecoff_img = xmalloc (program_size + sizeof (*head) + sizeof (*section));
 	grub_memset (ecoff_img, 0, program_size + sizeof (*head) + sizeof (*section));
@@ -1634,16 +1630,16 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	      target_addr = (image_target->link_addr - decompress_size);
 	    else
 	      target_addr = ALIGN_UP (image_target->link_addr
-				      + kernel_size + total_module_size, 32);
+				      + layout.kernel_size + total_module_size, 32);
 	  }
 	else
 	  target_addr = image_target->link_addr;
 	if (image_target->voidp_sizeof == 4)
 	  grub_mkimage_generate_elf32 (image_target, note, &core_img, &core_size,
-				       target_addr, align, kernel_size, bss_size);
+				       target_addr, layout.align, layout.kernel_size, layout.bss_size);
 	else
 	  grub_mkimage_generate_elf64 (image_target, note, &core_img, &core_size,
-				       target_addr, align, kernel_size, bss_size);
+				       target_addr, layout.align, layout.kernel_size, layout.bss_size);
       }
       break;
     }
@@ -1651,7 +1647,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
   grub_util_write_image (core_img, core_size, out, outname);
   free (core_img);
   free (kernel_path);
-  free (rel_section);
+  free (layout.reloc_section);
 
   grub_util_free_path_list (path_list);
 }
-- 
2.7.0


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.5: 0004-Provide-__bss_start-and-_end-symbols-in-grub-mkimage.patch --]
[-- Type: text/x-diff; name="0004-Provide-__bss_start-and-_end-symbols-in-grub-mkimage.patch", Size: 9292 bytes --]

From dc76d5c6eb07ddab8b20e71b1161fe3a72ca045f Mon Sep 17 00:00:00 2001
From: Vladimir Serbinenko <phcoder@gmail.com>
Date: Thu, 18 Feb 2016 20:57:21 +0100
Subject: [PATCH 4/6] Provide __bss_start and _end symbols in grub-mkimage.

For this ensure that all bss sections are merged.

We need this to correctly prelink non-PE relocatable images.
---
 include/grub/util/mkimage.h |   2 +
 util/grub-mkimagexx.c       | 133 ++++++++++++++++++++++++++++----------------
 2 files changed, 87 insertions(+), 48 deletions(-)

diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h
index 8169939..25a49d5 100644
--- a/include/grub/util/mkimage.h
+++ b/include/grub/util/mkimage.h
@@ -33,6 +33,8 @@ struct grub_mkimage_layout
   grub_size_t ia64_got_off;
   grub_size_t got_size;
   unsigned ia64jmpnum;
+  Elf_Addr bss_start;
+  Elf_Addr end;
 };
 
 /* Private header. Use only in mkimage-related sources.  */
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
index 74f86f5..433322d 100644
--- a/util/grub-mkimagexx.c
+++ b/util/grub-mkimagexx.c
@@ -490,6 +490,7 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections,
 			   Elf_Shdr *symtab_section, Elf_Addr *section_addresses,
 			   Elf_Half section_entsize, Elf_Half num_sections,
 			   void *jumpers, Elf_Addr jumpers_addr,
+			   Elf_Addr bss_start, Elf_Addr end,
 			   const struct grub_install_image_target_desc *image_target)
 {
   Elf_Word symtab_size, sym_size, num_syms;
@@ -528,16 +529,22 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections,
         }
       else if (cur_index == STN_UNDEF)
 	{
-	  if (sym->st_name)
+	  if (sym->st_name && grub_strcmp (name, "__bss_start"))
+	    sym->st_value = bss_start;
+	  else if (sym->st_name && grub_strcmp (name, "__end"))
+	    sym->st_value = end;
+	  else if (sym->st_name)
 	    grub_util_error ("undefined symbol %s", name);
 	  else
 	    continue;
 	}
       else if (cur_index >= num_sections)
 	grub_util_error ("section %d does not exist", cur_index);
-
-      sym->st_value = (grub_target_to_host (sym->st_value)
-		       + section_addresses[cur_index]);
+      else
+	{
+	  sym->st_value = (grub_target_to_host (sym->st_value)
+			   + section_addresses[cur_index]);
+	}
 
       if (image_target->elf_target == EM_IA_64 && ELF_ST_TYPE (sym->st_info)
 	  == STT_FUNC)
@@ -1462,9 +1469,7 @@ SUFFIX (is_text_section) (Elf_Shdr *s, const struct grub_install_image_target_de
 	  == (SHF_EXECINSTR | SHF_ALLOC));
 }
 
-/* Determine if this section is a data section. This assumes that
-   BSS is also a data section, since the converter initializes BSS
-   when producing PE32 to avoid a bug in EFI implementations.  */
+/* Determine if this section is a data section.  */
 static int
 SUFFIX (is_data_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
 {
@@ -1472,7 +1477,16 @@ SUFFIX (is_data_section) (Elf_Shdr *s, const struct grub_install_image_target_de
       && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
     return 0;
   return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
-	  == SHF_ALLOC);
+	  == SHF_ALLOC) && !(grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
+}
+
+static int
+SUFFIX (is_bss_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
+{
+  if (!is_relocatable (image_target))
+    return 0;
+  return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
+	  == SHF_ALLOC) && (grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
 }
 
 /* Return if the ELF header is valid.  */
@@ -1492,6 +1506,32 @@ SUFFIX (check_elf_header) (Elf_Ehdr *e, size_t size, const struct grub_install_i
   return 1;
 }
 
+static Elf_Addr
+SUFFIX (put_section) (Elf_Shdr *s, int i,
+		      Elf_Addr current_address,
+		      Elf_Addr *section_addresses,
+		      const char *strtab,
+		      const struct grub_install_image_target_desc *image_target)
+{
+	Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
+	const char *name = strtab + grub_host_to_target32 (s->sh_name);
+
+	if (align)
+	  current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
+				      align)
+	    - image_target->vaddr_offset;
+
+	grub_util_info ("locating the section %s at 0x%"
+			GRUB_HOST_PRIxLONG_LONG,
+			name, (unsigned long long) current_address);
+	if (!is_relocatable (image_target))
+	  current_address = grub_host_to_target_addr (s->sh_addr)
+	    - image_target->link_addr;
+	section_addresses[i] = current_address;
+	current_address += grub_host_to_target_addr (s->sh_size);
+	return current_address;
+}
+
 /* Locate section addresses by merging code sections and data sections
    into .text and .data, respectively. Return the array of section
    addresses.  */
@@ -1531,32 +1571,22 @@ SUFFIX (locate_sections) (const char *kernel_path,
        i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
     if (SUFFIX (is_text_section) (s, image_target))
       {
-	Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
-	const char *name = strtab + grub_host_to_target32 (s->sh_name);
-	if (align)
-	  current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
-				      align) - image_target->vaddr_offset;
-	grub_util_info ("locating the section %s at 0x%"
-			GRUB_HOST_PRIxLONG_LONG,
-			name, (unsigned long long) current_address);
-	if (image_target->id != IMAGE_EFI)
+	current_address = SUFFIX (put_section) (s, i,
+						current_address,
+						section_addresses,
+						strtab,
+						image_target);
+	if (!is_relocatable (image_target) &&
+	    grub_host_to_target_addr (s->sh_addr) != image_target->link_addr)
 	  {
-	    current_address = grub_host_to_target_addr (s->sh_addr)
-	      - image_target->link_addr;
-	    if (grub_host_to_target_addr (s->sh_addr)
-		!= image_target->link_addr)
-	      {
-		char *msg
-		  = grub_xasprintf (_("`%s' is miscompiled: its start address is 0x%llx"
-				      " instead of 0x%llx: ld.gold bug?"),
-				    kernel_path,
-				    (unsigned long long) grub_host_to_target_addr (s->sh_addr),
-				    (unsigned long long) image_target->link_addr);
-		grub_util_error ("%s", msg);
-	      }
+	    char *msg
+	      = grub_xasprintf (_("`%s' is miscompiled: its start address is 0x%llx"
+				  " instead of 0x%llx: ld.gold bug?"),
+				kernel_path,
+				(unsigned long long) grub_host_to_target_addr (s->sh_addr),
+				(unsigned long long) image_target->link_addr);
+	    grub_util_error ("%s", msg);
 	  }
-	section_addresses[i] = current_address;
-	current_address += grub_host_to_target_addr (s->sh_size);
       }
 
   current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
@@ -1569,27 +1599,31 @@ SUFFIX (locate_sections) (const char *kernel_path,
        i < num_sections;
        i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
     if (SUFFIX (is_data_section) (s, image_target))
-      {
-	Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
-	const char *name = strtab + grub_host_to_target32 (s->sh_name);
+      current_address = SUFFIX (put_section) (s, i,
+					      current_address,
+					      section_addresses,
+					      strtab,
+					      image_target);
 
-	if (align)
-	  current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
-				      align)
-	    - image_target->vaddr_offset;
+  current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
+			      image_target->section_align) - image_target->vaddr_offset;
 
-	grub_util_info ("locating the section %s at 0x%"
-			GRUB_HOST_PRIxLONG_LONG,
-			name, (unsigned long long) current_address);
-	if (image_target->id != IMAGE_EFI)
-	  current_address = grub_host_to_target_addr (s->sh_addr)
-	    - image_target->link_addr;
-	section_addresses[i] = current_address;
-	current_address += grub_host_to_target_addr (s->sh_size);
-      }
+  layout->bss_start = current_address;
+  
+  /* .bss */
+  for (i = 0, s = sections;
+       i < num_sections;
+       i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
+    if (SUFFIX (is_bss_section) (s, image_target))
+      current_address = SUFFIX (put_section) (s, i,
+					      current_address,
+					      section_addresses,
+					      strtab,
+					      image_target);
 
   current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
 			      image_target->section_align) - image_target->vaddr_offset;
+  layout->end = current_address;
   layout->kernel_size = current_address;
   return section_addresses;
 }
@@ -1789,8 +1823,11 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
        i < num_sections;
        i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
     if (SUFFIX (is_data_section) (s, image_target)
+	|| SUFFIX (is_bss_section) (s, image_target)
 	|| SUFFIX (is_text_section) (s, image_target))
       {
+	/* Explicitly initialize BSS
+	   when producing PE32 to avoid a bug in EFI implementations. */
 	if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
 	  memset (out_img + section_addresses[i], 0,
 		  grub_host_to_target_addr (s->sh_size));
-- 
2.7.0


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.6: 0005-Allow-_start-0-with-relocatable-images.patch --]
[-- Type: text/x-diff; name="0005-Allow-_start-0-with-relocatable-images.patch", Size: 1540 bytes --]

From d116b78258afc7664b0fbcae49bb5facbad08129 Mon Sep 17 00:00:00 2001
From: Vladimir Serbinenko <phcoder@gmail.com>
Date: Thu, 18 Feb 2016 20:58:38 +0100
Subject: [PATCH 5/6] Allow _start == 0 with relocatable images

---
 util/grub-mkimagexx.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
index 433322d..fff8112 100644
--- a/util/grub-mkimagexx.c
+++ b/util/grub-mkimagexx.c
@@ -495,7 +495,7 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections,
 {
   Elf_Word symtab_size, sym_size, num_syms;
   Elf_Off symtab_offset;
-  Elf_Addr start_address = 0;
+  Elf_Addr start_address = (Elf_Addr) -1;
   Elf_Sym *sym;
   Elf_Word i;
   Elf_Shdr *strtab_section;
@@ -560,7 +560,7 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections,
 		      (unsigned long long) sym->st_value,
 		      (unsigned long long) section_addresses[cur_index]);
 
-      if (! start_address)
+      if (start_address == (Elf_Addr)-1)
 	if (strcmp (name, "_start") == 0 || strcmp (name, "start") == 0)
 	  start_address = sym->st_value;
     }
@@ -1797,7 +1797,7 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
 					  layout->ia64jmp_off 
 					  + image_target->vaddr_offset,
 					  image_target);
-      if (layout->start_address == 0)
+      if (layout->start_address == (Elf_Addr) -1)
 	grub_util_error ("start symbol is not defined");
 
       SUFFIX (entry_point) = (Elf_Addr) layout->start_address;
-- 
2.7.0


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.7: 0006-arm-uboot-Make-self-relocatable-to-allow-loading-at-.patch --]
[-- Type: text/x-diff; name="0006-arm-uboot-Make-self-relocatable-to-allow-loading-at-.patch", Size: 27493 bytes --]

From a20df5d8ffa95a8af7bbc175c4beff8454cc9875 Mon Sep 17 00:00:00 2001
From: Vladimir Serbinenko <phcoder@gmail.com>
Date: Fri, 19 Feb 2016 00:43:36 +0100
Subject: [PATCH 6/6] arm-uboot: Make self-relocatable to allow loading at any
 address

---
 grub-core/Makefile.core.def        |   2 +-
 grub-core/kern/arm/uboot/startup.S |  58 +++++--
 include/grub/arm/uboot/kernel.h    |   2 +-
 include/grub/offsets.h             |   1 -
 include/grub/util/mkimage.h        |   5 +-
 util/grub-mkimagexx.c              | 313 +++++++++++++++++++++++++++++--------
 util/mkimage.c                     |   8 +-
 7 files changed, 303 insertions(+), 86 deletions(-)

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 8874501..58b4208 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -90,7 +90,7 @@ kernel = {
   i386_qemu_cppflags     = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)';
   emu_cflags = '$(CFLAGS_GNULIB)';
   emu_cppflags = '$(CPPFLAGS_GNULIB)';
-  arm_uboot_ldflags       = '-Wl,-Ttext=0x08000000';
+  arm_uboot_ldflags       = '-Wl,-r,-d';
   arm_uboot_stripflags    = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
 
   i386_pc_startup = kern/i386/pc/startup.S;
diff --git a/grub-core/kern/arm/uboot/startup.S b/grub-core/kern/arm/uboot/startup.S
index 0c4a5f6..5efaae1 100644
--- a/grub-core/kern/arm/uboot/startup.S
+++ b/grub-core/kern/arm/uboot/startup.S
@@ -55,10 +55,6 @@ FUNCTION(_start)
 VARIABLE(grub_total_module_size)
 	.long 	0
 
-VARIABLE(grub_uboot_machine_type)
-	.long   0
-VARIABLE(grub_uboot_boot_data)
-	.long   0
 VARIABLE(grub_modbase)
 	.long 0
 bss_start_ptr:
@@ -66,29 +62,66 @@ bss_start_ptr:
 end_ptr:
 	.long   EXT_C(_end)
 
+	@ Memory map at start:
+	@ * text+data
+	@ * list relocations
+	@ * modules
+	@ Before we enter C, we need to apply the relocations
+	@ and get following map:
+	@ * text+data
+	@ * BSS (cleared)
+	@ * stack
+	@ * modules
+	@
+	@ To make things easier we ensure
+	@ that BSS+stack is larger than list of relocations
+	@ by increasing stack if necessarry.
+	@ This allows us to always unconditionally copy backwards
+	@ Currently list of relocations is ~5K and stack is set
+	@ to be at least 256K
+
 FUNCTION(codestart)
 	@ Store context: Machine ID, atags/dtb, ...
 	@ U-Boot API signature is stored on the U-Boot heap
 	@ Stack pointer used as start address for signature probing
 	mov	r12, sp
 	adr	sp, entry_state
-	push	{r4-r12,lr}	@ store U-Boot context (sp in r12)
+	push	{r1-r12,lr}	@ store U-Boot context (sp in r12)
 
-	str     r1, EXT_C(grub_uboot_machine_type)
-	str     r2, EXT_C(grub_uboot_boot_data)
+	adr     r1, _start
+	ldr	r0, bss_start_ptr		@ src
+	add     r0, r0, r1
 
-	@ Modules have been stored as a blob in BSS,
+	add	r0, r0, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
+	mvn	r2, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
+	and	r0, r0, r2
+1:	
+        ldr     r3, [r0], #4  @load next offset
+	@ both -2 and -1 are treated the same as we have only one type of relocs
+	@ -2 means "end of this type of relocs" and -1 means "end of all relocs"
+        add     r2, r3, #2
+        cmp     r2, #1
+        bls     reloc_done
+	@ Adjust next offset
+        ldr     r2, [r3, r1]
+        add     r2, r2, r1
+        str     r2, [r3, r1]
+	b 1b
+
+reloc_done:
+
+	@ Modules have been stored as a blob
 	@ they need to be manually relocated to _end
-	ldr	r0, bss_start_ptr		@ src
 	add	r0, r0, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
 	mvn	r1, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
-	and	r0, r0, r1
+	and	r0, r0, r1	@ src = aligned end of relocations
 
 	ldr	r1, end_ptr		@ dst = End of BSS
 	ldr	r2, grub_total_module_size	@ blob size
 
 	add     r1, r1, #GRUB_KERNEL_MACHINE_STACK_SIZE
 	and	r1, r1, #~0x7	@ Ensure 8-byte alignment
+	
 	sub	sp, r1, #8
 	add     r1, r1, #1024
 
@@ -157,6 +190,11 @@ FUNCTION(grub_uboot_return)
 	.align	3
 @ U-boot context stack space
 entry_state_end:
+VARIABLE(grub_uboot_machine_type)
+	.long	0	@ r1
+VARIABLE(grub_uboot_boot_data)
+	.long	0	@ r2
+	.long	0	@ r3
 	.long	0	@ r4
 	.long	0	@ r5
 	.long	0	@ r6
diff --git a/include/grub/arm/uboot/kernel.h b/include/grub/arm/uboot/kernel.h
index 06e5433..ce0b149 100644
--- a/include/grub/arm/uboot/kernel.h
+++ b/include/grub/arm/uboot/kernel.h
@@ -26,7 +26,7 @@
 
 #endif /* ! ASM_FILE */
 
-#define GRUB_KERNEL_MACHINE_STACK_SIZE 0x40000
+#define GRUB_KERNEL_MACHINE_STACK_SIZE GRUB_KERNEL_ARM_STACK_SIZE
 #define GRUB_KERNEL_MACHINE_HEAP_SIZE  (grub_size_t) (16 * 1024 * 1024)
 
 #endif /* ! GRUB_KERNEL_MACHINE_HEADER */
diff --git a/include/grub/offsets.h b/include/grub/offsets.h
index 85e7401..3502a43 100644
--- a/include/grub/offsets.h
+++ b/include/grub/offsets.h
@@ -120,7 +120,6 @@
 
 #define GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN 	0x8
 #define GRUB_KERNEL_ARM_UBOOT_TOTAL_MODULE_SIZE	0x4
-#define GRUB_KERNEL_ARM_UBOOT_LINK_ADDR		0x08000000
 
 /* Minimal gap between _end and the start of the modules.  It's a hack
    for PowerMac to prevent "CLAIM failed" error.  The real fix is to
diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h
index 25a49d5..2a48942 100644
--- a/include/grub/util/mkimage.h
+++ b/include/grub/util/mkimage.h
@@ -33,8 +33,8 @@ struct grub_mkimage_layout
   grub_size_t ia64_got_off;
   grub_size_t got_size;
   unsigned ia64jmpnum;
-  Elf_Addr bss_start;
-  Elf_Addr end;
+  grub_uint32_t bss_start;
+  grub_uint32_t end;
 };
 
 /* Private header. Use only in mkimage-related sources.  */
@@ -83,6 +83,7 @@ struct grub_install_image_target_desc
   unsigned decompressor_compressed_size;
   unsigned decompressor_uncompressed_size;
   unsigned decompressor_uncompressed_addr;
+  unsigned reloc_table_offset;
   unsigned link_align;
   grub_uint16_t elf_target;
   unsigned section_align;
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
index fff8112..353a940 100644
--- a/util/grub-mkimagexx.c
+++ b/util/grub-mkimagexx.c
@@ -86,6 +86,12 @@ struct fixup_block_list
 
 #define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof))
 
+static int
+is_relocatable (const struct grub_install_image_target_desc *image_target)
+{
+  return image_target->id == IMAGE_EFI || image_target->id == IMAGE_UBOOT;
+}
+
 #ifdef MKIMAGE_ELF32
 
 /*
@@ -529,9 +535,9 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections,
         }
       else if (cur_index == STN_UNDEF)
 	{
-	  if (sym->st_name && grub_strcmp (name, "__bss_start"))
+	  if (sym->st_name && grub_strcmp (name, "__bss_start") == 0)
 	    sym->st_value = bss_start;
-	  else if (sym->st_name && grub_strcmp (name, "__end"))
+	  else if (sym->st_name && grub_strcmp (name, "_end") == 0)
 	    sym->st_value = end;
 	  else if (sym->st_name)
 	    grub_util_error ("undefined symbol %s", name);
@@ -1008,7 +1014,8 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
 		       grub_util_info ("  ABS32:\toffset=%d\t(0x%08x)",
 				       (int) sym_addr, (int) sym_addr);
 		       /* Data will be naturally aligned */
-		       sym_addr += 0x400;
+		       if (image_target->id == IMAGE_EFI)
+			 sym_addr += 0x400;
 		       *target = grub_host_to_target32 (grub_target_to_host32 (*target) + sym_addr);
 		     }
 		     break;
@@ -1194,25 +1201,45 @@ add_fixup_entry (struct fixup_block_list **cblock, grub_uint16_t type,
   return current_address;
 }
 
+struct raw_reloc
+{
+  struct raw_reloc *next;
+  grub_uint32_t offset;
+  enum raw_reloc_type {
+    RAW_RELOC_NONE = -1,
+    RAW_RELOC_32 = 0,
+    RAW_RELOC_MAX = 1,
+  } type;
+};
+
 struct translate_context
 {
+  /* PE */
   struct fixup_block_list *lst, *lst0;
   Elf_Addr current_address;
+
+  /* Raw */
+  struct raw_reloc *raw_relocs;
 };
 
 static void
-translate_reloc_start (struct translate_context *ctx)
+translate_reloc_start (struct translate_context *ctx,
+		       const struct grub_install_image_target_desc *image_target)
 {
-  ctx->lst = ctx->lst0 = xmalloc (sizeof (*ctx->lst) + 2 * 0x1000);
-  memset (ctx->lst, 0, sizeof (*ctx->lst) + 2 * 0x1000);
-  ctx->current_address = 0;
+  grub_memset (ctx, 0, sizeof (*ctx));
+  if (image_target->id == IMAGE_EFI)
+    {
+      ctx->lst = ctx->lst0 = xmalloc (sizeof (*ctx->lst) + 2 * 0x1000);
+      memset (ctx->lst, 0, sizeof (*ctx->lst) + 2 * 0x1000);
+      ctx->current_address = 0;
+    }
 }
 
 static void
-translate_relocation (struct translate_context *ctx,
-		      Elf_Addr addr,
-		      Elf_Addr info,
-		      const struct grub_install_image_target_desc *image_target)
+translate_relocation_pe (struct translate_context *ctx,
+			 Elf_Addr addr,
+			 Elf_Addr info,
+			 const struct grub_install_image_target_desc *image_target)
 {
   /* Necessary to relocate only absolute addresses.  */
   switch (image_target->elf_target)
@@ -1353,11 +1380,69 @@ translate_relocation (struct translate_context *ctx,
     }
 }
 
+static enum raw_reloc_type
+classify_raw_reloc (Elf_Addr info,
+		    const struct grub_install_image_target_desc *image_target)
+{
+    /* Necessary to relocate only absolute addresses.  */
+  switch (image_target->elf_target)
+    {
+    case EM_ARM:
+      switch (ELF_R_TYPE (info))
+	{
+	case R_ARM_V4BX:
+	case R_ARM_JUMP24:
+	case R_ARM_THM_CALL:
+	case R_ARM_THM_JUMP19:
+	case R_ARM_THM_JUMP24:
+	case R_ARM_CALL:
+	  return RAW_RELOC_NONE;
+	case R_ARM_ABS32:
+	  return RAW_RELOC_32;
+	default:
+	  grub_util_error (_("relocation 0x%x is not implemented yet"),
+			   (unsigned int) ELF_R_TYPE (info));
+	  break;
+	}
+      break;
+    default:
+      grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
+    }
+}
+
 static void
-finish_reloc_translation (struct translate_context *ctx,
-			  struct grub_mkimage_layout *layout,
+translate_relocation_raw (struct translate_context *ctx,
+			  Elf_Addr addr,
+			  Elf_Addr info,
 			  const struct grub_install_image_target_desc *image_target)
 {
+  enum raw_reloc_type class = classify_raw_reloc (info, image_target);
+  struct raw_reloc *rel;
+  if (class == RAW_RELOC_NONE)
+    return;
+  rel = xmalloc (sizeof (*rel));
+  rel->next = ctx->raw_relocs;
+  rel->type = class;
+  rel->offset = addr;
+  ctx->raw_relocs = rel;
+}
+
+static void
+translate_relocation (struct translate_context *ctx,
+		      Elf_Addr addr,
+		      Elf_Addr info,
+		      const struct grub_install_image_target_desc *image_target)
+{
+  if (image_target->id == IMAGE_EFI)
+    translate_relocation_pe (ctx, addr, info, image_target);
+  else
+    translate_relocation_raw (ctx, addr, info, image_target);
+}
+
+static void
+finish_reloc_translation_pe (struct translate_context *ctx, struct grub_mkimage_layout *layout,
+			     const struct grub_install_image_target_desc *image_target)
+{
   ctx->current_address = add_fixup_entry (&ctx->lst, 0, 0, 1, ctx->current_address, image_target);
 
   {
@@ -1381,14 +1466,90 @@ finish_reloc_translation (struct translate_context *ctx,
     }
 
   layout->reloc_size = ctx->current_address;
+  if (image_target->elf_target == EM_ARM && layout->reloc_size > GRUB_KERNEL_ARM_STACK_SIZE)
+    grub_util_error ("Reloc section (%d) is bigger than stack size (%d). "
+		     "This breaks assembly assumptions. Please increase stack size",
+		     (int) layout->reloc_size,
+		     (int) GRUB_KERNEL_ARM_STACK_SIZE);
 }
 
+/*
+  Layout:
+  <type 0 relocations>
+  <fffffffe>
+  <type 1 relocations>
+  <fffffffe>
+  ...
+  <type n relocations>
+  <ffffffff>
+  each relocation starts with 32-bit offset. Rest depends on relocation.
+  mkimage stops when it sees first unknown type or end marker.
+  This allows images to be created with mismatched mkimage and
+  kernel as long as no relocations are present in kernel that mkimage
+  isn't aware of (in which case mkimage aborts).
+  This also allows simple assembly to do the relocs.
+*/
+
+#define RAW_SEPARATOR 0xfffffffe
+#define RAW_END_MARKER 0xffffffff
+
+static void
+finish_reloc_translation_raw (struct translate_context *ctx, struct grub_mkimage_layout *layout,
+			      const struct grub_install_image_target_desc *image_target)
+{
+  size_t count = 0, sz;
+  enum raw_reloc_type highest = RAW_RELOC_NONE;
+  enum raw_reloc_type curtype;
+  struct raw_reloc *cur;
+  grub_uint32_t *p;
+  if (!ctx->raw_relocs)
+    {
+      layout->reloc_section = p = xmalloc (sizeof (grub_uint32_t));
+      p[0] = RAW_END_MARKER;
+      layout->reloc_size = sizeof (grub_uint32_t);
+      return;
+    }
+  for (cur = ctx->raw_relocs; cur; cur = cur->next)
+    {
+      count++;
+      if (cur->type > highest)
+	highest = cur->type;
+    }
+  /* highest separators, count relocations and one end marker.  */
+  sz = (highest + count + 1) * sizeof (grub_uint32_t);
+  layout->reloc_section = p = xmalloc (sz);
+  for (curtype = 0; curtype <= highest; curtype++)
+    {
+      /* Support for special cases would go here.  */
+      for (cur = ctx->raw_relocs; cur; cur = cur->next)
+	if (cur->type == curtype)
+	  {
+	    *p++ = cur->offset;
+	  }
+      *p++ = RAW_SEPARATOR;
+    }
+  *--p = RAW_END_MARKER;
+  layout->reloc_size = sz;
+}
+
+static void
+finish_reloc_translation (struct translate_context *ctx, struct grub_mkimage_layout *layout,
+			  const struct grub_install_image_target_desc *image_target)
+{
+  if (image_target->id == IMAGE_EFI)
+    finish_reloc_translation_pe (ctx, layout, image_target);
+  else
+    finish_reloc_translation_raw (ctx, layout, image_target);
+}
+
+
 static void
 translate_reloc_jumpers (struct translate_context *ctx,
 			 Elf_Addr jumpers, grub_size_t njumpers,
 			 const struct grub_install_image_target_desc *image_target)
 {
   unsigned i;
+  assert (image_target->id == IMAGE_EFI);
   for (i = 0; i < njumpers; i++)
     ctx->current_address = add_fixup_entry (&ctx->lst,
 					    GRUB_PE32_REL_BASED_DIR64,
@@ -1403,14 +1564,13 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout,
 		    Elf_Addr *section_addresses, Elf_Shdr *sections,
 		    Elf_Half section_entsize, Elf_Half num_sections,
 		    const char *strtab,
-		    Elf_Addr jumpers, grub_size_t njumpers,
 		    const struct grub_install_image_target_desc *image_target)
 {
   unsigned i;
   Elf_Shdr *s;
   struct translate_context ctx;
 
-  translate_reloc_start (&ctx);
+  translate_reloc_start (&ctx, image_target);
 
   for (i = 0, s = sections; i < num_sections;
        i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
@@ -1451,7 +1611,10 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout,
       }
 
   if (image_target->elf_target == EM_IA_64)
-    translate_reloc_jumpers (&ctx, jumpers, njumpers,
+    translate_reloc_jumpers (&ctx,
+			     layout->ia64jmp_off
+			     + image_target->vaddr_offset,
+			     2 * layout->ia64jmpnum + (layout->got_size / 8),
 			     image_target);
 
   finish_reloc_translation (&ctx, layout, image_target);
@@ -1462,7 +1625,7 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout,
 static int
 SUFFIX (is_text_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
 {
-  if (image_target->id != IMAGE_EFI 
+  if (!is_relocatable (image_target)
       && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
     return 0;
   return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
@@ -1473,7 +1636,7 @@ SUFFIX (is_text_section) (Elf_Shdr *s, const struct grub_install_image_target_de
 static int
 SUFFIX (is_data_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
 {
-  if (image_target->id != IMAGE_EFI 
+  if (!is_relocatable (image_target) 
       && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
     return 0;
   return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
@@ -1536,14 +1699,13 @@ SUFFIX (put_section) (Elf_Shdr *s, int i,
    into .text and .data, respectively. Return the array of section
    addresses.  */
 static Elf_Addr *
-SUFFIX (locate_sections) (const char *kernel_path,
+SUFFIX (locate_sections) (Elf_Ehdr *e, const char *kernel_path,
 			  Elf_Shdr *sections, Elf_Half section_entsize,
 			  Elf_Half num_sections, const char *strtab,
 			  struct grub_mkimage_layout *layout,
 			  const struct grub_install_image_target_desc *image_target)
 {
   int i;
-  Elf_Addr current_address;
   Elf_Addr *section_addresses;
   Elf_Shdr *s;
 
@@ -1555,7 +1717,7 @@ SUFFIX (locate_sections) (const char *kernel_path,
   section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
   memset (section_addresses, 0, sizeof (*section_addresses) * num_sections);
 
-  current_address = 0;
+  layout->kernel_size = 0;
 
   for (i = 0, s = sections;
        i < num_sections;
@@ -1571,8 +1733,8 @@ SUFFIX (locate_sections) (const char *kernel_path,
        i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
     if (SUFFIX (is_text_section) (s, image_target))
       {
-	current_address = SUFFIX (put_section) (s, i,
-						current_address,
+	layout->kernel_size = SUFFIX (put_section) (s, i,
+						layout->kernel_size,
 						section_addresses,
 						strtab,
 						image_target);
@@ -1589,42 +1751,63 @@ SUFFIX (locate_sections) (const char *kernel_path,
 	  }
       }
 
-  current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
+  layout->kernel_size = ALIGN_UP (layout->kernel_size + image_target->vaddr_offset,
 			      image_target->section_align)
     - image_target->vaddr_offset;
-  layout->exec_size = current_address;
+  layout->exec_size = layout->kernel_size;
 
   /* .data */
   for (i = 0, s = sections;
        i < num_sections;
        i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
     if (SUFFIX (is_data_section) (s, image_target))
-      current_address = SUFFIX (put_section) (s, i,
-					      current_address,
+      layout->kernel_size = SUFFIX (put_section) (s, i,
+					      layout->kernel_size,
 					      section_addresses,
 					      strtab,
 					      image_target);
 
-  current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
-			      image_target->section_align) - image_target->vaddr_offset;
+#ifdef MKIMAGE_ELF32
+  if (image_target->elf_target == EM_ARM)
+    {
+      grub_size_t tramp;
+      layout->kernel_size = ALIGN_UP (layout->kernel_size + image_target->vaddr_offset,
+				      image_target->section_align) - image_target->vaddr_offset;
 
-  layout->bss_start = current_address;
+      layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
+
+      tramp = arm_get_trampoline_size (e, sections, section_entsize,
+				       num_sections, image_target);
+
+      layout->tramp_off = layout->kernel_size;
+      layout->kernel_size += ALIGN_UP (tramp, 16);
+    }
+#endif
+
+  layout->bss_start = layout->kernel_size;
+  layout->end = layout->kernel_size;
   
   /* .bss */
   for (i = 0, s = sections;
        i < num_sections;
        i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
     if (SUFFIX (is_bss_section) (s, image_target))
-      current_address = SUFFIX (put_section) (s, i,
-					      current_address,
-					      section_addresses,
-					      strtab,
-					      image_target);
+      layout->end = SUFFIX (put_section) (s, i,
+					  layout->end,
+					  section_addresses,
+					  strtab,
+					  image_target);
 
-  current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
+  layout->end = ALIGN_UP (layout->end + image_target->vaddr_offset,
 			      image_target->section_align) - image_target->vaddr_offset;
-  layout->end = current_address;
-  layout->kernel_size = current_address;
+  /* Explicitly initialize BSS
+     when producing PE32 to avoid a bug in EFI implementations.
+     Platforms other than EFI and U-boot shouldn't have .bss in
+     their binaries as we build with -Wl,-Ttext.
+  */
+  if (image_target->id != IMAGE_UBOOT)
+    layout->kernel_size = layout->end;
+
   return section_addresses;
 }
 
@@ -1674,7 +1857,7 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
 		      + grub_host_to_target16 (e->e_shstrndx) * section_entsize);
   strtab = (char *) e + grub_host_to_target_addr (s->sh_offset);
 
-  section_addresses = SUFFIX (locate_sections) (kernel_path,
+  section_addresses = SUFFIX (locate_sections) (e, kernel_path,
 						sections, section_entsize,
 						num_sections, strtab,
 						layout,
@@ -1685,7 +1868,7 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
   for (i = 0; i < num_sections; i++)
     section_vaddresses[i] = section_addresses[i] + image_target->vaddr_offset;
 
-  if (image_target->id != IMAGE_EFI)
+  if (!is_relocatable (image_target))
     {
       Elf_Addr current_address = layout->kernel_size;
 
@@ -1706,7 +1889,7 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
 	    grub_util_info ("locating the section %s at 0x%"
 			    GRUB_HOST_PRIxLONG_LONG,
 			    name, (unsigned long long) current_address);
-	    if (image_target->id != IMAGE_EFI)
+	    if (!is_relocatable (image_target))
 	      current_address = grub_host_to_target_addr (s->sh_addr)
 		- image_target->link_addr;
 
@@ -1724,10 +1907,11 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
 
   if (image_target->id == IMAGE_SPARC64_AOUT
       || image_target->id == IMAGE_SPARC64_RAW
+      || image_target->id == IMAGE_UBOOT
       || image_target->id == IMAGE_SPARC64_CDCORE)
     layout->kernel_size = ALIGN_UP (layout->kernel_size, image_target->mod_align);
 
-  if (image_target->id == IMAGE_EFI)
+  if (is_relocatable (image_target))
     {
       symtab_section = NULL;
       for (i = 0, s = sections;
@@ -1740,22 +1924,6 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
 	  }
       if (! symtab_section)
 	grub_util_error ("%s", _("no symbol table"));
-
-#ifdef MKIMAGE_ELF32
-      if (image_target->elf_target == EM_ARM)
-	{
-	  grub_size_t tramp;
-
-	  layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
-
-	  tramp = arm_get_trampoline_size (e, sections, section_entsize,
-					   num_sections, image_target);
-
-	  layout->tramp_off = layout->kernel_size;
-	  layout->kernel_size += ALIGN_UP (tramp, 16);
-	}
-#endif
-
 #ifdef MKIMAGE_ELF64
       if (image_target->elf_target == EM_IA_64)
 	{
@@ -1770,14 +1938,13 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
 
 	  layout->ia64jmp_off = layout->kernel_size;
 	  layout->ia64jmpnum = SUFFIX (count_funcs) (e, symtab_section,
-					     image_target);
+						     image_target);
 	  layout->kernel_size += 16 * layout->ia64jmpnum;
 
 	  layout->ia64_got_off = layout->kernel_size;
 	  layout->kernel_size += ALIGN_UP (layout->got_size, 16);
 	}
 #endif
-
     }
   else
     {
@@ -1788,7 +1955,7 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
   out_img = xmalloc (layout->kernel_size + total_module_size);
   memset (out_img, 0, layout->kernel_size + total_module_size);
 
-  if (image_target->id == IMAGE_EFI)
+  if (is_relocatable (image_target))
     {
       layout->start_address = SUFFIX (relocate_symbols) (e, sections, symtab_section,
 					  section_vaddresses, section_entsize,
@@ -1796,6 +1963,8 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
 					  (char *) out_img + layout->ia64jmp_off, 
 					  layout->ia64jmp_off 
 					  + image_target->vaddr_offset,
+							 layout->bss_start,
+							 layout->end,
 					  image_target);
       if (layout->start_address == (Elf_Addr) -1)
 	grub_util_error ("start symbol is not defined");
@@ -1813,21 +1982,31 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
       make_reloc_section (e, layout,
 			  section_vaddresses, sections,
 			  section_entsize, num_sections,
-			  strtab, layout->ia64jmp_off
-			  + image_target->vaddr_offset,
-			  2 * layout->ia64jmpnum + (layout->got_size / 8),
+			  strtab,
 			  image_target);
+      if (image_target->id != IMAGE_EFI)
+	{
+	  out_img = xrealloc (out_img, layout->kernel_size + total_module_size
+			      + ALIGN_UP (layout->reloc_size, image_target->mod_align));
+	  memcpy (out_img + layout->kernel_size, layout->reloc_section, layout->reloc_size);
+	  memset (out_img + layout->kernel_size + layout->reloc_size, 0,
+		  total_module_size + ALIGN_UP (layout->reloc_size, image_target->mod_align) - layout->reloc_size);
+	  layout->kernel_size += ALIGN_UP (layout->reloc_size, image_target->mod_align);
+	}
     }
 
   for (i = 0, s = sections;
        i < num_sections;
        i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
     if (SUFFIX (is_data_section) (s, image_target)
-	|| SUFFIX (is_bss_section) (s, image_target)
+	/* Explicitly initialize BSS
+	   when producing PE32 to avoid a bug in EFI implementations.
+	   Platforms other than EFI and U-boot shouldn't have .bss in
+	   their binaries as we build with -Wl,-Ttext.
+	*/
+	|| (SUFFIX (is_bss_section) (s, image_target) && (image_target->id != IMAGE_UBOOT))
 	|| SUFFIX (is_text_section) (s, image_target))
       {
-	/* Explicitly initialize BSS
-	   when producing PE32 to avoid a bug in EFI implementations. */
 	if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
 	  memset (out_img + section_addresses[i], 0,
 		  grub_host_to_target_addr (s->sh_size));
diff --git a/util/mkimage.c b/util/mkimage.c
index 84b4823..06d28e7 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -86,6 +86,7 @@ static const struct grub_install_image_target_desc image_targets[] =
       .decompressor_compressed_size = TARGET_NO_FIELD,
       .decompressor_uncompressed_size = TARGET_NO_FIELD,
       .decompressor_uncompressed_addr = TARGET_NO_FIELD,
+      .reloc_table_offset = TARGET_NO_FIELD,
       .section_align = 1,
       .vaddr_offset = 0,
       .link_addr = GRUB_KERNEL_I386_COREBOOT_LINK_ADDR,
@@ -525,7 +526,6 @@ static const struct grub_install_image_target_desc image_targets[] =
       .decompressor_uncompressed_addr = TARGET_NO_FIELD,
       .section_align = GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN,
       .vaddr_offset = 0,
-      .link_addr = GRUB_KERNEL_ARM_UBOOT_LINK_ADDR,
       .elf_target = EM_ARM,
       .mod_gap = GRUB_KERNEL_ARM_UBOOT_MOD_GAP,
       .mod_align = GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN,
@@ -1520,9 +1520,9 @@ grub_install_generate_image (const char *dir, const char *prefix,
       hdr->ih_magic = grub_cpu_to_be32_compile_time (GRUB_UBOOT_IH_MAGIC);
       hdr->ih_time = grub_cpu_to_be32 (STABLE_EMBEDDING_TIMESTAMP);
       hdr->ih_size = grub_cpu_to_be32 (core_size);
-      hdr->ih_load = grub_cpu_to_be32 (image_target->link_addr);
-      hdr->ih_ep = grub_cpu_to_be32 (image_target->link_addr);
-      hdr->ih_type = GRUB_UBOOT_IH_TYPE_KERNEL;
+      hdr->ih_load = 0;
+      hdr->ih_ep = 0;
+      hdr->ih_type = GRUB_UBOOT_IH_TYPE_KERNEL_NOLOAD;
       hdr->ih_os = GRUB_UBOOT_IH_OS_LINUX;
       hdr->ih_arch = GRUB_UBOOT_IH_ARCH_ARM;
       hdr->ih_comp = GRUB_UBOOT_IH_COMP_NONE;
-- 
2.7.0


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 213 bytes --]

             reply	other threads:[~2016-02-23 10:35 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-23 10:35 Vladimir 'φ-coder/phcoder' Serbinenko [this message]
2016-02-23 17:33 ` [PATCH] U-Boot self-relocatable images Andrei Borzenkov
2016-02-23 20:09   ` Vladimir 'phcoder' Serbinenko

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=56CC35D6.4010108@gmail.com \
    --to=phcoder@gmail.com \
    --cc=Ian.Campbell@citrix.com \
    --cc=grub-devel@gnu.org \
    --cc=leif.lindholm@linaro.org \
    /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 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.