Commit a9468115699de562f08796bf2eabd832435bedec

Authored by Simon Glass
Committed by Tom Rini
1 parent ef0af64b1c

mkimage: Automatically make space in FDT when full

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@chromium.org>

Showing 6 changed files with 114 additions and 60 deletions Side-by-side Diff

tools/fit_check_sign.c
... ... @@ -62,10 +62,10 @@
62 62 break;
63 63 }
64 64  
65   - ffd = mmap_fdt(cmdname, fdtfile, &fit_blob, &fsbuf, false);
  65 + ffd = mmap_fdt(cmdname, fdtfile, 0, &fit_blob, &fsbuf, false);
66 66 if (ffd < 0)
67 67 return EXIT_FAILURE;
68   - kfd = mmap_fdt(cmdname, keyfile, &key_blob, &ksbuf, false);
  68 + kfd = mmap_fdt(cmdname, keyfile, 0, &key_blob, &ksbuf, false);
69 69 if (ffd < 0)
70 70 return EXIT_FAILURE;
71 71  
... ... @@ -38,8 +38,8 @@
38 38 return EXIT_FAILURE;
39 39 }
40 40  
41   -int mmap_fdt(const char *cmdname, const char *fname, void **blobp,
42   - struct stat *sbuf, bool delete_on_error)
  41 +int mmap_fdt(const char *cmdname, const char *fname, size_t size_inc,
  42 + void **blobp, struct stat *sbuf, bool delete_on_error)
43 43 {
44 44 void *ptr;
45 45 int fd;
... ... @@ -59,6 +59,15 @@
59 59 goto err;
60 60 }
61 61  
  62 + if (size_inc) {
  63 + sbuf->st_size += size_inc;
  64 + if (ftruncate(fd, sbuf->st_size)) {
  65 + fprintf(stderr, "%s: Can't expand %s: %s\n",
  66 + cmdname, fname, strerror(errno));
  67 + goto err;
  68 + }
  69 + }
  70 +
