X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=tools%2Ffit_image.c;h=e55a8943e764f6e32e740455d5ab1ae2fea6b122;hb=844e5b20f2691eccce9ac8f7e3732bbb5d0ac757;hp=765ff31e672abe7939e32c27aed856bcce5f404c;hpb=fb4cce0f98ea0784130ff544d7c85d0841bea2e6;p=u-boot diff --git a/tools/fit_image.c b/tools/fit_image.c index 765ff31e67..e55a8943e7 100644 --- a/tools/fit_image.c +++ b/tools/fit_image.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * (C) Copyright 2008 Semihalf * @@ -10,8 +11,6 @@ * some functions added to address abstraction * * All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0+ */ #include "imagetool.h" @@ -51,13 +50,16 @@ static int fit_add_file_data(struct image_tool_params *params, size_t size_inc, } /* for first image creation, add a timestamp at offset 0 i.e., root */ - if (params->datafile) - ret = fit_set_timestamp(ptr, 0, sbuf.st_mtime); + if (params->datafile) { + time_t time = imagetool_get_source_date(params, sbuf.st_mtime); + ret = fit_set_timestamp(ptr, 0, time); + } if (!ret) { ret = fit_add_verification_data(params->keydir, dest_blob, ptr, params->comment, - params->require_keys); + params->require_keys, + params->engine_id); } if (dest_blob) { @@ -83,8 +85,15 @@ static int fit_calc_size(struct image_tool_params *params) size = imagetool_get_filesize(params, params->datafile); if (size < 0) return -1; - total_size = size; + + if (params->fit_ramdisk) { + size = imagetool_get_filesize(params, params->fit_ramdisk); + 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) @@ -123,13 +132,14 @@ static int fdt_property_file(struct image_tool_params *params, ret = fdt_property_placeholder(fdt, "data", sbuf.st_size, &ptr); if (ret) - return ret; + goto err; 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; } + close(fd); return 0; err: @@ -174,7 +184,7 @@ static void get_basename(char *str, int size, const char *fname) * 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. + * tree files, we include an fdt- node for each of those too. */ static int fit_write_images(struct image_tool_params *params, char *fdt) { @@ -188,11 +198,12 @@ static int fit_write_images(struct image_tool_params *params, char *fdt) /* First the main image */ typename = genimg_get_type_short_name(params->fit_image_type); - snprintf(str, sizeof(str), "%s@1", typename); + 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, "arch", + genimg_get_arch_short_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)); @@ -213,7 +224,7 @@ static int fit_write_images(struct image_tool_params *params, char *fdt) 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); + snprintf(str, sizeof(str), "%s-%d", FIT_FDT_PROP, ++upto); fdt_begin_node(fdt, str); get_basename(str, sizeof(str), cont->fname); @@ -229,6 +240,20 @@ static int fit_write_images(struct image_tool_params *params, char *fdt) fdt_end_node(fdt); } + /* And a ramdisk file if available */ + if (params->fit_ramdisk) { + fdt_begin_node(fdt, FIT_RAMDISK_PROP "-1"); + + fdt_property_string(fdt, "type", FIT_RAMDISK_PROP); + fdt_property_string(fdt, "os", genimg_get_os_short_name(params->os)); + + ret = fdt_property_file(params, fdt, "data", params->fit_ramdisk); + if (ret) + return ret; + + fdt_end_node(fdt); + } + fdt_end_node(fdt); return 0; @@ -251,32 +276,42 @@ static void fit_write_configs(struct image_tool_params *params, char *fdt) int upto; fdt_begin_node(fdt, "configurations"); - fdt_property_string(fdt, "default", "conf@1"); + 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); + 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); + snprintf(str, sizeof(str), "%s-1", typename); fdt_property_string(fdt, typename, str); - snprintf(str, sizeof(str), FIT_FDT_PROP "@%d", upto); + if (params->fit_ramdisk) + fdt_property_string(fdt, FIT_RAMDISK_PROP, + FIT_RAMDISK_PROP "-1"); + + 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"); + fdt_begin_node(fdt, "conf-1"); typename = genimg_get_type_short_name(params->fit_image_type); - snprintf(str, sizeof(str), "%s@1", typename); + snprintf(str, sizeof(str), "%s-1", typename); fdt_property_string(fdt, typename, str); + + if (params->fit_ramdisk) + fdt_property_string(fdt, FIT_RAMDISK_PROP, + FIT_RAMDISK_PROP "-1"); + fdt_end_node(fdt); } @@ -329,30 +364,250 @@ static int fit_build(struct image_tool_params *params, const char *fname) if (ret < 0) { fprintf(stderr, "%s: Failed to build FIT image\n", params->cmdname); - goto err; + goto err_buf; } 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; + goto err_buf; } 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); + free(buf); return 0; err: + close(fd); +err_buf: 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_munmap; + } + 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_munmap; + } + + 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_munmap; + } + if (params->external_offset > 0) { + /* An external offset positions the data absolutely. */ + fdt_setprop_u32(fdt, node, "data-position", + params->external_offset + buf_ptr); + } else { + 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; + } + + /* Check if an offset for the external data was set. */ + if (params->external_offset > 0) { + if (params->external_offset < new_size) { + debug("External offset %x overlaps FIT length %x", + params->external_offset, new_size); + ret = -EINVAL; + goto err; + } + new_size = params->external_offset; + } + 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; + } + free(buf); + close(fd); + return 0; + +err_munmap: + munmap(fdt, sbuf.st_size); +err: + if (buf) + free(buf); + 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_has_fd; + } + 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_has_fd; + } + + 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_has_fd; + } + + 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_has_fd; + } + } + + /* Close the old fd so we can re-use it. */ + 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)); + ret = -EIO; + goto err_no_fd; + } + 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_has_fd; + } + + ret = 0; + +err_has_fd: + close(fd); +err_no_fd: + munmap(old_fdt, sbuf.st_size); + free(fdt); + return ret; +} + /** * fit_handle_file - main FIT file processing function * @@ -394,12 +649,12 @@ static int fit_handle_file(struct image_tool_params *params) } *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); + /* dtc -I dts -O dtb -p 500 -o tmpfile datafile */ + snprintf(cmd, sizeof(cmd), "%s %s -o \"%s\" \"%s\"", + MKIMAGE_DTC, params->dtc, tmpfile, params->datafile); debug("Trying to execute \"%s\"\n", cmd); } else { - snprintf(cmd, sizeof(cmd), "cp %s %s", + snprintf(cmd, sizeof(cmd), "cp \"%s\" \"%s\"", params->imagefile, tmpfile); } if (*cmd && system(cmd) == -1) { @@ -408,6 +663,11 @@ static int fit_handle_file(struct image_tool_params *params) 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. @@ -425,11 +685,18 @@ static int fit_handle_file(struct image_tool_params *params) } if (ret) { - fprintf(stderr, "%s Can't add hashes to FIT blob\n", - params->cmdname); + fprintf(stderr, "%s Can't add hashes to FIT blob: %d\n", + params->cmdname, ret); 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,