blob: bde1e5da4becf5c8f6b40d04c8da46245985d25b [file] [log] [blame]
developere1de5d42018-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;
Fabien Parent541f6d32020-10-16 19:52:37 +0200249static bool is_arm64_image;
developere1de5d42018-11-15 10:07:49 +0800250
251/* LK image name */
252static char lk_name[32] = "U-Boot";
253
254/* NAND header selected by user */
255static const union nand_boot_header *hdr_nand;
256
257/* GFH header + 2 * 4KB pages of NAND */
258static char hdr_tmp[sizeof(struct gfh_header) + 0x2000];
259
260static int mtk_image_check_image_types(uint8_t type)
261{
262 if (type == IH_TYPE_MTKIMAGE)
263 return EXIT_SUCCESS;
264 else
265 return EXIT_FAILURE;
266}
267
268static int mtk_brom_parse_imagename(const char *imagename)
269{
270#define is_blank_char(c) \
271 ((c) == '\t' || (c) == '\n' || (c) == '\r' || (c) == ' ')
272
273 char *buf = strdup(imagename), *key, *val, *end, *next;
274 int i;
275
276 /* User passed arguments from image name */
277 static const char *media = "";
278 static const char *nandinfo = "";
279 static const char *lk = "";
Fabien Parent541f6d32020-10-16 19:52:37 +0200280 static const char *arm64_param = "";
developere1de5d42018-11-15 10:07:49 +0800281
282 key = buf;
283 while (key) {
284 next = strchr(key, ';');
285 if (next)
286 *next = 0;
287
288 val = strchr(key, '=');
289 if (val) {
290 *val++ = 0;
291
292 /* Trim key */
293 while (is_blank_char(*key))
294 key++;
295
296 end = key + strlen(key) - 1;
297 while ((end >= key) && is_blank_char(*end))
298 end--;
299 end++;
300
301 if (is_blank_char(*end))
302 *end = 0;
303
304 /* Trim value */
305 while (is_blank_char(*val))
306 val++;
307
308 end = val + strlen(val) - 1;
309 while ((end >= val) && is_blank_char(*end))
310 end--;
311 end++;
312
313 if (is_blank_char(*end))
314 *end = 0;
315
316 /* record user passed arguments */
317 if (!strcmp(key, "media"))
318 media = val;
319
320 if (!strcmp(key, "nandinfo"))
321 nandinfo = val;
322
323 if (!strcmp(key, "lk"))
324 lk = val;
325
326 if (!strcmp(key, "lkname"))
Andy Shevchenkoe7722de2018-12-11 16:41:43 +0200327 snprintf(lk_name, sizeof(lk_name), "%s", val);
Fabien Parent541f6d32020-10-16 19:52:37 +0200328
329 if (!strcmp(key, "arm64"))
330 arm64_param = val;
developere1de5d42018-11-15 10:07:49 +0800331 }
332
333 if (next)
334 key = next + 1;
335 else
336 break;
337 }
338
339 /* if user specified LK image header, skip following checks */
340 if (lk && lk[0] == '1') {
341 use_lk_hdr = 1;
342 free(buf);
343 return 0;
344 }
345
346 /* parse media type */
347 for (i = 0; i < ARRAY_SIZE(brom_images); i++) {
348 if (!strcmp(brom_images[i].name, media)) {
349 hdr_media = brom_images[i].type;
350 break;
351 }
352 }
353
354 /* parse nand header type */
355 for (i = 0; i < ARRAY_SIZE(nand_headers); i++) {
356 if (!strcmp(nand_headers[i].name, nandinfo)) {
357 hdr_nand = nand_headers[i].data;
358 break;
359 }
360 }
361
Fabien Parent541f6d32020-10-16 19:52:37 +0200362 if (arm64_param && arm64_param[0] == '1')
363 is_arm64_image = true;
364
developere1de5d42018-11-15 10:07:49 +0800365 free(buf);
366
367 if (hdr_media == BRLYT_TYPE_INVALID) {
368 fprintf(stderr, "Error: media type is invalid or missing.\n");
369 fprintf(stderr, " Please specify -n \"media=<type>\"\n");
370 return -EINVAL;
371 }
372
373 if ((hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND) &&
374 !hdr_nand) {
375 fprintf(stderr, "Error: nand info is invalid or missing.\n");
376 fprintf(stderr, " Please specify -n \"media=%s;"
377 "nandinfo=<info>\"\n", media);
378 return -EINVAL;
379 }
380
381 return 0;
382}
383
384static int mtk_image_check_params(struct image_tool_params *params)
385{
386 if (!params->addr) {
387 fprintf(stderr, "Error: Load Address must be set.\n");
388 return -EINVAL;
389 }
390
391 if (!params->imagename) {
392 fprintf(stderr, "Error: Image Name must be set.\n");
393 return -EINVAL;
394 }
395
396 return mtk_brom_parse_imagename(params->imagename);
397}
398
399static int mtk_image_vrec_header(struct image_tool_params *params,
400 struct image_type_params *tparams)
401{
402 if (use_lk_hdr) {
403 tparams->header_size = sizeof(union lk_hdr);
404 tparams->hdr = &hdr_tmp;
405 memset(&hdr_tmp, 0xff, tparams->header_size);
406 return 0;
407 }
408
409 if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
410 tparams->header_size = 2 * le16_to_cpu(hdr_nand->pagesize);
411 else
412 tparams->header_size = sizeof(struct gen_device_header);
413
414 tparams->header_size += sizeof(struct gfh_header);
415 tparams->hdr = &hdr_tmp;
416
417 memset(&hdr_tmp, 0xff, tparams->header_size);
418
419 return SHA256_SUM_LEN;
420}
421
422static int mtk_image_verify_gen_header(const uint8_t *ptr, int print)
423{
424 union gen_boot_header *gbh = (union gen_boot_header *)ptr;
425 struct brom_layout_header *bh;
426 struct gfh_header *gfh;
427 const char *bootmedia;
428
429 if (!strcmp(gbh->name, SF_BOOT_NAME))
430 bootmedia = "Serial NOR";
431 else if (!strcmp(gbh->name, EMMC_BOOT_NAME))
432 bootmedia = "eMMC";
433 else if (!strcmp(gbh->name, SDMMC_BOOT_NAME))
434 bootmedia = "SD/MMC";
435 else
436 return -1;
437
438 if (print)
439 printf("Boot Media: %s\n", bootmedia);
440
441 if (le32_to_cpu(gbh->version) != 1 ||
442 le32_to_cpu(gbh->size) != sizeof(union gen_boot_header))
443 return -1;
444
445 bh = (struct brom_layout_header *)(ptr + le32_to_cpu(gbh->size));
446
447 if (strcmp(bh->name, BRLYT_NAME))
448 return -1;
449
450 if (le32_to_cpu(bh->magic) != BRLYT_MAGIC ||
451 (le32_to_cpu(bh->type) != BRLYT_TYPE_NOR &&
452 le32_to_cpu(bh->type) != BRLYT_TYPE_EMMC &&
453 le32_to_cpu(bh->type) != BRLYT_TYPE_SDMMC))
454 return -1;
455
456 gfh = (struct gfh_header *)(ptr + le32_to_cpu(bh->header_size));
457
458 if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
459 return -1;
460
461 if (le32_to_cpu(gfh->file_info.flash_type) != GFH_FLASH_TYPE_GEN)
462 return -1;
463
464 if (print)
465 printf("Load Address: %08x\n",
466 le32_to_cpu(gfh->file_info.load_addr) +
467 le32_to_cpu(gfh->file_info.jump_offset));
468
Fabien Parent541f6d32020-10-16 19:52:37 +0200469 if (print)
470 printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM");
471
developere1de5d42018-11-15 10:07:49 +0800472 return 0;
473}
474
475static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
476{
477 union nand_boot_header *nh = (union nand_boot_header *)ptr;
478 struct brom_layout_header *bh;
479 struct gfh_header *gfh;
480 const char *bootmedia;
481
482 if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh->version)) ||
483 strcmp(nh->id, NAND_BOOT_ID))
484 return -1;
485
486 bh = (struct brom_layout_header *)(ptr + le16_to_cpu(nh->pagesize));
487
488 if (strcmp(bh->name, BRLYT_NAME))
489 return -1;
490
491 if (le32_to_cpu(bh->magic) != BRLYT_MAGIC) {
492 return -1;
493 } else {
494 if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND)
495 bootmedia = "Parallel NAND";
496 else if (le32_to_cpu(bh->type) == BRLYT_TYPE_SNAND)
497 bootmedia = "Serial NAND";
498 else
499 return -1;
500 }
501
502 if (print) {
503 printf("Boot Media: %s\n", bootmedia);
504
505 if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND) {
506 uint64_t capacity =
507 (uint64_t)le16_to_cpu(nh->numblocks) *
508 (uint64_t)le16_to_cpu(nh->pages_of_block) *
509 (uint64_t)le16_to_cpu(nh->pagesize) * 8;
510 printf("Capacity: %dGb\n",
511 (uint32_t)(capacity >> 30));
512 }
513
514 if (le16_to_cpu(nh->pagesize) >= 1024)
515 printf("Page Size: %dKB\n",
516 le16_to_cpu(nh->pagesize) >> 10);
517 else
518 printf("Page Size: %dB\n",
519 le16_to_cpu(nh->pagesize));
520
521 printf("Spare Size: %dB\n", le16_to_cpu(nh->oobsize));
522 }
523
524 gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(nh->pagesize));
525
526 if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
527 return -1;
528
529 if (le32_to_cpu(gfh->file_info.flash_type) != GFH_FLASH_TYPE_NAND)
530 return -1;
531
532 if (print)
533 printf("Load Address: %08x\n",
534 le32_to_cpu(gfh->file_info.load_addr) +
535 le32_to_cpu(gfh->file_info.jump_offset));
536
Fabien Parent541f6d32020-10-16 19:52:37 +0200537 if (print)
538 printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM");
539
developere1de5d42018-11-15 10:07:49 +0800540 return 0;
541}
542
543static int mtk_image_verify_header(unsigned char *ptr, int image_size,
544 struct image_tool_params *params)
545{
546 union lk_hdr *lk = (union lk_hdr *)ptr;
547
548 /* nothing to verify for LK image header */
549 if (le32_to_cpu(lk->magic) == LK_PART_MAGIC)
550 return 0;
551
552 if (!strcmp((char *)ptr, NAND_BOOT_NAME))
553 return mtk_image_verify_nand_header(ptr, 0);
554 else
555 return mtk_image_verify_gen_header(ptr, 0);
556
557 return -1;
558}
559
560static void mtk_image_print_header(const void *ptr)
561{
562 union lk_hdr *lk = (union lk_hdr *)ptr;
563
564 if (le32_to_cpu(lk->magic) == LK_PART_MAGIC) {
565 printf("Image Type: MediaTek LK Image\n");
566 printf("Load Address: %08x\n", le32_to_cpu(lk->loadaddr));
567 return;
568 }
569
570 printf("Image Type: MediaTek BootROM Loadable Image\n");
571
572 if (!strcmp((char *)ptr, NAND_BOOT_NAME))
573 mtk_image_verify_nand_header(ptr, 1);
574 else
575 mtk_image_verify_gen_header(ptr, 1);
576}
577
578static void put_brom_layout_header(struct brom_layout_header *hdr, int type)
579{
580 strncpy(hdr->name, BRLYT_NAME, sizeof(hdr->name));
581 hdr->version = cpu_to_le32(1);
582 hdr->magic = cpu_to_le32(BRLYT_MAGIC);
583 hdr->type = cpu_to_le32(type);
584}
585
586static void put_ghf_common_header(struct gfh_common_header *gfh, int size,
587 int type, int ver)
588{
589 memcpy(gfh->magic, GFH_HEADER_MAGIC, sizeof(gfh->magic));
590 gfh->version = ver;
591 gfh->size = cpu_to_le16(size);
592 gfh->type = cpu_to_le16(type);
593}
594
595static void put_ghf_header(struct gfh_header *gfh, int file_size,
596 int dev_hdr_size, int load_addr, int flash_type)
597{
Fabien Parent541f6d32020-10-16 19:52:37 +0200598 uint32_t cfg_bits;
599
developere1de5d42018-11-15 10:07:49 +0800600 memset(gfh, 0, sizeof(struct gfh_header));
601
602 /* GFH_FILE_INFO header */
603 put_ghf_common_header(&gfh->file_info.gfh, sizeof(gfh->file_info),
604 GFH_TYPE_FILE_INFO, 1);
605 strncpy(gfh->file_info.name, GFH_FILE_INFO_NAME,
606 sizeof(gfh->file_info.name));
607 gfh->file_info.unused = cpu_to_le32(1);
608 gfh->file_info.file_type = cpu_to_le16(1);
609 gfh->file_info.flash_type = flash_type;
610 gfh->file_info.sig_type = GFH_SIG_TYPE_SHA256;
611 gfh->file_info.load_addr = cpu_to_le32(load_addr - sizeof(*gfh));
612 gfh->file_info.total_size = cpu_to_le32(file_size - dev_hdr_size);
613 gfh->file_info.max_size = cpu_to_le32(file_size);
614 gfh->file_info.hdr_size = sizeof(*gfh);
615 gfh->file_info.sig_size = SHA256_SUM_LEN;
616 gfh->file_info.jump_offset = sizeof(*gfh);
617 gfh->file_info.processed = cpu_to_le32(1);
618
619 /* GFH_BL_INFO header */
620 put_ghf_common_header(&gfh->bl_info.gfh, sizeof(gfh->bl_info),
621 GFH_TYPE_BL_INFO, 1);
622 gfh->bl_info.attr = cpu_to_le32(1);
623
624 /* GFH_BROM_CFG header */
625 put_ghf_common_header(&gfh->brom_cfg.gfh, sizeof(gfh->brom_cfg),
626 GFH_TYPE_BROM_CFG, 3);
Fabien Parent541f6d32020-10-16 19:52:37 +0200627 cfg_bits = GFH_BROM_CFG_USBDL_AUTO_DETECT_DIS |
628 GFH_BROM_CFG_USBDL_BY_KCOL0_TIMEOUT_EN |
629 GFH_BROM_CFG_USBDL_BY_FLAG_TIMEOUT_EN;
developere1de5d42018-11-15 10:07:49 +0800630 gfh->brom_cfg.usbdl_by_kcol0_timeout_ms = cpu_to_le32(5000);
Fabien Parent541f6d32020-10-16 19:52:37 +0200631 if (is_arm64_image) {
632 gfh->brom_cfg.jump_bl_arm64 = GFH_BROM_CFG_JUMP_BL_ARM64;
633 cfg_bits |= GFH_BROM_CFG_JUMP_BL_ARM64_EN;
634 }
635 gfh->brom_cfg.cfg_bits = cpu_to_le32(cfg_bits);
developere1de5d42018-11-15 10:07:49 +0800636
637 /* GFH_BL_SEC_KEY header */
638 put_ghf_common_header(&gfh->bl_sec_key.gfh, sizeof(gfh->bl_sec_key),
639 GFH_TYPE_BL_SEC_KEY, 1);
640
641 /* GFH_ANTI_CLONE header */
642 put_ghf_common_header(&gfh->anti_clone.gfh, sizeof(gfh->anti_clone),
643 GFH_TYPE_ANTI_CLONE, 1);
644 gfh->anti_clone.ac_offset = cpu_to_le32(0x10);
645 gfh->anti_clone.ac_len = cpu_to_le32(0x80);
646
647 /* GFH_BROM_SEC_CFG header */
648 put_ghf_common_header(&gfh->brom_sec_cfg.gfh,
649 sizeof(gfh->brom_sec_cfg),
650 GFH_TYPE_BROM_SEC_CFG, 1);
651 gfh->brom_sec_cfg.cfg_bits =
652 cpu_to_le32(BROM_SEC_CFG_JTAG_EN | BROM_SEC_CFG_UART_EN);
653}
654
655static void put_hash(uint8_t *buff, int size)
656{
657 sha256_context ctx;
658
659 sha256_starts(&ctx);
660 sha256_update(&ctx, buff, size);
661 sha256_finish(&ctx, buff + size);
662}
663
664static void mtk_image_set_gen_header(void *ptr, off_t filesize,
665 uint32_t loadaddr)
666{
667 struct gen_device_header *hdr = (struct gen_device_header *)ptr;
668 struct gfh_header *gfh;
669 const char *bootname = NULL;
670
671 if (hdr_media == BRLYT_TYPE_NOR)
672 bootname = SF_BOOT_NAME;
673 else if (hdr_media == BRLYT_TYPE_EMMC)
674 bootname = EMMC_BOOT_NAME;
675 else if (hdr_media == BRLYT_TYPE_SDMMC)
676 bootname = SDMMC_BOOT_NAME;
677
678 /* Generic device header */
Andy Shevchenkoe7722de2018-12-11 16:41:43 +0200679 snprintf(hdr->boot.name, sizeof(hdr->boot.name), "%s", bootname);
developere1de5d42018-11-15 10:07:49 +0800680 hdr->boot.version = cpu_to_le32(1);
681 hdr->boot.size = cpu_to_le32(sizeof(hdr->boot));
682
683 /* BRLYT header */
684 put_brom_layout_header(&hdr->brlyt, hdr_media);
685 hdr->brlyt.header_size = cpu_to_le32(sizeof(struct gen_device_header));
686 hdr->brlyt.total_size = cpu_to_le32(filesize);
687 hdr->brlyt.header_size_2 = hdr->brlyt.header_size;
688 hdr->brlyt.total_size_2 = hdr->brlyt.total_size;
689
690 /* GFH header */
691 gfh = (struct gfh_header *)(ptr + sizeof(struct gen_device_header));
692 put_ghf_header(gfh, filesize, sizeof(struct gen_device_header),
693 loadaddr, GFH_FLASH_TYPE_GEN);
694
695 /* Generate SHA256 hash */
696 put_hash((uint8_t *)gfh,
697 filesize - sizeof(struct gen_device_header) - SHA256_SUM_LEN);
698}
699
700static void mtk_image_set_nand_header(void *ptr, off_t filesize,
701 uint32_t loadaddr)
702{
703 union nand_boot_header *nh = (union nand_boot_header *)ptr;
704 struct brom_layout_header *brlyt;
705 struct gfh_header *gfh;
706 uint32_t payload_pages;
707 int i;
708
709 /* NAND device header, repeat 4 times */
710 for (i = 0; i < 4; i++)
711 memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header));
712
713 /* BRLYT header */
714 payload_pages = (filesize + le16_to_cpu(hdr_nand->pagesize) - 1) /
715 le16_to_cpu(hdr_nand->pagesize);
716 brlyt = (struct brom_layout_header *)
717 (ptr + le16_to_cpu(hdr_nand->pagesize));
718 put_brom_layout_header(brlyt, hdr_media);
719 brlyt->header_size = cpu_to_le32(2);
720 brlyt->total_size = cpu_to_le32(payload_pages);
721 brlyt->header_size_2 = brlyt->header_size;
722 brlyt->total_size_2 = brlyt->total_size;
723 brlyt->unused = cpu_to_le32(1);
724
725 /* GFH header */
726 gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(hdr_nand->pagesize));
727 put_ghf_header(gfh, filesize, 2 * le16_to_cpu(hdr_nand->pagesize),
728 loadaddr, GFH_FLASH_TYPE_NAND);
729
730 /* Generate SHA256 hash */
731 put_hash((uint8_t *)gfh,
732 filesize - 2 * le16_to_cpu(hdr_nand->pagesize) - SHA256_SUM_LEN);
733}
734
735static void mtk_image_set_header(void *ptr, struct stat *sbuf, int ifd,
736 struct image_tool_params *params)
737{
738 union lk_hdr *lk = (union lk_hdr *)ptr;
739
740 if (use_lk_hdr) {
741 lk->magic = cpu_to_le32(LK_PART_MAGIC);
742 lk->size = cpu_to_le32(sbuf->st_size - sizeof(union lk_hdr));
743 lk->loadaddr = cpu_to_le32(params->addr);
744 lk->mode = 0xffffffff; /* must be non-zero */
745 memset(lk->name, 0, sizeof(lk->name));
746 strncpy(lk->name, lk_name, sizeof(lk->name));
747 return;
748 }
749
750 if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
751 mtk_image_set_nand_header(ptr, sbuf->st_size, params->addr);
752 else
753 mtk_image_set_gen_header(ptr, sbuf->st_size, params->addr);
754}
755
756U_BOOT_IMAGE_TYPE(
757 mtk_image,
758 "MediaTek BootROM Loadable Image support",
759 0,
760 NULL,
761 mtk_image_check_params,
762 mtk_image_verify_header,
763 mtk_image_print_header,
764 mtk_image_set_header,
765 NULL,
766 mtk_image_check_image_types,
767 NULL,
768 mtk_image_vrec_header
769);