[U-Boot] [PATCH v3 10/14] mkimage: Automatically make space in FDT when full

Simon Glass sjg at chromium.org
Tue Jun 3 06:04:53 CEST 2014


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 <sjg at 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



More information about the U-Boot mailing list