* [PATCH] U-Boot self-relocatable images
@ 2016-02-23 10:35 Vladimir 'φ-coder/phcoder' Serbinenko
2016-02-23 17:33 ` Andrei Borzenkov
0 siblings, 1 reply; 3+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2016-02-23 10:35 UTC (permalink / raw)
To: The development of GRUB 2, Leif Lindholm, Ian Campbell
[-- 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 --]
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2016-02-23 20:09 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-02-23 10:35 [PATCH] U-Boot self-relocatable images Vladimir 'φ-coder/phcoder' Serbinenko
2016-02-23 17:33 ` Andrei Borzenkov
2016-02-23 20:09 ` Vladimir 'phcoder' Serbinenko
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.