62 71 errno = 0;
63 72 ptr = mmap(0, sbuf->st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
64 73 if ((ptr == MAP_FAILED) || (errno != 0)) {
... ... @@ -71,6 +80,18 @@
71 80 if (fdt_check_header(ptr)) {
72 81 fprintf(stderr, "%s: Invalid FIT blob\n", cmdname);
73 82 goto err;
  83 + }
  84 +
  85 + /* expand if needed */
  86 + if (size_inc) {
  87 + int ret;
  88 +
  89 + ret = fdt_open_into(ptr, ptr, sbuf->st_size);
  90 + if (ret) {
  91 + fprintf(stderr, "%s: Cannot expand FDT: %s\n",
  92 + cmdname, fdt_strerror(ret));
  93 + goto err;
  94 + }
74 95 }
75 96  
76 97 *blobp = ptr;
... ... @@ -21,13 +21,14 @@
21 21 *
22 22 * @cmdname: Tool name (for displaying with error messages)
23 23 * @fname: Filename containing FDT
  24 + * @size_inc: Amount to increase size by (0 = leave it alone)
24 25 * @blobp: Returns pointer to FDT blob
25 26 * @sbuf: File status information is stored here
26 27 * @delete_on_error: true to delete the file if we get an error
27 28 * @return 0 if OK, -1 on error.
28 29 */
29   -int mmap_fdt(const char *cmdname, const char *fname, void **blobp,
30   - struct stat *sbuf, bool delete_on_error);
  30 +int mmap_fdt(const char *cmdname, const char *fname, size_t size_inc,
  31 + void **blobp, struct stat *sbuf, bool delete_on_error);
31 32  
32 33 #endif /* _FIT_COMMON_H_ */
... ... @@ -22,6 +22,54 @@
22 22  
23 23 static image_header_t header;
24 24  
  25 +static int fit_add_file_data(struct image_tool_params *params, size_t size_inc,
  26 + const char *tmpfile)
  27 +{
  28 + int tfd, destfd = 0;
  29 + void *dest_blob = NULL;
  30 + off_t destfd_size = 0;
  31 + struct stat sbuf;
  32 + void *ptr;
  33 + int ret = 0;
  34 +
  35 + tfd = mmap_fdt(params->cmdname, tmpfile, size_inc, &ptr, &sbuf, true);
  36 + if (tfd < 0)
  37 + return -EIO;
  38 +
  39 + if (params->keydest) {
  40 + struct stat dest_sbuf;
  41 +
  42 + destfd = mmap_fdt(params->cmdname, params->keydest, size_inc,
  43 + &dest_blob, &dest_sbuf, false);
  44 + if (destfd < 0) {
  45 + ret = -EIO;
  46 + goto err_keydest;
  47 + }
  48 + destfd_size = dest_sbuf.st_size;
  49 + }
  50 +
  51 + /* for first image creation, add a timestamp at offset 0 i.e., root */
  52 + if (params->datafile)
  53 + ret = fit_set_timestamp(ptr, 0, sbuf.st_mtime);
  54 +
  55 + if (!ret) {
  56 + ret = fit_add_verification_data(params->keydir, dest_blob, ptr,
  57 + params->comment,
  58 + params->require_keys);
  59 + }
  60 +
  61 + if (dest_blob) {
  62 + munmap(dest_blob, destfd_size);
  63 + close(destfd);
  64 + }
  65 +
  66 +err_keydest:
  67 + munmap(ptr, sbuf.st_size);
  68 + close(tfd);
  69 +
  70 + return ret;
  71 +}
  72 +
25 73 /**
26 74 * fit_handle_file - main FIT file processing function
27 75 *
... ... @@ -38,11 +86,8 @@
38 86 {
39 87 char tmpfile[MKIMAGE_MAX_TMPFILE_LEN];
40 88 char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN];
41   - int tfd, destfd = 0;
42   - void *dest_blob = NULL;
43   - struct stat sbuf;
44   - void *ptr;
45   - off_t destfd_size = 0;
  89 + size_t size_inc;
  90 + int ret;
46 91  
47 92 /* Flattened Image Tree (FIT) format handling */
48 93 debug ("FIT format handling\n");
49 94  
50 95  
51 96  
52 97  
53 98  
54 99  
... ... @@ -73,59 +118,38 @@
73 118 goto err_system;
74 119 }
75 120  
76   - if (params->keydest) {
77   - destfd = mmap_fdt(params->cmdname, params->keydest,
78   - &dest_blob, &sbuf, 1);
79   - if (destfd < 0)
80   - goto err_keydest;
81   - destfd_size = sbuf.st_size;
  121 + /*
  122 + * Set hashes for images in the blob. Unfortunately we may need more
  123 + * space in either FDT, so keep trying until we succeed.
  124 + *
  125 + * Note: this is pretty inefficient for signing, since we must
  126 + * calculate the signature every time. It would be better to calculate
  127 + * all the data and then store it in a separate step. However, this
  128 + * would be considerably more complex to implement. Generally a few
  129 + * steps of this loop is enough to sign with several keys.
  130 + */
  131 + for (size_inc = 0; size_inc < 64 * 1024; size_inc += 1024) {
  132 + ret = fit_add_file_data(params, size_inc, tmpfile);
  133 + if (!ret || ret != -ENOSPC)
  134 + break;
82 135 }
83 136  
84   - tfd = mmap_fdt(params->cmdname, tmpfile, &ptr, &sbuf, 1);
85   - if (tfd < 0)
86   - goto err_mmap;
87   -
88   - /* set hashes for images in the blob */
89   - if (fit_add_verification_data(params->keydir,
90   - dest_blob, ptr, params->comment,
91   - params->require_keys)) {
  137 + if (ret) {
92 138 fprintf(stderr, "%s Can't add hashes to FIT blob\n",
93 139 params->cmdname);
94   - goto err_add_hashes;
  140 + goto err_system;
95 141 }
96 142  
97   - /* for first image creation, add a timestamp at offset 0 i.e., root */
98   - if (params->datafile && fit_set_timestamp(ptr, 0, sbuf.st_mtime)) {
99   - fprintf (stderr, "%s: Can't add image timestamp\n",
100   - params->cmdname);
101   - goto err_add_timestamp;
102   - }
103   - debug ("Added timestamp successfully\n");
104   -
105   - munmap ((void *)ptr, sbuf.st_size);
106   - close (tfd);
107   - if (dest_blob) {
108   - munmap(dest_blob, destfd_size);
109   - close(destfd);
110   - }
111   -
112 143 if (rename (tmpfile, params->imagefile) == -1) {
113 144 fprintf (stderr, "%s: Can't rename %s to %s: %s\n",
114 145 params->cmdname, tmpfile, params->imagefile,
115 146 strerror (errno));
116 147 unlink (tmpfile);
117 148 unlink (params->imagefile);
118   - return (EXIT_FAILURE);
  149 + return EXIT_FAILURE;
119 150 }
120   - return (EXIT_SUCCESS);
  151 + return EXIT_SUCCESS;
121 152  
122   -err_add_timestamp:
123   -err_add_hashes:
124   - munmap(ptr, sbuf.st_size);
125   -err_mmap:
126   - if (dest_blob)
127   - munmap(dest_blob, destfd_size);
128   -err_keydest:
129 153 err_system:
130 154 unlink(tmpfile);
131 155 return -1;
... ... @@ -68,7 +68,7 @@
68 68 break;
69 69 }
70 70  
71   - ffd = mmap_fdt(cmdname, fdtfile, &fit_blob, &fsbuf, false);
  71 + ffd = mmap_fdt(cmdname, fdtfile, 0, &fit_blob, &fsbuf, false);
72 72  
73 73 if (ffd < 0) {
74 74 printf("Could not open %s\n", fdtfile);
... ... @@ -224,7 +224,9 @@
224 224 ret = fit_image_write_sig(fit, noffset, value, value_len, comment,
225 225 NULL, 0);
226 226 if (ret) {
227   - printf("Can't write signature for '%s' signature node in '%s' image node: %s\n",
  227 + if (ret == -FDT_ERR_NOSPACE)
  228 + return -ENOSPC;
  229 + printf("Can't write signature for '%s' signature node in '%s' conf node: %s\n",
228 230 node_name, image_name, fdt_strerror(ret));
229 231 return -1;
230 232 }
... ... @@ -589,10 +591,13 @@
589 591 return -1;
590 592 }
591 593  
592   - if (fit_image_write_sig(fit, noffset, value, value_len, comment,
593   - region_prop, region_proplen)) {
594   - printf("Can't write signature for '%s' signature node in '%s' conf node\n",
595   - node_name, conf_name);
  594 + ret = fit_image_write_sig(fit, noffset, value, value_len, comment,
  595 + region_prop, region_proplen);
  596 + if (ret) {
  597 + if (ret == -FDT_ERR_NOSPACE)
  598 + return -ENOSPC;
  599 + printf("Can't write signature for '%s' signature node in '%s' conf node: %s\n",
  600 + node_name, conf_name, fdt_strerror(ret));
596 601 return -1;
597 602 }
598 603 free(value);
... ... @@ -602,10 +607,13 @@
602 607 info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
603 608  
604 609 /* Write the public key into the supplied FDT file */
605   - if (keydest && info.algo->add_verify_data(&info, keydest)) {
606   - printf("Failed to add verification data for '%s' signature node in '%s' image node\n",
607   - node_name, conf_name);
608   - return -1;
  610 + if (keydest) {
  611 + ret = info.algo->add_verify_data(&info, keydest);
  612 + if (ret) {
  613 + printf("Failed to add verification data for '%s' signature node in '%s' image node\n",
  614 + node_name, conf_name);
  615 + return ret == FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
  616 + }
609 617 }
610 618  
611 619 return 0;