blob: bd4720c5c9f81d438a27d286ae425d4127937599 [file] [log] [blame]
Yann Gautierba46a932018-07-05 16:50:22 +02001/*
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +01002 * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved
Yann Gautierba46a932018-07-05 16:50:22 +02003 *
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
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +010025#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
Yann Gautierba46a932018-07-05 16:50:22 +020029
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +010030struct stm32_header_v1 {
Yann Gautierba46a932018-07-05 16:50:22 +020031 uint32_t magic_number;
32 uint8_t image_signature[64];
33 uint32_t image_checksum;
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +010034 uint8_t header_version[4];
Yann Gautierba46a932018-07-05 16:50:22 +020035 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
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +010048struct 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
68static void stm32image_default_header(void *ptr)
Yann Gautierba46a932018-07-05 16:50:22 +020069{
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +010070 struct stm32_header_v1 *header = (struct stm32_header_v1 *)ptr;
71
72 if (!header) {
Yann Gautierba46a932018-07-05 16:50:22 +020073 return;
74 }
75
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +010076 header->magic_number = HEADER_MAGIC;
77 header->version_number = __cpu_to_le32(0);
Yann Gautierba46a932018-07-05 16:50:22 +020078}
79
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +010080static uint32_t stm32image_checksum(void *start, uint32_t len,
81 uint32_t header_size)
Yann Gautierba46a932018-07-05 16:50:22 +020082{
83 uint32_t csum = 0;
Yann Gautierba46a932018-07-05 16:50:22 +020084 uint8_t *p;
85
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +010086 if (len < header_size) {
Yann Gautierba46a932018-07-05 16:50:22 +020087 return 0;
88 }
89
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +010090 p = (unsigned char *)start + header_size;
91 len -= header_size;
Yann Gautierba46a932018-07-05 16:50:22 +020092
93 while (len > 0) {
94 csum += *p;
95 p++;
96 len--;
97 }
98
99 return csum;
100}
101
102static void stm32image_print_header(const void *ptr)
103{
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100104 struct stm32_header_v1 *stm32hdr = (struct stm32_header_v1 *)ptr;
105 struct stm32_header_v2 *stm32hdr_v2 = (struct stm32_header_v2 *)ptr;
Yann Gautierba46a932018-07-05 16:50:22 +0200106
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));
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100118
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",
Yann Gautierba46a932018-07-05 16:50:22 +0200135 __le32_to_cpu(stm32hdr->version_number));
136}
137
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100138static 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)
Yann Gautierba46a932018-07-05 16:50:22 +0200142{
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100143 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;
Yann Gautierba46a932018-07-05 16:50:22 +0200147
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100148 stm32image_default_header(ptr);
Yann Gautierba46a932018-07-05 16:50:22 +0200149
Nicolas Le Bayon7b86de42019-11-18 17:13:11 +0100150 stm32hdr->header_version[VER_MAJOR] = major;
151 stm32hdr->header_version[VER_MINOR] = minor;
Yann Gautierba46a932018-07-05 16:50:22 +0200152 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 -
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100155 header_size);
Nicolas Le Bayon7b86de42019-11-18 17:13:11 +0100156 stm32hdr->image_checksum =
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100157 __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
Yann Gautierba46a932018-07-05 16:50:22 +0200185 stm32hdr->version_number = __cpu_to_le32(ver);
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100186
187 return 0;
Yann Gautierba46a932018-07-05 16:50:22 +0200188}
189
190static int stm32image_create_header_file(char *srcname, char *destname,
191 uint32_t loadaddr, uint32_t entry,
Nicolas Le Bayon7b86de42019-11-18 17:13:11 +0100192 uint32_t version, uint32_t major,
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100193 uint32_t minor, uint32_t binary_type)
Yann Gautierba46a932018-07-05 16:50:22 +0200194{
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100195 int src_fd, dest_fd, header_size;
Yann Gautierba46a932018-07-05 16:50:22 +0200196 struct stat sbuf;
197 unsigned char *ptr;
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100198 void *stm32image_header;
Yann Gautierba46a932018-07-05 16:50:22 +0200199
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
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100224 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 }
Yann Gautierba46a932018-07-05 16:50:22 +0200238
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100239 memset(stm32image_header, 0, header_size);
240 if (write(dest_fd, stm32image_header, header_size) !=
241 header_size) {
Yann Gautierba46a932018-07-05 16:50:22 +0200242 fprintf(stderr, "Write error %s: %s\n", destname,
243 strerror(errno));
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100244 free(stm32image_header);
Yann Gautierba46a932018-07-05 16:50:22 +0200245 return -1;
246 }
247
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100248 free(stm32image_header);
249
Yann Gautierba46a932018-07-05 16:50:22 +0200250 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) {
Nicolas Le Bayon7b86de42019-11-18 17:13:11 +0100267 fprintf(stderr, "Can't write %s\n", destname);
Yann Gautierba46a932018-07-05 16:50:22 +0200268 return -1;
269 }
270
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100271 if (stm32image_set_header(ptr, &sbuf, dest_fd, loadaddr,
272 entry, version, major, minor,
273 binary_type, header_size) != 0) {
274 return -1;
275 }
Yann Gautierba46a932018-07-05 16:50:22 +0200276
277 stm32image_print_header(ptr);
278
279 munmap((void *)ptr, sbuf.st_size);
280 close(dest_fd);
281 return 0;
282}
283
284int main(int argc, char *argv[])
285{
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100286 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;
Nicolas Le Bayon7b86de42019-11-18 17:13:11 +0100293 int minor = 0;
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100294 char *dest = NULL;
295 char *src = NULL;
Yann Gautierba46a932018-07-05 16:50:22 +0200296
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100297 while ((opt = getopt(argc, argv, ":b:s:d:l:e:v:m:n:")) != -1) {
Yann Gautierba46a932018-07-05 16:50:22 +0200298 switch (opt) {
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100299 case 'b':
300 binary_type = strtol(optarg, NULL, 0);
301 break;
Yann Gautierba46a932018-07-05 16:50:22 +0200302 case 's':
303 src = optarg;
304 break;
305 case 'd':
306 dest = optarg;
307 break;
308 case 'l':
Nicolas Le Bayon7b86de42019-11-18 17:13:11 +0100309 loadaddr = strtol(optarg, NULL, 0);
Yann Gautierba46a932018-07-05 16:50:22 +0200310 break;
311 case 'e':
Nicolas Le Bayon7b86de42019-11-18 17:13:11 +0100312 entry = strtol(optarg, NULL, 0);
Yann Gautierba46a932018-07-05 16:50:22 +0200313 break;
314 case 'v':
Nicolas Le Bayon7b86de42019-11-18 17:13:11 +0100315 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);
Yann Gautierba46a932018-07-05 16:50:22 +0200322 break;
323 default:
324 fprintf(stderr,
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100325 "Usage : %s [-s srcfile] [-d destfile] [-l loadaddr] [-e entry_point] [-m major] [-n minor] [-b binary_type]\n",
Yann Gautierba46a932018-07-05 16:50:22 +0200326 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
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100351 if (binary_type == -1) {
352 fprintf(stderr, "Missing -b option\n");
353 return -1;
354 }
355
Yann Gautierba46a932018-07-05 16:50:22 +0200356 err = stm32image_create_header_file(src, dest, loadaddr,
Nicolas Le Bayondfa46cc2019-11-18 17:13:42 +0100357 entry, version, major, minor,
358 binary_type);
Yann Gautierba46a932018-07-05 16:50:22 +0200359
360 return err;
361}