From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1aYAJZ-0003oq-Un for mharc-grub-devel@gnu.org; Tue, 23 Feb 2016 05:35:34 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50493) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aYAJN-0003mm-Eb for grub-devel@gnu.org; Tue, 23 Feb 2016 05:35:31 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aYAJD-0005LB-Gq for grub-devel@gnu.org; Tue, 23 Feb 2016 05:35:21 -0500 Received: from mail-wm0-x231.google.com ([2a00:1450:400c:c09::231]:38168) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aYAJC-0005KP-Go for grub-devel@gnu.org; Tue, 23 Feb 2016 05:35:11 -0500 Received: by mail-wm0-x231.google.com with SMTP id a4so202301119wme.1 for ; Tue, 23 Feb 2016 02:35:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=to:from:subject:message-id:date:user-agent:mime-version :content-type; bh=75dINbXXPMxN1Y98C1MHTGXt4hDsLktNZMGlMzEss9g=; b=sxmbZfFZQdRxoGldgNlxLaeqKt7rRF52kj9vb5cVLarp+j1n1zifKKLZkpkDlaNZPG m63/R47YsNs/aUbSvA4FZcRevRpvx5mS8Fn7ZnwB5PZxJOrOYvD/I+H6/fnkXlFk2LCW EBc9OHU6KLoWPYytgv6dKY9TzewfzP/JIvRB5TIInJQf930kdq0iXMPTPs+nMYjiBj5C DVMIWBv5bUGHgThPHp2Ev1d8uBZ2DgJ4/yJDClasuapZhFUIagfmqV3I/movJ38VfM+B 5iCbgFf9wV8QIwClLQcSD1lPsWTLs4Th4wGpcubWfFuDg1VqGFHz8E6/lNoPQ3MF+Ar+ 7cfg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:to:from:subject:message-id:date:user-agent :mime-version:content-type; bh=75dINbXXPMxN1Y98C1MHTGXt4hDsLktNZMGlMzEss9g=; b=RMvSKTMSVS+rGz5y56GHGGkt8TpmafdDdpoqpMZoF4knn4KaejdH01l2C3mUYrGbjU 1b0bB15+qp8HBlqKOpxwAmhVTl3iSqpvRYK5pk6/4koYPFS+cmeyDFlfpo1sXZkaRvnx 1SGoZ/33CbRK+whbOnjB1vXhWJSkC2WGrIaV3zPSEvY2bKWFPM4oRRsukVPsL1ZC6MNM x9Ovy20VDC9HnVLzf6eABrv7CLvjawr11J8ojjTuWtU4HbZoo1OHl9BVHpR4UZ3aXbSi 11HCxgMHkxy8QPeEhpvhrReY9eCSxN0X3iXn0MWeZvfRusM1s0tUvUsQl5uO754Mm1dN vLYw== X-Gm-Message-State: AG10YOQZ74Au4gLG9lEyx7dECX1XnbRnRoaQQcSaGiBJ4AFMRyCSLpitWciIevtl97WG3Q== X-Received: by 10.28.88.81 with SMTP id m78mr18276920wmb.58.1456223709934; Tue, 23 Feb 2016 02:35:09 -0800 (PST) Received: from ?IPv6:2a02:120b:2c41:63f0:a2a8:cdff:fe64:b3b5? ([2a02:120b:2c41:63f0:a2a8:cdff:fe64:b3b5]) by smtp.gmail.com with ESMTPSA id o128sm1354770wmb.19.2016.02.23.02.35.08 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 23 Feb 2016 02:35:08 -0800 (PST) To: The development of GRUB 2 , Leif Lindholm , Ian Campbell From: =?UTF-8?Q?Vladimir_'=cf=86-coder/phcoder'_Serbinenko?= Subject: [PATCH] U-Boot self-relocatable images Message-ID: <56CC35D6.4010108@gmail.com> Date: Tue, 23 Feb 2016 11:35:02 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Icedove/38.6.0 MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="f2Lw3exVbS6RVxPDte6NSPwODSLXGSgbn" X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a00:1450:400c:c09::231 X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Feb 2016 10:35:31 -0000 This is an OpenPGP/MIME signed message (RFC 4880 and 3156) --f2Lw3exVbS6RVxPDte6NSPwODSLXGSgbn Content-Type: multipart/mixed; boundary="------------020603050304080701070805" This is a multi-part message in MIME format. --------------020603050304080701070805 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable 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 --------------020603050304080701070805 Content-Type: text/x-diff; name="0001-mkimage.c-Split-into-separate-files.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="0001-mkimage.c-Split-into-separate-files.patch" =46rom 80f8cfe29ace49167c1ad6439ddd15519b0a5455 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko 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 =3D { =20 common =3D util/grub-mkimage.c; common =3D util/mkimage.c; + common =3D util/grub-mkimage32.c; + common =3D util/grub-mkimage64.c; common =3D util/resolve.c; common =3D grub-core/kern/emu/argp_common.c; common =3D grub-core/osdep/init.c; @@ -510,6 +512,8 @@ program =3D { common =3D util/render-label.c; common =3D util/glue-efi.c; common =3D util/mkimage.c; + common =3D util/grub-mkimage32.c; + common =3D util/grub-mkimage64.c; common =3D util/grub-install-common.c; common =3D util/setup_bios.c; common =3D util/setup_sparc.c; @@ -552,6 +556,8 @@ program =3D { common =3D util/render-label.c; common =3D util/glue-efi.c; common =3D util/mkimage.c; + common =3D util/grub-mkimage32.c; + common =3D util/grub-mkimage64.c; common =3D util/grub-install-common.c; common =3D util/setup_bios.c; common =3D util/setup_sparc.c; @@ -595,6 +601,8 @@ program =3D { common =3D util/grub-install.c; common =3D util/probe.c; common =3D util/mkimage.c; + common =3D util/grub-mkimage32.c; + common =3D util/grub-mkimage64.c; common =3D util/grub-install-common.c; common =3D util/setup_bios.c; common =3D util/setup_sparc.c; @@ -632,6 +640,8 @@ program =3D { common =3D util/grub-mknetdir.c; =20 common =3D util/mkimage.c; + common =3D util/grub-mkimage32.c; + common =3D util/grub-mkimage64.c; common =3D util/grub-install-common.c; common =3D util/setup_bios.c; common =3D 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 . + */ + +#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,=20 + 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,=20 + 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_ELTORIT= O + } id; + enum + { + PLATFORM_FLAGS_NONE =3D 0, + PLATFORM_FLAGS_DECOMPRESSORS =3D 2, + PLATFORM_FLAGS_MODULES_BEFORE_KERNEL =3D 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_targ= et, (x))) +#define grub_host_to_target32(x) (grub_host_to_target32_real (image_targ= et, (x))) +#define grub_target_to_host64(x) (grub_target_to_host64_real (image_targ= et, (x))) +#define grub_host_to_target64(x) (grub_host_to_target64_real (image_targ= et, (x))) +#define grub_host_to_target_addr(x) (grub_host_to_target_addr_real (imag= e_target, (x))) +#define grub_target_to_host16(x) (grub_target_to_host16_real (image_targ= et, (x))) +#define grub_host_to_target16(x) (grub_host_to_target16_real (image_targ= et, (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_de= sc *image_target, grub_uint64_t in) +{ + if (image_target->voidp_sizeof =3D=3D 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 *i= mage_target, grub_uint64_t in) +{ + if (image_target->voidp_sizeof =3D=3D 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 . */ =20 -#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma GCC diagnostic ignored "-Wcast-align" =20 static Elf_Addr SUFFIX (entry_point); =20 -static void -SUFFIX (generate_elf) (const struct grub_install_image_target_desc *imag= e_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 IEEE127= 5, + "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 =3D grub_arm_thm_call_get_offset (target); + + grub_dprintf ("dl", " sym_addr =3D 0x%08x", sym_addr); + + offset +=3D sym_addr; + + grub_dprintf("dl", " BL*: target=3D%p, sym_addr=3D0x%08x, offset=3D%d\= n", + target, sym_addr, offset); + + /* Keep traditional (pre-Thumb2) limits on blx. In any case if the ker= nel + is bigger than 2M (currently under 150K) then we probably have a p= roblem + somewhere else. */ + if (offset < -0x200000 || offset >=3D 0x200000) + return grub_error (GRUB_ERR_BAD_MODULE, + "THM_CALL Relocation out of range."); + + grub_dprintf ("dl", " relative destination =3D %p", + (char *) target + offset); + + return grub_arm_thm_call_set_offset (target, offset); +} + +/* + * R_ARM_THM_JUMP19 + * + * Relocate conditional Thumb (T32) B.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 =3D grub_arm_thm_jump19_get_offset (target); + + /* Adjust and re-truncate offset */ + offset +=3D 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 =3D grub_arm_jump24_get_offset (target); + offset +=3D 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_targ= et_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; } =20 -static char * -SUFFIX (load_image) (const char *kernel_path, size_t *exec_size,=20 - 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,=20 + 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, =20 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 #include #include +#include =20 #define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof)) =20 @@ -58,40 +59,6 @@ /* use 2015-01-01T00:00:00+0000 as a stock timestamp */ #define STABLE_EMBEDDING_TIMESTAMP 1420070400 =20 -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_ELTORIT= O - } id; - enum - { - PLATFORM_FLAGS_NONE =3D 0, - PLATFORM_FLAGS_DECOMPRESSORS =3D 2, - PLATFORM_FLAGS_MODULES_BEFORE_KERNEL =3D 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[] =3D }, }; =20 -#define grub_target_to_host32(x) (grub_target_to_host32_real (image_targ= et, (x))) -#define grub_host_to_target32(x) (grub_host_to_target32_real (image_targ= et, (x))) -#define grub_target_to_host64(x) (grub_target_to_host64_real (image_targ= et, (x))) -#define grub_host_to_target64(x) (grub_host_to_target64_real (image_targ= et, (x))) -#define grub_host_to_target_addr(x) (grub_host_to_target_addr_real (imag= e_target, (x))) -#define grub_target_to_host16(x) (grub_target_to_host16_real (image_targ= et, (x))) -#define grub_host_to_target16(x) (grub_host_to_target16_real (image_targ= et, (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_de= sc *image_target, grub_uint64_t in) -{ - if (image_target->voidp_sizeof =3D=3D 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 *i= mage_target, grub_uint64_t in) -{ - if (image_target->voidp_sizeof =3D=3D 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 IEEE127= 5, - "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 =20 static void *SzAlloc(void *p __attribute__ ((unused)), size_t size) { re= turn xmalloc(size); } @@ -830,111 +684,6 @@ compress_kernel (const struct grub_install_image_ta= rget_desc *image_target, char *core_size =3D kernel_size; } =20 -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 =3D grub_arm_thm_call_get_offset (target); - - grub_dprintf ("dl", " sym_addr =3D 0x%08x", sym_addr); - - offset +=3D sym_addr; - - grub_dprintf("dl", " BL*: target=3D%p, sym_addr=3D0x%08x, offset=3D%d\= n", - target, sym_addr, offset); - - /* Keep traditional (pre-Thumb2) limits on blx. In any case if the ker= nel - is bigger than 2M (currently under 150K) then we probably have a p= roblem - somewhere else. */ - if (offset < -0x200000 || offset >=3D 0x200000) - return grub_error (GRUB_ERR_BAD_MODULE, - "THM_CALL Relocation out of range."); - - grub_dprintf ("dl", " relative destination =3D %p", - (char *) target + offset); - - return grub_arm_thm_call_set_offset (target, offset); -} - -/* - * R_ARM_THM_JUMP19 - * - * Relocate conditional Thumb (T32) B.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 =3D grub_arm_thm_jump19_get_offset (target); - - /* Adjust and re-truncate offset */ - offset +=3D 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 =3D grub_arm_jump24_get_offset (target); - offset +=3D 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, cons= t char *prefix, (unsigned long long) total_module_size); =20 if (image_target->voidp_sizeof =3D=3D 4) - kernel_img =3D load_image32 (kernel_path, &exec_size, &kernel_size, = &bss_size, - total_module_size, &start_address, &rel_section, - &reloc_size, &align, image_target); + kernel_img =3D 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 =3D load_image64 (kernel_path, &exec_size, &kernel_size, = &bss_size, - total_module_size, &start_address, &rel_section, - &reloc_size, &align, image_target); + kernel_img =3D 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 =3D=3D IMAGE_XEN && align < 4096) align =3D 4096; =20 @@ -1890,11 +1639,11 @@ grub_install_generate_image (const char *dir, con= st char *prefix, else target_addr =3D image_target->link_addr; if (image_target->voidp_sizeof =3D=3D 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_siz= e, + 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_siz= e, + target_addr, align, kernel_size, bss_size); } break; } --=20 2.7.0 --------------020603050304080701070805 Content-Type: text/x-diff; name="0002-mkimagexx-Split-PE-and-generic-part-for-relocations.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename*0="0002-mkimagexx-Split-PE-and-generic-part-for-relocations.pat"; filename*1="ch" =46rom 88091fb936a45f8dece352c5bec26e011f9573c3 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Thu, 18 Feb 2016 20:54:37 +0100 Subject: [PATCH 2/6] mkimagexx: Split PE and generic part for relocations= =2E 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 addre= ss 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; =20 @@ -1187,22 +1187,222 @@ SUFFIX (add_fixup_entry) (struct fixup_block_lis= t **cblock, grub_uint16_t type, return current_address; } =20 +struct translate_context +{ + struct fixup_block_list *lst, *lst0; + Elf_Addr current_address; +}; + +static void +translate_reloc_start (struct translate_context *ctx) +{ + ctx->lst =3D ctx->lst0 =3D xmalloc (sizeof (*ctx->lst) + 2 * 0x1000); + memset (ctx->lst, 0, sizeof (*ctx->lst) + 2 * 0x1000); + ctx->current_address =3D 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) =3D=3D R_386_32) + { + grub_util_info ("adding a relocation entry for 0x%" + GRUB_HOST_PRIxLONG_LONG, + (unsigned long long) addr); + ctx->current_address + =3D 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) =3D=3D R_X86_64_32) || + (ELF_R_TYPE (info) =3D=3D R_X86_64_32S)) + { + grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)"); + } + else if (ELF_R_TYPE (info) =3D=3D R_X86_64_64) + { + grub_util_info ("adding a relocation entry for 0x%" + GRUB_HOST_PRIxLONG_LONG, + (unsigned long long) addr); + ctx->current_address + =3D 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 + =3D 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 + =3D 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", __FUNCT= ION__, (unsigned int) addr, (unsigned int) ctx->current_address); + } + break; + /* Create fixup entry for PE/COFF loader */ + case R_ARM_ABS32: + { + ctx->current_address + =3D 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_ta= rget); + } +} + +static Elf_Addr +finish_reloc_translation (struct translate_context *ctx, void **out, + const struct grub_install_image_target_desc *image_target) +{ + ctx->current_address =3D add_fixup_entry (&ctx->lst, 0, 0, 1, ctx->cur= rent_address, image_target); + + { + grub_uint8_t *ptr; + ptr =3D *out =3D xmalloc (ctx->current_address); + for (ctx->lst =3D ctx->lst0; ctx->lst; ctx->lst =3D ctx->lst->next) + if (ctx->lst->state) + { + memcpy (ptr, &ctx->lst->b, grub_target_to_host32 (ctx->lst->b.block_s= ize)); + ptr +=3D grub_target_to_host32 (ctx->lst->b.block_size); + } + assert ((ctx->current_address + (grub_uint8_t *) *out) =3D=3D ptr); + } + + for (ctx->lst =3D ctx->lst0; ctx->lst; ) + { + struct fixup_block_list *next; + next =3D ctx->lst->next; + free (ctx->lst); + ctx->lst =3D 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 =3D 0; i < njumpers; i++) + ctx->current_address =3D 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 =3D 0; + struct translate_context ctx; =20 - lst =3D lst0 =3D xmalloc (sizeof (*lst) + 2 * 0x1000); - memset (lst, 0, sizeof (*lst) + 2 * 0x1000); + translate_reloc_start (&ctx); =20 for (i =3D 0, s =3D sections; i < num_sections; i++, s =3D (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; =20 offset =3D grub_target_to_host (r->r_offset); info =3D grub_target_to_host (r->r_info); =20 - /* Necessary to relocate only absolute addresses. */ - switch (image_target->elf_target) - { - case EM_386: - if (ELF_R_TYPE (info) =3D=3D R_386_32) - { - Elf_Addr addr; + addr =3D section_address + offset; =20 - addr =3D section_address + offset; - grub_util_info ("adding a relocation entry for 0x%" - GRUB_HOST_PRIxLONG_LONG, - (unsigned long long) addr); - current_address - =3D 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) =3D=3D R_X86_64_32) || - (ELF_R_TYPE (info) =3D=3D R_X86_64_32S)) - { - grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)"); - } - else if (ELF_R_TYPE (info) =3D=3D R_X86_64_64) - { - Elf_Addr addr; - - addr =3D section_address + offset; - grub_util_info ("adding a relocation entry for 0x%" - GRUB_HOST_PRIxLONG_LONG, - (unsigned long long) addr); - current_address - =3D 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 =3D section_address + offset; - grub_util_info ("adding a relocation entry for 0x%" - GRUB_HOST_PRIxLONG_LONG, - (unsigned long long) addr); - current_address - =3D 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 =3D section_address + offset; - current_address - =3D 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 =3D section_address + offset; - grub_util_info (" %s: not adding fixup: 0x%08x : 0x%08x", __FU= NCTION__, (unsigned int) addr, (unsigned int) current_address); - } - break; - /* Create fixup entry for PE/COFF loader */ - case R_ARM_ABS32: - { - Elf_Addr addr; - - addr =3D section_address + offset; - current_address - =3D 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); } } =20 if (image_target->elf_target =3D=3D EM_IA_64) - for (i =3D 0; i < njumpers; i++) - current_address =3D 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); =20 - current_address =3D SUFFIX (add_fixup_entry) (&lst, 0, 0, 1, current_a= ddress, image_target); - - { - grub_uint8_t *ptr; - ptr =3D *out =3D xmalloc (current_address); - for (lst =3D lst0; lst; lst =3D lst->next) - if (lst->state) - { - memcpy (ptr, &lst->b, grub_target_to_host32 (lst->b.block_size)); - ptr +=3D grub_target_to_host32 (lst->b.block_size); - } - assert ((current_address + (grub_uint8_t *) *out) =3D=3D ptr); - } - - for (lst =3D lst0; lst; ) - { - struct fixup_block_list *next; - next =3D lst->next; - free (lst); - lst =3D next; - } - - return current_address; + return finish_reloc_translation (&ctx, out, image_target); } =20 /* Determine if this section is a text section. Return false if this --=20 2.7.0 --------------020603050304080701070805 Content-Type: text/x-diff; name="0003-Encapsulate-image-layout-into-a-separate-structure.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename*0="0003-Encapsulate-image-layout-into-a-separate-structure.patc"; filename*1="h" =46rom 7cfa8d4568b714b463e0ad4ac900017a538a5840 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko 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 =20 +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,=20 - 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,=20 - 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 *c= tx, } } =20 -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 =3D add_fixup_entry (&ctx->lst, 0, 0, 1, ctx->cur= rent_address, image_target); =20 { grub_uint8_t *ptr; - ptr =3D *out =3D xmalloc (ctx->current_address); + layout->reloc_section =3D ptr =3D xmalloc (ctx->current_address); for (ctx->lst =3D ctx->lst0; ctx->lst; ctx->lst =3D ctx->lst->next) if (ctx->lst->state) { memcpy (ptr, &ctx->lst->b, grub_target_to_host32 (ctx->lst->b.block_s= ize)); ptr +=3D grub_target_to_host32 (ctx->lst->b.block_size); } - assert ((ctx->current_address + (grub_uint8_t *) *out) =3D=3D ptr); + assert ((ctx->current_address + (grub_uint8_t *) layout->reloc_secti= on) =3D=3D ptr); } =20 for (ctx->lst =3D ctx->lst0; ctx->lst; ) @@ -1372,7 +1373,7 @@ finish_reloc_translation (struct translate_context = *ctx, void **out, ctx->lst =3D next; } =20 - return ctx->current_address; + layout->reloc_size =3D ctx->current_address; } =20 static void @@ -1390,8 +1391,8 @@ translate_reloc_jumpers (struct translate_context *= ctx, } =20 /* 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); =20 - return finish_reloc_translation (&ctx, out, image_target); + finish_reloc_translation (&ctx, layout, image_target); } =20 /* 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; =20 - *all_align =3D 1; + layout->align =3D 1; /* Page-aligning simplifies relocation handling. */ if (image_target->elf_target =3D=3D EM_AARCH64) - *all_align =3D 4096; + layout->align =3D 4096; =20 section_addresses =3D xmalloc (sizeof (*section_addresses) * num_secti= ons); memset (section_addresses, 0, sizeof (*section_addresses) * num_sectio= ns); @@ -1521,8 +1521,8 @@ SUFFIX (locate_sections) (const char *kernel_path, i < num_sections; i++, s =3D (Elf_Shdr *) ((char *) s + section_entsize)) if ((grub_target_to_host (s->sh_flags) & SHF_ALLOC)=20 - && grub_host_to_target32 (s->sh_addralign) > *all_align) - *all_align =3D grub_host_to_target32 (s->sh_addralign); + && grub_host_to_target32 (s->sh_addralign) > layout->align) + layout->align =3D grub_host_to_target32 (s->sh_addralign); =20 =20 /* .text */ @@ -1562,7 +1562,7 @@ SUFFIX (locate_sections) (const char *kernel_path, current_address =3D ALIGN_UP (current_address + image_target->vaddr_of= fset, image_target->section_align) - image_target->vaddr_offset; - *exec_size =3D current_address; + layout->exec_size =3D current_address; =20 /* .data */ for (i =3D 0, s =3D sections; @@ -1590,16 +1590,14 @@ SUFFIX (locate_sections) (const char *kernel_path= , =20 current_address =3D ALIGN_UP (current_address + image_target->vaddr_of= fset, image_target->section_align) - image_target->vaddr_offset; - *kernel_sz =3D current_address; + layout->kernel_size =3D current_address; return section_addresses; } =20 char * -SUFFIX (grub_mkimage_load_image) (const char *kernel_path, size_t *exec_= size,=20 - 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 *ker= nel_path, size_t *exec_size, Elf_Off section_offset; Elf_Half section_entsize; grub_size_t kernel_size; - grub_size_t ia64jmp_off =3D 0, tramp_off =3D 0, ia64_got_off =3D 0; - unsigned ia64jmpnum =3D 0; Elf_Shdr *symtab_section =3D 0; - grub_size_t got =3D 0; =20 - *start =3D 0; + grub_memset (layout, 0, sizeof (*layout)); + + layout->start_address =3D 0; =20 kernel_size =3D grub_util_get_image_size (kernel_path); kernel_img =3D xmalloc (kernel_size); @@ -1646,7 +1643,7 @@ SUFFIX (grub_mkimage_load_image) (const char *kerne= l_path, size_t *exec_size, section_addresses =3D SUFFIX (locate_sections) (kernel_path, sections, section_entsize, num_sections, strtab, - exec_size, kernel_sz, align, + layout, image_target); =20 section_vaddresses =3D xmalloc (sizeof (*section_addresses) * num_sect= ions); @@ -1656,7 +1653,7 @@ SUFFIX (grub_mkimage_load_image) (const char *kerne= l_path, size_t *exec_size, =20 if (image_target->id !=3D IMAGE_EFI) { - Elf_Addr current_address =3D *kernel_sz; + Elf_Addr current_address =3D layout->kernel_size; =20 for (i =3D 0, s =3D sections; i < num_sections; @@ -1686,15 +1683,15 @@ SUFFIX (grub_mkimage_load_image) (const char *ker= nel_path, size_t *exec_size, current_address =3D ALIGN_UP (current_address + image_target->vadd= r_offset, image_target->section_align) - image_target->vaddr_offset; - *bss_size =3D current_address - *kernel_sz; + layout->bss_size =3D current_address - layout->kernel_size; } else - *bss_size =3D 0; + layout->bss_size =3D 0; =20 if (image_target->id =3D=3D IMAGE_SPARC64_AOUT || image_target->id =3D=3D IMAGE_SPARC64_RAW || image_target->id =3D=3D IMAGE_SPARC64_CDCORE) - *kernel_sz =3D ALIGN_UP (*kernel_sz, image_target->mod_align); + layout->kernel_size =3D ALIGN_UP (layout->kernel_size, image_target-= >mod_align); =20 if (image_target->id =3D=3D IMAGE_EFI) { @@ -1715,13 +1712,13 @@ SUFFIX (grub_mkimage_load_image) (const char *ker= nel_path, size_t *exec_size, { grub_size_t tramp; =20 - *kernel_sz =3D ALIGN_UP (*kernel_sz, 16); + layout->kernel_size =3D ALIGN_UP (layout->kernel_size, 16); =20 tramp =3D arm_get_trampoline_size (e, sections, section_entsize, num_sections, image_target); =20 - tramp_off =3D *kernel_sz; - *kernel_sz +=3D ALIGN_UP (tramp, 16); + layout->tramp_off =3D layout->kernel_size; + layout->kernel_size +=3D ALIGN_UP (tramp, 16); } #endif =20 @@ -1730,61 +1727,62 @@ SUFFIX (grub_mkimage_load_image) (const char *ker= nel_path, size_t *exec_size, { grub_size_t tramp; =20 - *kernel_sz =3D ALIGN_UP (*kernel_sz, 16); + layout->kernel_size =3D ALIGN_UP (layout->kernel_size, 16); =20 - grub_ia64_dl_get_tramp_got_size (e, &tramp, &got); + grub_ia64_dl_get_tramp_got_size (e, &tramp, &layout->got_size); =20 - tramp_off =3D *kernel_sz; - *kernel_sz +=3D ALIGN_UP (tramp, 16); + layout->tramp_off =3D layout->kernel_size; + layout->kernel_size +=3D ALIGN_UP (tramp, 16); =20 - ia64jmp_off =3D *kernel_sz; - ia64jmpnum =3D SUFFIX (count_funcs) (e, symtab_section, + layout->ia64jmp_off =3D layout->kernel_size; + layout->ia64jmpnum =3D SUFFIX (count_funcs) (e, symtab_section, image_target); - *kernel_sz +=3D 16 * ia64jmpnum; + layout->kernel_size +=3D 16 * layout->ia64jmpnum; =20 - ia64_got_off =3D *kernel_sz; - *kernel_sz +=3D ALIGN_UP (got, 16); + layout->ia64_got_off =3D layout->kernel_size; + layout->kernel_size +=3D ALIGN_UP (layout->got_size, 16); } #endif =20 } else { - *reloc_size =3D 0; - *reloc_section =3D NULL; + layout->reloc_size =3D 0; + layout->reloc_section =3D NULL; } =20 - out_img =3D xmalloc (*kernel_sz + total_module_size); - memset (out_img, 0, *kernel_sz + total_module_size); + out_img =3D xmalloc (layout->kernel_size + total_module_size); + memset (out_img, 0, layout->kernel_size + total_module_size); =20 if (image_target->id =3D=3D IMAGE_EFI) { - *start =3D SUFFIX (relocate_symbols) (e, sections, symtab_section,= + layout->start_address =3D SUFFIX (relocate_symbols) (e, sections, = symtab_section, section_vaddresses, section_entsize, num_sections,=20 - (char *) out_img + ia64jmp_off,=20 - ia64jmp_off=20 + (char *) out_img + layout->ia64jmp_off,=20 + layout->ia64jmp_off=20 + image_target->vaddr_offset, image_target); - if (*start =3D=3D 0) + if (layout->start_address =3D=3D 0) grub_util_error ("start symbol is not defined"); =20 - SUFFIX (entry_point) =3D (Elf_Addr) *start; + SUFFIX (entry_point) =3D (Elf_Addr) layout->start_address; =20 /* Resolve addresses in the virtual address space. */ SUFFIX (relocate_addresses) (e, sections, section_addresses,=20 section_entsize, num_sections, strtab, - out_img, tramp_off, ia64_got_off, + out_img, layout->tramp_off, + layout->ia64_got_off, image_target); =20 - *reloc_size =3D 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); } =20 for (i =3D 0, s =3D 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 =3D 0, config_size =3D 0; size_t prefix_size =3D 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 =3D 0; - size_t reloc_size =3D 0, align; size_t decompress_size =3D 0; + struct grub_mkimage_layout layout; =20 if (comp =3D=3D GRUB_COMPRESSION_AUTO) comp =3D image_target->default_compression; @@ -812,15 +809,13 @@ grub_install_generate_image (const char *dir, const= char *prefix, (unsigned long long) total_module_size); =20 if (image_target->voidp_sizeof =3D=3D 4) - kernel_img =3D 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 =3D grub_mkimage_load_image32 (kernel_path, total_module_= size, + &layout, image_target); else - kernel_img =3D 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 =3D=3D IMAGE_XEN && align < 4096) - align =3D 4096; + kernel_img =3D grub_mkimage_load_image64 (kernel_path, total_module_= size, + &layout, image_target); + if (image_target->id =3D=3D IMAGE_XEN && layout.align < 4096) + layout.align =3D 4096; =20 if ((image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS) && (image_target->total_module_size !=3D TARGET_NO_FIELD)) @@ -829,7 +824,7 @@ grub_install_generate_image (const char *dir, const c= har *prefix, =20 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); } =20 @@ -840,14 +835,14 @@ grub_install_generate_image (const char *dir, const= char *prefix, if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL) modinfo =3D (struct grub_module_info64 *) kernel_img; else - modinfo =3D (struct grub_module_info64 *) (kernel_img + kernel_size); + modinfo =3D (struct grub_module_info64 *) (kernel_img + layout.kernel_s= ize); modinfo->magic =3D grub_host_to_target32 (GRUB_MODULE_MAGIC); modinfo->offset =3D grub_host_to_target_addr (sizeof (struct grub_= module_info64)); modinfo->size =3D grub_host_to_target_addr (total_module_size); if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL) offset =3D sizeof (struct grub_module_info64); else - offset =3D kernel_size + sizeof (struct grub_module_info64); + offset =3D 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 =3D (struct grub_module_info32 *) kernel_img; else - modinfo =3D (struct grub_module_info32 *) (kernel_img + kernel_size); + modinfo =3D (struct grub_module_info32 *) (kernel_img + layout.kernel_s= ize); modinfo->magic =3D grub_host_to_target32 (GRUB_MODULE_MAGIC); modinfo->offset =3D grub_host_to_target_addr (sizeof (struct grub_= module_info32)); modinfo->size =3D grub_host_to_target_addr (total_module_size); if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL) offset =3D sizeof (struct grub_module_info32); else - offset =3D kernel_size + sizeof (struct grub_module_info32); + offset =3D layout.kernel_size + sizeof (struct grub_module_info32); } =20 for (p =3D path_list; p; p =3D p->next) @@ -942,8 +937,8 @@ grub_install_generate_image (const char *dir, const c= har *prefix, =20 grub_util_info ("kernel_img=3D%p, kernel_size=3D0x%" GRUB_HOST_PRIxLON= G_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); =20 @@ -995,7 +990,7 @@ grub_install_generate_image (const char *dir, const c= har *prefix, if (image_target->decompressor_uncompressed_size !=3D TARGET_NO_FI= ELD) *((grub_uint32_t *) (decompress_img + image_target->decompressor_uncompressed_size)) - =3D grub_host_to_target32 (kernel_size + total_module_size); + =3D grub_host_to_target32 (layout.kernel_size + total_module_size); =20 if (image_target->decompressor_uncompressed_addr !=3D TARGET_NO_FI= ELD) { @@ -1028,16 +1023,17 @@ grub_install_generate_image (const char *dir, con= st 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 > 0x6800= 0)) + || (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_ADD= R > 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, con= st char *prefix, reloc_addr =3D ALIGN_UP (header_size + core_size, image_target->section_align); =20 - pe_size =3D ALIGN_UP (reloc_addr + reloc_size, + pe_size =3D ALIGN_UP (reloc_addr + layout.reloc_size, image_target->section_align); - pe_img =3D xmalloc (reloc_addr + reloc_size); + pe_img =3D 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 - (hea= der_size + core_size)); - memcpy ((char *) pe_img + reloc_addr, rel_section, reloc_size); + memcpy ((char *) pe_img + reloc_addr, layout.reloc_section, layout.relo= c_size); header =3D pe_img; =20 /* The magic. */ @@ -1199,14 +1195,14 @@ grub_install_generate_image (const char *dir, con= st char *prefix, (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE + sizeof (struct grub_pe32_coff_header)); o->magic =3D grub_host_to_target16 (GRUB_PE32_PE32_MAGIC); - o->code_size =3D grub_host_to_target32 (exec_size); - o->data_size =3D grub_cpu_to_le32 (reloc_addr - exec_size + o->code_size =3D grub_host_to_target32 (layout.exec_size); + o->data_size =3D grub_cpu_to_le32 (reloc_addr - layout.exec_size - header_size); - o->bss_size =3D grub_cpu_to_le32 (bss_size); - o->entry_addr =3D grub_cpu_to_le32 (start_address); + o->bss_size =3D grub_cpu_to_le32 (layout.bss_size); + o->entry_addr =3D grub_cpu_to_le32 (layout.start_address); o->code_base =3D grub_cpu_to_le32 (header_size); =20 - o->data_base =3D grub_host_to_target32 (header_size + exec_size); + o->data_base =3D grub_host_to_target32 (header_size + layout.exec_s= ize); =20 o->image_base =3D 0; o->section_alignment =3D grub_host_to_target32 (image_target->secti= on_align); @@ -1224,7 +1220,7 @@ grub_install_generate_image (const char *dir, const= char *prefix, o->num_data_directories =3D grub_host_to_target32 (GRUB_PE32_NUM_DA= TA_DIRECTORIES); =20 o->base_relocation_table.rva =3D grub_host_to_target32 (reloc_addr)= ; - o->base_relocation_table.size =3D grub_host_to_target32 (reloc_size= ); + o->base_relocation_table.size =3D grub_host_to_target32 (layout.rel= oc_size); sections =3D o + 1; } else @@ -1237,11 +1233,11 @@ grub_install_generate_image (const char *dir, con= st char *prefix, (header + GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE + sizeof (struct grub_pe32_coff_header)); o->magic =3D grub_host_to_target16 (GRUB_PE32_PE64_MAGIC); - o->code_size =3D grub_host_to_target32 (exec_size); - o->data_size =3D grub_cpu_to_le32 (reloc_addr - exec_size + o->code_size =3D grub_host_to_target32 (layout.exec_size); + o->data_size =3D grub_cpu_to_le32 (reloc_addr - layout.exec_size - header_size); - o->bss_size =3D grub_cpu_to_le32 (bss_size); - o->entry_addr =3D grub_cpu_to_le32 (start_address); + o->bss_size =3D grub_cpu_to_le32 (layout.bss_size); + o->entry_addr =3D grub_cpu_to_le32 (layout.start_address); o->code_base =3D grub_cpu_to_le32 (header_size); o->image_base =3D 0; o->section_alignment =3D grub_host_to_target32 (image_target->secti= on_align); @@ -1260,15 +1256,15 @@ grub_install_generate_image (const char *dir, con= st char *prefix, =3D grub_host_to_target32 (GRUB_PE32_NUM_DATA_DIRECTORIES); =20 o->base_relocation_table.rva =3D grub_host_to_target32 (reloc_addr)= ; - o->base_relocation_table.size =3D grub_host_to_target32 (reloc_size= ); + o->base_relocation_table.size =3D grub_host_to_target32 (layout.rel= oc_size); sections =3D o + 1; } /* The sections. */ text_section =3D sections; strcpy (text_section->name, ".text"); - text_section->virtual_size =3D grub_cpu_to_le32 (exec_size); + text_section->virtual_size =3D grub_cpu_to_le32 (layout.exec_size); text_section->virtual_address =3D grub_cpu_to_le32 (header_size); - text_section->raw_data_size =3D grub_cpu_to_le32 (exec_size); + text_section->raw_data_size =3D grub_cpu_to_le32 (layout.exec_size); text_section->raw_data_offset =3D grub_cpu_to_le32 (header_size); text_section->characteristics =3D grub_cpu_to_le32_compile_time ( GRUB_PE32_SCN_CNT_CODE @@ -1277,10 +1273,10 @@ grub_install_generate_image (const char *dir, con= st char *prefix, =20 data_section =3D text_section + 1; strcpy (data_section->name, ".data"); - data_section->virtual_size =3D grub_cpu_to_le32 (kernel_size - exec_siz= e); - data_section->virtual_address =3D grub_cpu_to_le32 (header_size + exec_= size); - data_section->raw_data_size =3D grub_cpu_to_le32 (kernel_size - exec_si= ze); - data_section->raw_data_offset =3D grub_cpu_to_le32 (header_size + exec_= size); + data_section->virtual_size =3D grub_cpu_to_le32 (layout.kernel_size - l= ayout.exec_size); + data_section->virtual_address =3D grub_cpu_to_le32 (header_size + layou= t.exec_size); + data_section->raw_data_size =3D grub_cpu_to_le32 (layout.kernel_size - = layout.exec_size); + data_section->raw_data_offset =3D grub_cpu_to_le32 (header_size + layou= t.exec_size); data_section->characteristics =3D 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 =3D data_section + 1; strcpy (bss_section->name, ".bss"); - bss_section->virtual_size =3D grub_cpu_to_le32 (bss_size); - bss_section->virtual_address =3D grub_cpu_to_le32 (header_size + kernel= _size); + bss_section->virtual_size =3D grub_cpu_to_le32 (layout.bss_size); + bss_section->virtual_address =3D grub_cpu_to_le32 (header_size + layout= =2Ekernel_size); bss_section->raw_data_size =3D 0; bss_section->raw_data_offset =3D 0; bss_section->characteristics @@ -1303,10 +1299,10 @@ grub_install_generate_image (const char *dir, con= st char *prefix, =20 mods_section =3D data_section + 1; strcpy (mods_section->name, "mods"); - mods_section->virtual_size =3D grub_cpu_to_le32 (reloc_addr - kernel_si= ze - header_size); - mods_section->virtual_address =3D grub_cpu_to_le32 (header_size + kerne= l_size + bss_size); - mods_section->raw_data_size =3D grub_cpu_to_le32 (reloc_addr - kernel_s= ize - header_size); - mods_section->raw_data_offset =3D grub_cpu_to_le32 (header_size + kerne= l_size); + mods_section->virtual_size =3D grub_cpu_to_le32 (reloc_addr - layout.ke= rnel_size - header_size); + mods_section->virtual_address =3D grub_cpu_to_le32 (header_size + layou= t.kernel_size + layout.bss_size); + mods_section->raw_data_size =3D grub_cpu_to_le32 (reloc_addr - layout.k= ernel_size - header_size); + mods_section->raw_data_offset =3D grub_cpu_to_le32 (header_size + layou= t.kernel_size); mods_section->characteristics =3D 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, =20 reloc_section =3D mods_section + 1; strcpy (reloc_section->name, ".reloc"); - reloc_section->virtual_size =3D grub_cpu_to_le32 (reloc_size); - reloc_section->virtual_address =3D grub_cpu_to_le32 (reloc_addr + bss_s= ize); - reloc_section->raw_data_size =3D grub_cpu_to_le32 (reloc_size); + reloc_section->virtual_size =3D grub_cpu_to_le32 (layout.reloc_size); + reloc_section->virtual_address =3D grub_cpu_to_le32 (reloc_addr + layou= t.bss_size); + reloc_section->raw_data_size =3D grub_cpu_to_le32 (layout.reloc_size); reloc_section->raw_data_offset =3D grub_cpu_to_le32 (reloc_addr); reloc_section->characteristics =3D 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 =3D (image_target->link_addr - decompress_size); else target_addr =3D ALIGN_UP (image_target->link_addr - + kernel_size + total_module_size, 32); + + layout.kernel_size + total_module_size, 32); =20 ecoff_img =3D xmalloc (program_size + sizeof (*head) + sizeof (*section= )); grub_memset (ecoff_img, 0, program_size + sizeof (*head) + sizeof (*sec= tion)); @@ -1634,16 +1630,16 @@ grub_install_generate_image (const char *dir, con= st char *prefix, target_addr =3D (image_target->link_addr - decompress_size); else target_addr =3D ALIGN_UP (image_target->link_addr - + kernel_size + total_module_size, 32); + + layout.kernel_size + total_module_size, 32); } else target_addr =3D image_target->link_addr; if (image_target->voidp_sizeof =3D=3D 4) grub_mkimage_generate_elf32 (image_target, note, &core_img, &core_siz= e, - target_addr, align, kernel_size, bss_size); + target_addr, layout.align, layout.kernel_size, layout.bss_siz= e); else grub_mkimage_generate_elf64 (image_target, note, &core_img, &core_siz= e, - target_addr, align, kernel_size, bss_size); + target_addr, layout.align, layout.kernel_size, layout.bss_siz= e); } 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); =20 grub_util_free_path_list (path_list); } --=20 2.7.0 --------------020603050304080701070805 Content-Type: text/x-diff; name="0004-Provide-__bss_start-and-_end-symbols-in-grub-mkimage.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename*0="0004-Provide-__bss_start-and-_end-symbols-in-grub-mkimage.pa"; filename*1="tch" =46rom dc76d5c6eb07ddab8b20e71b1161fe3a72ca045f Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Thu, 18 Feb 2016 20:57:21 +0100 Subject: [PATCH 4/6] Provide __bss_start and _end symbols in grub-mkimage= =2E 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; }; =20 /* 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 *sec= tions, 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 *s= ections, } else if (cur_index =3D=3D STN_UNDEF) { - if (sym->st_name) + if (sym->st_name && grub_strcmp (name, "__bss_start")) + sym->st_value =3D bss_start; + else if (sym->st_name && grub_strcmp (name, "__end")) + sym->st_value =3D end; + else if (sym->st_name) grub_util_error ("undefined symbol %s", name); else continue; } else if (cur_index >=3D num_sections) grub_util_error ("section %d does not exist", cur_index); - - sym->st_value =3D (grub_target_to_host (sym->st_value) - + section_addresses[cur_index]); + else + { + sym->st_value =3D (grub_target_to_host (sym->st_value) + + section_addresses[cur_index]); + } =20 if (image_target->elf_target =3D=3D EM_IA_64 && ELF_ST_TYPE (sym->= st_info) =3D=3D STT_FUNC) @@ -1462,9 +1469,7 @@ SUFFIX (is_text_section) (Elf_Shdr *s, const struct= grub_install_image_target_de =3D=3D (SHF_EXECINSTR | SHF_ALLOC)); } =20 -/* 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_t= arget_desc *image_target) { @@ -1472,7 +1477,16 @@ SUFFIX (is_data_section) (Elf_Shdr *s, const struc= t grub_install_image_target_de && grub_target_to_host32 (s->sh_type) !=3D SHT_PROGBITS) return 0; return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLO= C)) - =3D=3D SHF_ALLOC); + =3D=3D SHF_ALLOC) && !(grub_target_to_host32 (s->sh_type) =3D=3D SHT_= NOBITS); +} + +static int +SUFFIX (is_bss_section) (Elf_Shdr *s, const struct grub_install_image_ta= rget_desc *image_target) +{ + if (!is_relocatable (image_target)) + return 0; + return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLO= C)) + =3D=3D SHF_ALLOC) && (grub_target_to_host32 (s->sh_type) =3D=3D SHT_N= OBITS); } =20 /* Return if the ELF header is valid. */ @@ -1492,6 +1506,32 @@ SUFFIX (check_elf_header) (Elf_Ehdr *e, size_t siz= e, const struct grub_install_i return 1; } =20 +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 =3D grub_host_to_target_addr (s->sh_addralign); + const char *name =3D strtab + grub_host_to_target32 (s->sh_name); + + if (align) + current_address =3D ALIGN_UP (current_address + image_target->vaddr_o= ffset, + 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 =3D grub_host_to_target_addr (s->sh_addr) + - image_target->link_addr; + section_addresses[i] =3D current_address; + current_address +=3D 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 =3D (Elf_Shdr *) ((char *) s + section_entsize)) if (SUFFIX (is_text_section) (s, image_target)) { - Elf_Word align =3D grub_host_to_target_addr (s->sh_addralign); - const char *name =3D strtab + grub_host_to_target32 (s->sh_name); - if (align) - current_address =3D ALIGN_UP (current_address + image_target->vaddr_o= ffset, - 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 !=3D IMAGE_EFI) + current_address =3D 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) !=3D image_target->link_addr)= { - current_address =3D grub_host_to_target_addr (s->sh_addr) - - image_target->link_addr; - if (grub_host_to_target_addr (s->sh_addr) - !=3D image_target->link_addr) - { - char *msg - =3D 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 + =3D 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] =3D current_address; - current_address +=3D grub_host_to_target_addr (s->sh_size); } =20 current_address =3D ALIGN_UP (current_address + image_target->vaddr_of= fset, @@ -1569,27 +1599,31 @@ SUFFIX (locate_sections) (const char *kernel_path= , i < num_sections; i++, s =3D (Elf_Shdr *) ((char *) s + section_entsize)) if (SUFFIX (is_data_section) (s, image_target)) - { - Elf_Word align =3D grub_host_to_target_addr (s->sh_addralign); - const char *name =3D strtab + grub_host_to_target32 (s->sh_name); + current_address =3D SUFFIX (put_section) (s, i, + current_address, + section_addresses, + strtab, + image_target); =20 - if (align) - current_address =3D ALIGN_UP (current_address + image_target->vaddr_o= ffset, - align) - - image_target->vaddr_offset; + current_address =3D ALIGN_UP (current_address + image_target->vaddr_of= fset, + image_target->section_align) - image_target->vaddr_offset; =20 - grub_util_info ("locating the section %s at 0x%" - GRUB_HOST_PRIxLONG_LONG, - name, (unsigned long long) current_address); - if (image_target->id !=3D IMAGE_EFI) - current_address =3D grub_host_to_target_addr (s->sh_addr) - - image_target->link_addr; - section_addresses[i] =3D current_address; - current_address +=3D grub_host_to_target_addr (s->sh_size); - } + layout->bss_start =3D current_address; + =20 + /* .bss */ + for (i =3D 0, s =3D sections; + i < num_sections; + i++, s =3D (Elf_Shdr *) ((char *) s + section_entsize)) + if (SUFFIX (is_bss_section) (s, image_target)) + current_address =3D SUFFIX (put_section) (s, i, + current_address, + section_addresses, + strtab, + image_target); =20 current_address =3D ALIGN_UP (current_address + image_target->vaddr_of= fset, image_target->section_align) - image_target->vaddr_offset; + layout->end =3D current_address; layout->kernel_size =3D current_address; return section_addresses; } @@ -1789,8 +1823,11 @@ SUFFIX (grub_mkimage_load_image) (const char *kern= el_path, i < num_sections; i++, s =3D (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) =3D=3D SHT_NOBITS) memset (out_img + section_addresses[i], 0, grub_host_to_target_addr (s->sh_size)); --=20 2.7.0 --------------020603050304080701070805 Content-Type: text/x-diff; name="0005-Allow-_start-0-with-relocatable-images.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="0005-Allow-_start-0-with-relocatable-images.patch" =46rom d116b78258afc7664b0fbcae49bb5facbad08129 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Thu, 18 Feb 2016 20:58:38 +0100 Subject: [PATCH 5/6] Allow _start =3D=3D 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 *sec= tions, { Elf_Word symtab_size, sym_size, num_syms; Elf_Off symtab_offset; - Elf_Addr start_address =3D 0; + Elf_Addr start_address =3D (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 *sec= tions, (unsigned long long) sym->st_value, (unsigned long long) section_addresses[cur_index]); =20 - if (! start_address) + if (start_address =3D=3D (Elf_Addr)-1) if (strcmp (name, "_start") =3D=3D 0 || strcmp (name, "start") =3D=3D 0= ) start_address =3D sym->st_value; } @@ -1797,7 +1797,7 @@ SUFFIX (grub_mkimage_load_image) (const char *kerne= l_path, layout->ia64jmp_off=20 + image_target->vaddr_offset, image_target); - if (layout->start_address =3D=3D 0) + if (layout->start_address =3D=3D (Elf_Addr) -1) grub_util_error ("start symbol is not defined"); =20 SUFFIX (entry_point) =3D (Elf_Addr) layout->start_address; --=20 2.7.0 --------------020603050304080701070805 Content-Type: text/x-diff; name="0006-arm-uboot-Make-self-relocatable-to-allow-loading-at-.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename*0="0006-arm-uboot-Make-self-relocatable-to-allow-loading-at-.pa"; filename*1="tch" =46rom a20df5d8ffa95a8af7bbc175c4beff8454cc9875 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko 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 =3D { i386_qemu_cppflags =3D '-DGRUB_BOOT_MACHINE_LINK_ADDR=3D$(GRUB_BOO= T_MACHINE_LINK_ADDR)'; emu_cflags =3D '$(CFLAGS_GNULIB)'; emu_cppflags =3D '$(CPPFLAGS_GNULIB)'; - arm_uboot_ldflags =3D '-Wl,-Ttext=3D0x08000000'; + arm_uboot_ldflags =3D '-Wl,-r,-d'; arm_uboot_stripflags =3D '--strip-unneeded -K start -R .note -R .co= mment -R .note.gnu.gold-version'; =20 i386_pc_startup =3D kern/i386/pc/startup.S; diff --git a/grub-core/kern/arm/uboot/startup.S b/grub-core/kern/arm/uboo= t/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 =20 -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) =20 + @ 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) =20 - 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 =20 - @ 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:=09 + ldr r3, [r0], #4 @load next offset + @ both -2 and -1 are treated the same as we have only one type of reloc= s + @ -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 =3D aligned end of relocations =20 ldr r1, end_ptr @ dst =3D End of BSS ldr r2, grub_total_module_size @ blob size =20 add r1, r1, #GRUB_KERNEL_MACHINE_STACK_SIZE and r1, r1, #~0x7 @ Ensure 8-byte alignment +=09 sub sp, r1, #8 add r1, r1, #1024 =20 @@ -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/ker= nel.h index 06e5433..ce0b149 100644 --- a/include/grub/arm/uboot/kernel.h +++ b/include/grub/arm/uboot/kernel.h @@ -26,7 +26,7 @@ =20 #endif /* ! ASM_FILE */ =20 -#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) =20 #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 @@ =20 #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 =20 /* 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; }; =20 /* 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 =20 #define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof)) =20 +static int +is_relocatable (const struct grub_install_image_target_desc *image_targe= t) +{ + return image_target->id =3D=3D IMAGE_EFI || image_target->id =3D=3D IM= AGE_UBOOT; +} + #ifdef MKIMAGE_ELF32 =20 /* @@ -529,9 +535,9 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sec= tions, } else if (cur_index =3D=3D STN_UNDEF) { - if (sym->st_name && grub_strcmp (name, "__bss_start")) + if (sym->st_name && grub_strcmp (name, "__bss_start") =3D=3D 0) sym->st_value =3D bss_start; - else if (sym->st_name && grub_strcmp (name, "__end")) + else if (sym->st_name && grub_strcmp (name, "_end") =3D=3D 0) sym->st_value =3D 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=3D%d\t(0x%08x)", (int) sym_addr, (int) sym_addr); /* Data will be naturally aligned */ - sym_addr +=3D 0x400; + if (image_target->id =3D=3D IMAGE_EFI) + sym_addr +=3D 0x400; *target =3D grub_host_to_target32 (grub_target_to_host32 (*targ= et) + sym_addr); } break; @@ -1194,25 +1201,45 @@ add_fixup_entry (struct fixup_block_list **cblock= , grub_uint16_t type, return current_address; } =20 +struct raw_reloc +{ + struct raw_reloc *next; + grub_uint32_t offset; + enum raw_reloc_type { + RAW_RELOC_NONE =3D -1, + RAW_RELOC_32 =3D 0, + RAW_RELOC_MAX =3D 1, + } type; +}; + struct translate_context { + /* PE */ struct fixup_block_list *lst, *lst0; Elf_Addr current_address; + + /* Raw */ + struct raw_reloc *raw_relocs; }; =20 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 =3D ctx->lst0 =3D xmalloc (sizeof (*ctx->lst) + 2 * 0x1000); - memset (ctx->lst, 0, sizeof (*ctx->lst) + 2 * 0x1000); - ctx->current_address =3D 0; + grub_memset (ctx, 0, sizeof (*ctx)); + if (image_target->id =3D=3D IMAGE_EFI) + { + ctx->lst =3D ctx->lst0 =3D xmalloc (sizeof (*ctx->lst) + 2 * 0x100= 0); + memset (ctx->lst, 0, sizeof (*ctx->lst) + 2 * 0x1000); + ctx->current_address =3D 0; + } } =20 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 *c= tx, } } =20 +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_ta= rget); + } +} + 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 =3D classify_raw_reloc (info, image_target);= + struct raw_reloc *rel; + if (class =3D=3D RAW_RELOC_NONE) + return; + rel =3D xmalloc (sizeof (*rel)); + rel->next =3D ctx->raw_relocs; + rel->type =3D class; + rel->offset =3D addr; + ctx->raw_relocs =3D 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 =3D=3D 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 =3D add_fixup_entry (&ctx->lst, 0, 0, 1, ctx->cur= rent_address, image_target); =20 { @@ -1381,14 +1466,90 @@ finish_reloc_translation (struct translate_contex= t *ctx, } =20 layout->reloc_size =3D ctx->current_address; + if (image_target->elf_target =3D=3D EM_ARM && layout->reloc_size > GRU= B_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); } =20 +/* + Layout: + + + + + ... + + + 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 =3D 0, sz; + enum raw_reloc_type highest =3D RAW_RELOC_NONE; + enum raw_reloc_type curtype; + struct raw_reloc *cur; + grub_uint32_t *p; + if (!ctx->raw_relocs) + { + layout->reloc_section =3D p =3D xmalloc (sizeof (grub_uint32_t)); + p[0] =3D RAW_END_MARKER; + layout->reloc_size =3D sizeof (grub_uint32_t); + return; + } + for (cur =3D ctx->raw_relocs; cur; cur =3D cur->next) + { + count++; + if (cur->type > highest) + highest =3D cur->type; + } + /* highest separators, count relocations and one end marker. */ + sz =3D (highest + count + 1) * sizeof (grub_uint32_t); + layout->reloc_section =3D p =3D xmalloc (sz); + for (curtype =3D 0; curtype <=3D highest; curtype++) + { + /* Support for special cases would go here. */ + for (cur =3D ctx->raw_relocs; cur; cur =3D cur->next) + if (cur->type =3D=3D curtype) + { + *p++ =3D cur->offset; + } + *p++ =3D RAW_SEPARATOR; + } + *--p =3D RAW_END_MARKER; + layout->reloc_size =3D sz; +} + +static void +finish_reloc_translation (struct translate_context *ctx, struct grub_mki= mage_layout *layout, + const struct grub_install_image_target_desc *image_target) +{ + if (image_target->id =3D=3D 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 =3D=3D IMAGE_EFI); for (i =3D 0; i < njumpers; i++) ctx->current_address =3D add_fixup_entry (&ctx->lst, GRUB_PE32_REL_BASED_DIR64, @@ -1403,14 +1564,13 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkim= age_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; =20 - translate_reloc_start (&ctx); + translate_reloc_start (&ctx, image_target); =20 for (i =3D 0, s =3D sections; i < num_sections; i++, s =3D (Elf_Shdr *) ((char *) s + section_entsize)) @@ -1451,7 +1611,10 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkima= ge_layout *layout, } =20 if (image_target->elf_target =3D=3D 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); =20 finish_reloc_translation (&ctx, layout, image_target); @@ -1462,7 +1625,7 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimag= e_layout *layout, static int SUFFIX (is_text_section) (Elf_Shdr *s, const struct grub_install_image_t= arget_desc *image_target) { - if (image_target->id !=3D IMAGE_EFI=20 + if (!is_relocatable (image_target) && grub_target_to_host32 (s->sh_type) !=3D SHT_PROGBITS) return 0; return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLO= C)) @@ -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_t= arget_desc *image_target) { - if (image_target->id !=3D IMAGE_EFI=20 + if (!is_relocatable (image_target)=20 && grub_target_to_host32 (s->sh_type) !=3D SHT_PROGBITS) return 0; return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLO= C)) @@ -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; =20 @@ -1555,7 +1717,7 @@ SUFFIX (locate_sections) (const char *kernel_path, section_addresses =3D xmalloc (sizeof (*section_addresses) * num_secti= ons); memset (section_addresses, 0, sizeof (*section_addresses) * num_sectio= ns); =20 - current_address =3D 0; + layout->kernel_size =3D 0; =20 for (i =3D 0, s =3D sections; i < num_sections; @@ -1571,8 +1733,8 @@ SUFFIX (locate_sections) (const char *kernel_path, i++, s =3D (Elf_Shdr *) ((char *) s + section_entsize)) if (SUFFIX (is_text_section) (s, image_target)) { - current_address =3D SUFFIX (put_section) (s, i, - current_address, + layout->kernel_size =3D SUFFIX (put_section) (s, i, + layout->kernel_size, section_addresses, strtab, image_target); @@ -1589,42 +1751,63 @@ SUFFIX (locate_sections) (const char *kernel_path= , } } =20 - current_address =3D ALIGN_UP (current_address + image_target->vaddr_of= fset, + layout->kernel_size =3D ALIGN_UP (layout->kernel_size + image_target->= vaddr_offset, image_target->section_align) - image_target->vaddr_offset; - layout->exec_size =3D current_address; + layout->exec_size =3D layout->kernel_size; =20 /* .data */ for (i =3D 0, s =3D sections; i < num_sections; i++, s =3D (Elf_Shdr *) ((char *) s + section_entsize)) if (SUFFIX (is_data_section) (s, image_target)) - current_address =3D SUFFIX (put_section) (s, i, - current_address, + layout->kernel_size =3D SUFFIX (put_section) (s, i, + layout->kernel_size, section_addresses, strtab, image_target); =20 - current_address =3D ALIGN_UP (current_address + image_target->vaddr_of= fset, - image_target->section_align) - image_target->vaddr_offset; +#ifdef MKIMAGE_ELF32 + if (image_target->elf_target =3D=3D EM_ARM) + { + grub_size_t tramp; + layout->kernel_size =3D ALIGN_UP (layout->kernel_size + image_targ= et->vaddr_offset, + image_target->section_align) - image_target->vaddr_offset; =20 - layout->bss_start =3D current_address; + layout->kernel_size =3D ALIGN_UP (layout->kernel_size, 16); + + tramp =3D arm_get_trampoline_size (e, sections, section_entsize, + num_sections, image_target); + + layout->tramp_off =3D layout->kernel_size; + layout->kernel_size +=3D ALIGN_UP (tramp, 16); + } +#endif + + layout->bss_start =3D layout->kernel_size; + layout->end =3D layout->kernel_size; =20 /* .bss */ for (i =3D 0, s =3D sections; i < num_sections; i++, s =3D (Elf_Shdr *) ((char *) s + section_entsize)) if (SUFFIX (is_bss_section) (s, image_target)) - current_address =3D SUFFIX (put_section) (s, i, - current_address, - section_addresses, - strtab, - image_target); + layout->end =3D SUFFIX (put_section) (s, i, + layout->end, + section_addresses, + strtab, + image_target); =20 - current_address =3D ALIGN_UP (current_address + image_target->vaddr_of= fset, + layout->end =3D ALIGN_UP (layout->end + image_target->vaddr_offset, image_target->section_align) - image_target->vaddr_offset; - layout->end =3D current_address; - layout->kernel_size =3D 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 !=3D IMAGE_UBOOT) + layout->kernel_size =3D layout->end; + return section_addresses; } =20 @@ -1674,7 +1857,7 @@ SUFFIX (grub_mkimage_load_image) (const char *kerne= l_path, + grub_host_to_target16 (e->e_shstrndx) * section_entsize); strtab =3D (char *) e + grub_host_to_target_addr (s->sh_offset); =20 - section_addresses =3D SUFFIX (locate_sections) (kernel_path, + section_addresses =3D SUFFIX (locate_sections) (e, kernel_path, sections, section_entsize, num_sections, strtab, layout, @@ -1685,7 +1868,7 @@ SUFFIX (grub_mkimage_load_image) (const char *kerne= l_path, for (i =3D 0; i < num_sections; i++) section_vaddresses[i] =3D section_addresses[i] + image_target->vaddr= _offset; =20 - if (image_target->id !=3D IMAGE_EFI) + if (!is_relocatable (image_target)) { Elf_Addr current_address =3D layout->kernel_size; =20 @@ -1706,7 +1889,7 @@ SUFFIX (grub_mkimage_load_image) (const char *kerne= l_path, grub_util_info ("locating the section %s at 0x%" GRUB_HOST_PRIxLONG_LONG, name, (unsigned long long) current_address); - if (image_target->id !=3D IMAGE_EFI) + if (!is_relocatable (image_target)) current_address =3D grub_host_to_target_addr (s->sh_addr) - image_target->link_addr; =20 @@ -1724,10 +1907,11 @@ SUFFIX (grub_mkimage_load_image) (const char *ker= nel_path, =20 if (image_target->id =3D=3D IMAGE_SPARC64_AOUT || image_target->id =3D=3D IMAGE_SPARC64_RAW + || image_target->id =3D=3D IMAGE_UBOOT || image_target->id =3D=3D IMAGE_SPARC64_CDCORE) layout->kernel_size =3D ALIGN_UP (layout->kernel_size, image_target-= >mod_align); =20 - if (image_target->id =3D=3D IMAGE_EFI) + if (is_relocatable (image_target)) { symtab_section =3D NULL; for (i =3D 0, s =3D sections; @@ -1740,22 +1924,6 @@ SUFFIX (grub_mkimage_load_image) (const char *kern= el_path, } if (! symtab_section) grub_util_error ("%s", _("no symbol table")); - -#ifdef MKIMAGE_ELF32 - if (image_target->elf_target =3D=3D EM_ARM) - { - grub_size_t tramp; - - layout->kernel_size =3D ALIGN_UP (layout->kernel_size, 16); - - tramp =3D arm_get_trampoline_size (e, sections, section_entsize, - num_sections, image_target); - - layout->tramp_off =3D layout->kernel_size; - layout->kernel_size +=3D ALIGN_UP (tramp, 16); - } -#endif - #ifdef MKIMAGE_ELF64 if (image_target->elf_target =3D=3D EM_IA_64) { @@ -1770,14 +1938,13 @@ SUFFIX (grub_mkimage_load_image) (const char *ker= nel_path, =20 layout->ia64jmp_off =3D layout->kernel_size; layout->ia64jmpnum =3D SUFFIX (count_funcs) (e, symtab_section, - image_target); + image_target); layout->kernel_size +=3D 16 * layout->ia64jmpnum; =20 layout->ia64_got_off =3D layout->kernel_size; layout->kernel_size +=3D ALIGN_UP (layout->got_size, 16); } #endif - } else { @@ -1788,7 +1955,7 @@ SUFFIX (grub_mkimage_load_image) (const char *kerne= l_path, out_img =3D xmalloc (layout->kernel_size + total_module_size); memset (out_img, 0, layout->kernel_size + total_module_size); =20 - if (image_target->id =3D=3D IMAGE_EFI) + if (is_relocatable (image_target)) { layout->start_address =3D SUFFIX (relocate_symbols) (e, sections, = symtab_section, section_vaddresses, section_entsize, @@ -1796,6 +1963,8 @@ SUFFIX (grub_mkimage_load_image) (const char *kerne= l_path, (char *) out_img + layout->ia64jmp_off,=20 layout->ia64jmp_off=20 + image_target->vaddr_offset, + layout->bss_start, + layout->end, image_target); if (layout->start_address =3D=3D (Elf_Addr) -1) grub_util_error ("start symbol is not defined"); @@ -1813,21 +1982,31 @@ SUFFIX (grub_mkimage_load_image) (const char *ker= nel_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 !=3D IMAGE_EFI) + { + out_img =3D xrealloc (out_img, layout->kernel_size + total_module_siz= e + + 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 +=3D ALIGN_UP (layout->reloc_size, image_target->= mod_align); + } } =20 for (i =3D 0, s =3D sections; i < num_sections; i++, s =3D (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 !=3D= 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) =3D=3D 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 imag= e_targets[] =3D .decompressor_compressed_size =3D TARGET_NO_FIELD, .decompressor_uncompressed_size =3D TARGET_NO_FIELD, .decompressor_uncompressed_addr =3D TARGET_NO_FIELD, + .reloc_table_offset =3D TARGET_NO_FIELD, .section_align =3D 1, .vaddr_offset =3D 0, .link_addr =3D GRUB_KERNEL_I386_COREBOOT_LINK_ADDR, @@ -525,7 +526,6 @@ static const struct grub_install_image_target_desc im= age_targets[] =3D .decompressor_uncompressed_addr =3D TARGET_NO_FIELD, .section_align =3D GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN, .vaddr_offset =3D 0, - .link_addr =3D GRUB_KERNEL_ARM_UBOOT_LINK_ADDR, .elf_target =3D EM_ARM, .mod_gap =3D GRUB_KERNEL_ARM_UBOOT_MOD_GAP, .mod_align =3D GRUB_KERNEL_ARM_UBOOT_MOD_ALIGN, @@ -1520,9 +1520,9 @@ grub_install_generate_image (const char *dir, const= char *prefix, hdr->ih_magic =3D grub_cpu_to_be32_compile_time (GRUB_UBOOT_IH_MAG= IC); hdr->ih_time =3D grub_cpu_to_be32 (STABLE_EMBEDDING_TIMESTAMP); hdr->ih_size =3D grub_cpu_to_be32 (core_size); - hdr->ih_load =3D grub_cpu_to_be32 (image_target->link_addr); - hdr->ih_ep =3D grub_cpu_to_be32 (image_target->link_addr); - hdr->ih_type =3D GRUB_UBOOT_IH_TYPE_KERNEL; + hdr->ih_load =3D 0; + hdr->ih_ep =3D 0; + hdr->ih_type =3D GRUB_UBOOT_IH_TYPE_KERNEL_NOLOAD; hdr->ih_os =3D GRUB_UBOOT_IH_OS_LINUX; hdr->ih_arch =3D GRUB_UBOOT_IH_ARCH_ARM; hdr->ih_comp =3D GRUB_UBOOT_IH_COMP_NONE; --=20 2.7.0 --------------020603050304080701070805-- --f2Lw3exVbS6RVxPDte6NSPwODSLXGSgbn Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iF4EAREKAAYFAlbMNdsACgkQmBXlbbo5nOvr5AEAn5L8samH6lAUbJNiTQ02Rwrx DH7yDkpEUC6PUROb4r4A/j9HALEjrLhoeoaEK97zSKQsAbf4kfpZHkVObwjQuGFN =S4JU -----END PGP SIGNATURE----- --f2Lw3exVbS6RVxPDte6NSPwODSLXGSgbn--