diff options
author | Lucas Stach <dev@lynxeye.de> | 2019-11-09 15:28:23 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2019-11-11 09:15:55 +0100 |
commit | 24fce509d00474d5978dc38828b39154431c8a49 (patch) | |
tree | 74d0475c0d71d6c91d4b282a6ecfa20d54720622 /scripts | |
parent | b2142963ef7391229dbe5021d72bbb209f53a8dd (diff) | |
download | barebox-24fce509d00474d5978dc38828b39154431c8a49.tar.gz barebox-24fce509d00474d5978dc38828b39154431c8a49.tar.xz |
ARM: zynq: move header generation to zynq_mkimage
Instead of generating a suitable image header with linker magic, move
all of this into zynq_mkimage. The configuration file format and parsing
is based on imx-image. This gets us one step further on the road to
proper multi-image support.
Signed-off-by: Lucas Stach <dev@lynxeye.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/Makefile | 1 | ||||
-rw-r--r-- | scripts/zynq_mkimage.c | 232 |
2 files changed, 222 insertions, 11 deletions
diff --git a/scripts/Makefile b/scripts/Makefile index 16bb513fbb..eb6718fadf 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -20,6 +20,7 @@ hostprogs-$(CONFIG_MVEBU_HOSTTOOLS) += kwbimage kwboot mvebuimg hostprogs-$(CONFIG_ARCH_OMAP) += omap_signGP mk-omap-image hostprogs-$(CONFIG_ARCH_S5PCxx) += s5p_cksum hostprogs-$(CONFIG_ARCH_DAVINCI) += mkublheader +HOSTCFLAGS_zynq_mkimage.o = -I$(srctree) -I$(srctree)/arch/arm/mach-zynq/include hostprogs-$(CONFIG_ARCH_ZYNQ) += zynq_mkimage hostprogs-$(CONFIG_ARCH_SOCFPGA) += socfpga_mkimage hostprogs-$(CONFIG_MXS_HOSTTOOLS)+= mxsimage mxsboot diff --git a/scripts/zynq_mkimage.c b/scripts/zynq_mkimage.c index 905d6fc69a..bf214ca5d0 100644 --- a/scripts/zynq_mkimage.c +++ b/scripts/zynq_mkimage.c @@ -15,35 +15,241 @@ #include <endian.h> #include <errno.h> #include <getopt.h> +#include <linux/kernel.h> +#include <mach/zynq-flash-header.h> #include <malloc.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <sys/stat.h> +#include <sys/types.h> static char *prgname; static void usage(char *name) { fprintf(stderr, "usage: %s [OPTIONS]\n\n" + "-c <config> configuration input file" "-f <input> input image file\n" "-o <output> output file\n" "-h this help\n", prgname); exit(1); } +#define MAXARGS 16 + +static int parse_line(char *line, char *argv[]) +{ + int nargs = 0; + + while (nargs < MAXARGS) { + + /* skip any white space */ + while ((*line == ' ') || (*line == '\t')) + ++line; + + if (*line == '\0') { /* end of line, no more args */ + argv[nargs] = NULL; + return nargs; + } + + argv[nargs++] = line; /* begin of argument string */ + + /* find end of string */ + while (*line && (*line != ' ') && (*line != '\t')) + ++line; + + if (*line == '\0') { /* end of line, no more args */ + argv[nargs] = NULL; + return nargs; + } + + *line++ = '\0'; /* terminate current arg */ + } + + printf("** Too many args (max. %d) **\n", MAXARGS); + + return nargs; +} + +struct command { + const char *name; + int (*parse)(char *buf, int argc, char *argv[]); +}; + +static int do_cmd_write_mem(char *buf, int argc, char *argv[]) +{ + unsigned int *wordbuf = (unsigned int *)(buf + REGINIT_OFFSET); + static int reginit_offset; + uint32_t addr, val, width; + char *end; + + if (argc != 4) { + fprintf(stderr, "usage: wm [8|16|32] <addr> <val>\n"); + return -EINVAL; + } + + width = strtoul(argv[1], &end, 0); + if (*end != '\0' || width != 32) { + fprintf(stderr, "illegal width token \"%s\"\n", argv[1]); + return -EINVAL; + } + + addr = strtoul(argv[2], &end, 0); + if (*end != '\0') { + fprintf(stderr, "illegal address token \"%s\"\n", argv[2]); + return -EINVAL; + } + + val = strtoul(argv[3], &end, 0); + if (*end != '\0') { + fprintf(stderr, "illegal value token \"%s\"\n", argv[3]); + return -EINVAL; + } + + wordbuf[reginit_offset] = htole32(addr); + wordbuf[reginit_offset + 1] = htole32(val); + wordbuf[reginit_offset + 1] = htole32(val); + + reginit_offset += 2; + + return 0; +} + +struct command cmds[] = { + { + .name = "wm", + .parse = do_cmd_write_mem, + }, +}; + +static char *readcmd(FILE *f) +{ + static char *buf; + char *str; + ssize_t ret; + + if (!buf) { + buf = malloc(4096); + if (!buf) + return NULL; + } + + str = buf; + *str = 0; + + while (1) { + ret = fread(str, 1, 1, f); + if (!ret) + return strlen(buf) ? buf : NULL; + + if (*str == '\n' || *str == ';') { + *str = 0; + return buf; + } + + str++; + } +} + +int parse_config(char *buf, const char *filename) +{ + FILE *f; + int lineno = 0; + char *line = NULL, *tmp; + char *argv[MAXARGS]; + int nargs, i, ret = 0; + + f = fopen(filename, "r"); + if (!f) { + fprintf(stderr, "Cannot open config file\n"); + exit(1); + } + + while (1) { + line = readcmd(f); + if (!line) + break; + + lineno++; + + tmp = strchr(line, '#'); + if (tmp) + *tmp = 0; + + nargs = parse_line(line, argv); + if (!nargs) + continue; + + ret = -ENOENT; + + for (i = 0; i < ARRAY_SIZE(cmds); i++) { + if (!strcmp(cmds[i].name, argv[0])) { + ret = cmds[i].parse(buf, nargs, argv); + if (ret) { + fprintf(stderr, "error in line %d: %s\n", + lineno, strerror(-ret)); + goto cleanup; + } + break; + } + } + + if (ret == -ENOENT) { + fprintf(stderr, "no such command: %s\n", argv[0]); + goto cleanup; + } + } + +cleanup: + fclose(f); + return ret; +} + +static void add_header(char *buf, unsigned int image_size) +{ + unsigned int *wordbuf = (unsigned int *)buf; + struct zynq_flash_header flash_header = { + .width_det = WIDTH_DETECTION_MAGIC, + .image_id = IMAGE_IDENTIFICATION, + .enc_stat = 0x0, + .user = 0x0, + .flash_offset = IMAGE_OFFSET, + .length = image_size, + .res0 = 0x0, + .start_of_exec = 0x0, + .total_len = image_size, + .res1 = 0x1, + .checksum = 0x0, + .res2 = 0x0, + }; + int i, sum = 0; + + memcpy(wordbuf + 0x8, &flash_header, sizeof(flash_header)); + + for (i = 0x8; i < 0x12; i++) + sum += htole32(wordbuf[i]); + + sum = ~sum; + wordbuf[i] = sum; +} + int main(int argc, char *argv[]) { FILE *ifile, *ofile; - unsigned int *buf; - const char *infile = NULL, *outfile = NULL; + char *buf; + const char *infile = NULL, *outfile = NULL, *cfgfile = NULL; struct stat st; - unsigned int i,sum = 0; int opt; prgname = argv[0]; - while ((opt = getopt(argc, argv, "f:ho:")) != -1) { + while ((opt = getopt(argc, argv, "c:f:ho:")) != -1) { switch (opt) { + case 'c': + cfgfile = optarg; + break; case 'f': infile = optarg; break; @@ -67,12 +273,17 @@ int main(int argc, char *argv[]) exit(1); } + if (!cfgfile) { + fprintf(stderr, "config file not given\n"); + exit(1); + } + if (stat(infile, &st) == -1) { perror("stat"); exit(EXIT_FAILURE); } - buf = malloc(st.st_size); + buf = calloc(st.st_size + IMAGE_OFFSET, sizeof(char)); if (!buf) { fprintf(stderr, "Unable to allocate buffer\n"); return -1; @@ -93,15 +304,14 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - fread(buf, 4, st.st_size, ifile); + fread(buf + IMAGE_OFFSET, sizeof(char), st.st_size, ifile); - for (i = 0x8; i < 0x12; i++) - sum += htole32(buf[i]); + add_header(buf, st.st_size); - sum = ~sum; - buf[i] = sum; + if (cfgfile) + parse_config(buf, cfgfile); - fwrite(buf, st.st_size / 4, 4, ofile); + fwrite(buf, sizeof(char), st.st_size + IMAGE_OFFSET, ofile); fclose(ofile); fclose(ifile); |