xref: /rk3399_ARM-atf/tools/stm32image/stm32image.c (revision e8ee2acd3dd29fdf76b2d2bc8b61b256cca974b1)
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) {
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 = 0;
113 	uint8_t *p;
114 
115 	if (len < header_size) {
116 		return 0;
117 	}
118 
119 	p = (unsigned char *)start + header_size;
120 	len -= header_size;
121 
122 	while (len > 0) {
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, dest_fd, header_size;
268 	struct stat sbuf;
269 	unsigned char *ptr;
270 	void *stm32image_header;
271 
272 	dest_fd = open(destname, O_RDWR | O_CREAT | O_TRUNC | O_APPEND, 0666);
273 	if (dest_fd == -1) {
274 		fprintf(stderr, "Can't open %s: %s\n", destname,
275 			strerror(errno));
276 		return -1;
277 	}
278 
279 	src_fd = open(srcname, O_RDONLY);
280 	if (src_fd == -1) {
281 		fprintf(stderr, "Can't open %s: %s\n", srcname,
282 			strerror(errno));
283 		return -1;
284 	}
285 
286 	if (fstat(src_fd, &sbuf) < 0) {
287 		return -1;
288 	}
289 
290 	ptr = mmap(NULL, sbuf.st_size, PROT_READ, MAP_SHARED, src_fd, 0);
291 	if (ptr == MAP_FAILED) {
292 		fprintf(stderr, "Can't read %s\n", srcname);
293 		return -1;
294 	}
295 
296 	if (minor == HEADER_SUBVERSION_VX_3) {
297 		stm32image_header = malloc(sizeof(struct stm32_header_v23));
298 		header_size = sizeof(struct stm32_header_v23);
299 	} else {
300 		switch (major) {
301 		case HEADER_VERSION_V1:
302 			stm32image_header = malloc(sizeof(struct stm32_header_v1));
303 			header_size = sizeof(struct stm32_header_v1);
304 			break;
305 
306 		case HEADER_VERSION_V2:
307 			stm32image_header = malloc(sizeof(struct stm32_header_v2));
308 			header_size = sizeof(struct stm32_header_v2);
309 			break;
310 
311 		default:
312 			return -1;
313 		}
314 	}
315 
316 	memset(stm32image_header, 0, header_size);
317 	if (write(dest_fd, stm32image_header, header_size) !=
318 	    header_size) {
319 		fprintf(stderr, "Write error %s: %s\n", destname,
320 			strerror(errno));
321 		free(stm32image_header);
322 		return -1;
323 	}
324 
325 	free(stm32image_header);
326 
327 	if (write(dest_fd, ptr, sbuf.st_size) != sbuf.st_size) {
328 		fprintf(stderr, "Write error on %s: %s\n", destname,
329 			strerror(errno));
330 		return -1;
331 	}
332 
333 	munmap((void *)ptr, sbuf.st_size);
334 	close(src_fd);
335 
336 	if (fstat(dest_fd, &sbuf) < 0) {
337 		return -1;
338 	}
339 
340 	ptr = mmap(0, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED,
341 		   dest_fd, 0);
342 
343 	if (ptr == MAP_FAILED) {
344 		fprintf(stderr, "Can't write %s\n", destname);
345 		return -1;
346 	}
347 
348 	if (stm32image_set_header(ptr, &sbuf, dest_fd, loadaddr,
349 				  entry, version, major, minor,
350 				  binary_type, header_size) != 0) {
351 		return -1;
352 	}
353 
354 	stm32image_print_header(ptr);
355 
356 	munmap((void *)ptr, sbuf.st_size);
357 	close(dest_fd);
358 	return 0;
359 }
360 
361 int main(int argc, char *argv[])
362 {
363 	int opt;
364 	int loadaddr = -1;
365 	int entry = -1;
366 	int err = 0;
367 	int version = 0;
368 	int binary_type = -1;
369 	int major = HEADER_VERSION_V2;
370 	int minor = 0;
371 	char *dest = NULL;
372 	char *src = NULL;
373 
374 	while ((opt = getopt(argc, argv, ":b:s:d:l:e:v:m:n:")) != -1) {
375 		switch (opt) {
376 		case 'b':
377 			binary_type = strtol(optarg, NULL, 0);
378 			break;
379 		case 's':
380 			src = optarg;
381 			break;
382 		case 'd':
383 			dest = optarg;
384 			break;
385 		case 'l':
386 			loadaddr = strtol(optarg, NULL, 0);
387 			break;
388 		case 'e':
389 			entry = strtol(optarg, NULL, 0);
390 			break;
391 		case 'v':
392 			version = strtol(optarg, NULL, 0);
393 			break;
394 		case 'm':
395 			major = strtol(optarg, NULL, 0);
396 			break;
397 		case 'n':
398 			minor = strtol(optarg, NULL, 0);
399 			break;
400 		default:
401 			fprintf(stderr,
402 				"Usage : %s [-s srcfile] [-d destfile] [-l loadaddr] [-e entry_point] [-m major] [-n minor] [-b binary_type]\n",
403 					argv[0]);
404 			return -1;
405 		}
406 	}
407 
408 	if (!src) {
409 		fprintf(stderr, "Missing -s option\n");
410 		return -1;
411 	}
412 
413 	if (!dest) {
414 		fprintf(stderr, "Missing -d option\n");
415 		return -1;
416 	}
417 
418 	if (loadaddr == -1) {
419 		fprintf(stderr, "Missing -l option\n");
420 		return -1;
421 	}
422 
423 	if (entry == -1) {
424 		fprintf(stderr, "Missing -e option\n");
425 		return -1;
426 	}
427 
428 	if (binary_type == -1) {
429 		fprintf(stderr, "Missing -b option\n");
430 		return -1;
431 	}
432 
433 	err = stm32image_create_header_file(src, dest, loadaddr,
434 					    entry, version, major, minor,
435 					    binary_type);
436 
437 	return err;
438 }
439