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
stm32image_default_header(void * ptr)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
stm32image_checksum(void * start,uint32_t len,uint32_t header_size)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
stm32image_print_header(const void * ptr)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
stm32image_set_header(void * ptr,struct stat * sbuf,int ifd,uint32_t loadaddr,uint32_t ep,uint32_t ver,uint32_t major,uint32_t minor,uint32_t binary_type,uint32_t header_size)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
stm32image_create_header_file(char * srcname,char * destname,uint32_t loadaddr,uint32_t entry,uint32_t version,uint32_t major,uint32_t minor,uint32_t binary_type)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
main(int argc,char * argv[])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