xref: /rk3399_ARM-atf/tools/stm32image/stm32image.c (revision 681296444e508e722565c6713effd2cf346a4dcf)
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 
stm32image_default_header(void * ptr,uint32_t minor)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 
stm32image_checksum(void * start,uint32_t len,uint32_t header_size)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 
stm32image_print_header(const void * ptr)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 
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)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 
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)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 
main(int argc,char * argv[])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