1 /* 2 * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <asm/byteorder.h> 8 #include <errno.h> 9 #include <fcntl.h> 10 #include <stdint.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <sys/mman.h> 15 #include <sys/stat.h> 16 #include <sys/types.h> 17 #include <unistd.h> 18 19 /* Magic = 'S' 'T' 'M' 0x32 */ 20 #define HEADER_MAGIC __be32_to_cpu(0x53544D32) 21 #define VER_MAJOR 2 22 #define VER_MINOR 1 23 #define VER_VARIANT 0 24 #define HEADER_VERSION_V1 0x1 25 #define HEADER_VERSION_V2 0x2 26 #define PADDING_HEADER_MAGIC __be32_to_cpu(0x5354FFFF) 27 #define PADDING_HEADER_FLAG (1 << 31) 28 #define PADDING_HEADER_LENGTH 0x180 29 30 struct stm32_header_v1 { 31 uint32_t magic_number; 32 uint8_t image_signature[64]; 33 uint32_t image_checksum; 34 uint8_t header_version[4]; 35 uint32_t image_length; 36 uint32_t image_entry_point; 37 uint32_t reserved1; 38 uint32_t load_address; 39 uint32_t reserved2; 40 uint32_t version_number; 41 uint32_t option_flags; 42 uint32_t ecdsa_algorithm; 43 uint8_t ecdsa_public_key[64]; 44 uint8_t padding[83]; 45 uint8_t binary_type; 46 }; 47 48 struct stm32_header_v2 { 49 uint32_t magic_number; 50 uint8_t image_signature[64]; 51 uint32_t image_checksum; 52 uint8_t header_version[4]; 53 uint32_t image_length; 54 uint32_t image_entry_point; 55 uint32_t reserved1; 56 uint32_t load_address; 57 uint32_t reserved2; 58 uint32_t version_number; 59 uint32_t extension_flags; 60 uint32_t extension_headers_length; 61 uint32_t binary_type; 62 uint8_t padding[16]; 63 uint32_t extension_header_type; 64 uint32_t extension_header_length; 65 uint8_t extension_padding[376]; 66 }; 67 68 static void stm32image_default_header(void *ptr) 69 { 70 struct stm32_header_v1 *header = (struct stm32_header_v1 *)ptr; 71 72 if (!header) { 73 return; 74 } 75 76 header->magic_number = HEADER_MAGIC; 77 header->version_number = __cpu_to_le32(0); 78 } 79 80 static uint32_t stm32image_checksum(void *start, uint32_t len, 81 uint32_t header_size) 82 { 83 uint32_t csum = 0; 84 uint8_t *p; 85 86 if (len < header_size) { 87 return 0; 88 } 89 90 p = (unsigned char *)start + header_size; 91 len -= header_size; 92 93 while (len > 0) { 94 csum += *p; 95 p++; 96 len--; 97 } 98 99 return csum; 100 } 101 102 static void stm32image_print_header(const void *ptr) 103 { 104 struct stm32_header_v1 *stm32hdr = (struct stm32_header_v1 *)ptr; 105 struct stm32_header_v2 *stm32hdr_v2 = (struct stm32_header_v2 *)ptr; 106 107 printf("Image Type : ST Microelectronics STM32 V%d.%d\n", 108 stm32hdr->header_version[VER_MAJOR], 109 stm32hdr->header_version[VER_MINOR]); 110 printf("Image Size : %lu bytes\n", 111 (unsigned long)__le32_to_cpu(stm32hdr->image_length)); 112 printf("Image Load : 0x%08x\n", 113 __le32_to_cpu(stm32hdr->load_address)); 114 printf("Entry Point : 0x%08x\n", 115 __le32_to_cpu(stm32hdr->image_entry_point)); 116 printf("Checksum : 0x%08x\n", 117 __le32_to_cpu(stm32hdr->image_checksum)); 118 119 switch (stm32hdr->header_version[VER_MAJOR]) { 120 case HEADER_VERSION_V1: 121 printf("Option : 0x%08x\n", 122 __le32_to_cpu(stm32hdr->option_flags)); 123 break; 124 125 case HEADER_VERSION_V2: 126 printf("Extension : 0x%08x\n", 127 __le32_to_cpu(stm32hdr_v2->extension_flags)); 128 break; 129 130 default: 131 printf("Incorrect header version\n"); 132 } 133 134 printf("Version : 0x%08x\n", 135 __le32_to_cpu(stm32hdr->version_number)); 136 } 137 138 static int stm32image_set_header(void *ptr, struct stat *sbuf, int ifd, 139 uint32_t loadaddr, uint32_t ep, uint32_t ver, 140 uint32_t major, uint32_t minor, 141 uint32_t binary_type, uint32_t header_size) 142 { 143 struct stm32_header_v1 *stm32hdr = (struct stm32_header_v1 *)ptr; 144 struct stm32_header_v2 *stm32hdr_v2 = (struct stm32_header_v2 *)ptr; 145 uint32_t ext_size = 0U; 146 uint32_t ext_flags = 0U; 147 148 stm32image_default_header(ptr); 149 150 stm32hdr->header_version[VER_MAJOR] = major; 151 stm32hdr->header_version[VER_MINOR] = minor; 152 stm32hdr->load_address = __cpu_to_le32(loadaddr); 153 stm32hdr->image_entry_point = __cpu_to_le32(ep); 154 stm32hdr->image_length = __cpu_to_le32((uint32_t)sbuf->st_size - 155 header_size); 156 stm32hdr->image_checksum = 157 __cpu_to_le32(stm32image_checksum(ptr, sbuf->st_size, 158 header_size)); 159 160 switch (stm32hdr->header_version[VER_MAJOR]) { 161 case HEADER_VERSION_V1: 162 /* Default option for header v1 : bit0 => no signature */ 163 stm32hdr->option_flags = __cpu_to_le32(0x00000001); 164 stm32hdr->ecdsa_algorithm = __cpu_to_le32(1); 165 stm32hdr->binary_type = (uint8_t)binary_type; 166 break; 167 168 case HEADER_VERSION_V2: 169 stm32hdr_v2->binary_type = binary_type; 170 ext_size += PADDING_HEADER_LENGTH; 171 ext_flags |= PADDING_HEADER_FLAG; 172 stm32hdr_v2->extension_flags = 173 __cpu_to_le32(ext_flags); 174 stm32hdr_v2->extension_headers_length = 175 __cpu_to_le32(ext_size); 176 stm32hdr_v2->extension_header_type = PADDING_HEADER_MAGIC; 177 stm32hdr_v2->extension_header_length = 178 __cpu_to_le32(PADDING_HEADER_LENGTH); 179 break; 180 181 default: 182 return -1; 183 } 184 185 stm32hdr->version_number = __cpu_to_le32(ver); 186 187 return 0; 188 } 189 190 static int stm32image_create_header_file(char *srcname, char *destname, 191 uint32_t loadaddr, uint32_t entry, 192 uint32_t version, uint32_t major, 193 uint32_t minor, uint32_t binary_type) 194 { 195 int src_fd, dest_fd, header_size; 196 struct stat sbuf; 197 unsigned char *ptr; 198 void *stm32image_header; 199 200 dest_fd = open(destname, O_RDWR | O_CREAT | O_TRUNC | O_APPEND, 0666); 201 if (dest_fd == -1) { 202 fprintf(stderr, "Can't open %s: %s\n", destname, 203 strerror(errno)); 204 return -1; 205 } 206 207 src_fd = open(srcname, O_RDONLY); 208 if (src_fd == -1) { 209 fprintf(stderr, "Can't open %s: %s\n", srcname, 210 strerror(errno)); 211 return -1; 212 } 213 214 if (fstat(src_fd, &sbuf) < 0) { 215 return -1; 216 } 217 218 ptr = mmap(NULL, sbuf.st_size, PROT_READ, MAP_SHARED, src_fd, 0); 219 if (ptr == MAP_FAILED) { 220 fprintf(stderr, "Can't read %s\n", srcname); 221 return -1; 222 } 223 224 switch (major) { 225 case HEADER_VERSION_V1: 226 stm32image_header = malloc(sizeof(struct stm32_header_v1)); 227 header_size = sizeof(struct stm32_header_v1); 228 break; 229 230 case HEADER_VERSION_V2: 231 stm32image_header = malloc(sizeof(struct stm32_header_v2)); 232 header_size = sizeof(struct stm32_header_v2); 233 break; 234 235 default: 236 return -1; 237 } 238 239 memset(stm32image_header, 0, header_size); 240 if (write(dest_fd, stm32image_header, header_size) != 241 header_size) { 242 fprintf(stderr, "Write error %s: %s\n", destname, 243 strerror(errno)); 244 free(stm32image_header); 245 return -1; 246 } 247 248 free(stm32image_header); 249 250 if (write(dest_fd, ptr, sbuf.st_size) != sbuf.st_size) { 251 fprintf(stderr, "Write error on %s: %s\n", destname, 252 strerror(errno)); 253 return -1; 254 } 255 256 munmap((void *)ptr, sbuf.st_size); 257 close(src_fd); 258 259 if (fstat(dest_fd, &sbuf) < 0) { 260 return -1; 261 } 262 263 ptr = mmap(0, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, 264 dest_fd, 0); 265 266 if (ptr == MAP_FAILED) { 267 fprintf(stderr, "Can't write %s\n", destname); 268 return -1; 269 } 270 271 if (stm32image_set_header(ptr, &sbuf, dest_fd, loadaddr, 272 entry, version, major, minor, 273 binary_type, header_size) != 0) { 274 return -1; 275 } 276 277 stm32image_print_header(ptr); 278 279 munmap((void *)ptr, sbuf.st_size); 280 close(dest_fd); 281 return 0; 282 } 283 284 int main(int argc, char *argv[]) 285 { 286 int opt; 287 int loadaddr = -1; 288 int entry = -1; 289 int err = 0; 290 int version = 0; 291 int binary_type = -1; 292 int major = HEADER_VERSION_V2; 293 int minor = 0; 294 char *dest = NULL; 295 char *src = NULL; 296 297 while ((opt = getopt(argc, argv, ":b:s:d:l:e:v:m:n:")) != -1) { 298 switch (opt) { 299 case 'b': 300 binary_type = strtol(optarg, NULL, 0); 301 break; 302 case 's': 303 src = optarg; 304 break; 305 case 'd': 306 dest = optarg; 307 break; 308 case 'l': 309 loadaddr = strtol(optarg, NULL, 0); 310 break; 311 case 'e': 312 entry = strtol(optarg, NULL, 0); 313 break; 314 case 'v': 315 version = strtol(optarg, NULL, 0); 316 break; 317 case 'm': 318 major = strtol(optarg, NULL, 0); 319 break; 320 case 'n': 321 minor = strtol(optarg, NULL, 0); 322 break; 323 default: 324 fprintf(stderr, 325 "Usage : %s [-s srcfile] [-d destfile] [-l loadaddr] [-e entry_point] [-m major] [-n minor] [-b binary_type]\n", 326 argv[0]); 327 return -1; 328 } 329 } 330 331 if (!src) { 332 fprintf(stderr, "Missing -s option\n"); 333 return -1; 334 } 335 336 if (!dest) { 337 fprintf(stderr, "Missing -d option\n"); 338 return -1; 339 } 340 341 if (loadaddr == -1) { 342 fprintf(stderr, "Missing -l option\n"); 343 return -1; 344 } 345 346 if (entry == -1) { 347 fprintf(stderr, "Missing -e option\n"); 348 return -1; 349 } 350 351 if (binary_type == -1) { 352 fprintf(stderr, "Missing -b option\n"); 353 return -1; 354 } 355 356 err = stm32image_create_header_file(src, dest, loadaddr, 357 entry, version, major, minor, 358 binary_type); 359 360 return err; 361 } 362