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