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