blob: de5ce4d964c13c7845e0937f6920feabacb4f932 [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
483static int mtk_image_verify_gen_header(const uint8_t *ptr, int print)
484{
485 union gen_boot_header *gbh = (union gen_boot_header *)ptr;
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800486 uint32_t gfh_offset, total_size, devh_size;
Ryder Lee3b975a12018-11-15 10:07:49 +0800487 struct brom_layout_header *bh;
488 struct gfh_header *gfh;
489 const char *bootmedia;
490
491 if (!strcmp(gbh->name, SF_BOOT_NAME))
492 bootmedia = "Serial NOR";
493 else if (!strcmp(gbh->name, EMMC_BOOT_NAME))
494 bootmedia = "eMMC";
495 else if (!strcmp(gbh->name, SDMMC_BOOT_NAME))
496 bootmedia = "SD/MMC";
497 else
498 return -1;
499
500 if (print)
501 printf("Boot Media: %s\n", bootmedia);
502
503 if (le32_to_cpu(gbh->version) != 1 ||
504 le32_to_cpu(gbh->size) != sizeof(union gen_boot_header))
505 return -1;
506
507 bh = (struct brom_layout_header *)(ptr + le32_to_cpu(gbh->size));
508
509 if (strcmp(bh->name, BRLYT_NAME))
510 return -1;
511
512 if (le32_to_cpu(bh->magic) != BRLYT_MAGIC ||
513 (le32_to_cpu(bh->type) != BRLYT_TYPE_NOR &&
514 le32_to_cpu(bh->type) != BRLYT_TYPE_EMMC &&
515 le32_to_cpu(bh->type) != BRLYT_TYPE_SDMMC))
516 return -1;
517
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800518 devh_size = sizeof(struct gen_device_header);
519
520 if (img_gen) {
521 gfh_offset = devh_size;
522 } else {
523 gfh_offset = le32_to_cpu(bh->header_size);
524
525 if (gfh_offset + sizeof(struct gfh_header) > img_size) {
526 /*
527 * This may happen if the hdr_offset used to generate
528 * this image is not zero.
529 * Since device header size is not fixed, we can't
530 * cover all possible cases.
531 * Assuming the image is valid only if the real
532 * device header size equals to devh_size.
533 */
534 total_size = le32_to_cpu(bh->total_size);
535
536 if (total_size - gfh_offset > img_size - devh_size)
537 return -1;
538
539 gfh_offset = devh_size;
540 }
541 }
542
543 gfh = (struct gfh_header *)(ptr + gfh_offset);
Ryder Lee3b975a12018-11-15 10:07:49 +0800544
545 if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
546 return -1;
547
548 if (le32_to_cpu(gfh->file_info.flash_type) != GFH_FLASH_TYPE_GEN)
549 return -1;
550
551 if (print)
552 printf("Load Address: %08x\n",
553 le32_to_cpu(gfh->file_info.load_addr) +
554 le32_to_cpu(gfh->file_info.jump_offset));
555
Fabien Parent44165e42020-10-16 19:52:37 +0200556 if (print)
557 printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM");
558
Ryder Lee3b975a12018-11-15 10:07:49 +0800559 return 0;
560}
561
562static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
563{
564 union nand_boot_header *nh = (union nand_boot_header *)ptr;
565 struct brom_layout_header *bh;
566 struct gfh_header *gfh;
567 const char *bootmedia;
568
569 if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh->version)) ||
570 strcmp(nh->id, NAND_BOOT_ID))
571 return -1;
572
573 bh = (struct brom_layout_header *)(ptr + le16_to_cpu(nh->pagesize));
574
575 if (strcmp(bh->name, BRLYT_NAME))
576 return -1;
577
578 if (le32_to_cpu(bh->magic) != BRLYT_MAGIC) {
579 return -1;
580 } else {
581 if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND)
582 bootmedia = "Parallel NAND";
583 else if (le32_to_cpu(bh->type) == BRLYT_TYPE_SNAND)
584 bootmedia = "Serial NAND";
585 else
586 return -1;
587 }
588
589 if (print) {
590 printf("Boot Media: %s\n", bootmedia);
591
592 if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND) {
593 uint64_t capacity =
594 (uint64_t)le16_to_cpu(nh->numblocks) *
595 (uint64_t)le16_to_cpu(nh->pages_of_block) *
596 (uint64_t)le16_to_cpu(nh->pagesize) * 8;
597 printf("Capacity: %dGb\n",
598 (uint32_t)(capacity >> 30));
599 }
600
601 if (le16_to_cpu(nh->pagesize) >= 1024)
602 printf("Page Size: %dKB\n",
603 le16_to_cpu(nh->pagesize) >> 10);
604 else
605 printf("Page Size: %dB\n",
606 le16_to_cpu(nh->pagesize));
607
608 printf("Spare Size: %dB\n", le16_to_cpu(nh->oobsize));
609 }
610
611 gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(nh->pagesize));
612
613 if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
614 return -1;
615
616 if (le32_to_cpu(gfh->file_info.flash_type) != GFH_FLASH_TYPE_NAND)
617 return -1;
618
619 if (print)
620 printf("Load Address: %08x\n",
621 le32_to_cpu(gfh->file_info.load_addr) +
622 le32_to_cpu(gfh->file_info.jump_offset));
623
Fabien Parent44165e42020-10-16 19:52:37 +0200624 if (print)
625 printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM");
626
Ryder Lee3b975a12018-11-15 10:07:49 +0800627 return 0;
628}
629
Weijie Gaoc561d142022-05-20 11:24:10 +0800630static uint32_t crc32be_cal(const void *data, size_t length)
631{
632 uint32_t crc = 0;
633 uint8_t c;
634
635 if (crc32tbl[1] != MT7621_IH_CRC_POLYNOMIAL)
636 crc32_normal_init(crc32tbl, MT7621_IH_CRC_POLYNOMIAL);
637
638 crc = crc32_normal_cal(crc, data, length, crc32tbl);
639
640 for (; length; length >>= 8) {
641 c = length & 0xff;
642 crc = crc32_normal_cal(crc, &c, 1, crc32tbl);
643 }
644
645 return ~crc;
646}
647
648static int mtk_image_verify_mt7621_header(const uint8_t *ptr, int print)
649{
650 const image_header_t *hdr = (const image_header_t *)ptr;
651 struct mt7621_nand_header *nhdr;
652 uint32_t spl_size, crcval;
653 image_header_t header;
654 int ret;
655
656 spl_size = image_get_size(hdr);
657
658 if (spl_size > img_size) {
659 if (print)
660 printf("Incomplete SPL image\n");
661 return -1;
662 }
663
664 ret = image_check_hcrc(hdr);
665 if (!ret) {
666 if (print)
667 printf("Bad header CRC\n");
668 return -1;
669 }
670
671 ret = image_check_dcrc(hdr);
672 if (!ret) {
673 if (print)
674 printf("Bad data CRC\n");
675 return -1;
676 }
677
678 /* Copy header so we can blank CRC field for re-calculation */
679 memmove(&header, hdr, image_get_header_size());
680 image_set_hcrc(&header, 0);
681
682 nhdr = (struct mt7621_nand_header *)header.ih_name;
683 crcval = be32_to_cpu(nhdr->crc);
684 nhdr->crc = 0;
685
686 if (crcval != crc32be_cal(&header, image_get_header_size())) {
687 if (print)
688 printf("Bad NAND header CRC\n");
689 return -1;
690 }
691
692 if (print) {
693 printf("Load Address: %08x\n", image_get_load(hdr));
694
695 printf("Image Name: %.*s\n", MT7621_IH_NMLEN,
696 image_get_name(hdr));
697
698 if (IMAGE_ENABLE_TIMESTAMP) {
699 printf("Created: ");
700 genimg_print_time((time_t)image_get_time(hdr));
701 }
702
703 printf("Data Size: ");
704 genimg_print_size(image_get_data_size(hdr));
705 }
706
707 return 0;
708}
709
Ryder Lee3b975a12018-11-15 10:07:49 +0800710static int mtk_image_verify_header(unsigned char *ptr, int image_size,
711 struct image_tool_params *params)
712{
Weijie Gaoc561d142022-05-20 11:24:10 +0800713 image_header_t *hdr = (image_header_t *)ptr;
Ryder Lee3b975a12018-11-15 10:07:49 +0800714 union lk_hdr *lk = (union lk_hdr *)ptr;
715
716 /* nothing to verify for LK image header */
717 if (le32_to_cpu(lk->magic) == LK_PART_MAGIC)
718 return 0;
719
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800720 img_size = image_size;
721
Weijie Gaoc561d142022-05-20 11:24:10 +0800722 if (image_get_magic(hdr) == IH_MAGIC)
723 return mtk_image_verify_mt7621_header(ptr, 0);
724
Ryder Lee3b975a12018-11-15 10:07:49 +0800725 if (!strcmp((char *)ptr, NAND_BOOT_NAME))
726 return mtk_image_verify_nand_header(ptr, 0);
727 else
728 return mtk_image_verify_gen_header(ptr, 0);
729
730 return -1;
731}
732
733static void mtk_image_print_header(const void *ptr)
734{
Weijie Gaoc561d142022-05-20 11:24:10 +0800735 image_header_t *hdr = (image_header_t *)ptr;
Ryder Lee3b975a12018-11-15 10:07:49 +0800736 union lk_hdr *lk = (union lk_hdr *)ptr;
737
738 if (le32_to_cpu(lk->magic) == LK_PART_MAGIC) {
739 printf("Image Type: MediaTek LK Image\n");
740 printf("Load Address: %08x\n", le32_to_cpu(lk->loadaddr));
741 return;
742 }
743
744 printf("Image Type: MediaTek BootROM Loadable Image\n");
745
Weijie Gaoc561d142022-05-20 11:24:10 +0800746 if (image_get_magic(hdr) == IH_MAGIC) {
747 mtk_image_verify_mt7621_header(ptr, 1);
748 return;
749 }
750
Ryder Lee3b975a12018-11-15 10:07:49 +0800751 if (!strcmp((char *)ptr, NAND_BOOT_NAME))
752 mtk_image_verify_nand_header(ptr, 1);
753 else
754 mtk_image_verify_gen_header(ptr, 1);
755}
756
757static void put_brom_layout_header(struct brom_layout_header *hdr, int type)
758{
759 strncpy(hdr->name, BRLYT_NAME, sizeof(hdr->name));
760 hdr->version = cpu_to_le32(1);
761 hdr->magic = cpu_to_le32(BRLYT_MAGIC);
762 hdr->type = cpu_to_le32(type);
763}
764
765static void put_ghf_common_header(struct gfh_common_header *gfh, int size,
766 int type, int ver)
767{
768 memcpy(gfh->magic, GFH_HEADER_MAGIC, sizeof(gfh->magic));
769 gfh->version = ver;
770 gfh->size = cpu_to_le16(size);
771 gfh->type = cpu_to_le16(type);
772}
773
774static void put_ghf_header(struct gfh_header *gfh, int file_size,
775 int dev_hdr_size, int load_addr, int flash_type)
776{
Fabien Parent44165e42020-10-16 19:52:37 +0200777 uint32_t cfg_bits;
778
Ryder Lee3b975a12018-11-15 10:07:49 +0800779 memset(gfh, 0, sizeof(struct gfh_header));
780
781 /* GFH_FILE_INFO header */
782 put_ghf_common_header(&gfh->file_info.gfh, sizeof(gfh->file_info),
783 GFH_TYPE_FILE_INFO, 1);
784 strncpy(gfh->file_info.name, GFH_FILE_INFO_NAME,
785 sizeof(gfh->file_info.name));
786 gfh->file_info.unused = cpu_to_le32(1);
787 gfh->file_info.file_type = cpu_to_le16(1);
788 gfh->file_info.flash_type = flash_type;
789 gfh->file_info.sig_type = GFH_SIG_TYPE_SHA256;
790 gfh->file_info.load_addr = cpu_to_le32(load_addr - sizeof(*gfh));
791 gfh->file_info.total_size = cpu_to_le32(file_size - dev_hdr_size);
792 gfh->file_info.max_size = cpu_to_le32(file_size);
793 gfh->file_info.hdr_size = sizeof(*gfh);
794 gfh->file_info.sig_size = SHA256_SUM_LEN;
795 gfh->file_info.jump_offset = sizeof(*gfh);
796 gfh->file_info.processed = cpu_to_le32(1);
797
798 /* GFH_BL_INFO header */
799 put_ghf_common_header(&gfh->bl_info.gfh, sizeof(gfh->bl_info),
800 GFH_TYPE_BL_INFO, 1);
801 gfh->bl_info.attr = cpu_to_le32(1);
802
803 /* GFH_BROM_CFG header */
804 put_ghf_common_header(&gfh->brom_cfg.gfh, sizeof(gfh->brom_cfg),
805 GFH_TYPE_BROM_CFG, 3);
Fabien Parent44165e42020-10-16 19:52:37 +0200806 cfg_bits = GFH_BROM_CFG_USBDL_AUTO_DETECT_DIS |
807 GFH_BROM_CFG_USBDL_BY_KCOL0_TIMEOUT_EN |
808 GFH_BROM_CFG_USBDL_BY_FLAG_TIMEOUT_EN;
Ryder Lee3b975a12018-11-15 10:07:49 +0800809 gfh->brom_cfg.usbdl_by_kcol0_timeout_ms = cpu_to_le32(5000);
Fabien Parent44165e42020-10-16 19:52:37 +0200810 if (is_arm64_image) {
811 gfh->brom_cfg.jump_bl_arm64 = GFH_BROM_CFG_JUMP_BL_ARM64;
812 cfg_bits |= GFH_BROM_CFG_JUMP_BL_ARM64_EN;
813 }
814 gfh->brom_cfg.cfg_bits = cpu_to_le32(cfg_bits);
Ryder Lee3b975a12018-11-15 10:07:49 +0800815
816 /* GFH_BL_SEC_KEY header */
817 put_ghf_common_header(&gfh->bl_sec_key.gfh, sizeof(gfh->bl_sec_key),
818 GFH_TYPE_BL_SEC_KEY, 1);
819
820 /* GFH_ANTI_CLONE header */
821 put_ghf_common_header(&gfh->anti_clone.gfh, sizeof(gfh->anti_clone),
822 GFH_TYPE_ANTI_CLONE, 1);
823 gfh->anti_clone.ac_offset = cpu_to_le32(0x10);
824 gfh->anti_clone.ac_len = cpu_to_le32(0x80);
825
826 /* GFH_BROM_SEC_CFG header */
827 put_ghf_common_header(&gfh->brom_sec_cfg.gfh,
828 sizeof(gfh->brom_sec_cfg),
829 GFH_TYPE_BROM_SEC_CFG, 1);
830 gfh->brom_sec_cfg.cfg_bits =
831 cpu_to_le32(BROM_SEC_CFG_JTAG_EN | BROM_SEC_CFG_UART_EN);
832}
833
834static void put_hash(uint8_t *buff, int size)
835{
836 sha256_context ctx;
837
838 sha256_starts(&ctx);
839 sha256_update(&ctx, buff, size);
840 sha256_finish(&ctx, buff + size);
841}
842
843static void mtk_image_set_gen_header(void *ptr, off_t filesize,
844 uint32_t loadaddr)
845{
846 struct gen_device_header *hdr = (struct gen_device_header *)ptr;
847 struct gfh_header *gfh;
848 const char *bootname = NULL;
849
850 if (hdr_media == BRLYT_TYPE_NOR)
851 bootname = SF_BOOT_NAME;
852 else if (hdr_media == BRLYT_TYPE_EMMC)
853 bootname = EMMC_BOOT_NAME;
854 else if (hdr_media == BRLYT_TYPE_SDMMC)
855 bootname = SDMMC_BOOT_NAME;
856
857 /* Generic device header */
Andy Shevchenko74473ed2018-12-11 16:41:43 +0200858 snprintf(hdr->boot.name, sizeof(hdr->boot.name), "%s", bootname);
Ryder Lee3b975a12018-11-15 10:07:49 +0800859 hdr->boot.version = cpu_to_le32(1);
860 hdr->boot.size = cpu_to_le32(sizeof(hdr->boot));
861
862 /* BRLYT header */
863 put_brom_layout_header(&hdr->brlyt, hdr_media);
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800864 hdr->brlyt.header_size = cpu_to_le32(hdr_offset + sizeof(*hdr));
865 hdr->brlyt.total_size = cpu_to_le32(hdr_offset + filesize);
Ryder Lee3b975a12018-11-15 10:07:49 +0800866 hdr->brlyt.header_size_2 = hdr->brlyt.header_size;
867 hdr->brlyt.total_size_2 = hdr->brlyt.total_size;
868
869 /* GFH header */
870 gfh = (struct gfh_header *)(ptr + sizeof(struct gen_device_header));
871 put_ghf_header(gfh, filesize, sizeof(struct gen_device_header),
872 loadaddr, GFH_FLASH_TYPE_GEN);
873
874 /* Generate SHA256 hash */
875 put_hash((uint8_t *)gfh,
876 filesize - sizeof(struct gen_device_header) - SHA256_SUM_LEN);
877}
878
879static void mtk_image_set_nand_header(void *ptr, off_t filesize,
880 uint32_t loadaddr)
881{
882 union nand_boot_header *nh = (union nand_boot_header *)ptr;
883 struct brom_layout_header *brlyt;
884 struct gfh_header *gfh;
885 uint32_t payload_pages;
886 int i;
887
888 /* NAND device header, repeat 4 times */
889 for (i = 0; i < 4; i++)
890 memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header));
891
892 /* BRLYT header */
893 payload_pages = (filesize + le16_to_cpu(hdr_nand->pagesize) - 1) /
894 le16_to_cpu(hdr_nand->pagesize);
895 brlyt = (struct brom_layout_header *)
896 (ptr + le16_to_cpu(hdr_nand->pagesize));
897 put_brom_layout_header(brlyt, hdr_media);
898 brlyt->header_size = cpu_to_le32(2);
899 brlyt->total_size = cpu_to_le32(payload_pages);
900 brlyt->header_size_2 = brlyt->header_size;
901 brlyt->total_size_2 = brlyt->total_size;
902 brlyt->unused = cpu_to_le32(1);
903
904 /* GFH header */
905 gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(hdr_nand->pagesize));
906 put_ghf_header(gfh, filesize, 2 * le16_to_cpu(hdr_nand->pagesize),
907 loadaddr, GFH_FLASH_TYPE_NAND);
908
909 /* Generate SHA256 hash */
910 put_hash((uint8_t *)gfh,
911 filesize - 2 * le16_to_cpu(hdr_nand->pagesize) - SHA256_SUM_LEN);
912}
913
Weijie Gaoc561d142022-05-20 11:24:10 +0800914static void mtk_image_set_mt7621_header(void *ptr, off_t filesize,
915 uint32_t loadaddr)
916{
917 image_header_t *hdr = (image_header_t *)ptr;
918 struct mt7621_stage1_header *shdr;
919 struct mt7621_nand_header *nhdr;
920 uint32_t datasize, crcval;
921
922 datasize = filesize - image_get_header_size();
923 nhdr = (struct mt7621_nand_header *)hdr->ih_name;
924 shdr = (struct mt7621_stage1_header *)(ptr + image_get_header_size());
925
926 shdr->ep = cpu_to_be32(loadaddr);
927 shdr->stage_size = cpu_to_be32(datasize);
928
929 image_set_magic(hdr, IH_MAGIC);
930 image_set_time(hdr, time(NULL));
931 image_set_size(hdr, datasize);
932 image_set_load(hdr, loadaddr);
933 image_set_ep(hdr, loadaddr);
934 image_set_os(hdr, IH_OS_U_BOOT);
935 image_set_arch(hdr, IH_ARCH_MIPS);
936 image_set_type(hdr, IH_TYPE_STANDALONE);
937 image_set_comp(hdr, IH_COMP_NONE);
938
939 crcval = crc32(0, (uint8_t *)shdr, datasize);
940 image_set_dcrc(hdr, crcval);
941
942 strncpy(nhdr->ih_name, "MT7621 NAND", MT7621_IH_NMLEN);
943
944 nhdr->ih_stage_offset = cpu_to_be32(image_get_header_size());
945
946 crcval = crc32be_cal(hdr, image_get_header_size());
947 nhdr->crc = cpu_to_be32(crcval);
948
949 crcval = crc32(0, (uint8_t *)hdr, image_get_header_size());
950 image_set_hcrc(hdr, crcval);
951}
952
Ryder Lee3b975a12018-11-15 10:07:49 +0800953static void mtk_image_set_header(void *ptr, struct stat *sbuf, int ifd,
954 struct image_tool_params *params)
955{
956 union lk_hdr *lk = (union lk_hdr *)ptr;
957
958 if (use_lk_hdr) {
959 lk->magic = cpu_to_le32(LK_PART_MAGIC);
960 lk->size = cpu_to_le32(sbuf->st_size - sizeof(union lk_hdr));
961 lk->loadaddr = cpu_to_le32(params->addr);
962 lk->mode = 0xffffffff; /* must be non-zero */
963 memset(lk->name, 0, sizeof(lk->name));
964 strncpy(lk->name, lk_name, sizeof(lk->name));
965 return;
966 }
967
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800968 img_gen = true;
969 img_size = sbuf->st_size;
970
Weijie Gaoc561d142022-05-20 11:24:10 +0800971 if (use_mt7621_hdr) {
972 mtk_image_set_mt7621_header(ptr, sbuf->st_size, params->addr);
973 return;
974 }
975
Ryder Lee3b975a12018-11-15 10:07:49 +0800976 if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
977 mtk_image_set_nand_header(ptr, sbuf->st_size, params->addr);
978 else
979 mtk_image_set_gen_header(ptr, sbuf->st_size, params->addr);
980}
981
982U_BOOT_IMAGE_TYPE(
983 mtk_image,
984 "MediaTek BootROM Loadable Image support",
985 0,
986 NULL,
987 mtk_image_check_params,
988 mtk_image_verify_header,
989 mtk_image_print_header,
990 mtk_image_set_header,
991 NULL,
992 mtk_image_check_image_types,
993 NULL,
994 mtk_image_vrec_header
995);