Merge branch 'master' of git://git.denx.de/u-boot-arm

Bringing in the MMC tree means that CONFIG_BOUNCE_BUFFER needed to be
added to include/configs/exynos5-dt.h now.

Conflicts:
	include/configs/exynos5250-dt.h

Signed-off-by: Tom Rini <trini@ti.com>
This commit is contained in:
Tom Rini
2014-01-10 10:56:00 -05:00
261 changed files with 14936 additions and 6638 deletions

View File

@@ -54,12 +54,14 @@ BIN_FILES-y += dumpimage$(SFX)
BIN_FILES-y += mkenvimage$(SFX)
BIN_FILES-y += mkimage$(SFX)
BIN_FILES-$(CONFIG_EXYNOS5250) += mk$(BOARD)spl$(SFX)
BIN_FILES-$(CONFIG_EXYNOS5420) += mk$(BOARD)spl$(SFX)
BIN_FILES-$(CONFIG_MX23) += mxsboot$(SFX)
BIN_FILES-$(CONFIG_MX28) += mxsboot$(SFX)
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
@@ -87,10 +89,11 @@ 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
OBJ_FILES-$(CONFIG_EXYNOS5250) += mkexynosspl.o
OBJ_FILES-$(CONFIG_EXYNOS_SPL) += mkexynosspl.o
OBJ_FILES-$(CONFIG_KIRKWOOD) += kwboot.o
OBJ_FILES-$(CONFIG_LCD_LOGO) += bmp_logo.o
OBJ_FILES-$(CONFIG_MX23) += mxsboot.o
@@ -278,6 +281,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 $@ $<

View File

