When adding hashes or signatures, the target FDT may be full. Detect this
and automatically try again after making 1KB of space.

Signed-off-by: Simon Glass <s...@chromium.org>
---

Changes in v3:
- Rebase to master

Changes in v2: None

 tools/fit_check_sign.c |   4 +-
 tools/fit_common.c     |  25 ++++++++++-
 tools/fit_common.h     |   5 ++-
 tools/fit_image.c      | 112 ++++++++++++++++++++++++++++++-------------------
 tools/fit_info.c       |   2 +-
 tools/image-host.c     |  26 ++++++++----
 6 files changed, 114 insertions(+), 60 deletions(-)

diff --git a/tools/fit_check_sign.c b/tools/fit_check_sign.c
index e6df610..c2aefae 100644
--- a/tools/fit_check_sign.c
+++ b/tools/fit_check_sign.c
@@ -61,10 +61,10 @@ int main(int argc, char **argv)
                        break;
        }
 
-       ffd = mmap_fdt(cmdname, fdtfile, &fit_blob, &fsbuf, false);
+       ffd = mmap_fdt(cmdname, fdtfile, 0, &fit_blob, &fsbuf, false);
        if (ffd < 0)
                return EXIT_FAILURE;
-       kfd = mmap_fdt(cmdname, keyfile, &key_blob, &ksbuf, false);
+       kfd = mmap_fdt(cmdname, keyfile, 0, &key_blob, &ksbuf, false);
        if (ffd < 0)
                return EXIT_FAILURE;
 
diff --git a/tools/fit_common.c b/tools/fit_common.c
index 286f357..81ba698 100644
--- a/tools/fit_common.c
+++ b/tools/fit_common.c
@@ -38,8 +38,8 @@ int fit_check_image_types(uint8_t type)
                return EXIT_FAILURE;
 }
 
