diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/fit_image.c | 216 | ||||
-rw-r--r-- | tools/imagetool.h | 1 | ||||
-rw-r--r-- | tools/mkimage.c | 8 |
3 files changed, 220 insertions, 5 deletions
diff --git a/tools/fit_image.c b/tools/fit_image.c index eb2a25eeac..ed101f1d31 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,207 @@ 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) +{ + int size, total_size; + + size = imagetool_get_filesize(params, params->datafile); + if (size < 0) + return -1; + + total_size = size; + + /* TODO(sjg@chromium.org): Add in the size of any other files */ + + /* 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); +} + +/** + * fit_write_images() - Write out a list of images to the FIT + * + * Include the main image (params->datafile). + */ +static int fit_write_images(struct image_tool_params *params, char *fdt) +{ + const char *typename; + char str[100]; + 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); + + fdt_end_node(fdt); + + return 0; +} + +/** + * fit_write_configs() - Write out a list of configurations to the FIT + * + * Create a configuration with the main image in it. + */ +static void fit_write_configs(struct image_tool_params *params, char *fdt) +{ + const char *typename; + char str[100]; + + fdt_begin_node(fdt, "configurations"); + fdt_property_string(fdt, "default", "conf@1"); + + 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_handle_file - main FIT file processing function * * fit_handle_file() runs dtc to convert .its to .itb, includes @@ -103,7 +306,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,7 +322,7 @@ 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; @@ -248,6 +458,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.h b/tools/imagetool.h index 3cf42ac96a..4f426e40a0 100644 --- a/tools/imagetool.h +++ b/tools/imagetool.h @@ -61,6 +61,7 @@ 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 */ }; diff --git a/tools/mkimage.c b/tools/mkimage.c index 4526da20b5..7add86c13d 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -85,7 +85,7 @@ static void usage(const char *msg) " -x ==> set XIP (execute in place)\n", params.cmdname); fprintf(stderr, - " %s [-D dtc_options] [-f fit-image.its|-F] fit-image\n", + " %s [-D dtc_options] [-f fit-image.its|-f auto|-F] fit-image\n", params.cmdname); fprintf(stderr, " -D => set all options for device tree compiler\n" @@ -159,7 +159,8 @@ static void process_args(int argc, char **argv) params.eflag = 1; break; case 'f': - params.datafile = optarg; + datafile = optarg; + params.auto_its = !strcmp(datafile, "auto"); /* no break */ case 'F': /* @@ -235,7 +236,8 @@ static void process_args(int argc, char **argv) */ if (params.type == IH_TYPE_FLATDT) { params.fit_image_type = type; - params.datafile = datafile; + if (!params.auto_its) + params.datafile = datafile; } else if (type != IH_TYPE_INVALID) { params.type = type; } |