@@ -14,93 +14,174 @@
#include <compiler.h>
#define CHECKSUM_OFFSET (14*1024-4)
#define BUFSIZE (14*1024)
#define FILE_PERM (S_IRUSR | S_IWUSR | S_IRGRP \
| S_IWGRP | S_IROTH | S_IWOTH)
/*
* Requirement:
* IROM code reads first 14K bytes from boot device.
* It then calculates the checksum of 14K-4 bytes and compare with data at
* 14K-4 offset.
*
* This function takes two filenames:
* IN "u-boot-spl.bin" and
* OUT "$(BOARD)-spl.bin as filenames.
* It reads the "u-boot-spl.bin" in 16K buffer.
* It calculates checksum of 14K-4 Bytes and stores at 14K-4 offset in buffer.
* It writes the buffer to "$(BOARD)-spl.bin" file.
*/
* Requirement for the fixed size SPL header:
* IROM code reads first (CHECKSUM_OFFSET + 4) bytes from boot device. It then
* calculates the checksum of CHECKSUM_OFFSET bytes and compares with data at
* CHECKSUM_OFFSET location.
*
* Requirement for the variable size SPL header:
* IROM code reads the below header to find out the size of the blob (total
* size, header size included) and its checksum. Then it reads the rest of the
* blob [i.e size - sizeof(struct var_size_header) bytes], calculates the
* checksum and compares it with value read from the header.
*/
struct var_size_header {
uint32_t spl_size;
uint32_t spl_checksum;
uint32_t reserved[2];
};
static const char *prog_name;
static void write_to_file(int ofd, void *buffer, int size)
{
if (write(ofd, buffer, size) == size)
return;
fprintf(stderr, "%s: Failed to write to output file: %s\n",
prog_name, strerror(errno));
exit(EXIT_FAILURE);
}
/*
* The argv is expected to include one optional parameter and two filenames:
* [--vs] IN OUT
*
* --vs - turns on the variable size SPL mode
* IN - the u-boot SPL binary, usually u-boot-spl.bin
* OUT - the prepared SPL blob, usually ${BOARD}-spl.bin
*
* This utility first reads the "u-boot-spl.bin" into a buffer. In case of
* fixed size SPL the buffer size is exactly CHECKSUM_OFFSET (such that
* smaller u-boot-spl.bin gets padded with 0xff bytes, the larger than limit
* u-boot-spl.bin causes an error). For variable size SPL the buffer size is
* eqaul to size of the IN file.
*
* Then it calculates checksum of the buffer by just summing up all bytes.
* Then
*
* - for fixed size SPL the buffer is written into the output file and the
* checksum is appended to the file in little endian format, which results
* in checksum added exactly at CHECKSUM_OFFSET.
*
* - for variable size SPL the checksum and file size are stored in the
* var_size_header structure (again, in little endian format) and the
* structure is written into the output file. Then the buffer is written
* into the output file.
*/
int main(int argc, char **argv)
{
unsigned char buffer[BUFSIZE];
unsigned char *buffer;
int i, ifd, ofd;
uint32_t checksum = 0;
off_t len;
ssize_t count;
int var_size_flag, read_size, count;
struct stat stat;
const int if_index = argc - 2; /* Input file name index in argv. */
const int of_index = argc - 1; /* Output file name index in argv. */
if (argc != 3) {
fprintf(stderr, "Usage: %s <infile> <outfile>\n", argv[0]);
/* Strip path off the program name. */
prog_name = strrchr(argv[0], '/');
if (prog_name)
prog_name++;
else
prog_name = argv[0];
if ((argc < 3) ||
(argc > 4) ||
((argc == 4) && strcmp(argv[1], "--vs"))) {
fprintf(stderr, "Usage: %s [--vs] <infile> <outfile>\n",
prog_name);
exit(EXIT_FAILURE);
}
ifd = open(argv[1], O_RDONLY);
/* four args mean variable size SPL wrapper is required */
var_size_flag = (argc == 4);
ifd = open(argv[if_index], O_RDONLY);
if (ifd < 0) {
fprintf(stderr, "%s: Can't open %s: %s\n",
argv[0], argv[1], strerror(errno));
prog_name, argv[if_index], strerror(errno));
exit(EXIT_FAILURE);
}
ofd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, FILE_PERM);
ofd = open(argv[of_index], O_WRONLY | O_CREAT | O_TRUNC, FILE_PERM);
if (ifd < 0) {
fprintf(stderr, "%s: Can't open %s: %s\n",
argv[0], argv[2], strerror(errno));
close(ifd);
prog_name, argv[of_index], strerror(errno));
exit(EXIT_FAILURE);
}
if (fstat(ifd, &stat)) {
fprintf(stderr, "%s: Unable to get size of %s: %s\n",
argv[0], argv[1], strerror(errno));
close(ifd);
close(ofd);
prog_name, argv[if_index], strerror(errno));
exit(EXIT_FAILURE);
}
len = stat.st_size;
count = (len < CHECKSUM_OFFSET) ? len : CHECKSUM_OFFSET;
if (read(ifd, buffer, count) != count) {
fprintf(stderr, "%s: Can't read %s: %s\n",
argv[0], argv[1], strerror(errno));
close(ifd);
close(ofd);
if (var_size_flag) {
read_size = len;
count = len;
} else {
if (len > CHECKSUM_OFFSET) {
fprintf(stderr,
"%s: %s is too big (exceeds %d bytes)\n",
prog_name, argv[if_index], CHECKSUM_OFFSET);
exit(EXIT_FAILURE);
}
count = CHECKSUM_OFFSET;
read_size = len;
}
buffer = malloc(count);
if (!buffer) {
fprintf(stderr,
"%s: Failed to allocate %d bytes to store %s\n",
prog_name, count, argv[if_index]);
exit(EXIT_FAILURE);
}
for (i = 0, checksum = 0; i < CHECKSUM_OFFSET; i++)
checksum += buffer[i];
if (read(ifd, buffer, read_size) != read_size) {
fprintf(stderr, "%s: Can't read %s: %s\n",
prog_name, argv[if_index], strerror(errno));
exit(EXIT_FAILURE);
}
/* Pad if needed with 0xff to make flashing faster. */
if (read_size < count)
memset((char *)buffer + read_size, 0xff, count - read_size);
for (i = 0, checksum = 0; i < count; i++)
checksum += buffer[i];
checksum = cpu_to_le32(checksum);
memcpy(&buffer[CHECKSUM_OFFSET], &checksum, sizeof(checksum));
if (var_size_flag) {
/* Prepare and write out the variable size SPL header. */
struct var_size_header vsh;
uint32_t spl_size;
if (write(ofd, buffer, BUFSIZE) != BUFSIZE) {
fprintf(stderr, "%s: Can't write %s: %s\n",
argv[0], argv[2], strerror(errno));
memset(&vsh, 0, sizeof(vsh));
memcpy(&vsh.spl_checksum, &checksum, sizeof(checksum));
close(ifd);
close(ofd);
exit(EXIT_FAILURE);
spl_size = cpu_to_le32(count + sizeof(struct var_size_header));
memcpy(&vsh.spl_size, &spl_size, sizeof(spl_size));
write_to_file(ofd, &vsh, sizeof(vsh));
}
write_to_file(ofd, buffer, count);
/* For fixed size SPL checksum is appended in the end. */
if (!var_size_flag)
write_to_file(ofd, &checksum, sizeof(checksum));
close(ifd);
close(ofd);
free(buffer);
return EXIT_SUCCESS;
}

View File

@@ -502,6 +502,7 @@ static int sb_token_to_long(char *tok, uint32_t *rid)
tok += 2;
errno = 0;
id = strtoul(tok, &endptr, 16);
if ((errno == ERANGE && id == ULONG_MAX) || (errno != 0 && id == 0)) {
fprintf(stderr, "ERR: Value can't be decoded!\n");

189
tools/relocate-rela.c Normal file
View File

@@ -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 <elf.h>
#include <errno.h>
#include <inttypes.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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 <bin file> <text base> " \
"<rela start> <rela end>\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;
}