-int mmap_fdt(const char *cmdname, const char *fname, void **blobp,
-            struct stat *sbuf, bool delete_on_error)
+int mmap_fdt(const char *cmdname, const char *fname, size_t size_inc,
+            void **blobp, struct stat *sbuf, bool delete_on_error)
 {
        void *ptr;
        int fd;
@@ -59,6 +59,15 @@ int mmap_fdt(const char *cmdname, const char *fname, void 
**blobp,
                goto err;
        }
 
+       if (size_inc) {
+               sbuf->st_size += size_inc;
+               if (ftruncate(fd, sbuf->st_size)) {
+                       fprintf(stderr, "%s: Can't expand %s: %s\n",
+                               cmdname, fname, strerror(errno));
+               goto err;
+               }
+       }
+
        errno = 0;
        ptr = mmap(0, sbuf->st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
        if ((ptr == MAP_FAILED) || (errno != 0)) {
@@ -73,6 +82,18 @@ int mmap_fdt(const char *cmdname, const char *fname, void 
**blobp,
                goto err;
        }
 
+       /* expand if needed */
+       if (size_inc) {
+               int ret;
+
+               ret = fdt_open_into(ptr, ptr, sbuf->st_size);
+               if (ret) {
+                       fprintf(stderr, "%s: Cannot expand FDT: %s\n",
+                               cmdname, fdt_strerror(ret));
+                       goto err;
+               }
+       }
+
        *blobp = ptr;
        return fd;
 
diff --git a/tools/fit_common.h b/tools/fit_common.h
index adcee6d..b8d8438 100644
--- a/tools/fit_common.h
+++ b/tools/fit_common.h
@@ -21,12 +21,13 @@ int fit_check_image_types(uint8_t type);
  *
  * @cmdname:   Tool name (for displaying with error messages)
  * @fname:     Filename containing FDT
+ * @size_inc:  Amount to increase size by (0 = leave it alone)
  * @blobp:     Returns pointer to FDT blob
  * @sbuf:      File status information is stored here
  * @delete_on_error:   true to delete the file if we get an error
  * @return 0 if OK, -1 on error.
  */
-int mmap_fdt(const char *cmdname, const char *fname, void **blobp,
-            struct stat *sbuf, bool delete_on_error);
+int mmap_fdt(const char *cmdname, const char *fname, size_t size_inc,
+            void **blobp, struct stat *sbuf, bool delete_on_error);
 
 #endif /* _FIT_COMMON_H_ */
diff --git a/tools/fit_image.c b/tools/fit_image.c
index eeee484..3ececf9 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -22,6 +22,54 @@
 
 static image_header_t header;
 
+static int fit_add_file_data(struct image_tool_params *params, size_t size_inc,
+                            const char *tmpfile)
+{
+       int tfd, destfd = 0;
+       void *dest_blob = NULL;
+       off_t destfd_size = 0;
+       struct stat sbuf;
+       void *ptr;
+       int ret = 0;
+
+       tfd = mmap_fdt(params->cmdname, tmpfile, size_inc, &ptr, &sbuf, true);
+       if (tfd < 0)
+               return -EIO;
+
+       if (params->keydest) {
+               struct stat dest_sbuf;
+
+               destfd = mmap_fdt(params->cmdname, params->keydest, size_inc,
+                                 &dest_blob, &dest_sbuf, false);
+               if (destfd < 0) {
+                       ret = -EIO;
+                       goto err_keydest;
+               }
+               destfd_size = dest_sbuf.st_size;
+       }
+
+       /* 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 (!ret) {
+               ret = fit_add_verification_data(params->keydir, dest_blob, ptr,
+                                               params->comment,
+                                               params->require_keys);
+       }
+
+       if (dest_blob) {
+               munmap(dest_blob, destfd_size);
+               close(destfd);
+       }
+
+err_keydest:
+       munmap(ptr, sbuf.st_size);
+       close(tfd);
+
+       return ret;
+}
+
 /**
  * fit_handle_file - main FIT file processing function
  *
@@ -38,11 +86,8 @@ static int fit_handle_file(struct image_tool_params *params)
 {
        char tmpfile[MKIMAGE_MAX_TMPFILE_LEN];
        char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN];
-       int tfd, destfd = 0;
-       void *dest_blob = NULL;
-       struct stat sbuf;
-       void *ptr;
-       off_t destfd_size = 0;
+       size_t size_inc;
+       int ret;
 
        /* Flattened Image Tree (FIT) format  handling */
        debug ("FIT format handling\n");
@@ -73,40 +118,26 @@ static int fit_handle_file(struct image_tool_params 
*params)
                goto err_system;
        }
 
-       if (params->keydest) {
-               destfd = mmap_fdt(params->cmdname, params->keydest,
-                                 &dest_blob, &sbuf, 1);
-               if (destfd < 0)
-                       goto err_keydest;
-               destfd_size = sbuf.st_size;
+       /*
+        * Set hashes for images in the blob. Unfortunately we may need more
+        * space in either FDT, so keep trying until we succeed.
+        *
+        * Note: this is pretty inefficient for signing, since we must
+        * calculate the signature every time. It would be better to calculate
+        * all the data and then store it in a separate step. However, this
+        * would be considerably more complex to implement. Generally a few
+        * steps of this loop is enough to sign with several keys.
+        */
+       for (size_inc = 0; size_inc < 64 * 1024; size_inc += 1024) {
+               ret = fit_add_file_data(params, size_inc, tmpfile);
+               if (!ret || ret != -ENOSPC)
+                       break;
        }
 
-       tfd = mmap_fdt(params->cmdname, tmpfile, &ptr, &sbuf, 1);
-       if (tfd < 0)
-               goto err_mmap;
-
-       /* set hashes for images in the blob */
-       if (fit_add_verification_data(params->keydir,
-                                     dest_blob, ptr, params->comment,
-                                     params->require_keys)) {
+       if (ret) {
                fprintf(stderr, "%s Can't add hashes to FIT blob\n",
                        params->cmdname);
-               goto err_add_hashes;
-       }
-
-       /* for first image creation, add a timestamp at offset 0 i.e., root  */
-       if (params->datafile && fit_set_timestamp(ptr, 0, sbuf.st_mtime)) {
-               fprintf (stderr, "%s: Can't add image timestamp\n",
-                               params->cmdname);
-               goto err_add_timestamp;
-       }
-       debug ("Added timestamp successfully\n");
-
-       munmap ((void *)ptr, sbuf.st_size);
-       close (tfd);
-       if (dest_blob) {
-               munmap(dest_blob, destfd_size);
-               close(destfd);
+               goto err_system;
        }
 
        if (rename (tmpfile, params->imagefile) == -1) {
@@ -115,17 +146,10 @@ static int fit_handle_file(struct image_tool_params 
*params)
                                strerror (errno));
                unlink (tmpfile);
                unlink (params->imagefile);
-               return (EXIT_FAILURE);
+               return EXIT_FAILURE;
        }
-       return (EXIT_SUCCESS);
+       return EXIT_SUCCESS;
 
-err_add_timestamp:
-err_add_hashes:
-       munmap(ptr, sbuf.st_size);
-err_mmap:
-       if (dest_blob)
-               munmap(dest_blob, destfd_size);
-err_keydest:
 err_system:
        unlink(tmpfile);
        return -1;
diff --git a/tools/fit_info.c b/tools/fit_info.c
index 9442ff1..afbed7b 100644
--- a/tools/fit_info.c
+++ b/tools/fit_info.c
@@ -68,7 +68,7 @@ int main(int argc, char **argv)
                        break;
                }
 
-       ffd = mmap_fdt(cmdname, fdtfile, &fit_blob, &fsbuf, false);
+       ffd = mmap_fdt(cmdname, fdtfile, 0, &fit_blob, &fsbuf, false);
 
        if (ffd < 0) {
                printf("Could not open %s\n", fdtfile);
diff --git a/tools/image-host.c b/tools/image-host.c
index 651f1c2..2be5e80 100644
--- a/tools/image-host.c
+++ b/tools/image-host.c
@@ -224,7 +224,9 @@ static int fit_image_process_sig(const char *keydir, void 
*keydest,
        ret = fit_image_write_sig(fit, noffset, value, value_len, comment,
                        NULL, 0);
        if (ret) {
-               printf("Can't write signature for '%s' signature node in '%s' 
image node: %s\n",
+               if (ret == -FDT_ERR_NOSPACE)
+                       return -ENOSPC;
+               printf("Can't write signature for '%s' signature node in '%s' 
conf node: %s\n",
                       node_name, image_name, fdt_strerror(ret));
                return -1;
        }
@@ -589,10 +591,13 @@ static int fit_config_process_sig(const char *keydir, 
void *keydest,
                return -1;
        }
 
-       if (fit_image_write_sig(fit, noffset, value, value_len, comment,
-                               region_prop, region_proplen)) {
-               printf("Can't write signature for '%s' signature node in '%s' 
conf node\n",
-                      node_name, conf_name);
+       ret = fit_image_write_sig(fit, noffset, value, value_len, comment,
+                               region_prop, region_proplen);
+       if (ret) {
+               if (ret == -FDT_ERR_NOSPACE)
+                       return -ENOSPC;
+               printf("Can't write signature for '%s' signature node in '%s' 
conf node: %s\n",
+                      node_name, conf_name, fdt_strerror(ret));
                return -1;
        }
        free(value);
@@ -602,10 +607,13 @@ static int fit_config_process_sig(const char *keydir, 
void *keydest,
        info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
 
        /* Write the public key into the supplied FDT file */
-       if (keydest && info.algo->add_verify_data(&info, keydest)) {
-               printf("Failed to add verification data for '%s' signature node 
in '%s' image node\n",
-                      node_name, conf_name);
-               return -1;
+       if (keydest) {
+               ret = info.algo->add_verify_data(&info, keydest);
+               if (ret) {
+                       printf("Failed to add verification data for '%s' 
signature node in '%s' image node\n",
+                              node_name, conf_name);
+                       return ret == FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
+               }
        }
 
        return 0;
-- 
1.9.1.423.g4596e3a

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to