diff options
author | Stefano Babic <sbabic@denx.de> | 2016-06-18 10:24:54 +0200 |
---|---|---|
committer | Stefano Babic <sbabic@denx.de> | 2016-06-18 10:25:13 +0200 |
commit | dc557e9a1fe00ca9d884bd88feef5bebf23fede4 (patch) | |
tree | ec09fdf8f7c4c44e30f4b38b7459a2cbbb71d094 /tools | |
parent | d2ba7a6adcef6e6f8c4418c7b0caf9d7ab98a6d4 (diff) | |
parent | 6b3943f1b04be60f147ee540fbd72c4c7ea89f80 (diff) | |
download | talos-obmc-uboot-dc557e9a1fe00ca9d884bd88feef5bebf23fede4.tar.gz talos-obmc-uboot-dc557e9a1fe00ca9d884bd88feef5bebf23fede4.zip |
Merge branch 'master' of git://git.denx.de/u-boot
Signed-off-by: Stefano Babic <sbabic@denx.de>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/.gitignore | 1 | ||||
-rw-r--r-- | tools/Makefile | 1 | ||||
-rw-r--r-- | tools/env/fw_env.c | 118 | ||||
-rw-r--r-- | tools/env/fw_env.h | 31 | ||||
-rw-r--r-- | tools/env/fw_env_main.c | 28 | ||||
-rwxr-xr-x | tools/genboardscfg.py | 1 | ||||
-rw-r--r-- | tools/palmtreo680/flash_u-boot.c | 177 | ||||
-rw-r--r-- | tools/rkimage.c | 7 | ||||
-rw-r--r-- | tools/zynqmpimage.c | 269 |
9 files changed, 371 insertions, 262 deletions
diff --git a/tools/.gitignore b/tools/.gitignore index ff07680308..cb1e722d45 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -1,4 +1,5 @@ /atmel_pmecc_params +/bin2header /bmp_logo /envcrc /fdtgrep diff --git a/tools/Makefile b/tools/Makefile index da50e1bffc..63355aa36d 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -98,6 +98,7 @@ dumpimage-mkimage-objs := aisimage.o \ common/hash.o \ ublimage.o \ zynqimage.o \ + zynqmpimage.o \ $(LIBFDT_OBJS) \ $(RSA_OBJS-y) diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c index 06cf63daa4..692abda731 100644 --- a/tools/env/fw_env.c +++ b/tools/env/fw_env.c @@ -35,9 +35,11 @@ #include "fw_env.h" -struct common_args common_args; -struct printenv_args printenv_args; -struct setenv_args setenv_args; +struct env_opts default_opts = { +#ifdef CONFIG_FILE + .config_file = CONFIG_FILE +#endif +}; #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) @@ -75,7 +77,8 @@ static int dev_current; #define CUR_ENVSIZE ENVSIZE(dev_current) -#define ENV_SIZE getenvsize() +static unsigned long usable_envsize; +#define ENV_SIZE usable_envsize struct env_image_single { uint32_t crc; /* CRC32 over data bytes */ @@ -106,7 +109,7 @@ static struct environment environment = { .flag_scheme = FLAG_NONE, }; -static int env_aes_cbc_crypt(char *data, const int enc); +static int env_aes_cbc_crypt(char *data, const int enc, uint8_t *key); static int HaveRedundEnv = 0; @@ -119,23 +122,11 @@ static unsigned char obsolete_flag = 0; static int flash_io (int mode); static char *envmatch (char * s1, char * s2); -static int parse_config (void); +static int parse_config(struct env_opts *opts); #if defined(CONFIG_FILE) static int get_config (char *); #endif -static inline ulong getenvsize (void) -{ - ulong rc = CUR_ENVSIZE - sizeof(uint32_t); - - if (HaveRedundEnv) - rc -= sizeof (char); - - if (common_args.aes_flag) - rc &= ~(AES_KEY_LENGTH - 1); - - return rc; -} static char *skip_chars(char *s) { @@ -239,12 +230,15 @@ int parse_aes_key(char *key, uint8_t *bin_key) * Print the current definition of one, or more, or all * environment variables */ -int fw_printenv (int argc, char *argv[]) +int fw_printenv(int argc, char *argv[], int value_only, struct env_opts *opts) { char *env, *nxt; int i, rc = 0; - if (fw_env_open()) + if (!opts) + opts = &default_opts; + + if (fw_env_open(opts)) return -1; if (argc == 0) { /* Print all env variables */ @@ -262,7 +256,7 @@ int fw_printenv (int argc, char *argv[]) return 0; } - if (printenv_args.name_suppress && argc != 1) { + if (value_only && argc != 1) { fprintf(stderr, "## Error: `-n' option requires exactly one argument\n"); return -1; @@ -283,7 +277,7 @@ int fw_printenv (int argc, char *argv[]) } val = envmatch (name, env); if (val) { - if (!printenv_args.name_suppress) { + if (!value_only) { fputs (name, stdout); putc ('=', stdout); } @@ -300,11 +294,16 @@ int fw_printenv (int argc, char *argv[]) return rc; } -int fw_env_close(void) +int fw_env_close(struct env_opts *opts) { int ret; - if (common_args.aes_flag) { - ret = env_aes_cbc_crypt(environment.data, 1); + + if (!opts) + opts = &default_opts; + + if (opts->aes_flag) { + ret = env_aes_cbc_crypt(environment.data, 1, + opts->aes_key); if (ret) { fprintf(stderr, "Error: can't encrypt env for flash\n"); @@ -457,7 +456,7 @@ int fw_env_write(char *name, char *value) * modified or deleted * */ -int fw_setenv(int argc, char *argv[]) +int fw_setenv(int argc, char *argv[], struct env_opts *opts) { int i; size_t len; @@ -465,13 +464,16 @@ int fw_setenv(int argc, char *argv[]) char *value = NULL; int valc; + if (!opts) + opts = &default_opts; + if (argc < 1) { fprintf(stderr, "## Error: variable name missing\n"); errno = EINVAL; return -1; } - if (fw_env_open()) { + if (fw_env_open(opts)) { fprintf(stderr, "Error: environment not initialized\n"); return -1; } @@ -507,7 +509,7 @@ int fw_setenv(int argc, char *argv[]) free(value); - return fw_env_close(); + return fw_env_close(opts); } /* @@ -527,7 +529,7 @@ int fw_setenv(int argc, char *argv[]) * 0 - OK * -1 - Error */ -int fw_parse_script(char *fname) +int fw_parse_script(char *fname, struct env_opts *opts) { FILE *fp; char dump[1024]; /* Maximum line length in the file */ @@ -537,7 +539,10 @@ int fw_parse_script(char *fname) int len; int ret = 0; - if (fw_env_open()) { + if (!opts) + opts = &default_opts; + + if (fw_env_open(opts)) { fprintf(stderr, "Error: environment not initialized\n"); return -1; } @@ -625,10 +630,9 @@ int fw_parse_script(char *fname) if (strcmp(fname, "-") != 0) fclose(fp); - ret |= fw_env_close(); + ret |= fw_env_close(opts); return ret; - } /* @@ -949,15 +953,15 @@ static int flash_flag_obsolete (int dev, int fd, off_t offset) } /* Encrypt or decrypt the environment before writing or reading it. */ -static int env_aes_cbc_crypt(char *payload, const int enc) +static int env_aes_cbc_crypt(char *payload, const int enc, uint8_t *key) { uint8_t *data = (uint8_t *)payload; - const int len = getenvsize(); + const int len = usable_envsize; uint8_t key_exp[AES_EXPAND_KEY_LENGTH]; uint32_t aes_blocks; /* First we expand the key. */ - aes_expand_key(common_args.aes_key, key_exp); + aes_expand_key(key, key_exp); /* Calculate the number of AES blocks to encrypt. */ aes_blocks = DIV_ROUND_UP(len, AES_KEY_LENGTH); @@ -1138,7 +1142,7 @@ static char *envmatch (char * s1, char * s2) /* * Prevent confusion if running from erased flash memory */ -int fw_env_open(void) +int fw_env_open(struct env_opts *opts) { int crc0, crc0_ok; unsigned char flag0; @@ -1153,7 +1157,10 @@ int fw_env_open(void) struct env_image_single *single; struct env_image_redundant *redundant; - if (parse_config ()) /* should fill envdevices */ + if (!opts) + opts = &default_opts; + + if (parse_config(opts)) /* should fill envdevices */ return -1; addr0 = calloc(1, CUR_ENVSIZE); @@ -1185,8 +1192,9 @@ int fw_env_open(void) crc0 = crc32 (0, (uint8_t *) environment.data, ENV_SIZE); - if (common_args.aes_flag) { - ret = env_aes_cbc_crypt(environment.data, 0); + if (opts->aes_flag) { + ret = env_aes_cbc_crypt(environment.data, 0, + opts->aes_key); if (ret) return ret; } @@ -1242,8 +1250,9 @@ int fw_env_open(void) crc1 = crc32 (0, (uint8_t *) redundant->data, ENV_SIZE); - if (common_args.aes_flag) { - ret = env_aes_cbc_crypt(redundant->data, 0); + if (opts->aes_flag) { + ret = env_aes_cbc_crypt(redundant->data, 0, + opts->aes_key); if (ret) return ret; } @@ -1320,18 +1329,18 @@ int fw_env_open(void) } -static int parse_config () +static int parse_config(struct env_opts *opts) { struct stat st; -#if defined(CONFIG_FILE) - if (!common_args.config_file) - common_args.config_file = CONFIG_FILE; + if (!opts) + opts = &default_opts; +#if defined(CONFIG_FILE) /* Fills in DEVNAME(), ENVSIZE(), DEVESIZE(). Or don't. */ - if (get_config(common_args.config_file)) { + if (get_config(opts->config_file)) { fprintf(stderr, "Cannot parse config file '%s': %m\n", - common_args.config_file); + opts->config_file); return -1; } #else @@ -1379,6 +1388,21 @@ static int parse_config () DEVNAME (1), strerror (errno)); return -1; } + + if (HaveRedundEnv && ENVSIZE(0) != ENVSIZE(1)) { + ENVSIZE(0) = ENVSIZE(1) = min(ENVSIZE(0), ENVSIZE(1)); + fprintf(stderr, + "Redundant environments have inequal size, set to 0x%08lx\n", + ENVSIZE(1)); + } + + usable_envsize = CUR_ENVSIZE - sizeof(uint32_t); + if (HaveRedundEnv) + usable_envsize -= sizeof(char); + + if (opts->aes_flag) + usable_envsize &= ~(AES_KEY_LENGTH - 1); + return 0; } diff --git a/tools/env/fw_env.h b/tools/env/fw_env.h index 57149e733b..dac964d933 100644 --- a/tools/env/fw_env.h +++ b/tools/env/fw_env.h @@ -57,33 +57,22 @@ "bootm" #endif -struct common_args { +struct env_opts { #ifdef CONFIG_FILE char *config_file; #endif - uint8_t aes_key[AES_KEY_LENGTH]; int aes_flag; /* Is AES encryption used? */ + uint8_t aes_key[AES_KEY_LENGTH]; }; -extern struct common_args common_args; - -struct printenv_args { - int name_suppress; -}; -extern struct printenv_args printenv_args; - -struct setenv_args { - char *script_file; -}; -extern struct setenv_args setenv_args; int parse_aes_key(char *key, uint8_t *bin_key); -extern int fw_printenv(int argc, char *argv[]); -extern char *fw_getenv (char *name); -extern int fw_setenv (int argc, char *argv[]); -extern int fw_parse_script(char *fname); -extern int fw_env_open(void); -extern int fw_env_write(char *name, char *value); -extern int fw_env_close(void); +int fw_printenv(int argc, char *argv[], int value_only, struct env_opts *opts); +char *fw_getenv(char *name); +int fw_setenv(int argc, char *argv[], struct env_opts *opts); +int fw_parse_script(char *fname, struct env_opts *opts); +int fw_env_open(struct env_opts *opts); +int fw_env_write(char *name, char *value); +int fw_env_close(struct env_opts *opts); -extern unsigned long crc32 (unsigned long, const unsigned char *, unsigned); +unsigned long crc32(unsigned long, const unsigned char *, unsigned); diff --git a/tools/env/fw_env_main.c b/tools/env/fw_env_main.c index 3706d8f1a6..7a17b28f40 100644 --- a/tools/env/fw_env_main.c +++ b/tools/env/fw_env_main.c @@ -49,6 +49,14 @@ static struct option long_options[] = { {NULL, 0, NULL, 0} }; +static struct env_opts env_opts; + +/* setenv options */ +static int noheader; + +/* getenv options */ +static char *script_file; + void usage_printenv(void) { @@ -108,22 +116,22 @@ static void parse_common_args(int argc, char *argv[]) int c; #ifdef CONFIG_FILE - common_args.config_file = CONFIG_FILE; + env_opts.config_file = CONFIG_FILE; #endif while ((c = getopt_long(argc, argv, ":a:c:h", long_options, NULL)) != EOF) { switch (c) { case 'a': - if (parse_aes_key(optarg, common_args.aes_key)) { + if (parse_aes_key(optarg, env_opts.aes_key)) { fprintf(stderr, "AES key parse error\n"); exit(EXIT_FAILURE); } - common_args.aes_flag = 1; + env_opts.aes_flag = 1; break; #ifdef CONFIG_FILE case 'c': - common_args.config_file = optarg; + env_opts.config_file = optarg; break; #endif case 'h': @@ -151,7 +159,7 @@ int parse_printenv_args(int argc, char *argv[]) EOF) { switch (c) { case 'n': - printenv_args.name_suppress = 1; + noheader = 1; break; case 'a': case 'c': @@ -177,7 +185,7 @@ int parse_setenv_args(int argc, char *argv[]) EOF) { switch (c) { case 's': - setenv_args.script_file = optarg; + script_file = optarg; break; case 'a': case 'c': @@ -240,14 +248,14 @@ int main(int argc, char *argv[]) } if (do_printenv) { - if (fw_printenv(argc, argv) != 0) + if (fw_printenv(argc, argv, noheader, &env_opts) != 0) retval = EXIT_FAILURE; } else { - if (!setenv_args.script_file) { - if (fw_setenv(argc, argv) != 0) + if (!script_file) { + if (fw_setenv(argc, argv, &env_opts) != 0) retval = EXIT_FAILURE; } else { - if (fw_parse_script(setenv_args.script_file) != 0) + if (fw_parse_script(script_file, &env_opts) != 0) retval = EXIT_FAILURE; } } diff --git a/tools/genboardscfg.py b/tools/genboardscfg.py index 23c956bb8e..c2efad55ab 100755 --- a/tools/genboardscfg.py +++ b/tools/genboardscfg.py @@ -21,7 +21,6 @@ import glob import multiprocessing import optparse import os -import subprocess import sys import tempfile import time diff --git a/tools/palmtreo680/flash_u-boot.c b/tools/palmtreo680/flash_u-boot.c deleted file mode 100644 index 832d3fef7b..0000000000 --- a/tools/palmtreo680/flash_u-boot.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2013 Mike Dunn <mikedunn@newsguy.com> - * - * This file is released under the terms of GPL v2 and any later version. - * See the file COPYING in the root directory of the source tree for details. - * - * - * This is a userspace Linux utility that, when run on the Treo 680, will - * program u-boot to flash. The docg4 driver *must* be loaded with the - * reliable_mode and ignore_badblocks parameters enabled: - * - * modprobe docg4 ignore_badblocks=1 reliable_mode=1 - * - * This utility writes the concatenated spl + u-boot image to the start of the - * mtd device in the format expected by the IPL/SPL. The image file and mtd - * device node are passed to the utility as arguments. The blocks must have - * been erased beforehand. - * - * When you compile this, note that it links to libmtd from mtd-utils, so ensure - * that your include and lib paths include this. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <string.h> -#include <sys/types.h> -#include <unistd.h> -#include <errno.h> -#include <mtd/mtd-user.h> -#include "libmtd.h" - -#define RELIABLE_BLOCKSIZE 0x10000 /* block capacity in reliable mode */ -#define STANDARD_BLOCKSIZE 0x40000 /* block capacity in normal mode */ -#define PAGESIZE 512 -#define PAGES_PER_BLOCK 512 -#define OOBSIZE 7 /* available to user (16 total) */ - -uint8_t ff_oob[OOBSIZE] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - -/* this is the magic number the IPL looks for (ASCII "BIPO") */ -uint8_t page0_oob[OOBSIZE] = {'B', 'I', 'P', 'O', 0xff, 0xff, 0xff}; - -int main(int argc, char * const argv[]) -{ - int devfd, datafd, num_blocks, block; - off_t file_size; - libmtd_t mtd_desc; - struct mtd_dev_info devinfo; - uint8_t *blockbuf; - char response[8]; - - if (argc != 3) { - printf("usage: %s <image file> <mtd dev node>\n", argv[0]); - return -EINVAL; - } - - mtd_desc = libmtd_open(); - if (mtd_desc == NULL) { - int errsv = errno; - fprintf(stderr, "can't initialize libmtd\n"); - return -errsv; - } - - /* open the spl image file and mtd device */ - datafd = open(argv[1], O_RDONLY); - if (datafd == -1) { - int errsv = errno; - perror(argv[1]); - return -errsv; - } - devfd = open(argv[2], O_WRONLY); - if (devfd == -1) { - int errsv = errno; - perror(argv[2]); - return -errsv; - } - if (mtd_get_dev_info(mtd_desc, argv[2], &devinfo) < 0) { - int errsv = errno; - perror(argv[2]); - return -errsv; - } - - /* determine the number of blocks needed by the image */ - file_size = lseek(datafd, 0, SEEK_END); - if (file_size == (off_t)-1) { - int errsv = errno; - perror("lseek"); - return -errsv; - } - num_blocks = (file_size + RELIABLE_BLOCKSIZE - 1) / RELIABLE_BLOCKSIZE; - file_size = lseek(datafd, 0, SEEK_SET); - if (file_size == (off_t)-1) { - int errsv = errno; - perror("lseek"); - return -errsv; - } - printf("The mtd partition contains %d blocks\n", devinfo.eb_cnt); - printf("U-Boot will occupy %d blocks\n", num_blocks); - if (num_blocks > devinfo.eb_cnt) { - fprintf(stderr, "Insufficient blocks on partition\n"); - return -EINVAL; - } - - printf("IMPORTANT: These blocks must be in an erased state!\n"); - printf("Do you want to proceed?\n"); - scanf("%s", response); - if ((response[0] != 'y') && (response[0] != 'Y')) { - printf("Exiting\n"); - close(devfd); - close(datafd); - return 0; - } - - blockbuf = calloc(RELIABLE_BLOCKSIZE, 1); - if (blockbuf == NULL) { - int errsv = errno; - perror("calloc"); - return -errsv; - } - - for (block = 0; block < num_blocks; block++) { - int ofs, page; - uint8_t *pagebuf = blockbuf, *buf = blockbuf; - uint8_t *oobbuf = page0_oob; /* magic num in oob of 1st page */ - size_t len = RELIABLE_BLOCKSIZE; - int ret; - - /* read data for one block from file */ - while (len) { - ssize_t read_ret = read(datafd, buf, len); - if (read_ret == -1) { - int errsv = errno; - if (errno == EINTR) - continue; - perror("read"); - return -errsv; - } else if (read_ret == 0) { - break; /* EOF */ - } - len -= read_ret; - buf += read_ret; - } - - printf("Block %d: writing\r", block + 1); - fflush(stdout); - - for (page = 0, ofs = 0; - page < PAGES_PER_BLOCK; - page++, ofs += PAGESIZE) { - if (page & 0x04) /* Odd-numbered 2k page */ - continue; /* skipped in reliable mode */ - - ret = mtd_write(mtd_desc, &devinfo, devfd, block, ofs, - pagebuf, PAGESIZE, oobbuf, OOBSIZE, - MTD_OPS_PLACE_OOB); - if (ret) { - fprintf(stderr, - "\nmtd_write returned %d on block %d, ofs %x\n", - ret, block + 1, ofs); - return -EIO; - } - oobbuf = ff_oob; /* oob for subsequent pages */ - - if (page & 0x01) /* odd-numbered subpage */ - pagebuf += PAGESIZE; - } - } - - printf("\nDone\n"); - - close(devfd); - close(datafd); - free(blockbuf); - return 0; -} diff --git a/tools/rkimage.c b/tools/rkimage.c index f9fdcfa712..ef31cb6944 100644 --- a/tools/rkimage.c +++ b/tools/rkimage.c @@ -13,11 +13,6 @@ static uint32_t header; -static int rkimage_check_params(struct image_tool_params *params) -{ - return 0; -} - static int rkimage_verify_header(unsigned char *buf, int size, struct image_tool_params *params) { @@ -56,7 +51,7 @@ U_BOOT_IMAGE_TYPE( "Rockchip Boot Image support", 4, &header, - rkimage_check_params, + rkcommon_check_params, rkimage_verify_header, rkimage_print_header, rkimage_set_header, diff --git a/tools/zynqmpimage.c b/tools/zynqmpimage.c new file mode 100644 index 0000000000..3f28eb401d --- /dev/null +++ b/tools/zynqmpimage.c @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2016 Michal Simek <michals@xilinx.com> + * Copyright (C) 2015 Nathan Rossi <nathan@nathanrossi.com> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * The following Boot Header format/structures and values are defined in the + * following documents: + * * ug1085 ZynqMP TRM (Chapter 9, Table 9-3) + * + * Expected Header Size = 0x9C0 + * Forced as 'little' endian, 32-bit words + * + * 0x 0 - Interrupt table (8 words) + * ... (Default value = 0xeafffffe) + * 0x 1f + * 0x 20 - Width detection + * * DEFAULT_WIDTHDETECTION 0xaa995566 + * 0x 24 - Image identifier + * * DEFAULT_IMAGEIDENTIFIER 0x584c4e58 + * 0x 28 - Encryption + * * 0x00000000 - None + * * 0xa5c3c5a3 - eFuse + * * 0xa5c3c5a7 - obfuscated key in eFUSE + * * 0x3a5c3c5a - bbRam + * * 0xa35c7ca5 - obfuscated key in boot header + * 0x 2C - Image load + * 0x 30 - Image offset + * 0x 34 - PFW image length + * 0x 38 - Total PFW image length + * 0x 3C - Image length + * 0x 40 - Total image length + * 0x 44 - Image attributes + * 0x 48 - Header checksum + * 0x 4c - Obfuscated key + * ... + * 0x 68 + * 0x 6c - Reserved + * 0x 70 - User defined + * ... + * 0x 9c + * 0x a0 - Secure header initialization vector + * ... + * 0x a8 + * 0x ac - Obfuscated key initialization vector + * ... + * 0x b4 + * 0x b8 - Register Initialization, 511 Address and Data word pairs + * * List is terminated with an address of 0xffffffff or + * ... * at the max number of entries + * 0x8b4 + * 0x8b8 - Reserved + * ... + * 0x9bf + * 0x9c0 - Data/Image starts here or above + */ + +#include "imagetool.h" +#include "mkimage.h" +#include <image.h> + +#define HEADER_INTERRUPT_DEFAULT (cpu_to_le32(0xeafffffe)) +#define HEADER_REGINIT_NULL (cpu_to_le32(0xffffffff)) +#define HEADER_WIDTHDETECTION (cpu_to_le32(0xaa995566)) +#define HEADER_IMAGEIDENTIFIER (cpu_to_le32(0x584c4e58)) + +enum { + ENCRYPTION_EFUSE = 0xa5c3c5a3, + ENCRYPTION_OEFUSE = 0xa5c3c5a7, + ENCRYPTION_BBRAM = 0x3a5c3c5a, + ENCRYPTION_OBBRAM = 0xa35c7ca5, + ENCRYPTION_NONE = 0x0, +}; + +struct zynqmp_reginit { + uint32_t address; + uint32_t data; +}; + +#define HEADER_INTERRUPT_VECTORS 8 +#define HEADER_REGINITS 256 + +struct zynqmp_header { + uint32_t interrupt_vectors[HEADER_INTERRUPT_VECTORS]; /* 0x0 */ + uint32_t width_detection; /* 0x20 */ + uint32_t image_identifier; /* 0x24 */ + uint32_t encryption; /* 0x28 */ + uint32_t image_load; /* 0x2c */ + uint32_t image_offset; /* 0x30 */ + uint32_t pfw_image_length; /* 0x34 */ + uint32_t total_pfw_image_length; /* 0x38 */ + uint32_t image_size; /* 0x3c */ + uint32_t image_stored_size; /* 0x40 */ + uint32_t image_attributes; /* 0x44 */ + uint32_t checksum; /* 0x48 */ + uint32_t __reserved1[27]; /* 0x4c */ + struct zynqmp_reginit register_init[HEADER_REGINITS]; /* 0xb8 */ + uint32_t __reserved4[66]; /* 0x9c0 */ +}; + +static struct zynqmp_header zynqmpimage_header; + +static uint32_t zynqmpimage_checksum(struct zynqmp_header *ptr) +{ + uint32_t checksum = 0; + + if (ptr == NULL) + return 0; + + checksum += le32_to_cpu(ptr->width_detection); + checksum += le32_to_cpu(ptr->image_identifier); + checksum += le32_to_cpu(ptr->encryption); + checksum += le32_to_cpu(ptr->image_load); + checksum += le32_to_cpu(ptr->image_offset); + checksum += le32_to_cpu(ptr->pfw_image_length); + checksum += le32_to_cpu(ptr->total_pfw_image_length); + checksum += le32_to_cpu(ptr->image_size); + checksum += le32_to_cpu(ptr->image_stored_size); + checksum += le32_to_cpu(ptr->image_attributes); + checksum = ~checksum; + + return cpu_to_le32(checksum); +} + +static void zynqmpimage_default_header(struct zynqmp_header *ptr) +{ + int i; + + if (ptr == NULL) + return; + + ptr->width_detection = HEADER_WIDTHDETECTION; + ptr->image_attributes = 0x800; + ptr->image_identifier = HEADER_IMAGEIDENTIFIER; + ptr->encryption = cpu_to_le32(ENCRYPTION_NONE); + + /* Setup not-supported/constant/reserved fields */ + for (i = 0; i < HEADER_INTERRUPT_VECTORS; i++) + ptr->interrupt_vectors[i] = HEADER_INTERRUPT_DEFAULT; + + for (i = 0; i < HEADER_REGINITS; i++) { + ptr->register_init[i].address = HEADER_REGINIT_NULL; + ptr->register_init[i].data = 0; + } + + /* + * Certain reserved fields are required to be set to 0, ensure they are + * set as such. + */ + ptr->pfw_image_length = 0x0; + ptr->total_pfw_image_length = 0x0; +} + +/* mkimage glue functions */ +static int zynqmpimage_verify_header(unsigned char *ptr, int image_size, + struct image_tool_params *params) +{ + struct zynqmp_header *zynqhdr = (struct zynqmp_header *)ptr; + + if (image_size < sizeof(struct zynqmp_header)) + return -1; + + if (zynqhdr->width_detection != HEADER_WIDTHDETECTION) + return -1; + if (zynqhdr->image_identifier != HEADER_IMAGEIDENTIFIER) + return -1; + + if (zynqmpimage_checksum(zynqhdr) != zynqhdr->checksum) + return -1; + + return 0; +} + +static void zynqmpimage_print_header(const void *ptr) +{ + struct zynqmp_header *zynqhdr = (struct zynqmp_header *)ptr; + int i; + + printf("Image Type : Xilinx Zynq Boot Image support\n"); + printf("Image Offset : 0x%08x\n", le32_to_cpu(zynqhdr->image_offset)); + printf("Image Size : %lu bytes (%lu bytes packed)\n", + (unsigned long)le32_to_cpu(zynqhdr->image_size), + (unsigned long)le32_to_cpu(zynqhdr->image_stored_size)); + printf("Image Load : 0x%08x\n", le32_to_cpu(zynqhdr->image_load)); + printf("Checksum : 0x%08x\n", le32_to_cpu(zynqhdr->checksum)); + + for (i = 0; i < HEADER_INTERRUPT_VECTORS; i++) { + if (zynqhdr->interrupt_vectors[i] == HEADER_INTERRUPT_DEFAULT) + continue; + + printf("Modified Interrupt Vector Address [%d]: 0x%08x\n", i, + le32_to_cpu(zynqhdr->interrupt_vectors[i])); + } + + for (i = 0; i < HEADER_REGINITS; i++) { + if (zynqhdr->register_init[i].address == HEADER_REGINIT_NULL) + break; + + if (i == 0) + printf("Custom Register Initialization:\n"); + + printf(" @ 0x%08x -> 0x%08x\n", + le32_to_cpu(zynqhdr->register_init[i].address), + le32_to_cpu(zynqhdr->register_init[i].data)); + } +} + +static int zynqmpimage_check_params(struct image_tool_params *params) +{ + if (!params) + return 0; + + if (params->addr != 0x0) { + fprintf(stderr, "Error: Load Address cannot be specified.\n"); + return -1; + } + + /* + * If the entry point is specified ensure it is 64 byte aligned. + */ + if (params->eflag && (params->ep % 64 != 0)) { + fprintf(stderr, + "Error: Entry Point must be aligned to a 64-byte boundary.\n"); + return -1; + } + + return !(params->lflag || params->dflag); +} + +static int zynqmpimage_check_image_types(uint8_t type) +{ + if (type == IH_TYPE_ZYNQMPIMAGE) + return EXIT_SUCCESS; + return EXIT_FAILURE; +} + +static void zynqmpimage_set_header(void *ptr, struct stat *sbuf, int ifd, + struct image_tool_params *params) +{ + struct zynqmp_header *zynqhdr = (struct zynqmp_header *)ptr; + zynqmpimage_default_header(zynqhdr); + + /* place image directly after header */ + zynqhdr->image_offset = + cpu_to_le32((uint32_t)sizeof(struct zynqmp_header)); + zynqhdr->image_size = cpu_to_le32(params->file_size - + sizeof(struct zynqmp_header)); + zynqhdr->image_stored_size = zynqhdr->image_size; + zynqhdr->image_load = 0xfffc0000; + if (params->eflag) + zynqhdr->image_load = cpu_to_le32((uint32_t)params->ep); + + zynqhdr->checksum = zynqmpimage_checksum(zynqhdr); +} + +U_BOOT_IMAGE_TYPE( + zynqmpimage, + "Xilinx ZynqMP Boot Image support", + sizeof(struct zynqmp_header), + (void *)&zynqmpimage_header, + zynqmpimage_check_params, + zynqmpimage_verify_header, + zynqmpimage_print_header, + zynqmpimage_set_header, + NULL, + zynqmpimage_check_image_types, + NULL, + NULL +); |