tools: mtk_image: add support for booting ARM64 images
[platform/kernel/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 static bool is_arm64_image;
250
251 /* LK image name */
252 static char lk_name[32] = "U-Boot";
253
254 /* NAND header selected by user */
255 static const union nand_boot_header *hdr_nand;
256
257 /* GFH header + 2 * 4KB pages of NAND */
258 static char hdr_tmp[sizeof(struct gfh_header) + 0x2000];
259
260 static 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
268 static 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 = "";
280         static const char *arm64_param = "";
281
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"))
327                                 snprintf(lk_name, sizeof(lk_name), "%s", val);
328
329                         if (!strcmp(key, "arm64"))
330                                 arm64_param = val;
331                 }
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
362         if (arm64_param && arm64_param[0] == '1')
363                 is_arm64_image = true;
364
365         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
384 static 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
399 static 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
422 static 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
469         if (print)
470                 printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM");
471
472         return 0;
473 }
474
475 static 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
537         if (print)
538                 printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM");
539
540         return 0;
541 }
542
543 static 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
560 static 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
578 static 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
586 static 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
595 static void put_ghf_header(struct gfh_header *gfh, int file_size,
596                            int dev_hdr_size, int load_addr, int flash_type)
597 {
598         uint32_t cfg_bits;
599
600         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);
627         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;
630         gfh->brom_cfg.usbdl_by_kcol0_timeout_ms = cpu_to_le32(5000);
631         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);
636
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
655 static 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
664 static 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 */
679         snprintf(hdr->boot.name, sizeof(hdr->boot.name), "%s", bootname);
680         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
700 static 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
735 static 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
756 U_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 );