blob: 2706d2de32ae2cf65a066927639f25ddd1f32c40 [file] [log] [blame]
Ryder Lee3b975a12018-11-15 10:07:49 +08001// 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 */
15static 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 */
37static 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 */
59static 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 */
81static 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 */
103static 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 */
125static 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 */
147static 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 */
169static 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
190static 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
224static 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 */
247static enum brlyt_img_type hdr_media;
248static int use_lk_hdr;
249
250/* LK image name */
251static char lk_name[32] = "U-Boot";
252
253/* NAND header selected by user */
254static const union nand_boot_header *hdr_nand;
255
256/* GFH header + 2 * 4KB pages of NAND */
257static char hdr_tmp[sizeof(struct gfh_header) + 0x2000];
258
259static 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
267static 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 strncpy(lk_name, val, sizeof(lk_name));
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
376static 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
391static 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
414static 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
464static 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
529static 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
546static 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
564static 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
572static 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
581static 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
635static 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
644static 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 strncpy(hdr->boot.name, bootname, sizeof(hdr->boot.name));
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
680static 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
715static 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
736U_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);