Merge https://gitlab.denx.de/u-boot/custodians/u-boot-marvell
[oweals/u-boot.git] / tools / mtk_image.c
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 );