diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/Makefile | 2 | ||||
-rw-r--r-- | tools/fit_image.c | 502 | ||||
-rw-r--r-- | tools/imagetool.c | 22 | ||||
-rw-r--r-- | tools/imagetool.h | 24 | ||||
-rw-r--r-- | tools/mkimage.c | 403 |
5 files changed, 770 insertions, 183 deletions
diff --git a/tools/Makefile b/tools/Makefile index 2881a7c439..1e4b4aaa02 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -59,7 +59,7 @@ FIT_SIG_OBJS-$(CONFIG_FIT_SIGNATURE) := common/image-sig.o # Flattened device tree objects LIBFDT_OBJS := $(addprefix lib/libfdt/, \ fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_wip.o \ - fdt_region.o) + fdt_region.o fdt_sw.o) RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := $(addprefix lib/rsa/, \ rsa-sign.o rsa-verify.o rsa-checksum.o \ rsa-mod-exp.o) diff --git a/tools/fit_image.c b/tools/fit_image.c index eb2a25eeac..3ecc88fb56 100644 --- a/tools/fit_image.c +++ b/tools/fit_image.c @@ -18,6 +18,8 @@ #include "fit_common.h" #include "mkimage.h" #include <image.h> +#include <stdarg.h> +#include <version.h> #include <u-boot/crc.h> static image_header_t header; @@ -71,6 +73,481 @@ err_keydest: } /** + * fit_calc_size() - Calculate the approximate size of the FIT we will generate + */ +static int fit_calc_size(struct image_tool_params *params) +{ + struct content_info *cont; + int size, total_size; + + size = imagetool_get_filesize(params, params->datafile); + if (size < 0) + return -1; + + total_size = size; + for (cont = params->content_head; cont; cont = cont->next) { + size = imagetool_get_filesize(params, cont->fname); + if (size < 0) + return -1; + + /* Add space for properties */ + total_size += size + 300; + } + + /* Add plenty of space for headers, properties, nodes, etc. */ + total_size += 4096; + + return total_size; +} + +static int fdt_property_file(struct image_tool_params *params, + void *fdt, const char *name, const char *fname) +{ + struct stat sbuf; + void *ptr; + int ret; + int fd; + + fd = open(fname, O_RDWR | O_BINARY); + if (fd < 0) { + fprintf(stderr, "%s: Can't open %s: %s\n", + params->cmdname, fname, strerror(errno)); + return -1; + } + + if (fstat(fd, &sbuf) < 0) { + fprintf(stderr, "%s: Can't stat %s: %s\n", + params->cmdname, fname, strerror(errno)); + goto err; + } + + ret = fdt_property_placeholder(fdt, "data", sbuf.st_size, &ptr); + if (ret) + return ret; + ret = read(fd, ptr, sbuf.st_size); + if (ret != sbuf.st_size) { + fprintf(stderr, "%s: Can't read %s: %s\n", + params->cmdname, fname, strerror(errno)); + goto err; + } + + return 0; +err: + close(fd); + return -1; +} + +static int fdt_property_strf(void *fdt, const char *name, const char *fmt, ...) +{ + char str[100]; + va_list ptr; + + va_start(ptr, fmt); + vsnprintf(str, sizeof(str), fmt, ptr); + va_end(ptr); + return fdt_property_string(fdt, name, str); +} + +static void get_basename(char *str, int size, const char *fname) +{ + const char *p, *start, *end; + int len; + + /* + * Use the base name as the 'name' field. So for example: + * + * "arch/arm/dts/sun7i-a20-bananapro.dtb" + * becomes "sun7i-a20-bananapro" + */ + p = strrchr(fname, '/'); + start = p ? p + 1 : fname; + p = strrchr(fname, '.'); + end = p ? p : fname + strlen(fname); + len = end - start; + if (len >= size) + len = size - 1; + memcpy(str, start, len); + str[len] = '\0'; +} + +/** + * fit_write_images() - Write out a list of images to the FIT + * + * We always include the main image (params->datafile). If there are device + * tree files, we include an fdt@ node for each of those too. + */ +static int fit_write_images(struct image_tool_params *params, char *fdt) +{ + struct content_info *cont; + const char *typename; + char str[100]; + int upto; + int ret; + + fdt_begin_node(fdt, "images"); + + /* First the main image */ + typename = genimg_get_type_short_name(params->fit_image_type); + snprintf(str, sizeof(str), "%s@1", typename); + fdt_begin_node(fdt, str); + fdt_property_string(fdt, "description", params->imagename); + fdt_property_string(fdt, "type", typename); + fdt_property_string(fdt, "arch", genimg_get_arch_name(params->arch)); + fdt_property_string(fdt, "os", genimg_get_os_short_name(params->os)); + fdt_property_string(fdt, "compression", + genimg_get_comp_short_name(params->comp)); + fdt_property_u32(fdt, "load", params->addr); + fdt_property_u32(fdt, "entry", params->ep); + + /* + * Put data last since it is large. SPL may only load the first part + * of the DT, so this way it can access all the above fields. + */ + ret = fdt_property_file(params, fdt, "data", params->datafile); + if (ret) + return ret; + fdt_end_node(fdt); + + /* Now the device tree files if available */ + upto = 0; + for (cont = params->content_head; cont; cont = cont->next) { + if (cont->type != IH_TYPE_FLATDT) + continue; + snprintf(str, sizeof(str), "%s@%d", FIT_FDT_PROP, ++upto); + fdt_begin_node(fdt, str); + + get_basename(str, sizeof(str), cont->fname); + fdt_property_string(fdt, "description", str); + ret = fdt_property_file(params, fdt, "data", cont->fname); + if (ret) + return ret; + fdt_property_string(fdt, "type", typename); + fdt_property_string(fdt, "arch", + genimg_get_arch_short_name(params->arch)); + fdt_property_string(fdt, "compression", + genimg_get_comp_short_name(IH_COMP_NONE)); + fdt_end_node(fdt); + } + + fdt_end_node(fdt); + + return 0; +} + +/** + * fit_write_configs() - Write out a list of configurations to the FIT + * + * If there are device tree files, we include a configuration for each, which + * selects the main image (params->datafile) and its corresponding device + * tree file. + * + * Otherwise we just create a configuration with the main image in it. + */ +static void fit_write_configs(struct image_tool_params *params, char *fdt) +{ + struct content_info *cont; + const char *typename; + char str[100]; + int upto; + + fdt_begin_node(fdt, "configurations"); + fdt_property_string(fdt, "default", "conf@1"); + + upto = 0; + for (cont = params->content_head; cont; cont = cont->next) { + if (cont->type != IH_TYPE_FLATDT) + continue; + typename = genimg_get_type_short_name(cont->type); + snprintf(str, sizeof(str), "conf@%d", ++upto); + fdt_begin_node(fdt, str); + + get_basename(str, sizeof(str), cont->fname); + fdt_property_string(fdt, "description", str); + + typename = genimg_get_type_short_name(params->fit_image_type); + snprintf(str, sizeof(str), "%s@1", typename); + fdt_property_string(fdt, typename, str); + + snprintf(str, sizeof(str), FIT_FDT_PROP "@%d", upto); + fdt_property_string(fdt, FIT_FDT_PROP, str); + fdt_end_node(fdt); + } + if (!upto) { + fdt_begin_node(fdt, "conf@1"); + typename = genimg_get_type_short_name(params->fit_image_type); + snprintf(str, sizeof(str), "%s@1", typename); + fdt_property_string(fdt, typename, str); + fdt_end_node(fdt); + } + + fdt_end_node(fdt); +} + +static int fit_build_fdt(struct image_tool_params *params, char *fdt, int size) +{ + int ret; + + ret = fdt_create(fdt, size); + if (ret) + return ret; + fdt_finish_reservemap(fdt); + fdt_begin_node(fdt, ""); + fdt_property_strf(fdt, "description", + "%s image with one or more FDT blobs", + genimg_get_type_name(params->fit_image_type)); + fdt_property_strf(fdt, "creator", "U-Boot mkimage %s", PLAIN_VERSION); + fdt_property_u32(fdt, "#address-cells", 1); + ret = fit_write_images(params, fdt); + if (ret) + return ret; + fit_write_configs(params, fdt); + fdt_end_node(fdt); + ret = fdt_finish(fdt); + if (ret) + return ret; + + return fdt_totalsize(fdt); +} + +static int fit_build(struct image_tool_params *params, const char *fname) +{ + char *buf; + int size; + int ret; + int fd; + + size = fit_calc_size(params); + if (size < 0) + return -1; + buf = malloc(size); + if (!buf) { + fprintf(stderr, "%s: Out of memory (%d bytes)\n", + params->cmdname, size); + return -1; + } + ret = fit_build_fdt(params, buf, size); + if (ret < 0) { + fprintf(stderr, "%s: Failed to build FIT image\n", + params->cmdname); + goto err; + } + size = ret; + fd = open(fname, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0666); + if (fd < 0) { + fprintf(stderr, "%s: Can't open %s: %s\n", + params->cmdname, fname, strerror(errno)); + goto err; + } + ret = write(fd, buf, size); + if (ret != size) { + fprintf(stderr, "%s: Can't write %s: %s\n", + params->cmdname, fname, strerror(errno)); + close(fd); + goto err; + } + close(fd); + + return 0; +err: + free(buf); + return -1; +} + +/** + * fit_extract_data() - Move all data outside the FIT + * + * This takes a normal FIT file and removes all the 'data' properties from it. + * The data is placed in an area after the FIT so that it can be accessed + * using an offset into that area. The 'data' properties turn into + * 'data-offset' properties. + * + * This function cannot cope with FITs with 'data-offset' properties. All + * data must be in 'data' properties on entry. + */ +static int fit_extract_data(struct image_tool_params *params, const char *fname) +{ + void *buf; + int buf_ptr; + int fit_size, new_size; + int fd; + struct stat sbuf; + void *fdt; + int ret; + int images; + int node; + + fd = mmap_fdt(params->cmdname, fname, 0, &fdt, &sbuf, false); + if (fd < 0) + return -EIO; + fit_size = fdt_totalsize(fdt); + + /* Allocate space to hold the image data we will extract */ + buf = malloc(fit_size); + if (!buf) { + ret = -ENOMEM; + goto err; + } + buf_ptr = 0; + + images = fdt_path_offset(fdt, FIT_IMAGES_PATH); + if (images < 0) { + debug("%s: Cannot find /images node: %d\n", __func__, images); + ret = -EINVAL; + goto err; + } + + for (node = fdt_first_subnode(fdt, images); + node >= 0; + node = fdt_next_subnode(fdt, node)) { + const char *data; + int len; + + data = fdt_getprop(fdt, node, "data", &len); + if (!data) + continue; + memcpy(buf + buf_ptr, data, len); + debug("Extracting data size %x\n", len); + + ret = fdt_delprop(fdt, node, "data"); + if (ret) { + ret = -EPERM; + goto err; + } + fdt_setprop_u32(fdt, node, "data-offset", buf_ptr); + fdt_setprop_u32(fdt, node, "data-size", len); + + buf_ptr += (len + 3) & ~3; + } + + /* Pack the FDT and place the data after it */ + fdt_pack(fdt); + + debug("Size reduced from %x to %x\n", fit_size, fdt_totalsize(fdt)); + debug("External data size %x\n", buf_ptr); + new_size = fdt_totalsize(fdt); + new_size = (new_size + 3) & ~3; + munmap(fdt, sbuf.st_size); + + if (ftruncate(fd, new_size)) { + debug("%s: Failed to truncate file: %s\n", __func__, + strerror(errno)); + ret = -EIO; + goto err; + } + if (lseek(fd, new_size, SEEK_SET) < 0) { + debug("%s: Failed to seek to end of file: %s\n", __func__, + strerror(errno)); + ret = -EIO; + goto err; + } + if (write(fd, buf, buf_ptr) != buf_ptr) { + debug("%s: Failed to write external data to file %s\n", + __func__, strerror(errno)); + ret = -EIO; + goto err; + } + close(fd); + + ret = 0; + +err: + close(fd); + return ret; +} + +static int fit_import_data(struct image_tool_params *params, const char *fname) +{ + void *fdt, *old_fdt; + int fit_size, new_size, size, data_base; + int fd; + struct stat sbuf; + int ret; + int images; + int node; + + fd = mmap_fdt(params->cmdname, fname, 0, &old_fdt, &sbuf, false); + if (fd < 0) + return -EIO; + fit_size = fdt_totalsize(old_fdt); + data_base = (fit_size + 3) & ~3; + + /* Allocate space to hold the new FIT */ + size = sbuf.st_size + 16384; + fdt = malloc(size); + if (!fdt) { + fprintf(stderr, "%s: Failed to allocate memory (%d bytes)\n", + __func__, size); + ret = -ENOMEM; + goto err; + } + ret = fdt_open_into(old_fdt, fdt, size); + if (ret) { + debug("%s: Failed to expand FIT: %s\n", __func__, + fdt_strerror(errno)); + ret = -EINVAL; + goto err; + } + + images = fdt_path_offset(fdt, FIT_IMAGES_PATH); + if (images < 0) { + debug("%s: Cannot find /images node: %d\n", __func__, images); + ret = -EINVAL; + goto err; + } + + for (node = fdt_first_subnode(fdt, images); + node >= 0; + node = fdt_next_subnode(fdt, node)) { + int buf_ptr; + int len; + + buf_ptr = fdtdec_get_int(fdt, node, "data-offset", -1); + len = fdtdec_get_int(fdt, node, "data-size", -1); + if (buf_ptr == -1 || len == -1) + continue; + debug("Importing data size %x\n", len); + + ret = fdt_setprop(fdt, node, "data", fdt + data_base + buf_ptr, + len); + if (ret) { + debug("%s: Failed to write property: %s\n", __func__, + fdt_strerror(ret)); + ret = -EINVAL; + goto err; + } + } + + munmap(fdt, sbuf.st_size); + close(fd); + + /* Pack the FDT and place the data after it */ + fdt_pack(fdt); + + new_size = fdt_totalsize(fdt); + debug("Size expanded from %x to %x\n", fit_size, new_size); + + fd = open(fname, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0666); + if (fd < 0) { + fprintf(stderr, "%s: Can't open %s: %s\n", + params->cmdname, fname, strerror(errno)); + goto err; + } + if (write(fd, fdt, new_size) != new_size) { + debug("%s: Failed to write external data to file %s\n", + __func__, strerror(errno)); + ret = -EIO; + goto err; + } + close(fd); + + ret = 0; + +err: + close(fd); + return ret; +} + +/** * fit_handle_file - main FIT file processing function * * fit_handle_file() runs dtc to convert .its to .itb, includes @@ -103,7 +580,14 @@ static int fit_handle_file(struct image_tool_params *params) sprintf (tmpfile, "%s%s", params->imagefile, MKIMAGE_TMPFILE_SUFFIX); /* We either compile the source file, or use the existing FIT image */ - if (params->datafile) { + if (params->auto_its) { + if (fit_build(params, tmpfile)) { + fprintf(stderr, "%s: failed to build FIT\n", + params->cmdname); + return EXIT_FAILURE; + } + *cmd = '\0'; + } else if (params->datafile) { /* dtc -I dts -O dtb -p 500 datafile > tmpfile */ snprintf(cmd, sizeof(cmd), "%s %s %s > %s", MKIMAGE_DTC, params->dtc, params->datafile, tmpfile); @@ -112,12 +596,17 @@ static int fit_handle_file(struct image_tool_params *params) snprintf(cmd, sizeof(cmd), "cp %s %s", params->imagefile, tmpfile); } - if (system (cmd) == -1) { + if (*cmd && system(cmd) == -1) { fprintf (stderr, "%s: system(%s) failed: %s\n", params->cmdname, cmd, strerror(errno)); goto err_system; } + /* Move the data so it is internal to the FIT, if needed */ + ret = fit_import_data(params, tmpfile); + if (ret) + goto err_system; + /* * Set hashes for images in the blob. Unfortunately we may need more * space in either FDT, so keep trying until we succeed. @@ -140,6 +629,13 @@ static int fit_handle_file(struct image_tool_params *params) goto err_system; } + /* Move the data so it is external to the FIT, if requested */ + if (params->external_data) { + ret = fit_extract_data(params, tmpfile); + if (ret) + goto err_system; + } + if (rename (tmpfile, params->imagefile) == -1) { fprintf (stderr, "%s: Can't rename %s to %s: %s\n", params->cmdname, tmpfile, params->imagefile, @@ -248,6 +744,8 @@ static int fit_extract_contents(void *ptr, struct image_tool_params *params) static int fit_check_params(struct image_tool_params *params) { + if (params->auto_its) + return 0; return ((params->dflag && (params->fflag || params->lflag)) || (params->fflag && (params->dflag || params->lflag)) || (params->lflag && (params->dflag || params->fflag))); diff --git a/tools/imagetool.c b/tools/imagetool.c index 4b0b73db52..351211cd53 100644 --- a/tools/imagetool.c +++ b/tools/imagetool.c @@ -91,3 +91,25 @@ int imagetool_save_subimage( return 0; } + +int imagetool_get_filesize(struct image_tool_params *params, const char *fname) +{ + struct stat sbuf; + int fd; + + fd = open(fname, O_RDONLY | O_BINARY); + if (fd < 0) { + fprintf(stderr, "%s: Can't open %s: %s\n", + params->cmdname, fname, strerror(errno)); + return -1; + } + + if (fstat(fd, &sbuf) < 0) { + fprintf(stderr, "%s: Can't stat %s: %s\n", + params->cmdname, fname, strerror(errno)); + return -1; + } + close(fd); + + return sbuf.st_size; +} diff --git a/tools/imagetool.h b/tools/imagetool.h index ad2deb58dc..24f8f4b2f6 100644 --- a/tools/imagetool.h +++ b/tools/imagetool.h @@ -27,6 +27,13 @@ #define IH_ARCH_DEFAULT IH_ARCH_INVALID +/* Information about a file that needs to be placed into the FIT */ +struct content_info { + struct content_info *next; + int type; /* File type (IH_TYPE_...) */ + const char *fname; +}; + /* * This structure defines all such variables those are initialized by * mkimage and dumpimage main core and need to be referred by image @@ -61,6 +68,11 @@ struct image_tool_params { int require_keys; /* 1 to mark signing keys as 'required' */ int file_size; /* Total size of output file */ int orig_file_size; /* Original size for file before padding */ + bool auto_its; /* Automatically create the .its file */ + int fit_image_type; /* Image type to put into the FIT */ + struct content_info *content_head; /* List of files to include */ + struct content_info *content_tail; + bool external_data; /* Store data outside the FIT */ }; /* @@ -180,6 +192,18 @@ int imagetool_save_subimage( ulong file_data, ulong file_len); +/** + * imagetool_get_filesize() - Utility function to obtain the size of a file + * + * This function prints a message if an error occurs, showing the error that + * was obtained. + * + * @params: mkimage parameters + * @fname: filename to check + * @return size of file, or -ve value on error + */ +int imagetool_get_filesize(struct image_tool_params *params, const char *fname); + /* * There is a c file associated with supported image type low level code * for ex. default_image.c, fit_image.c diff --git a/tools/mkimage.c b/tools/mkimage.c index facebcdf5a..29317830d1 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -13,10 +13,9 @@ #include <version.h> static void copy_file(int, const char *, int); -static void usage(void); /* parameters initialized by core will be used by the image type code */ -struct image_tool_params params = { +static struct image_tool_params params = { .os = IH_OS_LINUX, .arch = IH_ARCH_PPC, .type = IH_TYPE_KERNEL, @@ -67,6 +66,224 @@ static void show_image_types(void) fprintf(stderr, "\n"); } +static void usage(const char *msg) +{ + fprintf(stderr, "Error: %s\n", msg); + fprintf(stderr, "Usage: %s -l image\n" + " -l ==> list image header information\n", + params.cmdname); + fprintf(stderr, + " %s [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image\n" + " -A ==> set architecture to 'arch'\n" + " -O ==> set operating system to 'os'\n" + " -T ==> set image type to 'type'\n" + " -C ==> set compression type 'comp'\n" + " -a ==> set load address to 'addr' (hex)\n" + " -e ==> set entry point to 'ep' (hex)\n" + " -n ==> set image name to 'name'\n" + " -d ==> use image data from 'datafile'\n" + " -x ==> set XIP (execute in place)\n", + params.cmdname); + fprintf(stderr, + " %s [-D dtc_options] [-f fit-image.its|-f auto|-F] [-b <dtb_list>] fit-image\n" + " <dtb_list> is used with -f auto, and is a space-separated list of .dtb files\n", + params.cmdname); + fprintf(stderr, + " -D => set all options for device tree compiler\n" + " -f => input filename for FIT source\n"); +#ifdef CONFIG_FIT_SIGNATURE + fprintf(stderr, + "Signing / verified boot options: [-k keydir] [-K dtb] [ -c <comment>] [-r]\n" + " -k => set directory containing private keys\n" + " -K => write public keys to this .dtb file\n" + " -c => add comment in signature node\n" + " -F => re-sign existing FIT image\n" + " -r => mark keys used as 'required' in dtb\n"); +#else + fprintf(stderr, + "Signing / verified boot not supported (CONFIG_FIT_SIGNATURE undefined)\n"); +#endif + fprintf(stderr, " %s -V ==> print version information and exit\n", + params.cmdname); + fprintf(stderr, "Use -T to see a list of available image types\n"); + + exit(EXIT_FAILURE); +} + +static int add_content(int type, const char *fname) +{ + struct content_info *cont; + + cont = calloc(1, sizeof(*cont)); + if (!cont) + return -1; + cont->type = type; + cont->fname = fname; + if (params.content_tail) + params.content_tail->next = cont; + else + params.content_head = cont; + params.content_tail = cont; + + return 0; +} + +static void process_args(int argc, char **argv) +{ + char *ptr; + int type = IH_TYPE_INVALID; + char *datafile = NULL; + int expecting; + int opt; + + expecting = IH_TYPE_COUNT; /* Unknown */ + while ((opt = getopt(argc, argv, + "-a:A:bcC:d:D:e:Ef:Fk:K:ln:O:rR:sT:vVx")) != -1) { + switch (opt) { + case 'a': + params.addr = strtoull(optarg, &ptr, 16); + if (*ptr) { + fprintf(stderr, "%s: invalid load address %s\n", + params.cmdname, optarg); + exit(EXIT_FAILURE); + } + break; + case 'A': + params.arch = genimg_get_arch_id(optarg); + if (params.arch < 0) + usage("Invalid architecture"); + break; + case 'b': + expecting = IH_TYPE_FLATDT; + break; + case 'c': + params.comment = optarg; + break; + case 'C': + params.comp = genimg_get_comp_id(optarg); + if (params.comp < 0) + usage("Invalid compression type"); + break; + case 'd': + params.datafile = optarg; + params.dflag = 1; + break; + case 'D': + params.dtc = optarg; + break; + case 'e': + params.ep = strtoull(optarg, &ptr, 16); + if (*ptr) { + fprintf(stderr, "%s: invalid entry point %s\n", + params.cmdname, optarg); + exit(EXIT_FAILURE); + } + params.eflag = 1; + break; + case 'E': + params.external_data = true; + break; + case 'f': + datafile = optarg; + params.auto_its = !strcmp(datafile, "auto"); + /* no break */ + case 'F': + /* + * The flattened image tree (FIT) format + * requires a flattened device tree image type + */ + params.fit_image_type = params.type; + params.type = IH_TYPE_FLATDT; + params.fflag = 1; + break; + case 'k': + params.keydir = optarg; + break; + case 'K': + params.keydest = optarg; + break; + case 'l': + params.lflag = 1; + break; + case 'n': + params.imagename = optarg; + break; + case 'O': + params.os = genimg_get_os_id(optarg); + if (params.os < 0) + usage("Invalid operating system"); + break; + case 'r': + params.require_keys = 1; + break; + case 'R': + /* + * This entry is for the second configuration + * file, if only one is not enough. + */ + params.imagename2 = optarg; + break; + case 's': + params.skipcpy = 1; + break; + case 'T': + type = genimg_get_type_id(optarg); + if (type < 0) { + show_image_types(); + usage("Invalid image type"); + } + expecting = type; + break; + case 'v': + params.vflag++; + break; + case 'V': + printf("mkimage version %s\n", PLAIN_VERSION); + exit(EXIT_SUCCESS); + case 'x': + params.xflag++; + break; + case 1: + if (expecting == type || optind == argc) { + params.imagefile = optarg; + expecting = IH_TYPE_INVALID; + } else if (expecting == IH_TYPE_INVALID) { + fprintf(stderr, + "%s: Unknown content type: use -b before device tree files", + params.cmdname); + exit(EXIT_FAILURE); + } else { + if (add_content(expecting, optarg)) { + fprintf(stderr, + "%s: Out of memory adding content '%s'", + params.cmdname, optarg); + exit(EXIT_FAILURE); + } + } + break; + default: + usage("Invalid option"); + } + } + + /* + * For auto-generated FIT images we need to know the image type to put + * in the FIT, which is separate from the file's image type (which + * will always be IH_TYPE_FLATDT in this case). + */ + if (params.type == IH_TYPE_FLATDT) { + params.fit_image_type = type; + if (!params.auto_its) + params.datafile = datafile; + } else if (type != IH_TYPE_INVALID) { + params.type = type; + } + + if (!params.imagefile) + usage("Missing output filename"); +} + + int main(int argc, char **argv) { int ifd = -1; @@ -78,144 +295,10 @@ int main(int argc, char **argv) int dfd; params.cmdname = *argv; - params.addr = params.ep = 0; - - while (--argc > 0 && **++argv == '-') { - while (*++*argv) { - switch (**argv) { - case 'l': - params.lflag = 1; - break; - case 'A': - if ((--argc <= 0) || - (params.arch = - genimg_get_arch_id (*++argv)) < 0) - usage (); - goto NXTARG; - case 'c': - if (--argc <= 0) - usage(); - params.comment = *++argv; - goto NXTARG; - case 'C': - if ((--argc <= 0) || - (params.comp = - genimg_get_comp_id (*++argv)) < 0) - usage (); - goto NXTARG; - case 'D': - if (--argc <= 0) - usage (); - params.dtc = *++argv; - goto NXTARG; - - case 'O': - if ((--argc <= 0) || - (params.os = - genimg_get_os_id (*++argv)) < 0) - usage (); - goto NXTARG; - case 'T': - params.type = -1; - if (--argc >= 0 && argv[1]) { - params.type = - genimg_get_type_id(*++argv); - } - if (params.type < 0) { - show_image_types(); - usage(); - } - goto NXTARG; - case 'a': - if (--argc <= 0) - usage (); - params.addr = strtoull(*++argv, &ptr, 16); - if (*ptr) { - fprintf (stderr, - "%s: invalid load address %s\n", - params.cmdname, *argv); - exit (EXIT_FAILURE); - } - goto NXTARG; - case 'd': - if (--argc <= 0) - usage (); - params.datafile = *++argv; - params.dflag = 1; - goto NXTARG; - case 'e': - if (--argc <= 0) - usage (); - params.ep = strtoull(*++argv, &ptr, 16); - if (*ptr) { - fprintf (stderr, - "%s: invalid entry point %s\n", - params.cmdname, *argv); - exit (EXIT_FAILURE); - } - params.eflag = 1; - goto NXTARG; - case 'f': - if (--argc <= 0) - usage (); - params.datafile = *++argv; - /* no break */ - case 'F': - /* - * The flattened image tree (FIT) format - * requires a flattened device tree image type - */ - params.type = IH_TYPE_FLATDT; - params.fflag = 1; - goto NXTARG; - case 'k': - if (--argc <= 0) - usage(); - params.keydir = *++argv; - goto NXTARG; - case 'K': - if (--argc <= 0) - usage(); - params.keydest = *++argv; - goto NXTARG; - case 'n': - if (--argc <= 0) - usage (); - params.imagename = *++argv; - goto NXTARG; - case 'r': - params.require_keys = 1; - break; - case 'R': - if (--argc <= 0) - usage(); - /* - * This entry is for the second configuration - * file, if only one is not enough. - */ - params.imagename2 = *++argv; - goto NXTARG; - case 's': - params.skipcpy = 1; - break; - case 'v': - params.vflag++; - break; - case 'V': - printf("mkimage version %s\n", PLAIN_VERSION); - exit(EXIT_SUCCESS); - case 'x': - params.xflag++; - break; - default: - usage (); - } - } -NXTARG: ; - } + params.addr = 0; + params.ep = 0; - if (argc != 1) - usage (); + process_args(argc, argv); /* set tparams as per input type_id */ tparams = imagetool_get_type(params.type); @@ -231,7 +314,7 @@ NXTARG: ; */ if (tparams->check_params) if (tparams->check_params (¶ms)) - usage (); + usage("Bad parameters for image type"); if (!params.eflag) { params.ep = params.addr; @@ -240,8 +323,6 @@ NXTARG: ; params.ep += tparams->header_size; } - params.imagefile = *argv; - if (params.fflag){ if (tparams->fflag_handle) /* @@ -579,41 +660,3 @@ copy_file (int ifd, const char *datafile, int pad) (void) munmap((void *)ptr, sbuf.st_size); (void) close (dfd); } - -static void usage(void) -{ - fprintf (stderr, "Usage: %s -l image\n" - " -l ==> list image header information\n", - params.cmdname); - fprintf (stderr, " %s [-x] -A arch -O os -T type -C comp " - "-a addr -e ep -n name -d data_file[:data_file...] image\n" - " -A ==> set architecture to 'arch'\n" - " -O ==> set operating system to 'os'\n" - " -T ==> set image type to 'type'\n" - " -C ==> set compression type 'comp'\n" - " -a ==> set load address to 'addr' (hex)\n" - " -e ==> set entry point to 'ep' (hex)\n" - " -n ==> set image name to 'name'\n" - " -d ==> use image data from 'datafile'\n" - " -x ==> set XIP (execute in place)\n", - params.cmdname); - fprintf(stderr, " %s [-D dtc_options] [-f fit-image.its|-F] fit-image\n", - params.cmdname); - fprintf(stderr, " -D => set all options for device tree compiler\n" - " -f => input filename for FIT source\n"); -#ifdef CONFIG_FIT_SIGNATURE - fprintf(stderr, "Signing / verified boot options: [-k keydir] [-K dtb] [ -c <comment>] [-r]\n" - " -k => set directory containing private keys\n" - " -K => write public keys to this .dtb file\n" - " -c => add comment in signature node\n" - " -F => re-sign existing FIT image\n" - " -r => mark keys used as 'required' in dtb\n"); -#else - fprintf(stderr, "Signing / verified boot not supported (CONFIG_FIT_SIGNATURE undefined)\n"); -#endif - fprintf (stderr, " %s -V ==> print version information and exit\n", - params.cmdname); - fprintf(stderr, "Use -T to see a list of available image types\n"); - - exit (EXIT_FAILURE); -} |