blob: 418c5fd54b472e3b21549fbddb93f1131cbb7959 [file] [log] [blame]
Ryder Lee3b975a12018-11-15 10:07:49 +08001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Generate MediaTek BootROM header for SPL/U-Boot images
4 *
5 * Copyright (C) 2018 MediaTek Inc.
6 * Author: Weijie Gao <weijie.gao@mediatek.com>
7 */
8
9#include <image.h>
10#include <u-boot/sha256.h>
11#include "imagetool.h"
12#include "mtk_image.h"
13
14/* NAND header for SPI-NAND with 2KB page + 64B spare */
15static const union nand_boot_header snand_hdr_2k_64_data = {
16 .data = {
17 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
18 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
19 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
20 0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x40, 0x00,
21 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
22 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
23 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
24 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
25 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
26 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
27 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29 0x00, 0x00, 0x00, 0x00, 0x7B, 0xC4, 0x17, 0x9D,
30 0xCA, 0x42, 0x90, 0xD0, 0x98, 0xD0, 0xE0, 0xF7,
31 0xDB, 0xCD, 0x16, 0xF6, 0x03, 0x73, 0xD2, 0xB8,
32 0x93, 0xB2, 0x56, 0x5A, 0x84, 0x6E, 0x00, 0x00
33 }
34};
35
36/* NAND header for SPI-NAND with 2KB page + 120B/128B spare */
37static const union nand_boot_header snand_hdr_2k_128_data = {
38 .data = {
39 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
40 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
41 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
42 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
43 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
44 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51 0x00, 0x00, 0x00, 0x00, 0x90, 0x28, 0xED, 0x13,
52 0x7F, 0x12, 0x22, 0xCD, 0x3D, 0x06, 0xF1, 0xB3,
53 0x6F, 0x2E, 0xD9, 0xA0, 0x9D, 0x7A, 0xBD, 0xD7,
54 0xB3, 0x28, 0x3C, 0x13, 0xDB, 0x4E, 0x00, 0x00
55 }
56};
57
58/* NAND header for SPI-NAND with 4KB page + 256B spare */
59static const union nand_boot_header snand_hdr_4k_256_data = {
60 .data = {
61 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
62 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
63 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
64 0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0xE0, 0x00,
65 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x00, 0x00, 0x00, 0x00, 0x47, 0xED, 0x0E, 0xC3,
74 0x83, 0xBF, 0x41, 0xD2, 0x85, 0x21, 0x97, 0x57,
75 0xC4, 0x2E, 0x6B, 0x7A, 0x40, 0xE0, 0xCF, 0x8F,
76 0x37, 0xBD, 0x17, 0xB6, 0xC7, 0xFE, 0x00, 0x00
77 }
78};
79
80/* NAND header for Parallel NAND 1Gb with 2KB page + 64B spare */
81static const union nand_boot_header nand_hdr_1gb_2k_64_data = {
82 .data = {
83 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
84 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
85 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
86 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
87 0x40, 0x00, 0x00, 0x04, 0x0B, 0x00, 0x11, 0x00,
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
94 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x1C, 0x12,
96 0x8F, 0xFD, 0xF8, 0x32, 0x6F, 0x6D, 0xCF, 0x6C,
97 0xDA, 0x21, 0x70, 0x8C, 0xDA, 0x0A, 0x22, 0x82,
98 0xAA, 0x59, 0xFA, 0x7C, 0x42, 0x2D, 0x00, 0x00
99 }
100};
101
102/* NAND header for Parallel NAND 2Gb with 2KB page + 64B spare */
103static const union nand_boot_header nand_hdr_2gb_2k_64_data = {
104 .data = {
105 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
106 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
107 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
108 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
109 0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
112 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117 0x00, 0x00, 0x00, 0x00, 0x20, 0x9C, 0x3D, 0x2D,
118 0x7B, 0x68, 0x63, 0x52, 0x2E, 0x04, 0x63, 0xF1,
119 0x35, 0x4E, 0x44, 0x3E, 0xF8, 0xAC, 0x9B, 0x95,
120 0xAB, 0xFE, 0xE4, 0xE1, 0xD5, 0xF9, 0x00, 0x00
121 }
122};
123
124/* NAND header for Parallel NAND 4Gb with 2KB page + 64B spare */
125static const union nand_boot_header nand_hdr_4gb_2k_64_data = {
126 .data = {
127 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
128 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
129 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
130 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
131 0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
139 0x00, 0x00, 0x00, 0x00, 0xE3, 0x0F, 0x86, 0x32,
140 0x68, 0x05, 0xD9, 0xC8, 0x13, 0xDF, 0xC5, 0x0B,
141 0x35, 0x3A, 0x68, 0xA5, 0x3C, 0x0C, 0x73, 0x87,
142 0x63, 0xB0, 0xBE, 0xCC, 0x84, 0x47, 0x00, 0x00
143 }
144};
145
146/* NAND header for Parallel NAND 2Gb with 2KB page + 128B spare */
147static const union nand_boot_header nand_hdr_2gb_2k_128_data = {
148 .data = {
149 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
150 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
151 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
152 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
153 0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161 0x00, 0x00, 0x00, 0x00, 0x01, 0xA5, 0xE9, 0x5A,
162 0xDF, 0x58, 0x62, 0x41, 0xD6, 0x26, 0x77, 0xBC,
163 0x76, 0x1F, 0x27, 0x4E, 0x4F, 0x6C, 0xC3, 0xF0,
164 0x36, 0xDE, 0xD9, 0xB3, 0xFF, 0x93, 0x00, 0x00
165 }
166};
167
168/* NAND header for Parallel NAND 4Gb with 2KB page + 128B spare */
169static const union nand_boot_header nand_hdr_4gb_2k_128_data = {
170 .data = {
171 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
172 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
173 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
174 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
175 0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
176 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
182 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
183 0x00, 0x00, 0x00, 0x00, 0xC2, 0x36, 0x52, 0x45,
184 0xCC, 0x35, 0xD8, 0xDB, 0xEB, 0xFD, 0xD1, 0x46,
185 0x76, 0x6B, 0x0B, 0xD5, 0x8B, 0xCC, 0x2B, 0xE2,
186 0xFE, 0x90, 0x83, 0x9E, 0xAE, 0x2D, 0x00, 0x00
187 }
188};
189
190static const struct nand_header_type {
191 const char *name;
192 const union nand_boot_header *data;
193} nand_headers[] = {
194 {
195 .name = "2k+64",
196 .data = &snand_hdr_2k_64_data
197 }, {
198 .name = "2k+120",
199 .data = &snand_hdr_2k_128_data
200 }, {
201 .name = "2k+128",
202 .data = &snand_hdr_2k_128_data
203 }, {
204 .name = "4k+256",
205 .data = &snand_hdr_4k_256_data
206 }, {
207 .name = "1g:2k+64",
208 .data = &nand_hdr_1gb_2k_64_data
209 }, {
210 .name = "2g:2k+64",
211 .data = &nand_hdr_2gb_2k_64_data
212 }, {
213 .name = "4g:2k+64",
214 .data = &nand_hdr_4gb_2k_64_data
215 }, {
216 .name = "2g:2k+128",
217 .data = &nand_hdr_2gb_2k_128_data
218 }, {
219 .name = "4g:2k+128",
220 .data = &nand_hdr_4gb_2k_128_data
221 }
222};
223
224static const struct brom_img_type {
225 const char *name;
226 enum brlyt_img_type type;
227} brom_images[] = {
228 {
229 .name = "nand",
230 .type = BRLYT_TYPE_NAND
231 }, {
232 .name = "emmc",
233 .type = BRLYT_TYPE_EMMC
234 }, {
235 .name = "nor",
236 .type = BRLYT_TYPE_NOR
237 }, {
238 .name = "sdmmc",
239 .type = BRLYT_TYPE_SDMMC
240 }, {
241 .name = "snand",
242 .type = BRLYT_TYPE_SNAND
243 }
244};
245
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800246/* Indicates whether we're generating or verifying */
247static bool img_gen;
248static uint32_t img_size;
249
Ryder Lee3b975a12018-11-15 10:07:49 +0800250/* Image type selected by user */
251static enum brlyt_img_type hdr_media;
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800252static uint32_t hdr_offset;
Ryder Lee3b975a12018-11-15 10:07:49 +0800253static int use_lk_hdr;
Fabien Parent44165e42020-10-16 19:52:37 +0200254static bool is_arm64_image;
Ryder Lee3b975a12018-11-15 10:07:49 +0800255
256/* LK image name */
257static char lk_name[32] = "U-Boot";
258
259/* NAND header selected by user */
260static const union nand_boot_header *hdr_nand;
261
262/* GFH header + 2 * 4KB pages of NAND */
263static char hdr_tmp[sizeof(struct gfh_header) + 0x2000];
264
265static 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
273static 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 = "";
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800283 static const char *hdr_offs = "";
Ryder Lee3b975a12018-11-15 10:07:49 +0800284 static const char *nandinfo = "";
285 static const char *lk = "";
Fabien Parent44165e42020-10-16 19:52:37 +0200286 static const char *arm64_param = "";
Ryder Lee3b975a12018-11-15 10:07:49 +0800287
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
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800326 if (!strcmp(key, "hdroffset"))
327 hdr_offs = val;
328
Ryder Lee3b975a12018-11-15 10:07:49 +0800329 if (!strcmp(key, "nandinfo"))
330 nandinfo = val;
331
332 if (!strcmp(key, "lk"))
333 lk = val;
334
335 if (!strcmp(key, "lkname"))
Andy Shevchenko74473ed2018-12-11 16:41:43 +0200336 snprintf(lk_name, sizeof(lk_name), "%s", val);
Fabien Parent44165e42020-10-16 19:52:37 +0200337
338 if (!strcmp(key, "arm64"))
339 arm64_param = val;
Ryder Lee3b975a12018-11-15 10:07:49 +0800340 }
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
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800371 /* parse device header offset */
372 if (hdr_offs && hdr_offs[0])
373 hdr_offset = strtoul(hdr_offs, NULL, 0);
374
Fabien Parent44165e42020-10-16 19:52:37 +0200375 if (arm64_param && arm64_param[0] == '1')
376 is_arm64_image = true;
377
Ryder Lee3b975a12018-11-15 10:07:49 +0800378 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
397static 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
412static 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
435static int mtk_image_verify_gen_header(const uint8_t *ptr, int print)
436{
437 union gen_boot_header *gbh = (union gen_boot_header *)ptr;
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800438 uint32_t gfh_offset, total_size, devh_size;
Ryder Lee3b975a12018-11-15 10:07:49 +0800439 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
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800470 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);
Ryder Lee3b975a12018-11-15 10:07:49 +0800496
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
Fabien Parent44165e42020-10-16 19:52:37 +0200508 if (print)
509 printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM");
510
Ryder Lee3b975a12018-11-15 10:07:49 +0800511 return 0;
512}
513
514static 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
Fabien Parent44165e42020-10-16 19:52:37 +0200576 if (print)
577 printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM");
578
Ryder Lee3b975a12018-11-15 10:07:49 +0800579 return 0;
580}
581
582static 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
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800591 img_size = image_size;
592
Ryder Lee3b975a12018-11-15 10:07:49 +0800593 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
601static 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
619static 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
627static 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
636static void put_ghf_header(struct gfh_header *gfh, int file_size,
637 int dev_hdr_size, int load_addr, int flash_type)
638{
Fabien Parent44165e42020-10-16 19:52:37 +0200639 uint32_t cfg_bits;
640
Ryder Lee3b975a12018-11-15 10:07:49 +0800641 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);
Fabien Parent44165e42020-10-16 19:52:37 +0200668 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;
Ryder Lee3b975a12018-11-15 10:07:49 +0800671 gfh->brom_cfg.usbdl_by_kcol0_timeout_ms = cpu_to_le32(5000);
Fabien Parent44165e42020-10-16 19:52:37 +0200672 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);
Ryder Lee3b975a12018-11-15 10:07:49 +0800677
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
696static 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
705static 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 */
Andy Shevchenko74473ed2018-12-11 16:41:43 +0200720 snprintf(hdr->boot.name, sizeof(hdr->boot.name), "%s", bootname);
Ryder Lee3b975a12018-11-15 10:07:49 +0800721 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);
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800726 hdr->brlyt.header_size = cpu_to_le32(hdr_offset + sizeof(*hdr));
727 hdr->brlyt.total_size = cpu_to_le32(hdr_offset + filesize);
Ryder Lee3b975a12018-11-15 10:07:49 +0800728 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
741static 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
776static 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
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800791 img_gen = true;
792 img_size = sbuf->st_size;
793
Ryder Lee3b975a12018-11-15 10:07:49 +0800794 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
800U_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);