summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/binman/ftest.py8
-rw-r--r--tools/fit_image.c80
2 files changed, 74 insertions, 14 deletions
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 1e570aba287..3d556535e07 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -4019,7 +4019,7 @@ class TestFunctional(unittest.TestCase):
self.assertEqual({
'image-pos': 0,
'offset': 0,
- 'size': 1890,
+ 'size': 1378,
'u-boot:image-pos': 0,
'u-boot:offset': 0,
@@ -4027,7 +4027,7 @@ class TestFunctional(unittest.TestCase):
'fit:image-pos': 4,
'fit:offset': 4,
- 'fit:size': 1840,
+ 'fit:size': 1328,
'fit/images/kernel:image-pos': 304,
'fit/images/kernel:offset': 300,
@@ -4045,8 +4045,8 @@ class TestFunctional(unittest.TestCase):
'fit/images/fdt-1/u-boot-spl-dtb:offset': 0,
'fit/images/fdt-1/u-boot-spl-dtb:size': 6,
- 'u-boot-nodtb:image-pos': 1844,
- 'u-boot-nodtb:offset': 1844,
+ 'u-boot-nodtb:image-pos': 1332,
+ 'u-boot-nodtb:offset': 1332,
'u-boot-nodtb:size': 46,
}, props)
diff --git a/tools/fit_image.c b/tools/fit_image.c
index 8fdde012bda..8717dc9a3b1 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -24,6 +24,65 @@
static struct legacy_img_hdr header;
+static int fit_estimate_hash_sig_size(struct image_tool_params *params, const char *fname)
+{
+ bool signing = IMAGE_ENABLE_SIGN && (params->keydir || params->keyfile);
+ struct stat sbuf;
+ void *fdt;
+ int fd;
+ int estimate = 0;
+ int depth, noffset;
+ const char *name;
+
+ fd = mmap_fdt(params->cmdname, fname, 0, &fdt, &sbuf, false, true);
+ if (fd < 0)
+ return -EIO;
+
+ /*
+ * Walk the FIT image, looking for nodes named hash* and
+ * signature*. Since the interesting nodes are subnodes of an
+ * image or configuration node, we are only interested in
+ * those at depth exactly 3.
+ *
+ * The estimate for a hash node is based on a sha512 digest
+ * being 64 bytes, with another 64 bytes added to account for
+ * fdt structure overhead (the tags and the name of the
+ * "value" property).
+ *
+ * The estimate for a signature node is based on an rsa4096
+ * signature being 512 bytes, with another 512 bytes to
+ * account for fdt overhead and the various other properties
+ * (hashed-nodes etc.) that will also be filled in.
+ *
+ * One could try to be more precise in the estimates by
+ * looking at the "algo" property and, in the case of
+ * configuration signatures, the sign-images property. Also,
+ * when signing an already created FIT image, the hash nodes
+ * already have properly sized value properties, so one could
+ * also take pre-existence of "value" properties in hash nodes
+ * into account. But this rather simple approach should work
+ * well enough in practice.
+ */
+ for (depth = 0, noffset = fdt_next_node(fdt, 0, &depth);
+ noffset >= 0 && depth > 0;
+ noffset = fdt_next_node(fdt, noffset, &depth)) {
+ if (depth != 3)
+ continue;
+
+ name = fdt_get_name(fdt, noffset, NULL);
+ if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME)))
+ estimate += 128;
+
+ if (signing && !strncmp(name, FIT_SIG_NODENAME, strlen(FIT_SIG_NODENAME)))
+ estimate += 1024;
+ }
+
+ munmap(fdt, sbuf.st_size);
+ close(fd);
+
+ return estimate;
+}
+
static int fit_add_file_data(struct image_tool_params *params, size_t size_inc,
const char *tmpfile)
{
@@ -844,16 +903,16 @@ static int fit_handle_file(struct image_tool_params *params)
rename(tmpfile, bakfile);
/*
- * 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.
+ * Set hashes for images in the blob and compute
+ * signatures. We do an attempt at estimating the expected
+ * extra size, but just in case that is not sufficient, keep
+ * trying adding 1K, with a reasonable upper bound of 64K
+ * total, until we succeed.
*/
- for (size_inc = 0; size_inc < 64 * 1024; size_inc += 1024) {
+ size_inc = fit_estimate_hash_sig_size(params, bakfile);
+ if (size_inc < 0)
+ goto err_system;
+ do {
if (copyfile(bakfile, tmpfile) < 0) {
printf("Can't copy %s to %s\n", bakfile, tmpfile);
ret = -EIO;
@@ -862,7 +921,8 @@ static int fit_handle_file(struct image_tool_params *params)
ret = fit_add_file_data(params, size_inc, tmpfile);
if (!ret || ret != -ENOSPC)
break;
- }
+ size_inc += 1024;
+ } while (size_inc < 64 * 1024);
if (ret) {
fprintf(stderr, "%s Can't add hashes to FIT blob: %d\n",