1 /* 2 * Copyright (c) 2017-2026, 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 HEADER_SUBVERSION_VX_3 0x3 27 #define PADDING_HEADER_MAGIC __be32_to_cpu(0x5354FFFF) 28 #define PADDING_HEADER_FLAG (1 << 31) 29 #define PADDING_HEADER_LENGTH 0x180 30 #define PADDING_HEADER_LENGTH_V23 0x1A0 31 32 struct stm32_header_v1 { 33 uint32_t magic_number; 34 uint8_t image_signature[64]; 35 uint32_t image_checksum; 36 uint8_t header_version[4]; 37 uint32_t image_length; 38 uint32_t image_entry_point; 39 uint32_t reserved1; 40 uint32_t load_address; 41 uint32_t reserved2; 42 uint32_t version_number; 43 uint32_t option_flags; 44 uint32_t ecdsa_algorithm; 45 uint8_t ecdsa_public_key[64]; 46 uint8_t padding[83]; 47 uint8_t binary_type; 48 }; 49 50 struct stm32_header_v2 { 51 uint32_t magic_number; 52 uint8_t image_signature[64]; 53 uint32_t image_checksum; 54 uint8_t header_version[4]; 55 uint32_t image_length; 56 uint32_t image_entry_point; 57 uint32_t reserved1; 58 uint32_t load_address; 59 uint32_t reserved2; 60 uint32_t version_number; 61 uint32_t extension_flags; 62 uint32_t extension_headers_length; 63 uint32_t binary_type; 64 uint8_t padding[16]; 65 uint32_t extension_header_type; 66 uint32_t extension_header_length; 67 uint8_t extension_padding[376]; 68 }; 69 70 struct stm32_header_v23 { 71 uint32_t magic_number; 72 uint8_t image_signature[96]; 73 uint32_t image_checksum; 74 uint8_t header_version[4]; 75 uint32_t image_length; 76 uint32_t image_entry_point; 77 uint32_t reserved1; 78 uint32_t load_address; 79 uint32_t reserved2; 80 uint32_t version_number; 81 uint32_t extension_flags; 82 uint32_t extension_headers_length; 83 uint32_t binary_type; 84 uint8_t padding[8]; 85 uint32_t non_secure_payload_length; 86 uint32_t non_secure_payload_hash; 87 uint32_t extension_header_type; 88 uint32_t extension_header_length; 89 uint8_t extension_padding[408]; 90 }; 91 92 static void stm32image_default_header(void *ptr, uint32_t minor) 93 { 94 struct stm32_header_v1 *header = (struct stm32_header_v1 *)ptr; 95 struct stm32_header_v23 *header_v23 = (struct stm32_header_v23 *)ptr; 96 97 if (header == NULL) { 98 return; 99 } 100 101 header->magic_number = HEADER_MAGIC; 102 if (minor == HEADER_SUBVERSION_VX_3) { 103 header_v23->version_number = __cpu_to_le32(0); 104 } else { 105 header->version_number = __cpu_to_le32(0); 106 } 107 } 108 109 static uint32_t stm32image_checksum(void *start, uint32_t len, 110 uint32_t header_size) 111 { 112 uint32_t csum = 0U; 113 uint8_t *p; 114 115 if (len < header_size) { 116 return 0U; 117 } 118 119 p = (uint8_t *)start + header_size; 120 len -= header_size; 121 122 while (len > 0U) { 123 csum += *p; 124 p++; 125 len--; 126 } 127 128 return csum; 129 } 130 131 static void stm32image_print_header(const void *ptr) 132 { 133 struct stm32_header_v1 *stm32hdr = (struct stm32_header_v1 *)ptr; 134 struct stm32_header_v2 *stm32hdr_v2 = (struct stm32_header_v2 *)ptr; 135 struct stm32_header_v23 *stm32hdr_v23 = (struct stm32_header_v23 *)ptr; 136 137 if (stm32hdr_v23->header_version[VER_MINOR] == HEADER_SUBVERSION_VX_3) { 138 printf("Image Type : ST Microelectronics STM32 V%d.%d\n", 139 stm32hdr_v23->header_version[VER_MAJOR], 140 stm32hdr_v23->header_version[VER_MINOR]); 141 printf("Image Size : %lu bytes\n", 142 (unsigned long)__le32_to_cpu(stm32hdr_v23->image_length)); 143 printf("Image Load : 0x%08x\n", 144 __le32_to_cpu(stm32hdr_v23->load_address)); 145 printf("Entry Point : 0x%08x\n", 146 __le32_to_cpu(stm32hdr_v23->image_entry_point)); 147 printf("Checksum : 0x%08x\n", 148 __le32_to_cpu(stm32hdr_v23->image_checksum)); 149 printf("Extension : 0x%08x\n", 150 __le32_to_cpu(stm32hdr_v23->extension_flags)); 151 printf("Version : 0x%08x\n", 152 __le32_to_cpu(stm32hdr_v23->version_number)); 153 } else { 154 printf("Image Type : ST Microelectronics STM32 V%d.%d\n", 155 stm32hdr->header_version[VER_MAJOR], 156 stm32hdr->header_version[VER_MINOR]); 157 printf("Image Size : %lu bytes\n", 158 (unsigned long)__le32_to_cpu(stm32hdr->image_length)); 159 printf("Image Load : 0x%08x\n", 160 __le32_to_cpu(stm32hdr->load_address)); 161 printf("Entry Point : 0x%08x\n", 162 __le32_to_cpu(stm32hdr->image_entry_point)); 163 printf("Checksum : 0x%08x\n", 164 __le32_to_cpu(stm32hdr->image_checksum)); 165 166 switch (stm32hdr->header_version[VER_MAJOR]) { 167 case HEADER_VERSION_V1: 168 printf("Option : 0x%08x\n", 169 __le32_to_cpu(stm32hdr->option_flags)); 170 break; 171 172 case HEADER_VERSION_V2: 173 printf("Extension : 0x%08x\n", 174 __le32_to_cpu(stm32hdr_v2->extension_flags)); 175 break; 176 177 default: 178 printf("Incorrect header version\n"); 179 } 180 181 printf("Version : 0x%08x\n", 182 __le32_to_cpu(stm32hdr->version_number)); 183 } 184 } 185 186 static int stm32image_set_header(void *ptr, struct stat *sbuf, int ifd, 187 uint32_t loadaddr, uint32_t ep, uint32_t ver, 188 uint32_t major, uint32_t minor, 189 uint32_t binary_type, uint32_t header_size) 190 { 191 struct stm32_header_v1 *stm32hdr = (struct stm32_header_v1 *)ptr; 192 struct stm32_header_v2 *stm32hdr_v2 = (struct stm32_header_v2 *)ptr; 193 struct stm32_header_v23 *stm32hdr_v23 = (struct stm32_header_v23 *)ptr; 194 uint32_t ext_size = 0U; 195 uint32_t ext_flags = 0U; 196 197 stm32image_default_header(ptr, minor); 198 199 if (minor == HEADER_SUBVERSION_VX_3) { 200 stm32hdr_v23->header_version[VER_MAJOR] = major; 201 stm32hdr_v23->header_version[VER_MINOR] = minor; 202 stm32hdr_v23->load_address = __cpu_to_le32(loadaddr); 203 stm32hdr_v23->image_entry_point = __cpu_to_le32(ep); 204 stm32hdr_v23->image_length = __cpu_to_le32((uint32_t)sbuf->st_size - 205 header_size); 206 stm32hdr_v23->image_checksum = 207 __cpu_to_le32(stm32image_checksum(ptr, sbuf->st_size, 208 header_size)); 209 stm32hdr_v23->binary_type = binary_type; 210 ext_size += PADDING_HEADER_LENGTH_V23; 211 ext_flags |= PADDING_HEADER_FLAG; 212 stm32hdr_v23->extension_flags = 213 __cpu_to_le32(ext_flags); 214 stm32hdr_v23->extension_headers_length = 215 __cpu_to_le32(ext_size); 216 stm32hdr_v23->extension_header_type = PADDING_HEADER_MAGIC; 217 stm32hdr_v23->extension_header_length = 218 __cpu_to_le32(PADDING_HEADER_LENGTH_V23); 219 stm32hdr_v23->version_number = __cpu_to_le32(ver); 220 } else { 221 stm32hdr->header_version[VER_MAJOR] = major; 222 stm32hdr->header_version[VER_MINOR] = minor; 223 stm32hdr->load_address = __cpu_to_le32(loadaddr); 224 stm32hdr->image_entry_point = __cpu_to_le32(ep); 225 stm32hdr->image_length = __cpu_to_le32((uint32_t)sbuf->st_size - 226 header_size); 227 stm32hdr->image_checksum = 228 __cpu_to_le32(stm32image_checksum(ptr, sbuf->st_size, 229 header_size)); 230 231 switch (stm32hdr->header_version[VER_MAJOR]) { 232 case HEADER_VERSION_V1: 233 /* Default option for header v1 : bit0 => no signature */ 234 stm32hdr->option_flags = __cpu_to_le32(0x00000001); 235 stm32hdr->ecdsa_algorithm = __cpu_to_le32(1); 236 stm32hdr->binary_type = (uint8_t)binary_type; 237 break; 238 239 case HEADER_VERSION_V2: 240 stm32hdr_v2->binary_type = binary_type; 241 ext_size += PADDING_HEADER_LENGTH; 242 ext_flags |= PADDING_HEADER_FLAG; 243 stm32hdr_v2->extension_flags = 244 __cpu_to_le32(ext_flags); 245 stm32hdr_v2->extension_headers_length = 246 __cpu_to_le32(ext_size); 247 stm32hdr_v2->extension_header_type = PADDING_HEADER_MAGIC; 248 stm32hdr_v2->extension_header_length = 249 __cpu_to_le32(PADDING_HEADER_LENGTH); 250 break; 251 252 default: 253 return -1; 254 } 255 256 stm32hdr->version_number = __cpu_to_le32(ver); 257 } 258 259 return 0; 260 } 261 262 static int stm32image_create_header_file(char *srcname, char *destname, 263 uint32_t loadaddr, uint32_t entry, 264 uint32_t version, uint32_t major, 265 uint32_t minor, uint32_t binary_type) 266 { 267 int src_fd = -1, dest_fd = -1; 268 struct stat sbuf; 269 unsigned char *ptr = NULL; 270 void *stm32image_header; 271 size_t map_size = 0U, header_size = 0U; 272 ssize_t wr; 273 int ret = -1; 274 275 dest_fd = open(destname, O_RDWR | O_CREAT | O_TRUNC | O_APPEND, 0666); 276 if (dest_fd == -1) { 277 fprintf(stderr, "Can't open %s: %s\n", destname, 278 strerror(errno)); 279 return -1; 280 } 281 282 src_fd = open(srcname, O_RDONLY); 283 if (src_fd == -1) { 284 fprintf(stderr, "Can't open %s: %s\n", srcname, 285 strerror(errno)); 286 goto out; 287 } 288 289 /* Source file section */ 290 if (fstat(src_fd, &sbuf) < 0) { 291 goto out; 292 } 293 294 if (sbuf.st_size < 0) { 295 fprintf(stderr, "Invalid file size for %s\n", srcname); 296 goto out; 297 } 298 299 map_size = (size_t)sbuf.st_size; 300 301 ptr = mmap(NULL, map_size, PROT_READ, MAP_SHARED, src_fd, 0); 302 if (ptr == MAP_FAILED) { 303 fprintf(stderr, "Can't read %s\n", srcname); 304 ptr = NULL; 305 map_size = 0U; 306 goto out; 307 } 308 309 if (minor == HEADER_SUBVERSION_VX_3) { 310 header_size = sizeof(struct stm32_header_v23); 311 stm32image_header = malloc(header_size); 312 } else { 313 switch (major) { 314 case HEADER_VERSION_V1: 315 header_size = sizeof(struct stm32_header_v1); 316 stm32image_header = malloc(header_size); 317 break; 318 319 case HEADER_VERSION_V2: 320 header_size = sizeof(struct stm32_header_v2); 321 stm32image_header = malloc(header_size); 322 break; 323 324 default: 325 fprintf(stderr, "Unsupported header version (major=%u, minor=%u)\n", 326 major, minor); 327 goto out; 328 } 329 } 330 331 if (stm32image_header == NULL) { 332 fprintf(stderr, "malloc failed for header\n"); 333 goto out; 334 } 335 336 memset(stm32image_header, 0, header_size); 337 338 wr = write(dest_fd, stm32image_header, header_size); 339 if ((wr < 0) || ((size_t)wr != header_size)) { 340 fprintf(stderr, "Write error %s (header): %s\n", 341 destname, strerror(errno)); 342 free(stm32image_header); 343 goto out; 344 } 345 346 free(stm32image_header); 347 348 wr = write(dest_fd, ptr, map_size); 349 if ((wr < 0) || ((size_t)wr != map_size)) { 350 fprintf(stderr, "Write error %s (payload): %s\n", 351 destname, strerror(errno)); 352 goto out; 353 } 354 355 if ((ptr != NULL) && (map_size > 0U)) { 356 munmap(ptr, map_size); 357 ptr = NULL; 358 map_size = 0U; 359 } 360 361 if (src_fd >= 0) { 362 close(src_fd); 363 src_fd = -1; 364 } 365 366 /* Dest file section */ 367 if (fstat(dest_fd, &sbuf) < 0) { 368 goto out; 369 } 370 371 if (sbuf.st_size < 0) { 372 fprintf(stderr, "Invalid dest file size for %s\n", destname); 373 goto out; 374 } 375 376 map_size = (size_t)sbuf.st_size; 377 378 ptr = mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, 379 dest_fd, 0); 380 if (ptr == MAP_FAILED) { 381 fprintf(stderr, "Can't write %s\n", destname); 382 ptr = NULL; 383 map_size = 0U; 384 goto out; 385 } 386 387 if (stm32image_set_header(ptr, &sbuf, dest_fd, loadaddr, 388 entry, version, major, minor, 389 binary_type, header_size) != 0) { 390 fprintf(stderr, "stm32image_set_header failed\n"); 391 goto out; 392 } 393 394 stm32image_print_header(ptr); 395 ret = 0; 396 397 out: 398 if ((ptr != NULL) && (map_size > 0U)) { 399 munmap(ptr, map_size); 400 } 401 if (src_fd >= 0) { 402 close(src_fd); 403 } 404 if (dest_fd >= 0) { 405 close(dest_fd); 406 } 407 408 return ret; 409 } 410 411 int main(int argc, char *argv[]) 412 { 413 int opt; 414 int loadaddr = -1; 415 int entry = -1; 416 int err = 0; 417 int version = 0; 418 int binary_type = -1; 419 int major = HEADER_VERSION_V2; 420 int minor = 0; 421 char *dest = NULL; 422 char *src = NULL; 423 424 while ((opt = getopt(argc, argv, ":b:s:d:l:e:v:m:n:")) != -1) { 425 switch (opt) { 426 case 'b': 427 binary_type = strtol(optarg, NULL, 0); 428 break; 429 case 's': 430 src = optarg; 431 break; 432 case 'd': 433 dest = optarg; 434 break; 435 case 'l': 436 loadaddr = strtol(optarg, NULL, 0); 437 break; 438 case 'e': 439 entry = strtol(optarg, NULL, 0); 440 break; 441 case 'v': 442 version = strtol(optarg, NULL, 0); 443 break; 444 case 'm': 445 major = strtol(optarg, NULL, 0); 446 break; 447 case 'n': 448 minor = strtol(optarg, NULL, 0); 449 break; 450 default: 451 fprintf(stderr, 452 "Usage : %s [-s srcfile] [-d destfile] [-l loadaddr] [-e entry_point] [-m major] [-n minor] [-b binary_type]\n", 453 argv[0]); 454 return -1; 455 } 456 } 457 458 if (src == NULL) { 459 fprintf(stderr, "Missing -s option\n"); 460 return -1; 461 } 462 463 if (dest == NULL) { 464 fprintf(stderr, "Missing -d option\n"); 465 return -1; 466 } 467 468 if (loadaddr == -1) { 469 fprintf(stderr, "Missing -l option\n"); 470 return -1; 471 } 472 473 if (entry == -1) { 474 fprintf(stderr, "Missing -e option\n"); 475 return -1; 476 } 477 478 if (binary_type == -1) { 479 fprintf(stderr, "Missing -b option\n"); 480 return -1; 481 } 482 483 err = stm32image_create_header_file(src, dest, loadaddr, 484 entry, version, major, minor, 485 binary_type); 486 487 return err; 488 } 489