diff options
author | Yang Zhang <yang.z.zhang@intel.com> | 2015-08-28 09:58:54 +0800 |
---|---|---|
committer | Yang Zhang <yang.z.zhang@intel.com> | 2015-09-01 12:44:00 +0800 |
commit | e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch) | |
tree | 66b09f592c55df2878107a468a91d21506104d3f /qemu/roms/u-boot/tools/mkenvimage.c | |
parent | 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (diff) |
Add qemu 2.4.0
Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5
Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Diffstat (limited to 'qemu/roms/u-boot/tools/mkenvimage.c')
-rw-r--r-- | qemu/roms/u-boot/tools/mkenvimage.c | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/qemu/roms/u-boot/tools/mkenvimage.c b/qemu/roms/u-boot/tools/mkenvimage.c new file mode 100644 index 000000000..bbd3041e3 --- /dev/null +++ b/qemu/roms/u-boot/tools/mkenvimage.c @@ -0,0 +1,295 @@ +/* + * (C) Copyright 2011 Free Electrons + * David Wagner <david.wagner@free-electrons.com> + * + * Inspired from envcrc.c: + * (C) Copyright 2001 + * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <libgen.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> + +#include "compiler.h" +#include <u-boot/crc.h> +#include <version.h> + +#define CRC_SIZE sizeof(uint32_t) + +static void usage(const char *exec_name) +{ + fprintf(stderr, "%s [-h] [-r] [-b] [-p <byte>] -s <environment partition size> -o <output> <input file>\n" + "\n" + "This tool takes a key=value input file (same as would a `printenv' show) and generates the corresponding environment image, ready to be flashed.\n" + "\n" + "\tThe input file is in format:\n" + "\t\tkey1=value1\n" + "\t\tkey2=value2\n" + "\t\t...\n" + "\t-r : the environment has multiple copies in flash\n" + "\t-b : the target is big endian (default is little endian)\n" + "\t-p <byte> : fill the image with <byte> bytes instead of 0xff bytes\n" + "\t-V : print version information and exit\n" + "\n" + "If the input file is \"-\", data is read from standard input\n", + exec_name); +} + +long int xstrtol(const char *s) +{ + long int tmp; + + errno = 0; + tmp = strtol(s, NULL, 0); + if (!errno) + return tmp; + + if (errno == ERANGE) + fprintf(stderr, "Bad integer format: %s\n", s); + else + fprintf(stderr, "Error while parsing %s: %s\n", s, + strerror(errno)); + + exit(EXIT_FAILURE); +} + +int main(int argc, char **argv) +{ + uint32_t crc, targetendian_crc; + const char *txt_filename = NULL, *bin_filename = NULL; + int txt_fd, bin_fd; + unsigned char *dataptr, *envptr; + unsigned char *filebuf = NULL; + unsigned int filesize = 0, envsize = 0, datasize = 0; + int bigendian = 0; + int redundant = 0; + unsigned char padbyte = 0xff; + + int option; + int ret = EXIT_SUCCESS; + + struct stat txt_file_stat; + + int fp, ep; + const char *prg; + + prg = basename(argv[0]); + + /* Turn off getopt()'s internal error message */ + opterr = 0; + + /* Parse the cmdline */ + while ((option = getopt(argc, argv, ":s:o:rbp:hV")) != -1) { + switch (option) { + case 's': + datasize = xstrtol(optarg); + break; + case 'o': + bin_filename = strdup(optarg); + if (!bin_filename) { + fprintf(stderr, "Can't strdup() the output filename\n"); + return EXIT_FAILURE; + } + break; + case 'r': + redundant = 1; + break; + case 'b': + bigendian = 1; + break; + case 'p': + padbyte = xstrtol(optarg); + break; + case 'h': + usage(prg); + return EXIT_SUCCESS; + case 'V': + printf("%s version %s\n", prg, PLAIN_VERSION); + return EXIT_SUCCESS; + case ':': + fprintf(stderr, "Missing argument for option -%c\n", + optopt); + usage(prg); + return EXIT_FAILURE; + default: + fprintf(stderr, "Wrong option -%c\n", optopt); + usage(prg); + return EXIT_FAILURE; + } + } + + /* Check datasize and allocate the data */ + if (datasize == 0) { + fprintf(stderr, "Please specify the size of the environment partition.\n"); + usage(prg); + return EXIT_FAILURE; + } + + dataptr = malloc(datasize * sizeof(*dataptr)); + if (!dataptr) { + fprintf(stderr, "Can't alloc %d bytes for dataptr.\n", + datasize); + return EXIT_FAILURE; + } + + /* + * envptr points to the beginning of the actual environment (after the + * crc and possible `redundant' byte + */ + envsize = datasize - (CRC_SIZE + redundant); + envptr = dataptr + CRC_SIZE + redundant; + + /* Pad the environment with the padding byte */ + memset(envptr, padbyte, envsize); + + /* Open the input file ... */ + if (optind >= argc || strcmp(argv[optind], "-") == 0) { + int readbytes = 0; + int readlen = sizeof(*envptr) * 4096; + txt_fd = STDIN_FILENO; + + do { + filebuf = realloc(filebuf, readlen); + if (!filebuf) { + fprintf(stderr, "Can't realloc memory for the input file buffer\n"); + return EXIT_FAILURE; + } + readbytes = read(txt_fd, filebuf + filesize, readlen); + if (errno) { + fprintf(stderr, "Error while reading stdin: %s\n", + strerror(errno)); + return EXIT_FAILURE; + } + filesize += readbytes; + } while (readbytes == readlen); + + } else { + txt_filename = argv[optind]; + txt_fd = open(txt_filename, O_RDONLY); + if (txt_fd == -1) { + fprintf(stderr, "Can't open \"%s\": %s\n", + txt_filename, strerror(errno)); + return EXIT_FAILURE; + } + /* ... and check it */ + ret = fstat(txt_fd, &txt_file_stat); + if (ret == -1) { + fprintf(stderr, "Can't stat() on \"%s\": %s\n", + txt_filename, strerror(errno)); + return EXIT_FAILURE; + } + + filesize = txt_file_stat.st_size; + + filebuf = mmap(NULL, sizeof(*envptr) * filesize, PROT_READ, + MAP_PRIVATE, txt_fd, 0); + if (filebuf == MAP_FAILED) { + fprintf(stderr, "mmap (%zu bytes) failed: %s\n", + sizeof(*envptr) * filesize, + strerror(errno)); + fprintf(stderr, "Falling back to read()\n"); + + filebuf = malloc(sizeof(*envptr) * filesize); + ret = read(txt_fd, filebuf, sizeof(*envptr) * filesize); + if (ret != sizeof(*envptr) * filesize) { + fprintf(stderr, "Can't read the whole input file (%zu bytes): %s\n", + sizeof(*envptr) * filesize, + strerror(errno)); + + return EXIT_FAILURE; + } + } + ret = close(txt_fd); + } + /* The +1 is for the additionnal ending \0. See below. */ + if (filesize + 1 > envsize) { + fprintf(stderr, "The input file is larger than the environment partition size\n"); + return EXIT_FAILURE; + } + + /* Replace newlines separating variables with \0 */ + for (fp = 0, ep = 0 ; fp < filesize ; fp++) { + if (filebuf[fp] == '\n') { + if (ep == 0) { + /* + * Newlines at the beginning of the file ? + * Ignore them. + */ + continue; + } else if (filebuf[fp-1] == '\\') { + /* + * Embedded newline in a variable. + * + * The backslash was added to the envptr; rewind + * and replace it with a newline + */ + ep--; + envptr[ep++] = '\n'; + } else { + /* End of a variable */ + envptr[ep++] = '\0'; + } + } else { + envptr[ep++] = filebuf[fp]; + } + } + /* + * Make sure there is a final '\0' + * And do it again on the next byte to mark the end of the environment. + */ + if (envptr[ep-1] != '\0') { + envptr[ep++] = '\0'; + /* + * The text file doesn't have an ending newline. We need to + * check the env size again to make sure we have room for two \0 + */ + if (ep >= envsize) { + fprintf(stderr, "The environment file is too large for the target environment storage\n"); + return EXIT_FAILURE; + } + envptr[ep] = '\0'; + } else { + envptr[ep] = '\0'; + } + + /* Computes the CRC and put it at the beginning of the data */ + crc = crc32(0, envptr, envsize); + targetendian_crc = bigendian ? cpu_to_be32(crc) : cpu_to_le32(crc); + + memcpy(dataptr, &targetendian_crc, sizeof(targetendian_crc)); + if (redundant) + dataptr[sizeof(targetendian_crc)] = 1; + + if (!bin_filename || strcmp(bin_filename, "-") == 0) { + bin_fd = STDOUT_FILENO; + } else { + bin_fd = creat(bin_filename, S_IRUSR | S_IWUSR | S_IRGRP | + S_IWGRP); + if (bin_fd == -1) { + fprintf(stderr, "Can't open output file \"%s\": %s\n", + bin_filename, strerror(errno)); + return EXIT_FAILURE; + } + } + + if (write(bin_fd, dataptr, sizeof(*dataptr) * datasize) != + sizeof(*dataptr) * datasize) { + fprintf(stderr, "write() failed: %s\n", strerror(errno)); + return EXIT_FAILURE; + } + + ret = close(bin_fd); + + return ret; +} |