diff options
author | Simon Glass <sjg@chromium.org> | 2016-02-22 22:55:51 -0700 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2016-03-14 19:18:28 -0400 |
commit | 8e35bb07eb68e524804f2ef53dd18c7cec0b06fc (patch) | |
tree | 6e4b4062aad571ec3b94243d06723bfc09fe74b6 /tools/fit_image.c | |
parent | cef2e51489567260857984c3e95d98eb03c97fe9 (diff) |
mkimage: Support automatic creating of a FIT without a .its
At present, when generating a FIT, mkimage requires a .its file containing
the structure of the FIT and referring to the images to be included.
Creating the .its file is a separate step that makes it harder to use FIT.
This is not required for creating legacy images.
Often the FIT is pretty standard, consisting of an OS image, some device
tree files and a single configuration. We can handle this case automatically
and avoid needing a .its file at all.
To start with, support automatically generate the FIT using a new '-f auto'
option. Initially this only supports adding a single image (e.g. a linux
kernel) and a single configuration.
Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'tools/fit_image.c')
-rw-r--r-- | tools/fit_image.c | 216 |
1 files changed, 214 insertions, 2 deletions
diff --git a/tools/fit_image.c b/tools/fit_image.c index eb2a25eeac6..ed101f1d31d 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))); |