Rather than rely on dirty hacks to compile the environment on the host and extract the CRC from that, have envcrc extract the environment straight from the ELF object that will be linked into u-boot itself. This makes the envcrc code a bit more complicated, but it simplifies the build process and host requirements because we don't have to try and recreate the environment that the target will be seeing on the host. This avoids some issues that crop up from time to time where the preprocessor defines on the host don't expand in the same way as for the target -- in case the target uses those defines to customize the environment, or the host defines conflicts with some of the target values.
Signed-off-by: Mike Frysinger <vap...@gentoo.org> --- common/Makefile | 4 +- common/env_embedded.c | 30 +--------- tools/Makefile | 3 +- tools/envcrc.c | 156 ++++++++++++++++++++++++++++++++++++++++++------- diff --git a/common/Makefile b/common/Makefile index c8e5d26..02bc71b 100644 --- a/common/Makefile +++ b/common/Makefile @@ -173,9 +173,9 @@ all: $(LIB) $(AOBJS) $(LIB): $(obj).depend $(OBJS) $(AR) $(ARFLAGS) $@ $(OBJS) -$(obj)env_embedded.o: $(src)env_embedded.c $(obj)../tools/envcrc +$(obj)env_embedded.o: $(src)env_embedded.c $(obj)env_common.o $(obj)../tools/envcrc $(CC) $(AFLAGS) -Wa,--no-warn \ - -DENV_CRC=$(shell $(obj)../tools/envcrc) \ + -DENV_CRC=$(shell $(obj)../tools/envcrc $(obj)env_common.o) \ -c -o $@ $(src)env_embedded.c $(obj)../tools/envcrc: diff --git a/common/env_embedded.c b/common/env_embedded.c index ae6cac4..60736c7 100644 --- a/common/env_embedded.c +++ b/common/env_embedded.c @@ -21,26 +21,10 @@ * MA 02111-1307 USA */ -#ifndef __ASSEMBLY__ -#define __ASSEMBLY__ /* Dirty trick to get only #defines */ -#endif -#define __ASM_STUB_PROCESSOR_H__ /* don't include asm/processor. */ #include <config.h> -#undef __ASSEMBLY__ #include <environment.h> /* - * Handle HOSTS that have prepended - * crap on symbol names, not TARGETS. - */ -#if defined(__APPLE__) -/* Leading underscore on symbols */ -# define SYM_CHAR "_" -#else /* No leading character on symbols */ -# define SYM_CHAR -#endif - -/* * Generate embedded environment table * inside U-Boot image, if needed. */ @@ -75,7 +59,7 @@ #else # define GEN_SET_VALUE(name, value) asm (GEN_SYMNAME(name) " = " GEN_VALUE(value)) #endif -#define GEN_SYMNAME(str) SYM_CHAR #str +#define GEN_SYMNAME(str) #str #define GEN_VALUE(str) #str #define GEN_ABS(name, value) \ asm (".globl " GEN_SYMNAME(name)); \ @@ -197,17 +181,7 @@ env_t redundand_environment __PPCENV__ = { #endif /* CONFIG_ENV_ADDR_REDUND */ /* - * These will end up in the .text section - * if the environment strings are embedded - * in the image. When this is used for - * tools/envcrc, they are placed in the - * .data/.sdata section. - * - */ -unsigned long env_size __PPCTEXT__ = sizeof(env_t); - -/* - * Add in absolutes. + * Add in absolutes. This symbol is only referenced from linker scripts. */ GEN_ABS(env_offset, CONFIG_ENV_OFFSET); diff --git a/tools/Makefile b/tools/Makefile index 43c284c..982d65a 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -80,7 +80,6 @@ BIN_FILES-$(CONFIG_INCA_IP) += inca-swap-bytes$(SFX) BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX) # Source files which exist outside the tools directory -EXT_OBJ_FILES-y += common/env_embedded.o EXT_OBJ_FILES-y += lib_generic/crc32.o EXT_OBJ_FILES-y += lib_generic/md5.o EXT_OBJ_FILES-y += lib_generic/sha1.o @@ -156,7 +155,7 @@ MAKEDEPEND = makedepend all: $(obj).depend $(BINS) $(LOGO-y) subdirs -$(obj)envcrc$(SFX): $(obj)envcrc.o $(obj)crc32.o $(obj)env_embedded.o $(obj)sha1.o +$(obj)envcrc$(SFX): $(obj)envcrc.o $(obj)crc32.o $(obj)sha1.o $(CC) $(CFLAGS) -o $@ $^ $(obj)ubsha1$(SFX): $(obj)ubsha1.o $(obj)sha1.o $(obj)os_support.o diff --git a/tools/envcrc.c b/tools/envcrc.c index 5b0f7cd..87453e5 100644 --- a/tools/envcrc.c +++ b/tools/envcrc.c @@ -21,11 +21,15 @@ * MA 02111-1307 USA */ +#include "compiler.h" +#include <errno.h> +#include <stdbool.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <unistd.h> +#include "elf.h" #ifndef __ASSEMBLY__ #define __ASSEMBLY__ /* Dirty trick to get only #defines */ @@ -67,48 +71,156 @@ #define ENV_SIZE (CONFIG_ENV_SIZE - ENV_HEADER_SIZE) +unsigned char host_endian(void) +{ + struct { + union { + uint16_t sint; + unsigned char str[2]; + } u; + } data; + data.u.sint = 0xBBAA; + return data.u.str[0] == 0xBB ? ELFDATA2MSB : ELFDATA2LSB; +} +bool swapit; +#define EGET(val) ( \ + !swapit ? (val) : \ + sizeof(val) == 1 ? (val) : \ + sizeof(val) == 2 ? uswap_16(val) : \ + sizeof(val) == 4 ? uswap_32(val) : \ + sizeof(val) == 8 ? uswap_64(val) : \ + 1 \ +) extern uint32_t crc32 (uint32_t, const unsigned char *, unsigned int); -#ifdef ENV_IS_EMBEDDED -extern unsigned int env_size; -extern unsigned char environment; -#endif /* ENV_IS_EMBEDDED */ +static bool elfread(FILE *fp, long offset, void *ptr, size_t size, size_t nmemb) +{ + if (fseek(fp, offset, SEEK_SET)) + return false; + if (fread(ptr, size, nmemb, fp) != nmemb) + return false; + return true; +} + +/* Avoid using elf.h since not all systems have it */ +unsigned char environment[CONFIG_ENV_SIZE]; +bool read_env_from_elf(const char *elf_file) +{ + const char env_symbol[] = "default_environment"; + char buf[256]; + FILE *fp; + bool ret = false; + int i; + + Elf32_Ehdr ehdr; + Elf32_Shdr shdr, strtab, symtab; + Elf32_Sym sym; + + fp = fopen(elf_file, "r"); + if (!fp) + return false; + + /* Make sure this is a valid ELF */ + if (!elfread(fp, 0, &ehdr, sizeof(ehdr), 1)) + goto done; + if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG)) { + errno = EINVAL; + goto done; + } + if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) { + errno = EINVAL; + goto done; + } + swapit = host_endian() == ehdr.e_ident[EI_DATA] ? false : true; + + /* Find the string & symbol table */ + memset(&strtab, 0, sizeof(strtab)); /* shut gcc the hell up */ + memset(&symtab, 0, sizeof(symtab)); /* shut gcc the hell up */ + strtab.sh_type = SHT_NULL; + symtab.sh_type = SHT_NULL; + for (i = 0; i < EGET(ehdr.e_shnum); ++i) { + long off = EGET(ehdr.e_shoff) + i * EGET(ehdr.e_shentsize); + if (!elfread(fp, off, &shdr, sizeof(shdr), 1)) + goto done; + if (EGET(shdr.sh_type) == SHT_STRTAB) + strtab = shdr; + else if (EGET(shdr.sh_type) == SHT_SYMTAB) + symtab = shdr; + } + if (strtab.sh_type == SHT_NULL || symtab.sh_type == SHT_NULL) { + errno = EINVAL; + goto done; + } + + /* Find the environment symbol */ + for (i = 0; i < EGET(symtab.sh_size) / EGET(symtab.sh_entsize); ++i) { + char *tbuf; + long off = EGET(symtab.sh_offset) + i * sizeof(sym); + if (!elfread(fp, off, &sym, sizeof(sym), 1)) + goto done; + off = EGET(strtab.sh_offset) + EGET(sym.st_name); + tbuf = buf; + if (!elfread(fp, off, tbuf, 1, sizeof(env_symbol))) + goto done; + /* handle ABI prefixed symbols automatically */ + if (tbuf[0] == '_') { + tbuf[sizeof(env_symbol)] = '\0'; + ++tbuf; + } + if (!strcmp(tbuf, env_symbol)) { + off = EGET(ehdr.e_shoff) + EGET(sym.st_shndx) * EGET(ehdr.e_shentsize); + if (!elfread(fp, off, &shdr, sizeof(shdr), 1)) + goto done; + off = EGET(shdr.sh_offset) + EGET(sym.st_value); + if (!elfread(fp, off, environment + ENV_HEADER_SIZE, 1, EGET(sym.st_size))) + goto done; + ret = true; + break; + } + } + + done: + fclose(fp); + return ret; +} int main (int argc, char **argv) { -#ifdef ENV_IS_EMBEDDED +#ifdef ENV_IS_EMBEDDED unsigned char pad = 0x00; uint32_t crc; - unsigned char *envptr = &environment, + unsigned char *envptr = environment, *dataptr = envptr + ENV_HEADER_SIZE; unsigned int datasize = ENV_SIZE; - unsigned int eoe; + const char *env_file; - if (argv[1] && !strncmp(argv[1], "--binary", 8)) { + if (argc < 2) { + puts("Usage: envcrc <environment object> [--binary [le]]"); + return 1; + } + env_file = argv[1]; + + if (argv[2] && !strncmp(argv[2], "--binary", 8)) { int ipad = 0xff; - if (argv[1][8] == '=') - sscanf(argv[1] + 9, "%i", &ipad); + if (argv[2][8] == '=') + sscanf(argv[2] + 9, "%i", &ipad); pad = ipad; } + memset(dataptr, pad, datasize); - if (pad) { - /* find the end of env */ - for (eoe = 0; eoe < datasize - 1; ++eoe) - if (!dataptr[eoe] && !dataptr[eoe+1]) { - eoe += 2; - break; - } - if (eoe < datasize - 1) - memset(dataptr + eoe, pad, datasize - eoe); + if (!read_env_from_elf(env_file)) { + fprintf(stderr, "unable to read environment from %s: %s\n", + env_file, strerror(errno)); + return 1; } crc = crc32 (0, dataptr, datasize); /* Check if verbose mode is activated passing a parameter to the program */ - if (argc > 1) { - if (!strncmp(argv[1], "--binary", 8)) { - int le = (argc > 2 ? !strcmp(argv[2], "le") : 1); + if (argc > 2) { + if (!strncmp(argv[2], "--binary", 8)) { + int le = (argc > 3 ? !strcmp(argv[3], "le") : 1); size_t i, start, end, step; if (le) { start = 0; -- 1.6.3.1 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot