blob: dcd6525f321fe3fcb7d929a98177f439b5111d62 [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
Weijie Gaoc561d142022-05-20 11:24:10 +08009#include <time.h>
Ryder Lee3b975a12018-11-15 10:07:49 +080010#include <image.h>
Weijie Gaoc561d142022-05-20 11:24:10 +080011#include <u-boot/crc.h>
Ryder Lee3b975a12018-11-15 10:07:49 +080012#include <u-boot/sha256.h>
13#include "imagetool.h"
14#include "mtk_image.h"
15
16/* NAND header for SPI-NAND with 2KB page + 64B spare */
17static const union nand_boot_header snand_hdr_2k_64_data = {
18 .data = {
19 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
20 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
21 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
22 0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x40, 0x00,
23 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 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, 0x00, 0x00, 0x00, 0x00,
30 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31 0x00, 0x00, 0x00, 0x00, 0x7B, 0xC4, 0x17, 0x9D,
32 0xCA, 0x42, 0x90, 0xD0, 0x98, 0xD0, 0xE0, 0xF7,
33 0xDB, 0xCD, 0x16, 0xF6, 0x03, 0x73, 0xD2, 0xB8,
34 0x93, 0xB2, 0x56, 0x5A, 0x84, 0x6E, 0x00, 0x00
35 }
36};
37
38/* NAND header for SPI-NAND with 2KB page + 120B/128B spare */
39static const union nand_boot_header snand_hdr_2k_128_data = {
40 .data = {
41 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
42 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
43 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
44 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
45 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 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, 0x00, 0x00, 0x00, 0x00,
52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
53 0x00, 0x00, 0x00, 0x00, 0x90, 0x28, 0xED, 0x13,
54 0x7F, 0x12, 0x22, 0xCD, 0x3D, 0x06, 0xF1, 0xB3,
55 0x6F, 0x2E, 0xD9, 0xA0, 0x9D, 0x7A, 0xBD, 0xD7,
56 0xB3, 0x28, 0x3C, 0x13, 0xDB, 0x4E, 0x00, 0x00
57 }
58};
59
60/* NAND header for SPI-NAND with 4KB page + 256B spare */
61static const union nand_boot_header snand_hdr_4k_256_data = {
62 .data = {
63 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
64 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
65 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
66 0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0xE0, 0x00,
67 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 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, 0x00, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x47, 0xED, 0x0E, 0xC3,
76 0x83, 0xBF, 0x41, 0xD2, 0x85, 0x21, 0x97, 0x57,
77 0xC4, 0x2E, 0x6B, 0x7A, 0x40, 0xE0, 0xCF, 0x8F,
78 0x37, 0xBD, 0x17, 0xB6, 0xC7, 0xFE, 0x00, 0x00
79 }
80};
81
82/* NAND header for Parallel NAND 1Gb with 2KB page + 64B spare */
83static const union nand_boot_header nand_hdr_1gb_2k_64_data = {
84 .data = {
85 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
86 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
87 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
88 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
89 0x40, 0x00, 0x00, 0x04, 0x0B, 0x00, 0x11, 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, 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x1C, 0x12,
98 0x8F, 0xFD, 0xF8, 0x32, 0x6F, 0x6D, 0xCF, 0x6C,
99 0xDA, 0x21, 0x70, 0x8C, 0xDA, 0x0A, 0x22, 0x82,
100 0xAA, 0x59, 0xFA, 0x7C, 0x42, 0x2D, 0x00, 0x00
101 }
102};
103
104/* NAND header for Parallel NAND 2Gb with 2KB page + 64B spare */
105static const union nand_boot_header nand_hdr_2gb_2k_64_data = {
106 .data = {
107 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
108 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
109 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
110 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
111 0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 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, 0x00, 0x00, 0x00, 0x00,
118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00, 0x20, 0x9C, 0x3D, 0x2D,
120 0x7B, 0x68, 0x63, 0x52, 0x2E, 0x04, 0x63, 0xF1,
121 0x35, 0x4E, 0x44, 0x3E, 0xF8, 0xAC, 0x9B, 0x95,
122 0xAB, 0xFE, 0xE4, 0xE1, 0xD5, 0xF9, 0x00, 0x00
123 }
124};
125
126/* NAND header for Parallel NAND 4Gb with 2KB page + 64B spare */
127static const union nand_boot_header nand_hdr_4gb_2k_64_data = {
128 .data = {
129 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
130 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
131 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
132 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
133 0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 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, 0x00, 0x00, 0x00, 0x00,
140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141 0x00, 0x00, 0x00, 0x00, 0xE3, 0x0F, 0x86, 0x32,
142 0x68, 0x05, 0xD9, 0xC8, 0x13, 0xDF, 0xC5, 0x0B,
143 0x35, 0x3A, 0x68, 0xA5, 0x3C, 0x0C, 0x73, 0x87,
144 0x63, 0xB0, 0xBE, 0xCC, 0x84, 0x47, 0x00, 0x00
145 }
146};
147
148/* NAND header for Parallel NAND 2Gb with 2KB page + 128B spare */
149static const union nand_boot_header nand_hdr_2gb_2k_128_data = {
150 .data = {
151 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
152 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
153 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
154 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
155 0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 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, 0x00, 0x00, 0x00, 0x00,
162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163 0x00, 0x00, 0x00, 0x00, 0x01, 0xA5, 0xE9, 0x5A,
164 0xDF, 0x58, 0x62, 0x41, 0xD6, 0x26, 0x77, 0xBC,
165 0x76, 0x1F, 0x27, 0x4E, 0x4F, 0x6C, 0xC3, 0xF0,
166 0x36, 0xDE, 0xD9, 0xB3, 0xFF, 0x93, 0x00, 0x00
167 }
168};
169
170/* NAND header for Parallel NAND 4Gb with 2KB page + 128B spare */
171static const union nand_boot_header nand_hdr_4gb_2k_128_data = {
172 .data = {
173 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
174 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
175 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
176 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
177 0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 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, 0x00, 0x00, 0x00, 0x00,
184 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
185 0x00, 0x00, 0x00, 0x00, 0xC2, 0x36, 0x52, 0x45,
186 0xCC, 0x35, 0xD8, 0xDB, 0xEB, 0xFD, 0xD1, 0x46,
187 0x76, 0x6B, 0x0B, 0xD5, 0x8B, 0xCC, 0x2B, 0xE2,
188 0xFE, 0x90, 0x83, 0x9E, 0xAE, 0x2D, 0x00, 0x00
189 }
190};
191
192static const struct nand_header_type {
193 const char *name;
194 const union nand_boot_header *data;
195} nand_headers[] = {
196 {
197 .name = "2k+64",
198 .data = &snand_hdr_2k_64_data
199 }, {
200 .name = "2k+120",
201 .data = &snand_hdr_2k_128_data
202 }, {
203 .name = "2k+128",
204 .data = &snand_hdr_2k_128_data
205 }, {
206 .name = "4k+256",
207 .data = &snand_hdr_4k_256_data
208 }, {
209 .name = "1g:2k+64",
210 .data = &nand_hdr_1gb_2k_64_data
211 }, {
212 .name = "2g:2k+64",
213 .data = &nand_hdr_2gb_2k_64_data
214 }, {
215 .name = "4g:2k+64",
216 .data = &nand_hdr_4gb_2k_64_data
217 }, {
218 .name = "2g:2k+128",
219 .data = &nand_hdr_2gb_2k_128_data
220 }, {
221 .name = "4g:2k+128",
222 .data = &nand_hdr_4gb_2k_128_data
223 }
224};
225
226static const struct brom_img_type {
227 const char *name;
228 enum brlyt_img_type type;
229} brom_images[] = {
230 {
231 .name = "nand",
232 .type = BRLYT_TYPE_NAND
233 }, {
234 .name = "emmc",
235 .type = BRLYT_TYPE_EMMC
236 }, {
237 .name = "nor",
238 .type = BRLYT_TYPE_NOR
239 }, {
240 .name = "sdmmc",
241 .type = BRLYT_TYPE_SDMMC
242 }, {
243 .name = "snand",
244 .type = BRLYT_TYPE_SNAND
245 }
246};
247
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800248/* Indicates whether we're generating or verifying */
249static bool img_gen;
250static uint32_t img_size;
251
Ryder Lee3b975a12018-11-15 10:07:49 +0800252/* Image type selected by user */
253static enum brlyt_img_type hdr_media;
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800254static uint32_t hdr_offset;
Ryder Lee3b975a12018-11-15 10:07:49 +0800255static int use_lk_hdr;
Weijie Gaoc561d142022-05-20 11:24:10 +0800256static int use_mt7621_hdr;
Fabien Parent44165e42020-10-16 19:52:37 +0200257static bool is_arm64_image;
Ryder Lee3b975a12018-11-15 10:07:49 +0800258
259/* LK image name */
260static char lk_name[32] = "U-Boot";
261
Weijie Gaoc561d142022-05-20 11:24:10 +0800262/* CRC32 normal table required by MT7621 image */
263static uint32_t crc32tbl[256];
264
Ryder Lee3b975a12018-11-15 10:07:49 +0800265/* NAND header selected by user */
266static const union nand_boot_header *hdr_nand;
267
268/* GFH header + 2 * 4KB pages of NAND */
269static char hdr_tmp[sizeof(struct gfh_header) + 0x2000];
270
Weijie Gaoc561d142022-05-20 11:24:10 +0800271static uint32_t crc32_normal_cal(uint32_t crc, const void *data, size_t length,
272 const uint32_t *crc32c_table)
273{
274 const uint8_t *p = data;
275
276 while (length--)
277 crc = crc32c_table[(uint8_t)((crc >> 24) ^ *p++)] ^ (crc << 8);
278
279 return crc;
280}
281
282static void crc32_normal_init(uint32_t *crc32c_table, uint32_t poly)
283{
284 uint32_t v, i, j;
285
286 for (i = 0; i < 256; i++) {
287 v = i << 24;
288 for (j = 0; j < 8; j++)
289 v = (v << 1) ^ ((v & (1 << 31)) ? poly : 0);
290
291 crc32c_table[i] = v;
292 }
293}
294
Ryder Lee3b975a12018-11-15 10:07:49 +0800295static int mtk_image_check_image_types(uint8_t type)
296{
297 if (type == IH_TYPE_MTKIMAGE)
298 return EXIT_SUCCESS;
299 else
300 return EXIT_FAILURE;
301}
302
303static int mtk_brom_parse_imagename(const char *imagename)
304{
305#define is_blank_char(c) \
306 ((c) == '\t' || (c) == '\n' || (c) == '\r' || (c) == ' ')
307
308 char *buf = strdup(imagename), *key, *val, *end, *next;
309 int i;
310
311 /* User passed arguments from image name */
312 static const char *media = "";
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800313 static const char *hdr_offs = "";
Ryder Lee3b975a12018-11-15 10:07:49 +0800314 static const char *nandinfo = "";
315 static const char *lk = "";
Weijie Gaoc561d142022-05-20 11:24:10 +0800316 static const char *mt7621 = "";
Fabien Parent44165e42020-10-16 19:52:37 +0200317 static const char *arm64_param = "";
Ryder Lee3b975a12018-11-15 10:07:49 +0800318
319 key = buf;
320 while (key) {
321 next = strchr(key, ';');
322 if (next)
323 *next = 0;
324
325 val = strchr(key, '=');
326 if (val) {
327 *val++ = 0;
328
329 /* Trim key */
330 while (is_blank_char(*key))
331 key++;
332
333 end = key + strlen(key) - 1;
334 while ((end >= key) && is_blank_char(*end))
335 end--;
336 end++;
337
338 if (is_blank_char(*end))
339 *end = 0;
340
341 /* Trim value */
342 while (is_blank_char(*val))
343 val++;
344
345 end = val + strlen(val) - 1;
346 while ((end >= val) && is_blank_char(*end))
347 end--;
348 end++;
349
350 if (is_blank_char(*end))
351 *end = 0;
352
353 /* record user passed arguments */
354 if (!strcmp(key, "media"))
355 media = val;
356
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800357 if (!strcmp(key, "hdroffset"))
358 hdr_offs = val;
359
Ryder Lee3b975a12018-11-15 10:07:49 +0800360 if (!strcmp(key, "nandinfo"))
361 nandinfo = val;
362
363 if (!strcmp(key, "lk"))
364 lk = val;
365
Weijie Gaoc561d142022-05-20 11:24:10 +0800366 if (!strcmp(key, "mt7621"))
367 mt7621 = val;
368
Ryder Lee3b975a12018-11-15 10:07:49 +0800369 if (!strcmp(key, "lkname"))
Andy Shevchenko74473ed2018-12-11 16:41:43 +0200370 snprintf(lk_name, sizeof(lk_name), "%s", val);
Fabien Parent44165e42020-10-16 19:52:37 +0200371
372 if (!strcmp(key, "arm64"))
373 arm64_param = val;
Ryder Lee3b975a12018-11-15 10:07:49 +0800374 }
375
376 if (next)
377 key = next + 1;
378 else
379 break;
380 }
381
382 /* if user specified LK image header, skip following checks */
383 if (lk && lk[0] == '1') {
384 use_lk_hdr = 1;
385 free(buf);
386 return 0;
387 }
388
Weijie Gaoc561d142022-05-20 11:24:10 +0800389 /* if user specified MT7621 image header, skip following checks */
390 if (mt7621 && mt7621[0] == '1') {
391 use_mt7621_hdr = 1;
392 free(buf);
393 return 0;
394 }
395
Ryder Lee3b975a12018-11-15 10:07:49 +0800396 /* parse media type */
397 for (i = 0; i < ARRAY_SIZE(brom_images); i++) {
398 if (!strcmp(brom_images[i].name, media)) {
399 hdr_media = brom_images[i].type;
400 break;
401 }
402 }
403
404 /* parse nand header type */
405 for (i = 0; i < ARRAY_SIZE(nand_headers); i++) {
406 if (!strcmp(nand_headers[i].name, nandinfo)) {
407 hdr_nand = nand_headers[i].data;
408 break;
409 }
410 }
411
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800412 /* parse device header offset */
413 if (hdr_offs && hdr_offs[0])
414 hdr_offset = strtoul(hdr_offs, NULL, 0);
415
Fabien Parent44165e42020-10-16 19:52:37 +0200416 if (arm64_param && arm64_param[0] == '1')
417 is_arm64_image = true;
418
Ryder Lee3b975a12018-11-15 10:07:49 +0800419 free(buf);
420
421 if (hdr_media == BRLYT_TYPE_INVALID) {
422 fprintf(stderr, "Error: media type is invalid or missing.\n");
423 fprintf(stderr, " Please specify -n \"media=<type>\"\n");
424 return -EINVAL;
425 }
426
427 if ((hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND) &&
428 !hdr_nand) {
429 fprintf(stderr, "Error: nand info is invalid or missing.\n");
430 fprintf(stderr, " Please specify -n \"media=%s;"
431 "nandinfo=<info>\"\n", media);
432 return -EINVAL;
433 }
434
435 return 0;
436}
437
438static int mtk_image_check_params(struct image_tool_params *params)
439{
440 if (!params->addr) {
441 fprintf(stderr, "Error: Load Address must be set.\n");
442 return -EINVAL;
443 }
444
445 if (!params->imagename) {
446 fprintf(stderr, "Error: Image Name must be set.\n");
447 return -EINVAL;
448 }
449
450 return mtk_brom_parse_imagename(params->imagename);
451}
452
453static int mtk_image_vrec_header(struct image_tool_params *params,
454 struct image_type_params *tparams)
455{
456 if (use_lk_hdr) {
457 tparams->header_size = sizeof(union lk_hdr);
458 tparams->hdr = &hdr_tmp;
459 memset(&hdr_tmp, 0xff, tparams->header_size);
460 return 0;
461 }
462
Weijie Gaoc561d142022-05-20 11:24:10 +0800463 if (use_mt7621_hdr) {
464 tparams->header_size = image_get_header_size();
465 tparams->hdr = &hdr_tmp;
466 memset(&hdr_tmp, 0, tparams->header_size);
467 return 0;
468 }
469
Ryder Lee3b975a12018-11-15 10:07:49 +0800470 if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
471 tparams->header_size = 2 * le16_to_cpu(hdr_nand->pagesize);
472 else
473 tparams->header_size = sizeof(struct gen_device_header);
474
475 tparams->header_size += sizeof(struct gfh_header);
476 tparams->hdr = &hdr_tmp;
477
478 memset(&hdr_tmp, 0xff, tparams->header_size);
479
480 return SHA256_SUM_LEN;
481}
482
Weijie Gao687e10e2022-09-09 20:00:18 +0800483static int mtk_image_verify_gfh(struct gfh_header *gfh, uint32_t type, int print)
484{
485 if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
486 return -1;
487
488 if (le32_to_cpu(gfh->file_info.flash_type) != type)
489 return -1;
490
491 if (print)
492 printf("Load Address: %08x\n",
493 le32_to_cpu(gfh->file_info.load_addr) +
494 le32_to_cpu(gfh->file_info.jump_offset));
495
496 if (print)
497 printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM");
498
499 return 0;
500}
501
Ryder Lee3b975a12018-11-15 10:07:49 +0800502static int mtk_image_verify_gen_header(const uint8_t *ptr, int print)
503{
504 union gen_boot_header *gbh = (union gen_boot_header *)ptr;
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800505 uint32_t gfh_offset, total_size, devh_size;
Ryder Lee3b975a12018-11-15 10:07:49 +0800506 struct brom_layout_header *bh;
507 struct gfh_header *gfh;
508 const char *bootmedia;
509
510 if (!strcmp(gbh->name, SF_BOOT_NAME))
511 bootmedia = "Serial NOR";
512 else if (!strcmp(gbh->name, EMMC_BOOT_NAME))
513 bootmedia = "eMMC";
514 else if (!strcmp(gbh->name, SDMMC_BOOT_NAME))
515 bootmedia = "SD/MMC";
516 else
517 return -1;
518
519 if (print)
520 printf("Boot Media: %s\n", bootmedia);
521
522 if (le32_to_cpu(gbh->version) != 1 ||
523 le32_to_cpu(gbh->size) != sizeof(union gen_boot_header))
524 return -1;
525
526 bh = (struct brom_layout_header *)(ptr + le32_to_cpu(gbh->size));
527
528 if (strcmp(bh->name, BRLYT_NAME))
529 return -1;
530
531 if (le32_to_cpu(bh->magic) != BRLYT_MAGIC ||
532 (le32_to_cpu(bh->type) != BRLYT_TYPE_NOR &&
533 le32_to_cpu(bh->type) != BRLYT_TYPE_EMMC &&
534 le32_to_cpu(bh->type) != BRLYT_TYPE_SDMMC))
535 return -1;
536
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800537 devh_size = sizeof(struct gen_device_header);
538
539 if (img_gen) {
540 gfh_offset = devh_size;
541 } else {
542 gfh_offset = le32_to_cpu(bh->header_size);
543
544 if (gfh_offset + sizeof(struct gfh_header) > img_size) {
545 /*
546 * This may happen if the hdr_offset used to generate
547 * this image is not zero.
548 * Since device header size is not fixed, we can't
549 * cover all possible cases.
550 * Assuming the image is valid only if the real
551 * device header size equals to devh_size.
552 */
553 total_size = le32_to_cpu(bh->total_size);
554
555 if (total_size - gfh_offset > img_size - devh_size)
556 return -1;
557
558 gfh_offset = devh_size;
559 }
560 }
561
562 gfh = (struct gfh_header *)(ptr + gfh_offset);
Ryder Lee3b975a12018-11-15 10:07:49 +0800563
Weijie Gao687e10e2022-09-09 20:00:18 +0800564 return mtk_image_verify_gfh(gfh, GFH_FLASH_TYPE_GEN, print);
Ryder Lee3b975a12018-11-15 10:07:49 +0800565}
566
567static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
568{
569 union nand_boot_header *nh = (union nand_boot_header *)ptr;
570 struct brom_layout_header *bh;
571 struct gfh_header *gfh;
572 const char *bootmedia;
573
574 if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh->version)) ||
575 strcmp(nh->id, NAND_BOOT_ID))
576 return -1;
577
578 bh = (struct brom_layout_header *)(ptr + le16_to_cpu(nh->pagesize));
579
580 if (strcmp(bh->name, BRLYT_NAME))
581 return -1;
582
583 if (le32_to_cpu(bh->magic) != BRLYT_MAGIC) {
584 return -1;
585 } else {
586 if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND)
587 bootmedia = "Parallel NAND";
588 else if (le32_to_cpu(bh->type) == BRLYT_TYPE_SNAND)
589 bootmedia = "Serial NAND";
590 else
591 return -1;
592 }
593
594 if (print) {
595 printf("Boot Media: %s\n", bootmedia);
596
597 if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND) {
598 uint64_t capacity =
599 (uint64_t)le16_to_cpu(nh->numblocks) *
600 (uint64_t)le16_to_cpu(nh->pages_of_block) *
601 (uint64_t)le16_to_cpu(nh->pagesize) * 8;
602 printf("Capacity: %dGb\n",
603 (uint32_t)(capacity >> 30));
604 }
605
606 if (le16_to_cpu(nh->pagesize) >= 1024)
607 printf("Page Size: %dKB\n",
608 le16_to_cpu(nh->pagesize) >> 10);
609 else
610 printf("Page Size: %dB\n",
611 le16_to_cpu(nh->pagesize));
612
613 printf("Spare Size: %dB\n", le16_to_cpu(nh->oobsize));
614 }
615
616 gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(nh->pagesize));
617
Weijie Gao687e10e2022-09-09 20:00:18 +0800618 return mtk_image_verify_gfh(gfh, GFH_FLASH_TYPE_NAND, print);
Ryder Lee3b975a12018-11-15 10:07:49 +0800619}
620
Weijie Gaoc561d142022-05-20 11:24:10 +0800621static uint32_t crc32be_cal(const void *data, size_t length)
622{
623 uint32_t crc = 0;
624 uint8_t c;
625
626 if (crc32tbl[1] != MT7621_IH_CRC_POLYNOMIAL)
627 crc32_normal_init(crc32tbl, MT7621_IH_CRC_POLYNOMIAL);
628
629 crc = crc32_normal_cal(crc, data, length, crc32tbl);
630
631 for (; length; length >>= 8) {
632 c = length & 0xff;
633 crc = crc32_normal_cal(crc, &c, 1, crc32tbl);
634 }
635
636 return ~crc;
637}
638
639static int mtk_image_verify_mt7621_header(const uint8_t *ptr, int print)
640{
641 const image_header_t *hdr = (const image_header_t *)ptr;
642 struct mt7621_nand_header *nhdr;
643 uint32_t spl_size, crcval;
644 image_header_t header;
645 int ret;
646
647 spl_size = image_get_size(hdr);
648
649 if (spl_size > img_size) {
650 if (print)
651 printf("Incomplete SPL image\n");
652 return -1;
653 }
654
655 ret = image_check_hcrc(hdr);
656 if (!ret) {
657 if (print)
658 printf("Bad header CRC\n");
659 return -1;
660 }
661
662 ret = image_check_dcrc(hdr);
663 if (!ret) {
664 if (print)
665 printf("Bad data CRC\n");
666 return -1;
667 }
668
669 /* Copy header so we can blank CRC field for re-calculation */
670 memmove(&header, hdr, image_get_header_size());
671 image_set_hcrc(&header, 0);
672
673 nhdr = (struct mt7621_nand_header *)header.ih_name;
674 crcval = be32_to_cpu(nhdr->crc);
675 nhdr->crc = 0;
676
677 if (crcval != crc32be_cal(&header, image_get_header_size())) {
678 if (print)
679 printf("Bad NAND header CRC\n");
680 return -1;
681 }
682
683 if (print) {
684 printf("Load Address: %08x\n", image_get_load(hdr));
685
686 printf("Image Name: %.*s\n", MT7621_IH_NMLEN,
687 image_get_name(hdr));
688
689 if (IMAGE_ENABLE_TIMESTAMP) {
690 printf("Created: ");
691 genimg_print_time((time_t)image_get_time(hdr));
692 }
693
694 printf("Data Size: ");
695 genimg_print_size(image_get_data_size(hdr));
696 }
697
698 return 0;
699}
700
Ryder Lee3b975a12018-11-15 10:07:49 +0800701static int mtk_image_verify_header(unsigned char *ptr, int image_size,
702 struct image_tool_params *params)
703{
Weijie Gaoc561d142022-05-20 11:24:10 +0800704 image_header_t *hdr = (image_header_t *)ptr;
Ryder Lee3b975a12018-11-15 10:07:49 +0800705 union lk_hdr *lk = (union lk_hdr *)ptr;
706
707 /* nothing to verify for LK image header */
708 if (le32_to_cpu(lk->magic) == LK_PART_MAGIC)
709 return 0;
710
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800711 img_size = image_size;
712
Weijie Gaoc561d142022-05-20 11:24:10 +0800713 if (image_get_magic(hdr) == IH_MAGIC)
714 return mtk_image_verify_mt7621_header(ptr, 0);
715
Ryder Lee3b975a12018-11-15 10:07:49 +0800716 if (!strcmp((char *)ptr, NAND_BOOT_NAME))
717 return mtk_image_verify_nand_header(ptr, 0);
718 else
719 return mtk_image_verify_gen_header(ptr, 0);
720
721 return -1;
722}
723
724static void mtk_image_print_header(const void *ptr)
725{
Weijie Gaoc561d142022-05-20 11:24:10 +0800726 image_header_t *hdr = (image_header_t *)ptr;
Ryder Lee3b975a12018-11-15 10:07:49 +0800727 union lk_hdr *lk = (union lk_hdr *)ptr;
728
729 if (le32_to_cpu(lk->magic) == LK_PART_MAGIC) {
730 printf("Image Type: MediaTek LK Image\n");
731 printf("Load Address: %08x\n", le32_to_cpu(lk->loadaddr));
732 return;
733 }
734
735 printf("Image Type: MediaTek BootROM Loadable Image\n");
736
Weijie Gaoc561d142022-05-20 11:24:10 +0800737 if (image_get_magic(hdr) == IH_MAGIC) {
738 mtk_image_verify_mt7621_header(ptr, 1);
739 return;
740 }
741
Ryder Lee3b975a12018-11-15 10:07:49 +0800742 if (!strcmp((char *)ptr, NAND_BOOT_NAME))
743 mtk_image_verify_nand_header(ptr, 1);
744 else
745 mtk_image_verify_gen_header(ptr, 1);
746}
747
748static void put_brom_layout_header(struct brom_layout_header *hdr, int type)
749{
750 strncpy(hdr->name, BRLYT_NAME, sizeof(hdr->name));
751 hdr->version = cpu_to_le32(1);
752 hdr->magic = cpu_to_le32(BRLYT_MAGIC);
753 hdr->type = cpu_to_le32(type);
754}
755
756static void put_ghf_common_header(struct gfh_common_header *gfh, int size,
757 int type, int ver)
758{
759 memcpy(gfh->magic, GFH_HEADER_MAGIC, sizeof(gfh->magic));
760 gfh->version = ver;
761 gfh->size = cpu_to_le16(size);
762 gfh->type = cpu_to_le16(type);
763}
764
765static void put_ghf_header(struct gfh_header *gfh, int file_size,
766 int dev_hdr_size, int load_addr, int flash_type)
767{
Fabien Parent44165e42020-10-16 19:52:37 +0200768 uint32_t cfg_bits;
769
Ryder Lee3b975a12018-11-15 10:07:49 +0800770 memset(gfh, 0, sizeof(struct gfh_header));
771
772 /* GFH_FILE_INFO header */
773 put_ghf_common_header(&gfh->file_info.gfh, sizeof(gfh->file_info),
774 GFH_TYPE_FILE_INFO, 1);
775 strncpy(gfh->file_info.name, GFH_FILE_INFO_NAME,
776 sizeof(gfh->file_info.name));
777 gfh->file_info.unused = cpu_to_le32(1);
778 gfh->file_info.file_type = cpu_to_le16(1);
779 gfh->file_info.flash_type = flash_type;
780 gfh->file_info.sig_type = GFH_SIG_TYPE_SHA256;
781 gfh->file_info.load_addr = cpu_to_le32(load_addr - sizeof(*gfh));
782 gfh->file_info.total_size = cpu_to_le32(file_size - dev_hdr_size);
783 gfh->file_info.max_size = cpu_to_le32(file_size);
784 gfh->file_info.hdr_size = sizeof(*gfh);
785 gfh->file_info.sig_size = SHA256_SUM_LEN;
786 gfh->file_info.jump_offset = sizeof(*gfh);
787 gfh->file_info.processed = cpu_to_le32(1);
788
789 /* GFH_BL_INFO header */
790 put_ghf_common_header(&gfh->bl_info.gfh, sizeof(gfh->bl_info),
791 GFH_TYPE_BL_INFO, 1);
792 gfh->bl_info.attr = cpu_to_le32(1);
793
794 /* GFH_BROM_CFG header */
795 put_ghf_common_header(&gfh->brom_cfg.gfh, sizeof(gfh->brom_cfg),
796 GFH_TYPE_BROM_CFG, 3);
Fabien Parent44165e42020-10-16 19:52:37 +0200797 cfg_bits = GFH_BROM_CFG_USBDL_AUTO_DETECT_DIS |
798 GFH_BROM_CFG_USBDL_BY_KCOL0_TIMEOUT_EN |
799 GFH_BROM_CFG_USBDL_BY_FLAG_TIMEOUT_EN;
Ryder Lee3b975a12018-11-15 10:07:49 +0800800 gfh->brom_cfg.usbdl_by_kcol0_timeout_ms = cpu_to_le32(5000);
Fabien Parent44165e42020-10-16 19:52:37 +0200801 if (is_arm64_image) {
802 gfh->brom_cfg.jump_bl_arm64 = GFH_BROM_CFG_JUMP_BL_ARM64;
803 cfg_bits |= GFH_BROM_CFG_JUMP_BL_ARM64_EN;
804 }
805 gfh->brom_cfg.cfg_bits = cpu_to_le32(cfg_bits);
Ryder Lee3b975a12018-11-15 10:07:49 +0800806
807 /* GFH_BL_SEC_KEY header */
808 put_ghf_common_header(&gfh->bl_sec_key.gfh, sizeof(gfh->bl_sec_key),
809 GFH_TYPE_BL_SEC_KEY, 1);
810
811 /* GFH_ANTI_CLONE header */
812 put_ghf_common_header(&gfh->anti_clone.gfh, sizeof(gfh->anti_clone),
813 GFH_TYPE_ANTI_CLONE, 1);
814 gfh->anti_clone.ac_offset = cpu_to_le32(0x10);
815 gfh->anti_clone.ac_len = cpu_to_le32(0x80);
816
817 /* GFH_BROM_SEC_CFG header */
818 put_ghf_common_header(&gfh->brom_sec_cfg.gfh,
819 sizeof(gfh->brom_sec_cfg),
820 GFH_TYPE_BROM_SEC_CFG, 1);
821 gfh->brom_sec_cfg.cfg_bits =
822 cpu_to_le32(BROM_SEC_CFG_JTAG_EN | BROM_SEC_CFG_UART_EN);
823}
824
825static void put_hash(uint8_t *buff, int size)
826{
827 sha256_context ctx;
828
829 sha256_starts(&ctx);
830 sha256_update(&ctx, buff, size);
831 sha256_finish(&ctx, buff + size);
832}
833
834static void mtk_image_set_gen_header(void *ptr, off_t filesize,
835 uint32_t loadaddr)
836{
837 struct gen_device_header *hdr = (struct gen_device_header *)ptr;
838 struct gfh_header *gfh;
839 const char *bootname = NULL;
840
841 if (hdr_media == BRLYT_TYPE_NOR)
842 bootname = SF_BOOT_NAME;
843 else if (hdr_media == BRLYT_TYPE_EMMC)
844 bootname = EMMC_BOOT_NAME;
845 else if (hdr_media == BRLYT_TYPE_SDMMC)
846 bootname = SDMMC_BOOT_NAME;
847
848 /* Generic device header */
Andy Shevchenko74473ed2018-12-11 16:41:43 +0200849 snprintf(hdr->boot.name, sizeof(hdr->boot.name), "%s", bootname);
Ryder Lee3b975a12018-11-15 10:07:49 +0800850 hdr->boot.version = cpu_to_le32(1);
851 hdr->boot.size = cpu_to_le32(sizeof(hdr->boot));
852
853 /* BRLYT header */
854 put_brom_layout_header(&hdr->brlyt, hdr_media);
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800855 hdr->brlyt.header_size = cpu_to_le32(hdr_offset + sizeof(*hdr));
856 hdr->brlyt.total_size = cpu_to_le32(hdr_offset + filesize);
Ryder Lee3b975a12018-11-15 10:07:49 +0800857 hdr->brlyt.header_size_2 = hdr->brlyt.header_size;
858 hdr->brlyt.total_size_2 = hdr->brlyt.total_size;
859
860 /* GFH header */
861 gfh = (struct gfh_header *)(ptr + sizeof(struct gen_device_header));
862 put_ghf_header(gfh, filesize, sizeof(struct gen_device_header),
863 loadaddr, GFH_FLASH_TYPE_GEN);
864
865 /* Generate SHA256 hash */
866 put_hash((uint8_t *)gfh,
867 filesize - sizeof(struct gen_device_header) - SHA256_SUM_LEN);
868}
869
870static void mtk_image_set_nand_header(void *ptr, off_t filesize,
871 uint32_t loadaddr)
872{
873 union nand_boot_header *nh = (union nand_boot_header *)ptr;
874 struct brom_layout_header *brlyt;
875 struct gfh_header *gfh;
876 uint32_t payload_pages;
877 int i;
878
879 /* NAND device header, repeat 4 times */
880 for (i = 0; i < 4; i++)
881 memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header));
882
883 /* BRLYT header */
884 payload_pages = (filesize + le16_to_cpu(hdr_nand->pagesize) - 1) /
885 le16_to_cpu(hdr_nand->pagesize);
886 brlyt = (struct brom_layout_header *)
887 (ptr + le16_to_cpu(hdr_nand->pagesize));
888 put_brom_layout_header(brlyt, hdr_media);
889 brlyt->header_size = cpu_to_le32(2);
890 brlyt->total_size = cpu_to_le32(payload_pages);
891 brlyt->header_size_2 = brlyt->header_size;
892 brlyt->total_size_2 = brlyt->total_size;
893 brlyt->unused = cpu_to_le32(1);
894
895 /* GFH header */
896 gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(hdr_nand->pagesize));
897 put_ghf_header(gfh, filesize, 2 * le16_to_cpu(hdr_nand->pagesize),
898 loadaddr, GFH_FLASH_TYPE_NAND);
899
900 /* Generate SHA256 hash */
901 put_hash((uint8_t *)gfh,
902 filesize - 2 * le16_to_cpu(hdr_nand->pagesize) - SHA256_SUM_LEN);
903}
904
Weijie Gaoc561d142022-05-20 11:24:10 +0800905static void mtk_image_set_mt7621_header(void *ptr, off_t filesize,
906 uint32_t loadaddr)
907{
908 image_header_t *hdr = (image_header_t *)ptr;
909 struct mt7621_stage1_header *shdr;
910 struct mt7621_nand_header *nhdr;
911 uint32_t datasize, crcval;
912
913 datasize = filesize - image_get_header_size();
914 nhdr = (struct mt7621_nand_header *)hdr->ih_name;
915 shdr = (struct mt7621_stage1_header *)(ptr + image_get_header_size());
916
917 shdr->ep = cpu_to_be32(loadaddr);
918 shdr->stage_size = cpu_to_be32(datasize);
919
920 image_set_magic(hdr, IH_MAGIC);
921 image_set_time(hdr, time(NULL));
922 image_set_size(hdr, datasize);
923 image_set_load(hdr, loadaddr);
924 image_set_ep(hdr, loadaddr);
925 image_set_os(hdr, IH_OS_U_BOOT);
926 image_set_arch(hdr, IH_ARCH_MIPS);
927 image_set_type(hdr, IH_TYPE_STANDALONE);
928 image_set_comp(hdr, IH_COMP_NONE);
929
930 crcval = crc32(0, (uint8_t *)shdr, datasize);
931 image_set_dcrc(hdr, crcval);
932
933 strncpy(nhdr->ih_name, "MT7621 NAND", MT7621_IH_NMLEN);
934
935 nhdr->ih_stage_offset = cpu_to_be32(image_get_header_size());
936
937 crcval = crc32be_cal(hdr, image_get_header_size());
938 nhdr->crc = cpu_to_be32(crcval);
939
940 crcval = crc32(0, (uint8_t *)hdr, image_get_header_size());
941 image_set_hcrc(hdr, crcval);
942}
943
Ryder Lee3b975a12018-11-15 10:07:49 +0800944static void mtk_image_set_header(void *ptr, struct stat *sbuf, int ifd,
945 struct image_tool_params *params)
946{
947 union lk_hdr *lk = (union lk_hdr *)ptr;
948
949 if (use_lk_hdr) {
950 lk->magic = cpu_to_le32(LK_PART_MAGIC);
951 lk->size = cpu_to_le32(sbuf->st_size - sizeof(union lk_hdr));
952 lk->loadaddr = cpu_to_le32(params->addr);
953 lk->mode = 0xffffffff; /* must be non-zero */
954 memset(lk->name, 0, sizeof(lk->name));
955 strncpy(lk->name, lk_name, sizeof(lk->name));
956 return;
957 }
958
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800959 img_gen = true;
960 img_size = sbuf->st_size;
961
Weijie Gaoc561d142022-05-20 11:24:10 +0800962 if (use_mt7621_hdr) {
963 mtk_image_set_mt7621_header(ptr, sbuf->st_size, params->addr);
964 return;
965 }
966
Ryder Lee3b975a12018-11-15 10:07:49 +0800967 if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
968 mtk_image_set_nand_header(ptr, sbuf->st_size, params->addr);
969 else
970 mtk_image_set_gen_header(ptr, sbuf->st_size, params->addr);
971}
972
973U_BOOT_IMAGE_TYPE(
974 mtk_image,
975 "MediaTek BootROM Loadable Image support",
976 0,
977 NULL,
978 mtk_image_check_params,
979 mtk_image_verify_header,
980 mtk_image_print_header,
981 mtk_image_set_header,
982 NULL,
983 mtk_image_check_image_types,
984 NULL,
985 mtk_image_vrec_header
986);