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