From 7dcd3a21ff556a196d60227fa04c9cdc5f9faa9c Mon Sep 17 00:00:00 2001 From: Vidya Sagar Date: Thu, 31 Oct 2013 14:51:38 +0530 Subject: tegra: allow build to succeed with SPL disabled u-boot-dtb-tegra.bin and u-boot-nodtb-tegra.bin binaries are generated only if the SPL build is enabled as they have dependency on SPL build Signed-off-by: Vidya Sagar Signed-off-by: Tom Warren --- Makefile | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 7310c4ef0af..0d86b555d70 100644 --- a/Makefile +++ b/Makefile @@ -350,12 +350,14 @@ endif # enable combined SPL/u-boot/dtb rules for tegra ifneq ($(CONFIG_TEGRA),) +ifeq ($(CONFIG_SPL),y) ifeq ($(CONFIG_OF_SEPARATE),y) ALL-y += $(obj)u-boot-dtb-tegra.bin else ALL-y += $(obj)u-boot-nodtb-tegra.bin endif endif +endif build := -f $(TOPDIR)/scripts/Makefile.build -C -- cgit v1.3.1 From 8137af19e75a761d4d9e3ada6820ea7824078a54 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Sat, 14 Dec 2013 11:47:32 +0800 Subject: arm64: Add tool to statically apply RELA relocations ARM64 uses the newer RELA-style relocations rather than the older REL. RELA relocations have an addend in the relocation struct, rather than expecting the loader to read a value from the location to be updated. While this is beneficial for ordinary program loading, it's problematic for U-Boot because the location to be updated starts out with zero, rather than a pre-relocation value. Since we need to be able to run C code before relocation, we need a tool to apply the relocations at build time. In theory this tool is applicable to other newer architectures (mainly 64-bit), but currently the only relocations it supports are for arm64, and it assumes a 64-bit little-endian target. If the latter limitation is ever to be changed, we'll need a way to tell the tool what format the image is in. Eventually this may be replaced by a tool that uses libelf or similar and operates directly on the ELF file. I've written some code for such an approach but libelf does not make it easy to poke addresses by memory address (rather than by section), and I was hesitant to write code to manually parse the program headers and do the update outside of libelf (or to iterate over sections) -- especially since it wouldn't get test coverage on things like binaries with multiple PT_LOAD segments. This should be good enough for now to let the manual relocation stuff be removed from the arm64 patches. Signed-off-by: Scott Wood Signed-off-by: David Feng --- Makefile | 12 ++++ tools/Makefile | 6 ++ tools/relocate-rela.c | 189 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 207 insertions(+) create mode 100644 tools/relocate-rela.c (limited to 'Makefile') diff --git a/Makefile b/Makefile index 0d86b555d70..85a9330f10a 100644 --- a/Makefile +++ b/Makefile @@ -334,6 +334,17 @@ else BOARD_SIZE_CHECK = endif +# Statically apply RELA-style relocations (currently arm64 only) +ifneq ($(CONFIG_STATIC_RELA),) +# $(1) is u-boot ELF, $(2) is u-boot bin, $(3) is text base +DO_STATIC_RELA = \ + start=$$($(NM) $(1) | grep __rel_dyn_start | cut -f 1 -d ' '); \ + end=$$($(NM) $(1) | grep __rel_dyn_end | cut -f 1 -d ' '); \ + $(obj)tools/relocate-rela $(2) $(3) $$start $$end +else +DO_STATIC_RELA = +endif + # Always append ALL so that arch config.mk's can add custom ones ALL-y += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map @@ -378,6 +389,7 @@ $(obj)u-boot.srec: $(obj)u-boot $(obj)u-boot.bin: $(obj)u-boot $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@ + $(call DO_STATIC_RELA,$<,$@,$(CONFIG_SYS_TEXT_BASE)) $(BOARD_SIZE_CHECK) $(obj)u-boot.ldr: $(obj)u-boot diff --git a/tools/Makefile b/tools/Makefile index d4bc84d2789..4a7e7e57288 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -60,6 +60,7 @@ BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX) BIN_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1$(SFX) BIN_FILES-$(CONFIG_KIRKWOOD) += kwboot$(SFX) BIN_FILES-y += proftool(SFX) +BIN_FILES-$(CONFIG_STATIC_RELA) += relocate-rela$(SFX) # Source files which exist outside the tools directory EXT_OBJ_FILES-$(CONFIG_BUILD_ENVCRC) += common/env_embedded.o @@ -85,6 +86,7 @@ NOPED_OBJ_FILES-y += os_support.o NOPED_OBJ_FILES-y += pblimage.o NOPED_OBJ_FILES-y += proftool.o NOPED_OBJ_FILES-y += ublimage.o +NOPED_OBJ_FILES-y += relocate-rela.o OBJ_FILES-$(CONFIG_BUILD_ENVCRC) += envcrc.o OBJ_FILES-$(CONFIG_CMD_LOADS) += img2srec.o OBJ_FILES-$(CONFIG_CMD_NET) += gen_eth_addr.o @@ -251,6 +253,10 @@ $(obj)kwboot$(SFX): $(obj)kwboot.o $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTSTRIP) $@ +$(obj)relocate-rela$(SFX): $(obj)relocate-rela.o + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ + $(HOSTSTRIP) $@ + # Some of the tool objects need to be accessed from outside the tools directory $(obj)%.o: $(SRCTREE)/common/%.c $(HOSTCC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $< diff --git a/tools/relocate-rela.c b/tools/relocate-rela.c new file mode 100644 index 00000000000..93b4c3923e7 --- /dev/null +++ b/tools/relocate-rela.c @@ -0,0 +1,189 @@ +/* + * Copyright 2013 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause + * + * 64-bit and little-endian target only until we need to support a different + * arch that needs this. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef R_AARCH64_RELATIVE +#define R_AARCH64_RELATIVE 1027 +#endif + +static const bool debug_en; + +static void debug(const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + if (debug_en) + vprintf(fmt, args); +} + +static bool supported_rela(Elf64_Rela *rela) +{ + uint64_t mask = 0xffffffffULL; /* would be different on 32-bit */ + uint32_t type = rela->r_info & mask; + + switch (type) { +#ifdef R_AARCH64_RELATIVE + case R_AARCH64_RELATIVE: + return true; +#endif + default: + fprintf(stderr, "warning: unsupported relocation type %" + PRIu32 " at %" PRIx64 "\n", + type, rela->r_offset); + + return false; + } +} + +static inline uint64_t swap64(uint64_t val) +{ + return ((val >> 56) & 0x00000000000000ffULL) | + ((val >> 40) & 0x000000000000ff00ULL) | + ((val >> 24) & 0x0000000000ff0000ULL) | + ((val >> 8) & 0x00000000ff000000ULL) | + ((val << 8) & 0x000000ff00000000ULL) | + ((val << 24) & 0x0000ff0000000000ULL) | + ((val << 40) & 0x00ff000000000000ULL) | + ((val << 56) & 0xff00000000000000ULL); +} + +#if __BYTE_ORDER == __LITTLE_ENDIAN +static inline uint64_t be64(uint64_t val) +{ + return swap64(val); +} + +static inline uint64_t le64(uint64_t val) +{ + return val; +} +#else +static inline uint64_t le64(uint64_t val) +{ + return swap64(val); +} + +static inline uint64_t be64(uint64_t val) +{ + return val; +} +#endif + +static bool read_num(const char *str, uint64_t *num) +{ + char *endptr; + *num = strtoull(str, &endptr, 16); + return str[0] && !endptr[0]; +} + +int main(int argc, char **argv) +{ + FILE *f; + int i, num; + uint64_t rela_start, rela_end, text_base; + + if (argc != 5) { + fprintf(stderr, "Statically apply ELF rela relocations\n"); + fprintf(stderr, "Usage: %s " \ + " \n", argv[0]); + fprintf(stderr, "All numbers in hex.\n"); + return 1; + } + + f = fopen(argv[1], "r+b"); + if (!f) { + fprintf(stderr, "%s: Cannot open %s: %s\n", + argv[0], argv[1], strerror(errno)); + return 2; + } + + if (!read_num(argv[2], &text_base) || + !read_num(argv[3], &rela_start) || + !read_num(argv[4], &rela_end)) { + fprintf(stderr, "%s: bad number\n", argv[0]); + return 3; + } + + if (rela_start > rela_end || rela_start < text_base || + (rela_end - rela_start) % 24) { + fprintf(stderr, "%s: bad rela bounds\n", argv[0]); + return 3; + } + + rela_start -= text_base; + rela_end -= text_base; + + num = (rela_end - rela_start) / sizeof(Elf64_Rela); + + for (i = 0; i < num; i++) { + Elf64_Rela rela, swrela; + uint64_t pos = rela_start + sizeof(Elf64_Rela) * i; + uint64_t addr; + + if (fseek(f, pos, SEEK_SET) < 0) { + fprintf(stderr, "%s: %s: seek to %" PRIx64 + " failed: %s\n", + argv[0], argv[1], pos, strerror(errno)); + } + + if (fread(&rela, sizeof(rela), 1, f) != 1) { + fprintf(stderr, "%s: %s: read rela failed at %" + PRIx64 "\n", + argv[0], argv[1], pos); + return 4; + } + + swrela.r_offset = le64(rela.r_offset); + swrela.r_info = le64(rela.r_info); + swrela.r_addend = le64(rela.r_addend); + + if (!supported_rela(&swrela)) + continue; + + debug("Rela %" PRIx64 " %" PRIu64 " %" PRIx64 "\n", + swrela.r_offset, swrela.r_info, swrela.r_addend); + + if (swrela.r_offset < text_base) { + fprintf(stderr, "%s: %s: bad rela at %" PRIx64 "\n", + argv[0], argv[1], pos); + return 4; + } + + addr = swrela.r_offset - text_base; + + if (fseek(f, addr, SEEK_SET) < 0) { + fprintf(stderr, "%s: %s: seek to %" + PRIx64 " failed: %s\n", + argv[0], argv[1], addr, strerror(errno)); + } + + if (fwrite(&rela.r_addend, sizeof(rela.r_addend), 1, f) != 1) { + fprintf(stderr, "%s: %s: write failed at %" PRIx64 "\n", + argv[0], argv[1], addr); + return 4; + } + } + + if (fclose(f) < 0) { + fprintf(stderr, "%s: %s: close failed: %s\n", + argv[0], argv[1], strerror(errno)); + return 4; + } + + return 0; +} -- cgit v1.3.1 From f4dc714aaa2d86b84724ec01fb848da63aa63666 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Sat, 14 Dec 2013 11:47:33 +0800 Subject: arm64: Turn u-boot.bin back into an ELF file after relocate-rela While performing relocations on u-boot.bin should be good enough for booting on real hardware, some simulators insist on booting an ELF file (and yet don't perform ELF relocations), so convert the relocated binary back into an ELF file. This can go away in the future if we change relocate-rela to operate directly on the ELF file, or if and when we stop caring about a simulator with this restriction. Signed-off-by: Scott Wood Signed-off-by: David Feng --- Makefile | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 85a9330f10a..a4c2928eb62 100644 --- a/Makefile +++ b/Makefile @@ -358,6 +358,7 @@ ALL-$(CONFIG_OF_SEPARATE) += $(obj)u-boot.dtb $(obj)u-boot-dtb.bin ifneq ($(CONFIG_SPL_TARGET),) ALL-$(CONFIG_SPL) += $(obj)$(subst ",,$(CONFIG_SPL_TARGET)) endif +ALL-$(CONFIG_REMAKE_ELF) += $(obj)u-boot.elf # enable combined SPL/u-boot/dtb rules for tegra ifneq ($(CONFIG_TEGRA),) @@ -528,6 +529,18 @@ $(obj)u-boot-img-spl-at-end.bin: $(obj)spl/u-boot-spl.bin $(obj)u-boot.img conv=notrunc 2>/dev/null cat $(obj)u-boot-pad.img $(obj)spl/u-boot-spl.bin > $@ +# Create a new ELF from a raw binary file. This is useful for arm64 +# where static relocation needs to be performed on the raw binary, +# but certain simulators only accept an ELF file (but don't do the +# relocation). +# FIXME refactor dts/Makefile to share target/arch detection +$(obj)u-boot.elf: $(obj)u-boot.bin + @$(OBJCOPY) -B aarch64 -I binary -O elf64-littleaarch64 \ + $< $(obj)u-boot-elf.o + @$(LD) $(obj)u-boot-elf.o -o $@ \ + --defsym=_start=$(CONFIG_SYS_TEXT_BASE) \ + -Ttext=$(CONFIG_SYS_TEXT_BASE) + ifeq ($(CONFIG_SANDBOX),y) GEN_UBOOT = \ cd $(LNDIR) && $(CC) $(SYMS) -T $(obj)u-boot.lds \ -- cgit v1.3.1 From 54799e4596bf8af33fd4a8dee153be7011c06d8d Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Sat, 14 Dec 2013 11:47:34 +0800 Subject: arm64: Make checkarmreloc accept arm64 relocations Signed-off-by: Scott Wood Signed-off-by: David Feng --- Makefile | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index a4c2928eb62..dc5ba046164 100644 --- a/Makefile +++ b/Makefile @@ -744,12 +744,16 @@ tools: $(VERSION_FILE) $(TIMESTAMP_FILE) $(MAKE) -C $@ all endif # config.mk -# ARM relocations should all be R_ARM_RELATIVE. +# ARM relocations should all be R_ARM_RELATIVE (32-bit) or +# R_AARCH64_RELATIVE (64-bit). checkarmreloc: $(obj)u-boot - @if test "R_ARM_RELATIVE" != \ - "`$(CROSS_COMPILE)readelf -r $< | cut -d ' ' -f 4 | grep R_ARM | sort -u`"; \ - then echo "$< contains relocations other than \ - R_ARM_RELATIVE"; false; fi + @RELOC="`$(CROSS_COMPILE)readelf -r -W $< | cut -d ' ' -f 4 | \ + grep R_A | sort -u`"; \ + if test "$$RELOC" != "R_ARM_RELATIVE" -a \ + "$$RELOC" != "R_AARCH64_RELATIVE"; then \ + echo "$< contains unexpected relocations: $$RELOC"; \ + false; \ + fi $(VERSION_FILE): @mkdir -p $(dir $(VERSION_FILE)) -- cgit v1.3.1