1 /* 2 * (C) Copyright 2008 Semihalf 3 * 4 * (C) Copyright 2000-2004 5 * DENX Software Engineering 6 * Wolfgang Denk, wd@denx.de 7 * 8 * Updated-by: Prafulla Wadaskar <prafulla@marvell.com> 9 * FIT image specific code abstracted from mkimage.c 10 * some functions added to address abstraction 11 * 12 * All rights reserved. 13 * 14 * SPDX-License-Identifier: GPL-2.0+ 15 */ 16 17 #include "imagetool.h" 18 #include "fit_common.h" 19 #include "mkimage.h" 20 #include <image.h> 21 #include <u-boot/crc.h> 22 23 static image_header_t header; 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 73 /** 74 * fit_handle_file - main FIT file processing function 75 * 76 * fit_handle_file() runs dtc to convert .its to .itb, includes 77 * binary data, updates timestamp property and calculates hashes. 78 * 79 * datafile - .its file 80 * imagefile - .itb file 81 * 82 * returns: 83 * only on success, otherwise calls exit (EXIT_FAILURE); 84 */ 85 static int fit_handle_file(struct image_tool_params *params) 86 { 87 char tmpfile[MKIMAGE_MAX_TMPFILE_LEN]; 88 char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN]; 89 size_t size_inc; 90 int ret; 91 92 /* Flattened Image Tree (FIT) format handling */ 93 debug ("FIT format handling\n"); 94 95 /* call dtc to include binary properties into the tmp file */ 96 if (strlen (params->imagefile) + 97 strlen (MKIMAGE_TMPFILE_SUFFIX) + 1 > sizeof (tmpfile)) { 98 fprintf (stderr, "%s: Image file name (%s) too long, " 99 "can't create tmpfile", 100 params->imagefile, params->cmdname); 101 return (EXIT_FAILURE); 102 } 103 sprintf (tmpfile, "%s%s", params->imagefile, MKIMAGE_TMPFILE_SUFFIX); 104 105 /* We either compile the source file, or use the existing FIT image */ 106 if (params->datafile) { 107 /* dtc -I dts -O dtb -p 500 datafile > tmpfile */ 108 snprintf(cmd, sizeof(cmd), "%s %s %s > %s", 109 MKIMAGE_DTC, params->dtc, params->datafile, tmpfile); 110 debug("Trying to execute \"%s\"\n", cmd); 111 } else { 112 snprintf(cmd, sizeof(cmd), "cp %s %s", 113 params->imagefile, tmpfile); 114 } 115 if (system (cmd) == -1) { 116 fprintf (stderr, "%s: system(%s) failed: %s\n", 117 params->cmdname, cmd, strerror(errno)); 118 goto err_system; 119 } 120 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; 135 } 136 137 if (ret) { 138 fprintf(stderr, "%s Can't add hashes to FIT blob\n", 139 params->cmdname); 140 goto err_system; 141 } 142 143 if (rename (tmpfile, params->imagefile) == -1) { 144 fprintf (stderr, "%s: Can't rename %s to %s: %s\n", 145 params->cmdname, tmpfile, params->imagefile, 146 strerror (errno)); 147 unlink (tmpfile); 148 unlink (params->imagefile); 149 return EXIT_FAILURE; 150 } 151 return EXIT_SUCCESS; 152 153 err_system: 154 unlink(tmpfile); 155 return -1; 156 } 157 158 static int fit_check_params(struct image_tool_params *params) 159 { 160 return ((params->dflag && (params->fflag || params->lflag)) || 161 (params->fflag && (params->dflag || params->lflag)) || 162 (params->lflag && (params->dflag || params->fflag))); 163 } 164 165 static struct image_type_params fitimage_params = { 166 .name = "FIT Image support", 167 .header_size = sizeof(image_header_t), 168 .hdr = (void*)&header, 169 .verify_header = fit_verify_header, 170 .print_header = fit_print_contents, 171 .check_image_type = fit_check_image_types, 172 .fflag_handle = fit_handle_file, 173 .set_header = NULL, /* FIT images use DTB header */ 174 .check_params = fit_check_params, 175 }; 176 177 void init_fit_image_type (void) 178 { 179 register_image_type(&fitimage_params); 180 } 181