xref: /openbmc/u-boot/tools/mtk_image.c (revision fd0bc623)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Generate MediaTek BootROM header for SPL/U-Boot images
4  *
5  * Copyright (C) 2018 MediaTek Inc.
6  * Author: Weijie Gao <weijie.gao@mediatek.com>
7  */
8 
9 #include <image.h>
10 #include <u-boot/sha256.h>
11 #include "imagetool.h"
12 #include "mtk_image.h"
13 
14 /* NAND header for SPI-NAND with 2KB page + 64B spare */
15 static const union nand_boot_header snand_hdr_2k_64_data = {
16 	.data = {
17 		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
18 		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
19 		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
20 		0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x40, 0x00,
21 		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
22 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
23 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
24 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
25 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
26 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
27 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29 		0x00, 0x00, 0x00, 0x00, 0x7B, 0xC4, 0x17, 0x9D,
30 		0xCA, 0x42, 0x90, 0xD0, 0x98, 0xD0, 0xE0, 0xF7,
31 		0xDB, 0xCD, 0x16, 0xF6, 0x03, 0x73, 0xD2, 0xB8,
32 		0x93, 0xB2, 0x56, 0x5A, 0x84, 0x6E, 0x00, 0x00
33 	}
34 };
35 
36 /* NAND header for SPI-NAND with 2KB page + 120B/128B spare */
37 static const union nand_boot_header snand_hdr_2k_128_data = {
38 	.data = {
39 		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
40 		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
41 		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
42 		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
43 		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
44 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51 		0x00, 0x00, 0x00, 0x00, 0x90, 0x28, 0xED, 0x13,
52 		0x7F, 0x12, 0x22, 0xCD, 0x3D, 0x06, 0xF1, 0xB3,
53 		0x6F, 0x2E, 0xD9, 0xA0, 0x9D, 0x7A, 0xBD, 0xD7,
54 		0xB3, 0x28, 0x3C, 0x13, 0xDB, 0x4E, 0x00, 0x00
55 	}
56 };
57 
58 /* NAND header for SPI-NAND with 4KB page + 256B spare */
59 static const union nand_boot_header snand_hdr_4k_256_data = {
60 	.data = {
61 		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
62 		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
63 		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
64 		0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0xE0, 0x00,
65 		0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
66 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 		0x00, 0x00, 0x00, 0x00, 0x47, 0xED, 0x0E, 0xC3,
74 		0x83, 0xBF, 0x41, 0xD2, 0x85, 0x21, 0x97, 0x57,
75 		0xC4, 0x2E, 0x6B, 0x7A, 0x40, 0xE0, 0xCF, 0x8F,
76 		0x37, 0xBD, 0x17, 0xB6, 0xC7, 0xFE, 0x00, 0x00
77 	}
78 };
79 
80 /* NAND header for Parallel NAND 1Gb with 2KB page + 64B spare */
81 static const union nand_boot_header nand_hdr_1gb_2k_64_data = {
82 	.data = {
83 		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
84 		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
85 		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
86 		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
87 		0x40, 0x00, 0x00, 0x04, 0x0B, 0x00, 0x11, 0x00,
88 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
94 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 		0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x1C, 0x12,
96 		0x8F, 0xFD, 0xF8, 0x32, 0x6F, 0x6D, 0xCF, 0x6C,
97 		0xDA, 0x21, 0x70, 0x8C, 0xDA, 0x0A, 0x22, 0x82,
98 		0xAA, 0x59, 0xFA, 0x7C, 0x42, 0x2D, 0x00, 0x00
99 	}
100 };
101 
102 /* NAND header for Parallel NAND 2Gb with 2KB page + 64B spare */
103 static const union nand_boot_header nand_hdr_2gb_2k_64_data = {
104 	.data = {
105 		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
106 		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
107 		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
108 		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
109 		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
110 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
111 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
112 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
113 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
114 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117 		0x00, 0x00, 0x00, 0x00, 0x20, 0x9C, 0x3D, 0x2D,
118 		0x7B, 0x68, 0x63, 0x52, 0x2E, 0x04, 0x63, 0xF1,
119 		0x35, 0x4E, 0x44, 0x3E, 0xF8, 0xAC, 0x9B, 0x95,
120 		0xAB, 0xFE, 0xE4, 0xE1, 0xD5, 0xF9, 0x00, 0x00
121 	}
122 };
123 
124 /* NAND header for Parallel NAND 4Gb with 2KB page + 64B spare */
125 static const union nand_boot_header nand_hdr_4gb_2k_64_data = {
126 	.data = {
127 		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
128 		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
129 		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
130 		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
131 		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
132 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
135 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
136 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
138 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
139 		0x00, 0x00, 0x00, 0x00, 0xE3, 0x0F, 0x86, 0x32,
140 		0x68, 0x05, 0xD9, 0xC8, 0x13, 0xDF, 0xC5, 0x0B,
141 		0x35, 0x3A, 0x68, 0xA5, 0x3C, 0x0C, 0x73, 0x87,
142 		0x63, 0xB0, 0xBE, 0xCC, 0x84, 0x47, 0x00, 0x00
143 	}
144 };
145 
146 /* NAND header for Parallel NAND 2Gb with 2KB page + 128B spare */
147 static const union nand_boot_header nand_hdr_2gb_2k_128_data = {
148 	.data = {
149 		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
150 		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
151 		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
152 		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
153 		0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
154 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161 		0x00, 0x00, 0x00, 0x00, 0x01, 0xA5, 0xE9, 0x5A,
162 		0xDF, 0x58, 0x62, 0x41, 0xD6, 0x26, 0x77, 0xBC,
163 		0x76, 0x1F, 0x27, 0x4E, 0x4F, 0x6C, 0xC3, 0xF0,
164 		0x36, 0xDE, 0xD9, 0xB3, 0xFF, 0x93, 0x00, 0x00
165 	}
166 };
167 
168 /* NAND header for Parallel NAND 4Gb with 2KB page + 128B spare */
169 static const union nand_boot_header nand_hdr_4gb_2k_128_data = {
170 	.data = {
171 		0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
172 		0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
173 		0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
174 		0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
175 		0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
176 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
177 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
182 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
183 		0x00, 0x00, 0x00, 0x00, 0xC2, 0x36, 0x52, 0x45,
184 		0xCC, 0x35, 0xD8, 0xDB, 0xEB, 0xFD, 0xD1, 0x46,
185 		0x76, 0x6B, 0x0B, 0xD5, 0x8B, 0xCC, 0x2B, 0xE2,
186 		0xFE, 0x90, 0x83, 0x9E, 0xAE, 0x2D, 0x00, 0x00
187 	}
188 };
189 
190 static const struct nand_header_type {
191 	const char *name;
192 	const union nand_boot_header *data;
193 } nand_headers[] = {
194 	{
195 		.name = "2k+64",
196 		.data = &snand_hdr_2k_64_data
197 	}, {
198 		.name = "2k+120",
199 		.data = &snand_hdr_2k_128_data
200 	}, {
201 		.name = "2k+128",
202 		.data = &snand_hdr_2k_128_data
203 	}, {
204 		.name = "4k+256",
205 		.data = &snand_hdr_4k_256_data
206 	}, {
207 		.name = "1g:2k+64",
208 		.data = &nand_hdr_1gb_2k_64_data
209 	}, {
210 		.name = "2g:2k+64",
211 		.data = &nand_hdr_2gb_2k_64_data
212 	}, {
213 		.name = "4g:2k+64",
214 		.data = &nand_hdr_4gb_2k_64_data
215 	}, {
216 		.name = "2g:2k+128",
217 		.data = &nand_hdr_2gb_2k_128_data
218 	}, {
219 		.name = "4g:2k+128",
220 		.data = &nand_hdr_4gb_2k_128_data
221 	}
222 };
223 
224 static const struct brom_img_type {
225 	const char *name;
226 	enum brlyt_img_type type;
227 } brom_images[] = {
228 	{
229 		.name = "nand",
230 		.type = BRLYT_TYPE_NAND
231 	}, {
232 		.name = "emmc",
233 		.type = BRLYT_TYPE_EMMC
234 	}, {
235 		.name = "nor",
236 		.type = BRLYT_TYPE_NOR
237 	}, {
238 		.name = "sdmmc",
239 		.type = BRLYT_TYPE_SDMMC
240 	}, {
241 		.name = "snand",
242 		.type = BRLYT_TYPE_SNAND
243 	}
244 };
245 
246 /* Image type selected by user */
247 static enum brlyt_img_type hdr_media;
248 static int use_lk_hdr;
249 
250 /* LK image name */
251 static char lk_name[32] = "U-Boot";
252 
253 /* NAND header selected by user */
254 static const union nand_boot_header *hdr_nand;
255 
256 /* GFH header + 2 * 4KB pages of NAND */
257 static char hdr_tmp[sizeof(struct gfh_header) + 0x2000];
258 
259 static int mtk_image_check_image_types(uint8_t type)
260 {
261 	if (type == IH_TYPE_MTKIMAGE)
262 		return EXIT_SUCCESS;
263 	else
264 		return EXIT_FAILURE;
265 }
266 
267 static int mtk_brom_parse_imagename(const char *imagename)
268 {
269 #define is_blank_char(c) \
270 	((c) == '\t' || (c) == '\n' || (c) == '\r' || (c) == ' ')
271 
272 	char *buf = strdup(imagename), *key, *val, *end, *next;
273 	int i;
274 
275 	/* User passed arguments from image name */
276 	static const char *media = "";
277 	static const char *nandinfo = "";
278 	static const char *lk = "";
279 
280 	key = buf;
281 	while (key) {
282 		next = strchr(key, ';');
283 		if (next)
284 			*next = 0;
285 
286 		val = strchr(key, '=');
287 		if (val) {
288 			*val++ = 0;
289 
290 			/* Trim key */
291 			while (is_blank_char(*key))
292 				key++;
293 
294 			end = key + strlen(key) - 1;
295 			while ((end >= key) && is_blank_char(*end))
296 				end--;
297 			end++;
298 
299 			if (is_blank_char(*end))
300 				*end = 0;
301 
302 			/* Trim value */
303 			while (is_blank_char(*val))
304 				val++;
305 
306 			end = val + strlen(val) - 1;
307 			while ((end >= val) && is_blank_char(*end))
308 				end--;
309 			end++;
310 
311 			if (is_blank_char(*end))
312 				*end = 0;
313 
314 			/* record user passed arguments */
315 			if (!strcmp(key, "media"))
316 				media = val;
317 
318 			if (!strcmp(key, "nandinfo"))
319 				nandinfo = val;
320 
321 			if (!strcmp(key, "lk"))
322 				lk = val;
323 
324 			if (!strcmp(key, "lkname"))
325 				snprintf(lk_name, sizeof(lk_name), "%s", val);
326 		}
327 
328 		if (next)
329 			key = next + 1;
330 		else
331 			break;
332 	}
333 
334 	/* if user specified LK image header, skip following checks */
335 	if (lk && lk[0] == '1') {
336 		use_lk_hdr = 1;
337 		free(buf);
338 		return 0;
339 	}
340 
341 	/* parse media type */
342 	for (i = 0; i < ARRAY_SIZE(brom_images); i++) {
343 		if (!strcmp(brom_images[i].name, media)) {
344 			hdr_media = brom_images[i].type;
345 			break;
346 		}
347 	}
348 
349 	/* parse nand header type */
350 	for (i = 0; i < ARRAY_SIZE(nand_headers); i++) {
351 		if (!strcmp(nand_headers[i].name, nandinfo)) {
352 			hdr_nand = nand_headers[i].data;
353 			break;
354 		}
355 	}
356 
357 	free(buf);
358 
359 	if (hdr_media == BRLYT_TYPE_INVALID) {
360 		fprintf(stderr, "Error: media type is invalid or missing.\n");
361 		fprintf(stderr, "       Please specify -n \"media=<type>\"\n");
362 		return -EINVAL;
363 	}
364 
365 	if ((hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND) &&
366 	    !hdr_nand) {
367 		fprintf(stderr, "Error: nand info is invalid or missing.\n");
368 		fprintf(stderr, "       Please specify -n \"media=%s;"
369 				"nandinfo=<info>\"\n", media);
370 		return -EINVAL;
371 	}
372 
373 	return 0;
374 }
375 
376 static int mtk_image_check_params(struct image_tool_params *params)
377 {
378 	if (!params->addr) {
379 		fprintf(stderr, "Error: Load Address must be set.\n");
380 		return -EINVAL;
381 	}
382 
383 	if (!params->imagename) {
384 		fprintf(stderr, "Error: Image Name must be set.\n");
385 		return -EINVAL;
386 	}
387 
388 	return mtk_brom_parse_imagename(params->imagename);
389 }
390 
391 static int mtk_image_vrec_header(struct image_tool_params *params,
392 				 struct image_type_params *tparams)
393 {
394 	if (use_lk_hdr) {
395 		tparams->header_size = sizeof(union lk_hdr);
396 		tparams->hdr = &hdr_tmp;
397 		memset(&hdr_tmp, 0xff, tparams->header_size);
398 		return 0;
399 	}
400 
401 	if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
402 		tparams->header_size = 2 * le16_to_cpu(hdr_nand->pagesize);
403 	else
404 		tparams->header_size = sizeof(struct gen_device_header);
405 
406 	tparams->header_size += sizeof(struct gfh_header);
407 	tparams->hdr = &hdr_tmp;
408 
409 	memset(&hdr_tmp, 0xff, tparams->header_size);
410 
411 	return SHA256_SUM_LEN;
412 }
413 
414 static int mtk_image_verify_gen_header(const uint8_t *ptr, int print)
415 {
416 	union gen_boot_header *gbh = (union gen_boot_header *)ptr;
417 	struct brom_layout_header *bh;
418 	struct gfh_header *gfh;
419 	const char *bootmedia;
420 
421 	if (!strcmp(gbh->name, SF_BOOT_NAME))
422 		bootmedia = "Serial NOR";
423 	else if (!strcmp(gbh->name, EMMC_BOOT_NAME))
424 		bootmedia = "eMMC";
425 	else if (!strcmp(gbh->name, SDMMC_BOOT_NAME))
426 		bootmedia = "SD/MMC";
427 	else
428 		return -1;
429 
430 	if (print)
431 		printf("Boot Media:   %s\n", bootmedia);
432 
433 	if (le32_to_cpu(gbh->version) != 1 ||
434 	    le32_to_cpu(gbh->size) != sizeof(union gen_boot_header))
435 		return -1;
436 
437 	bh = (struct brom_layout_header *)(ptr + le32_to_cpu(gbh->size));
438 
439 	if (strcmp(bh->name, BRLYT_NAME))
440 		return -1;
441 
442 	if (le32_to_cpu(bh->magic) != BRLYT_MAGIC ||
443 	    (le32_to_cpu(bh->type) != BRLYT_TYPE_NOR &&
444 	    le32_to_cpu(bh->type) != BRLYT_TYPE_EMMC &&
445 	    le32_to_cpu(bh->type) != BRLYT_TYPE_SDMMC))
446 		return -1;
447 
448 	gfh = (struct gfh_header *)(ptr + le32_to_cpu(bh->header_size));
449 
450 	if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
451 		return -1;
452 
453 	if (le32_to_cpu(gfh->file_info.flash_type) != GFH_FLASH_TYPE_GEN)
454 		return -1;
455 
456 	if (print)
457 		printf("Load Address: %08x\n",
458 		       le32_to_cpu(gfh->file_info.load_addr) +
459 		       le32_to_cpu(gfh->file_info.jump_offset));
460 
461 	return 0;
462 }
463 
464 static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
465 {
466 	union nand_boot_header *nh = (union nand_boot_header *)ptr;
467 	struct brom_layout_header *bh;
468 	struct gfh_header *gfh;
469 	const char *bootmedia;
470 
471 	if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh->version)) ||
472 	    strcmp(nh->id, NAND_BOOT_ID))
473 		return -1;
474 
475 	bh = (struct brom_layout_header *)(ptr + le16_to_cpu(nh->pagesize));
476 
477 	if (strcmp(bh->name, BRLYT_NAME))
478 		return -1;
479 
480 	if (le32_to_cpu(bh->magic) != BRLYT_MAGIC) {
481 		return -1;
482 	} else {
483 		if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND)
484 			bootmedia = "Parallel NAND";
485 		else if (le32_to_cpu(bh->type) == BRLYT_TYPE_SNAND)
486 			bootmedia = "Serial NAND";
487 		else
488 			return -1;
489 	}
490 
491 	if (print) {
492 		printf("Boot Media: %s\n", bootmedia);
493 
494 		if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND) {
495 			uint64_t capacity =
496 				(uint64_t)le16_to_cpu(nh->numblocks) *
497 				(uint64_t)le16_to_cpu(nh->pages_of_block) *
498 				(uint64_t)le16_to_cpu(nh->pagesize) * 8;
499 			printf("Capacity:     %dGb\n",
500 			       (uint32_t)(capacity >> 30));
501 		}
502 
503 		if (le16_to_cpu(nh->pagesize) >= 1024)
504 			printf("Page Size:    %dKB\n",
505 			       le16_to_cpu(nh->pagesize) >> 10);
506 		else
507 			printf("Page Size:    %dB\n",
508 			       le16_to_cpu(nh->pagesize));
509 
510 		printf("Spare Size:   %dB\n", le16_to_cpu(nh->oobsize));
511 	}
512 
513 	gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(nh->pagesize));
514 
515 	if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
516 		return -1;
517 
518 	if (le32_to_cpu(gfh->file_info.flash_type) != GFH_FLASH_TYPE_NAND)
519 		return -1;
520 
521 	if (print)
522 		printf("Load Address: %08x\n",
523 		       le32_to_cpu(gfh->file_info.load_addr) +
524 		       le32_to_cpu(gfh->file_info.jump_offset));
525 
526 	return 0;
527 }
528 
529 static int mtk_image_verify_header(unsigned char *ptr, int image_size,
530 				   struct image_tool_params *params)
531 {
532 	union lk_hdr *lk = (union lk_hdr *)ptr;
533 
534 	/* nothing to verify for LK image header */
535 	if (le32_to_cpu(lk->magic) == LK_PART_MAGIC)
536 		return 0;
537 
538 	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
539 		return mtk_image_verify_nand_header(ptr, 0);
540 	else
541 		return mtk_image_verify_gen_header(ptr, 0);
542 
543 	return -1;
544 }
545 
546 static void mtk_image_print_header(const void *ptr)
547 {
548 	union lk_hdr *lk = (union lk_hdr *)ptr;
549 
550 	if (le32_to_cpu(lk->magic) == LK_PART_MAGIC) {
551 		printf("Image Type:   MediaTek LK Image\n");
552 		printf("Load Address: %08x\n", le32_to_cpu(lk->loadaddr));
553 		return;
554 	}
555 
556 	printf("Image Type:   MediaTek BootROM Loadable Image\n");
557 
558 	if (!strcmp((char *)ptr, NAND_BOOT_NAME))
559 		mtk_image_verify_nand_header(ptr, 1);
560 	else
561 		mtk_image_verify_gen_header(ptr, 1);
562 }
563 
564 static void put_brom_layout_header(struct brom_layout_header *hdr, int type)
565 {
566 	strncpy(hdr->name, BRLYT_NAME, sizeof(hdr->name));
567 	hdr->version = cpu_to_le32(1);
568 	hdr->magic = cpu_to_le32(BRLYT_MAGIC);
569 	hdr->type = cpu_to_le32(type);
570 }
571 
572 static void put_ghf_common_header(struct gfh_common_header *gfh, int size,
573 				  int type, int ver)
574 {
575 	memcpy(gfh->magic, GFH_HEADER_MAGIC, sizeof(gfh->magic));
576 	gfh->version = ver;
577 	gfh->size = cpu_to_le16(size);
578 	gfh->type = cpu_to_le16(type);
579 }
580 
581 static void put_ghf_header(struct gfh_header *gfh, int file_size,
582 			   int dev_hdr_size, int load_addr, int flash_type)
583 {
584 	memset(gfh, 0, sizeof(struct gfh_header));
585 
586 	/* GFH_FILE_INFO header */
587 	put_ghf_common_header(&gfh->file_info.gfh, sizeof(gfh->file_info),
588 			      GFH_TYPE_FILE_INFO, 1);
589 	strncpy(gfh->file_info.name, GFH_FILE_INFO_NAME,
590 		sizeof(gfh->file_info.name));
591 	gfh->file_info.unused = cpu_to_le32(1);
592 	gfh->file_info.file_type = cpu_to_le16(1);
593 	gfh->file_info.flash_type = flash_type;
594 	gfh->file_info.sig_type = GFH_SIG_TYPE_SHA256;
595 	gfh->file_info.load_addr = cpu_to_le32(load_addr - sizeof(*gfh));
596 	gfh->file_info.total_size = cpu_to_le32(file_size - dev_hdr_size);
597 	gfh->file_info.max_size = cpu_to_le32(file_size);
598 	gfh->file_info.hdr_size = sizeof(*gfh);
599 	gfh->file_info.sig_size = SHA256_SUM_LEN;
600 	gfh->file_info.jump_offset = sizeof(*gfh);
601 	gfh->file_info.processed = cpu_to_le32(1);
602 
603 	/* GFH_BL_INFO header */
604 	put_ghf_common_header(&gfh->bl_info.gfh, sizeof(gfh->bl_info),
605 			      GFH_TYPE_BL_INFO, 1);
606 	gfh->bl_info.attr = cpu_to_le32(1);
607 
608 	/* GFH_BROM_CFG header */
609 	put_ghf_common_header(&gfh->brom_cfg.gfh, sizeof(gfh->brom_cfg),
610 			      GFH_TYPE_BROM_CFG, 3);
611 	gfh->brom_cfg.cfg_bits = cpu_to_le32(
612 		GFH_BROM_CFG_USBDL_AUTO_DETECT_DIS |
613 		GFH_BROM_CFG_USBDL_BY_KCOL0_TIMEOUT_EN |
614 		GFH_BROM_CFG_USBDL_BY_FLAG_TIMEOUT_EN);
615 	gfh->brom_cfg.usbdl_by_kcol0_timeout_ms = cpu_to_le32(5000);
616 
617 	/* GFH_BL_SEC_KEY header */
618 	put_ghf_common_header(&gfh->bl_sec_key.gfh, sizeof(gfh->bl_sec_key),
619 			      GFH_TYPE_BL_SEC_KEY, 1);
620 
621 	/* GFH_ANTI_CLONE header */
622 	put_ghf_common_header(&gfh->anti_clone.gfh, sizeof(gfh->anti_clone),
623 			      GFH_TYPE_ANTI_CLONE, 1);
624 	gfh->anti_clone.ac_offset = cpu_to_le32(0x10);
625 	gfh->anti_clone.ac_len = cpu_to_le32(0x80);
626 
627 	/* GFH_BROM_SEC_CFG header */
628 	put_ghf_common_header(&gfh->brom_sec_cfg.gfh,
629 			      sizeof(gfh->brom_sec_cfg),
630 			      GFH_TYPE_BROM_SEC_CFG, 1);
631 	gfh->brom_sec_cfg.cfg_bits =
632 		cpu_to_le32(BROM_SEC_CFG_JTAG_EN | BROM_SEC_CFG_UART_EN);
633 }
634 
635 static void put_hash(uint8_t *buff, int size)
636 {
637 	sha256_context ctx;
638 
639 	sha256_starts(&ctx);
640 	sha256_update(&ctx, buff, size);
641 	sha256_finish(&ctx, buff + size);
642 }
643 
644 static void mtk_image_set_gen_header(void *ptr, off_t filesize,
645 				     uint32_t loadaddr)
646 {
647 	struct gen_device_header *hdr = (struct gen_device_header *)ptr;
648 	struct gfh_header *gfh;
649 	const char *bootname = NULL;
650 
651 	if (hdr_media == BRLYT_TYPE_NOR)
652 		bootname = SF_BOOT_NAME;
653 	else if (hdr_media == BRLYT_TYPE_EMMC)
654 		bootname = EMMC_BOOT_NAME;
655 	else if (hdr_media == BRLYT_TYPE_SDMMC)
656 		bootname = SDMMC_BOOT_NAME;
657 
658 	/* Generic device header */
659 	snprintf(hdr->boot.name, sizeof(hdr->boot.name), "%s", bootname);
660 	hdr->boot.version = cpu_to_le32(1);
661 	hdr->boot.size = cpu_to_le32(sizeof(hdr->boot));
662 
663 	/* BRLYT header */
664 	put_brom_layout_header(&hdr->brlyt, hdr_media);
665 	hdr->brlyt.header_size = cpu_to_le32(sizeof(struct gen_device_header));
666 	hdr->brlyt.total_size = cpu_to_le32(filesize);
667 	hdr->brlyt.header_size_2 = hdr->brlyt.header_size;
668 	hdr->brlyt.total_size_2 = hdr->brlyt.total_size;
669 
670 	/* GFH header */
671 	gfh = (struct gfh_header *)(ptr + sizeof(struct gen_device_header));
672 	put_ghf_header(gfh, filesize, sizeof(struct gen_device_header),
673 		       loadaddr, GFH_FLASH_TYPE_GEN);
674 
675 	/* Generate SHA256 hash */
676 	put_hash((uint8_t *)gfh,
677 		 filesize - sizeof(struct gen_device_header) - SHA256_SUM_LEN);
678 }
679 
680 static void mtk_image_set_nand_header(void *ptr, off_t filesize,
681 				      uint32_t loadaddr)
682 {
683 	union nand_boot_header *nh = (union nand_boot_header *)ptr;
684 	struct brom_layout_header *brlyt;
685 	struct gfh_header *gfh;
686 	uint32_t payload_pages;
687 	int i;
688 
689 	/* NAND device header, repeat 4 times */
690 	for (i = 0; i < 4; i++)
691 		memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header));
692 
693 	/* BRLYT header */
694 	payload_pages = (filesize + le16_to_cpu(hdr_nand->pagesize) - 1) /
695 			le16_to_cpu(hdr_nand->pagesize);
696 	brlyt = (struct brom_layout_header *)
697 		(ptr + le16_to_cpu(hdr_nand->pagesize));
698 	put_brom_layout_header(brlyt, hdr_media);
699 	brlyt->header_size = cpu_to_le32(2);
700 	brlyt->total_size = cpu_to_le32(payload_pages);
701 	brlyt->header_size_2 = brlyt->header_size;
702 	brlyt->total_size_2 = brlyt->total_size;
703 	brlyt->unused = cpu_to_le32(1);
704 
705 	/* GFH header */
706 	gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(hdr_nand->pagesize));
707 	put_ghf_header(gfh, filesize, 2 * le16_to_cpu(hdr_nand->pagesize),
708 		       loadaddr, GFH_FLASH_TYPE_NAND);
709 
710 	/* Generate SHA256 hash */
711 	put_hash((uint8_t *)gfh,
712 		 filesize - 2 * le16_to_cpu(hdr_nand->pagesize) - SHA256_SUM_LEN);
713 }
714 
715 static void mtk_image_set_header(void *ptr, struct stat *sbuf, int ifd,
716 				 struct image_tool_params *params)
717 {
718 	union lk_hdr *lk = (union lk_hdr *)ptr;
719 
720 	if (use_lk_hdr) {
721 		lk->magic = cpu_to_le32(LK_PART_MAGIC);
722 		lk->size = cpu_to_le32(sbuf->st_size - sizeof(union lk_hdr));
723 		lk->loadaddr = cpu_to_le32(params->addr);
724 		lk->mode = 0xffffffff; /* must be non-zero */
725 		memset(lk->name, 0, sizeof(lk->name));
726 		strncpy(lk->name, lk_name, sizeof(lk->name));
727 		return;
728 	}
729 
730 	if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
731 		mtk_image_set_nand_header(ptr, sbuf->st_size, params->addr);
732 	else
733 		mtk_image_set_gen_header(ptr, sbuf->st_size, params->addr);
734 }
735 
736 U_BOOT_IMAGE_TYPE(
737 	mtk_image,
738 	"MediaTek BootROM Loadable Image support",
739 	0,
740 	NULL,
741 	mtk_image_check_params,
742 	mtk_image_verify_header,
743 	mtk_image_print_header,
744 	mtk_image_set_header,
745 	NULL,
746 	mtk_image_check_image_types,
747 	NULL,
748 	mtk_image_vrec_header
749 );
750