mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-13 15:03:58 +03:00
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:
@@ -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 $@ $<
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
189
tools/relocate-rela.c
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user