blob: 1b1aed59924f05695782da6ac999d20b72a11d6a [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"
Weijie Gaocadb1a82022-09-09 20:00:21 +080015#include "mtk_nand_headers.h"
Ryder Lee3b975a12018-11-15 10:07:49 +080016
17static const struct brom_img_type {
18 const char *name;
19 enum brlyt_img_type type;
20} brom_images[] = {
21 {
22 .name = "nand",
23 .type = BRLYT_TYPE_NAND
24 }, {
25 .name = "emmc",
26 .type = BRLYT_TYPE_EMMC
27 }, {
28 .name = "nor",
29 .type = BRLYT_TYPE_NOR
30 }, {
31 .name = "sdmmc",
32 .type = BRLYT_TYPE_SDMMC
33 }, {
34 .name = "snand",
35 .type = BRLYT_TYPE_SNAND
Weijie Gao3e333212022-09-09 20:00:25 +080036 }, {
37 .name = "spim-nand",
38 .type = BRLYT_TYPE_SNAND
Ryder Lee3b975a12018-11-15 10:07:49 +080039 }
40};
41
Weijie Gaocfd48ec2021-03-09 15:52:31 +080042/* Indicates whether we're generating or verifying */
43static bool img_gen;
44static uint32_t img_size;
45
Ryder Lee3b975a12018-11-15 10:07:49 +080046/* Image type selected by user */
47static enum brlyt_img_type hdr_media;
Weijie Gaocfd48ec2021-03-09 15:52:31 +080048static uint32_t hdr_offset;
Ryder Lee3b975a12018-11-15 10:07:49 +080049static int use_lk_hdr;
Weijie Gaoc561d142022-05-20 11:24:10 +080050static int use_mt7621_hdr;
Fabien Parent44165e42020-10-16 19:52:37 +020051static bool is_arm64_image;
Ryder Lee3b975a12018-11-15 10:07:49 +080052
53/* LK image name */
54static char lk_name[32] = "U-Boot";
55
Weijie Gaoc561d142022-05-20 11:24:10 +080056/* CRC32 normal table required by MT7621 image */
57static uint32_t crc32tbl[256];
58
Ryder Lee3b975a12018-11-15 10:07:49 +080059/* NAND header selected by user */
Weijie Gao3e333212022-09-09 20:00:25 +080060static const struct nand_header_type *hdr_nand;
Weijie Gaocadb1a82022-09-09 20:00:21 +080061static uint32_t hdr_nand_size;
Ryder Lee3b975a12018-11-15 10:07:49 +080062
63/* GFH header + 2 * 4KB pages of NAND */
64static char hdr_tmp[sizeof(struct gfh_header) + 0x2000];
65
Weijie Gaoc561d142022-05-20 11:24:10 +080066static uint32_t crc32_normal_cal(uint32_t crc, const void *data, size_t length,
67 const uint32_t *crc32c_table)
68{
69 const uint8_t *p = data;
70
71 while (length--)
72 crc = crc32c_table[(uint8_t)((crc >> 24) ^ *p++)] ^ (crc << 8);
73
74 return crc;
75}
76
77static void crc32_normal_init(uint32_t *crc32c_table, uint32_t poly)
78{
79 uint32_t v, i, j;
80
81 for (i = 0; i < 256; i++) {
82 v = i << 24;
83 for (j = 0; j < 8; j++)
84 v = (v << 1) ^ ((v & (1 << 31)) ? poly : 0);
85
86 crc32c_table[i] = v;
87 }
88}
89
Ryder Lee3b975a12018-11-15 10:07:49 +080090static int mtk_image_check_image_types(uint8_t type)
91{
92 if (type == IH_TYPE_MTKIMAGE)
93 return EXIT_SUCCESS;
94 else
95 return EXIT_FAILURE;
96}
97
98static int mtk_brom_parse_imagename(const char *imagename)
99{
100#define is_blank_char(c) \
101 ((c) == '\t' || (c) == '\n' || (c) == '\r' || (c) == ' ')
102
103 char *buf = strdup(imagename), *key, *val, *end, *next;
104 int i;
105
106 /* User passed arguments from image name */
107 static const char *media = "";
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800108 static const char *hdr_offs = "";
Ryder Lee3b975a12018-11-15 10:07:49 +0800109 static const char *nandinfo = "";
110 static const char *lk = "";
Weijie Gaoc561d142022-05-20 11:24:10 +0800111 static const char *mt7621 = "";
Fabien Parent44165e42020-10-16 19:52:37 +0200112 static const char *arm64_param = "";
Ryder Lee3b975a12018-11-15 10:07:49 +0800113
114 key = buf;
115 while (key) {
116 next = strchr(key, ';');
117 if (next)
118 *next = 0;
119
120 val = strchr(key, '=');
121 if (val) {
122 *val++ = 0;
123
124 /* Trim key */
125 while (is_blank_char(*key))
126 key++;
127
128 end = key + strlen(key) - 1;
129 while ((end >= key) && is_blank_char(*end))
130 end--;
131 end++;
132
133 if (is_blank_char(*end))
134 *end = 0;
135
136 /* Trim value */
137 while (is_blank_char(*val))
138 val++;
139
140 end = val + strlen(val) - 1;
141 while ((end >= val) && is_blank_char(*end))
142 end--;
143 end++;
144
145 if (is_blank_char(*end))
146 *end = 0;
147
148 /* record user passed arguments */
149 if (!strcmp(key, "media"))
150 media = val;
151
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800152 if (!strcmp(key, "hdroffset"))
153 hdr_offs = val;
154
Ryder Lee3b975a12018-11-15 10:07:49 +0800155 if (!strcmp(key, "nandinfo"))
156 nandinfo = val;
157
158 if (!strcmp(key, "lk"))
159 lk = val;
160
Weijie Gaoc561d142022-05-20 11:24:10 +0800161 if (!strcmp(key, "mt7621"))
162 mt7621 = val;
163
Ryder Lee3b975a12018-11-15 10:07:49 +0800164 if (!strcmp(key, "lkname"))
Andy Shevchenko74473ed2018-12-11 16:41:43 +0200165 snprintf(lk_name, sizeof(lk_name), "%s", val);
Fabien Parent44165e42020-10-16 19:52:37 +0200166
167 if (!strcmp(key, "arm64"))
168 arm64_param = val;
Ryder Lee3b975a12018-11-15 10:07:49 +0800169 }
170
171 if (next)
172 key = next + 1;
173 else
174 break;
175 }
176
177 /* if user specified LK image header, skip following checks */
178 if (lk && lk[0] == '1') {
179 use_lk_hdr = 1;
180 free(buf);
181 return 0;
182 }
183
Weijie Gaoc561d142022-05-20 11:24:10 +0800184 /* if user specified MT7621 image header, skip following checks */
185 if (mt7621 && mt7621[0] == '1') {
186 use_mt7621_hdr = 1;
187 free(buf);
188 return 0;
189 }
190
Ryder Lee3b975a12018-11-15 10:07:49 +0800191 /* parse media type */
192 for (i = 0; i < ARRAY_SIZE(brom_images); i++) {
193 if (!strcmp(brom_images[i].name, media)) {
194 hdr_media = brom_images[i].type;
195 break;
196 }
197 }
198
199 /* parse nand header type */
Weijie Gaocadb1a82022-09-09 20:00:21 +0800200 hdr_nand = mtk_nand_header_find(nandinfo);
Ryder Lee3b975a12018-11-15 10:07:49 +0800201
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800202 /* parse device header offset */
203 if (hdr_offs && hdr_offs[0])
204 hdr_offset = strtoul(hdr_offs, NULL, 0);
205
Fabien Parent44165e42020-10-16 19:52:37 +0200206 if (arm64_param && arm64_param[0] == '1')
207 is_arm64_image = true;
208
Ryder Lee3b975a12018-11-15 10:07:49 +0800209 free(buf);
210
211 if (hdr_media == BRLYT_TYPE_INVALID) {
212 fprintf(stderr, "Error: media type is invalid or missing.\n");
213 fprintf(stderr, " Please specify -n \"media=<type>\"\n");
214 return -EINVAL;
215 }
216
217 if ((hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND) &&
218 !hdr_nand) {
219 fprintf(stderr, "Error: nand info is invalid or missing.\n");
220 fprintf(stderr, " Please specify -n \"media=%s;"
221 "nandinfo=<info>\"\n", media);
222 return -EINVAL;
223 }
224
Weijie Gaocadb1a82022-09-09 20:00:21 +0800225 if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
226 hdr_nand_size = mtk_nand_header_size(hdr_nand);
227
Ryder Lee3b975a12018-11-15 10:07:49 +0800228 return 0;
229}
230
231static int mtk_image_check_params(struct image_tool_params *params)
232{
233 if (!params->addr) {
234 fprintf(stderr, "Error: Load Address must be set.\n");
235 return -EINVAL;
236 }
237
238 if (!params->imagename) {
239 fprintf(stderr, "Error: Image Name must be set.\n");
240 return -EINVAL;
241 }
242
243 return mtk_brom_parse_imagename(params->imagename);
244}
245
246static int mtk_image_vrec_header(struct image_tool_params *params,
247 struct image_type_params *tparams)
248{
249 if (use_lk_hdr) {
250 tparams->header_size = sizeof(union lk_hdr);
251 tparams->hdr = &hdr_tmp;
252 memset(&hdr_tmp, 0xff, tparams->header_size);
253 return 0;
254 }
255
Weijie Gaoc561d142022-05-20 11:24:10 +0800256 if (use_mt7621_hdr) {
257 tparams->header_size = image_get_header_size();
258 tparams->hdr = &hdr_tmp;
259 memset(&hdr_tmp, 0, tparams->header_size);
260 return 0;
261 }
262
Ryder Lee3b975a12018-11-15 10:07:49 +0800263 if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
Weijie Gaocadb1a82022-09-09 20:00:21 +0800264 tparams->header_size = hdr_nand_size;
Ryder Lee3b975a12018-11-15 10:07:49 +0800265 else
266 tparams->header_size = sizeof(struct gen_device_header);
267
268 tparams->header_size += sizeof(struct gfh_header);
269 tparams->hdr = &hdr_tmp;
270
271 memset(&hdr_tmp, 0xff, tparams->header_size);
272
273 return SHA256_SUM_LEN;
274}
275
Weijie Gao687e10e2022-09-09 20:00:18 +0800276static int mtk_image_verify_gfh(struct gfh_header *gfh, uint32_t type, int print)
277{
278 if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
279 return -1;
280
281 if (le32_to_cpu(gfh->file_info.flash_type) != type)
282 return -1;
283
284 if (print)
285 printf("Load Address: %08x\n",
286 le32_to_cpu(gfh->file_info.load_addr) +
287 le32_to_cpu(gfh->file_info.jump_offset));
288
289 if (print)
290 printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM");
291
292 return 0;
293}
294
Ryder Lee3b975a12018-11-15 10:07:49 +0800295static int mtk_image_verify_gen_header(const uint8_t *ptr, int print)
296{
297 union gen_boot_header *gbh = (union gen_boot_header *)ptr;
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800298 uint32_t gfh_offset, total_size, devh_size;
Ryder Lee3b975a12018-11-15 10:07:49 +0800299 struct brom_layout_header *bh;
300 struct gfh_header *gfh;
301 const char *bootmedia;
302
303 if (!strcmp(gbh->name, SF_BOOT_NAME))
304 bootmedia = "Serial NOR";
305 else if (!strcmp(gbh->name, EMMC_BOOT_NAME))
306 bootmedia = "eMMC";
307 else if (!strcmp(gbh->name, SDMMC_BOOT_NAME))
308 bootmedia = "SD/MMC";
309 else
310 return -1;
311
312 if (print)
313 printf("Boot Media: %s\n", bootmedia);
314
315 if (le32_to_cpu(gbh->version) != 1 ||
316 le32_to_cpu(gbh->size) != sizeof(union gen_boot_header))
317 return -1;
318
319 bh = (struct brom_layout_header *)(ptr + le32_to_cpu(gbh->size));
320
321 if (strcmp(bh->name, BRLYT_NAME))
322 return -1;
323
324 if (le32_to_cpu(bh->magic) != BRLYT_MAGIC ||
325 (le32_to_cpu(bh->type) != BRLYT_TYPE_NOR &&
326 le32_to_cpu(bh->type) != BRLYT_TYPE_EMMC &&
327 le32_to_cpu(bh->type) != BRLYT_TYPE_SDMMC))
328 return -1;
329
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800330 devh_size = sizeof(struct gen_device_header);
331
332 if (img_gen) {
333 gfh_offset = devh_size;
334 } else {
335 gfh_offset = le32_to_cpu(bh->header_size);
336
337 if (gfh_offset + sizeof(struct gfh_header) > img_size) {
338 /*
339 * This may happen if the hdr_offset used to generate
340 * this image is not zero.
341 * Since device header size is not fixed, we can't
342 * cover all possible cases.
343 * Assuming the image is valid only if the real
344 * device header size equals to devh_size.
345 */
346 total_size = le32_to_cpu(bh->total_size);
347
348 if (total_size - gfh_offset > img_size - devh_size)
349 return -1;
350
351 gfh_offset = devh_size;
352 }
353 }
354
355 gfh = (struct gfh_header *)(ptr + gfh_offset);
Ryder Lee3b975a12018-11-15 10:07:49 +0800356
Weijie Gao687e10e2022-09-09 20:00:18 +0800357 return mtk_image_verify_gfh(gfh, GFH_FLASH_TYPE_GEN, print);
Ryder Lee3b975a12018-11-15 10:07:49 +0800358}
359
360static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
361{
Ryder Lee3b975a12018-11-15 10:07:49 +0800362 struct brom_layout_header *bh;
Weijie Gaocadb1a82022-09-09 20:00:21 +0800363 struct nand_header_info info;
Ryder Lee3b975a12018-11-15 10:07:49 +0800364 struct gfh_header *gfh;
365 const char *bootmedia;
Weijie Gaocadb1a82022-09-09 20:00:21 +0800366 int ret;
Ryder Lee3b975a12018-11-15 10:07:49 +0800367
Weijie Gaocadb1a82022-09-09 20:00:21 +0800368 ret = mtk_nand_header_info(ptr, &info);
369 if (ret < 0)
370 return ret;
Ryder Lee3b975a12018-11-15 10:07:49 +0800371
Weijie Gao3e333212022-09-09 20:00:25 +0800372 if (!ret) {
373 bh = (struct brom_layout_header *)(ptr + info.page_size);
Ryder Lee3b975a12018-11-15 10:07:49 +0800374
Weijie Gao3e333212022-09-09 20:00:25 +0800375 if (strcmp(bh->name, BRLYT_NAME))
376 return -1;
Ryder Lee3b975a12018-11-15 10:07:49 +0800377
Weijie Gao3e333212022-09-09 20:00:25 +0800378 if (le32_to_cpu(bh->magic) != BRLYT_MAGIC)
379 return -1;
380
Ryder Lee3b975a12018-11-15 10:07:49 +0800381 if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND)
382 bootmedia = "Parallel NAND";
383 else if (le32_to_cpu(bh->type) == BRLYT_TYPE_SNAND)
Weijie Gaocadb1a82022-09-09 20:00:21 +0800384 bootmedia = "Serial NAND (SNFI/AP)";
Ryder Lee3b975a12018-11-15 10:07:49 +0800385 else
386 return -1;
Weijie Gao3e333212022-09-09 20:00:25 +0800387 } else {
388 if (info.snfi)
389 bootmedia = "Serial NAND (SNFI/HSM)";
390 else
391 bootmedia = "Serial NAND (SPIM)";
Ryder Lee3b975a12018-11-15 10:07:49 +0800392 }
393
394 if (print) {
Weijie Gaocadb1a82022-09-09 20:00:21 +0800395 printf("Boot Media: %s\n", bootmedia);
Ryder Lee3b975a12018-11-15 10:07:49 +0800396
Weijie Gaocadb1a82022-09-09 20:00:21 +0800397 if (info.page_size >= 1024)
398 printf("Page Size: %dKB\n", info.page_size >> 10);
Ryder Lee3b975a12018-11-15 10:07:49 +0800399 else
Weijie Gaocadb1a82022-09-09 20:00:21 +0800400 printf("Page Size: %dB\n", info.page_size);
Ryder Lee3b975a12018-11-15 10:07:49 +0800401
Weijie Gaocadb1a82022-09-09 20:00:21 +0800402 printf("Spare Size: %dB\n", info.spare_size);
Ryder Lee3b975a12018-11-15 10:07:49 +0800403 }
404
Weijie Gaocadb1a82022-09-09 20:00:21 +0800405 gfh = (struct gfh_header *)(ptr + info.gfh_offset);
Ryder Lee3b975a12018-11-15 10:07:49 +0800406
Weijie Gao687e10e2022-09-09 20:00:18 +0800407 return mtk_image_verify_gfh(gfh, GFH_FLASH_TYPE_NAND, print);
Ryder Lee3b975a12018-11-15 10:07:49 +0800408}
409
Weijie Gaoc561d142022-05-20 11:24:10 +0800410static uint32_t crc32be_cal(const void *data, size_t length)
411{
412 uint32_t crc = 0;
413 uint8_t c;
414
415 if (crc32tbl[1] != MT7621_IH_CRC_POLYNOMIAL)
416 crc32_normal_init(crc32tbl, MT7621_IH_CRC_POLYNOMIAL);
417
418 crc = crc32_normal_cal(crc, data, length, crc32tbl);
419
420 for (; length; length >>= 8) {
421 c = length & 0xff;
422 crc = crc32_normal_cal(crc, &c, 1, crc32tbl);
423 }
424
425 return ~crc;
426}
427
428static int mtk_image_verify_mt7621_header(const uint8_t *ptr, int print)
429{
Simon Glassf3543e62022-09-06 20:26:52 -0600430 const struct legacy_img_hdr *hdr = (const struct legacy_img_hdr *)ptr;
Weijie Gaoc561d142022-05-20 11:24:10 +0800431 struct mt7621_nand_header *nhdr;
432 uint32_t spl_size, crcval;
Simon Glassf3543e62022-09-06 20:26:52 -0600433 struct legacy_img_hdr header;
Weijie Gaoc561d142022-05-20 11:24:10 +0800434 int ret;
435
436 spl_size = image_get_size(hdr);
437
438 if (spl_size > img_size) {
439 if (print)
440 printf("Incomplete SPL image\n");
441 return -1;
442 }
443
444 ret = image_check_hcrc(hdr);
445 if (!ret) {
446 if (print)
447 printf("Bad header CRC\n");
448 return -1;
449 }
450
451 ret = image_check_dcrc(hdr);
452 if (!ret) {
453 if (print)
454 printf("Bad data CRC\n");
455 return -1;
456 }
457
458 /* Copy header so we can blank CRC field for re-calculation */
459 memmove(&header, hdr, image_get_header_size());
460 image_set_hcrc(&header, 0);
461
462 nhdr = (struct mt7621_nand_header *)header.ih_name;
463 crcval = be32_to_cpu(nhdr->crc);
464 nhdr->crc = 0;
465
466 if (crcval != crc32be_cal(&header, image_get_header_size())) {
467 if (print)
468 printf("Bad NAND header CRC\n");
469 return -1;
470 }
471
472 if (print) {
473 printf("Load Address: %08x\n", image_get_load(hdr));
474
475 printf("Image Name: %.*s\n", MT7621_IH_NMLEN,
476 image_get_name(hdr));
477
478 if (IMAGE_ENABLE_TIMESTAMP) {
479 printf("Created: ");
480 genimg_print_time((time_t)image_get_time(hdr));
481 }
482
483 printf("Data Size: ");
484 genimg_print_size(image_get_data_size(hdr));
485 }
486
487 return 0;
488}
489
Ryder Lee3b975a12018-11-15 10:07:49 +0800490static int mtk_image_verify_header(unsigned char *ptr, int image_size,
491 struct image_tool_params *params)
492{
Simon Glassf3543e62022-09-06 20:26:52 -0600493 struct legacy_img_hdr *hdr = (struct legacy_img_hdr *)ptr;
Ryder Lee3b975a12018-11-15 10:07:49 +0800494 union lk_hdr *lk = (union lk_hdr *)ptr;
495
496 /* nothing to verify for LK image header */
497 if (le32_to_cpu(lk->magic) == LK_PART_MAGIC)
498 return 0;
499
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800500 img_size = image_size;
501
Weijie Gaoc561d142022-05-20 11:24:10 +0800502 if (image_get_magic(hdr) == IH_MAGIC)
503 return mtk_image_verify_mt7621_header(ptr, 0);
504
Weijie Gaocadb1a82022-09-09 20:00:21 +0800505 if (is_mtk_nand_header(ptr))
Ryder Lee3b975a12018-11-15 10:07:49 +0800506 return mtk_image_verify_nand_header(ptr, 0);
507 else
508 return mtk_image_verify_gen_header(ptr, 0);
509
510 return -1;
511}
512
Pali Rohár2972d7d2023-03-29 21:25:54 +0200513static void mtk_image_print_header(const void *ptr, struct image_tool_params *params)
Ryder Lee3b975a12018-11-15 10:07:49 +0800514{
Simon Glassf3543e62022-09-06 20:26:52 -0600515 struct legacy_img_hdr *hdr = (struct legacy_img_hdr *)ptr;
Ryder Lee3b975a12018-11-15 10:07:49 +0800516 union lk_hdr *lk = (union lk_hdr *)ptr;
517
518 if (le32_to_cpu(lk->magic) == LK_PART_MAGIC) {
519 printf("Image Type: MediaTek LK Image\n");
520 printf("Load Address: %08x\n", le32_to_cpu(lk->loadaddr));
521 return;
522 }
523
524 printf("Image Type: MediaTek BootROM Loadable Image\n");
525
Weijie Gaoc561d142022-05-20 11:24:10 +0800526 if (image_get_magic(hdr) == IH_MAGIC) {
527 mtk_image_verify_mt7621_header(ptr, 1);
528 return;
529 }
530
Weijie Gaocadb1a82022-09-09 20:00:21 +0800531 if (is_mtk_nand_header(ptr))
Ryder Lee3b975a12018-11-15 10:07:49 +0800532 mtk_image_verify_nand_header(ptr, 1);
533 else
534 mtk_image_verify_gen_header(ptr, 1);
535}
536
537static void put_brom_layout_header(struct brom_layout_header *hdr, int type)
538{
539 strncpy(hdr->name, BRLYT_NAME, sizeof(hdr->name));
540 hdr->version = cpu_to_le32(1);
541 hdr->magic = cpu_to_le32(BRLYT_MAGIC);
542 hdr->type = cpu_to_le32(type);
543}
544
Weijie Gao2bff97a2023-07-19 17:17:45 +0800545static void put_ghf_common_header(struct gfh_common_header *gfh, uint16_t size,
546 uint16_t type, uint8_t ver)
Ryder Lee3b975a12018-11-15 10:07:49 +0800547{
Weijie Gao2bff97a2023-07-19 17:17:45 +0800548 uint32_t magic_version = GFH_HEADER_MAGIC |
549 (uint32_t)ver << GFH_HEADER_VERSION_SHIFT;
550
551 gfh->magic_version = cpu_to_le32(magic_version);
Ryder Lee3b975a12018-11-15 10:07:49 +0800552 gfh->size = cpu_to_le16(size);
553 gfh->type = cpu_to_le16(type);
554}
555
556static void put_ghf_header(struct gfh_header *gfh, int file_size,
557 int dev_hdr_size, int load_addr, int flash_type)
558{
Fabien Parent44165e42020-10-16 19:52:37 +0200559 uint32_t cfg_bits;
560
Ryder Lee3b975a12018-11-15 10:07:49 +0800561 memset(gfh, 0, sizeof(struct gfh_header));
562
563 /* GFH_FILE_INFO header */
564 put_ghf_common_header(&gfh->file_info.gfh, sizeof(gfh->file_info),
565 GFH_TYPE_FILE_INFO, 1);
566 strncpy(gfh->file_info.name, GFH_FILE_INFO_NAME,
567 sizeof(gfh->file_info.name));
568 gfh->file_info.unused = cpu_to_le32(1);
569 gfh->file_info.file_type = cpu_to_le16(1);
570 gfh->file_info.flash_type = flash_type;
571 gfh->file_info.sig_type = GFH_SIG_TYPE_SHA256;
572 gfh->file_info.load_addr = cpu_to_le32(load_addr - sizeof(*gfh));
573 gfh->file_info.total_size = cpu_to_le32(file_size - dev_hdr_size);
574 gfh->file_info.max_size = cpu_to_le32(file_size);
575 gfh->file_info.hdr_size = sizeof(*gfh);
576 gfh->file_info.sig_size = SHA256_SUM_LEN;
577 gfh->file_info.jump_offset = sizeof(*gfh);
578 gfh->file_info.processed = cpu_to_le32(1);
579
580 /* GFH_BL_INFO header */
581 put_ghf_common_header(&gfh->bl_info.gfh, sizeof(gfh->bl_info),
582 GFH_TYPE_BL_INFO, 1);
583 gfh->bl_info.attr = cpu_to_le32(1);
584
585 /* GFH_BROM_CFG header */
586 put_ghf_common_header(&gfh->brom_cfg.gfh, sizeof(gfh->brom_cfg),
587 GFH_TYPE_BROM_CFG, 3);
Fabien Parent44165e42020-10-16 19:52:37 +0200588 cfg_bits = GFH_BROM_CFG_USBDL_AUTO_DETECT_DIS |
589 GFH_BROM_CFG_USBDL_BY_KCOL0_TIMEOUT_EN |
590 GFH_BROM_CFG_USBDL_BY_FLAG_TIMEOUT_EN;
Ryder Lee3b975a12018-11-15 10:07:49 +0800591 gfh->brom_cfg.usbdl_by_kcol0_timeout_ms = cpu_to_le32(5000);
Fabien Parent44165e42020-10-16 19:52:37 +0200592 if (is_arm64_image) {
593 gfh->brom_cfg.jump_bl_arm64 = GFH_BROM_CFG_JUMP_BL_ARM64;
594 cfg_bits |= GFH_BROM_CFG_JUMP_BL_ARM64_EN;
595 }
596 gfh->brom_cfg.cfg_bits = cpu_to_le32(cfg_bits);
Ryder Lee3b975a12018-11-15 10:07:49 +0800597
598 /* GFH_BL_SEC_KEY header */
599 put_ghf_common_header(&gfh->bl_sec_key.gfh, sizeof(gfh->bl_sec_key),
600 GFH_TYPE_BL_SEC_KEY, 1);
601
602 /* GFH_ANTI_CLONE header */
603 put_ghf_common_header(&gfh->anti_clone.gfh, sizeof(gfh->anti_clone),
604 GFH_TYPE_ANTI_CLONE, 1);
605 gfh->anti_clone.ac_offset = cpu_to_le32(0x10);
606 gfh->anti_clone.ac_len = cpu_to_le32(0x80);
607
608 /* GFH_BROM_SEC_CFG header */
609 put_ghf_common_header(&gfh->brom_sec_cfg.gfh,
610 sizeof(gfh->brom_sec_cfg),
611 GFH_TYPE_BROM_SEC_CFG, 1);
612 gfh->brom_sec_cfg.cfg_bits =
613 cpu_to_le32(BROM_SEC_CFG_JTAG_EN | BROM_SEC_CFG_UART_EN);
614}
615
616static void put_hash(uint8_t *buff, int size)
617{
618 sha256_context ctx;
619
620 sha256_starts(&ctx);
621 sha256_update(&ctx, buff, size);
622 sha256_finish(&ctx, buff + size);
623}
624
625static void mtk_image_set_gen_header(void *ptr, off_t filesize,
626 uint32_t loadaddr)
627{
628 struct gen_device_header *hdr = (struct gen_device_header *)ptr;
629 struct gfh_header *gfh;
630 const char *bootname = NULL;
631
632 if (hdr_media == BRLYT_TYPE_NOR)
633 bootname = SF_BOOT_NAME;
634 else if (hdr_media == BRLYT_TYPE_EMMC)
635 bootname = EMMC_BOOT_NAME;
636 else if (hdr_media == BRLYT_TYPE_SDMMC)
637 bootname = SDMMC_BOOT_NAME;
638
639 /* Generic device header */
Andy Shevchenko74473ed2018-12-11 16:41:43 +0200640 snprintf(hdr->boot.name, sizeof(hdr->boot.name), "%s", bootname);
Ryder Lee3b975a12018-11-15 10:07:49 +0800641 hdr->boot.version = cpu_to_le32(1);
642 hdr->boot.size = cpu_to_le32(sizeof(hdr->boot));
643
644 /* BRLYT header */
645 put_brom_layout_header(&hdr->brlyt, hdr_media);
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800646 hdr->brlyt.header_size = cpu_to_le32(hdr_offset + sizeof(*hdr));
647 hdr->brlyt.total_size = cpu_to_le32(hdr_offset + filesize);
Ryder Lee3b975a12018-11-15 10:07:49 +0800648 hdr->brlyt.header_size_2 = hdr->brlyt.header_size;
649 hdr->brlyt.total_size_2 = hdr->brlyt.total_size;
650
651 /* GFH header */
652 gfh = (struct gfh_header *)(ptr + sizeof(struct gen_device_header));
653 put_ghf_header(gfh, filesize, sizeof(struct gen_device_header),
654 loadaddr, GFH_FLASH_TYPE_GEN);
655
656 /* Generate SHA256 hash */
657 put_hash((uint8_t *)gfh,
658 filesize - sizeof(struct gen_device_header) - SHA256_SUM_LEN);
659}
660
661static void mtk_image_set_nand_header(void *ptr, off_t filesize,
662 uint32_t loadaddr)
663{
Ryder Lee3b975a12018-11-15 10:07:49 +0800664 struct brom_layout_header *brlyt;
665 struct gfh_header *gfh;
Weijie Gaocadb1a82022-09-09 20:00:21 +0800666 uint32_t payload_pages, nand_page_size;
Ryder Lee3b975a12018-11-15 10:07:49 +0800667
Weijie Gaocadb1a82022-09-09 20:00:21 +0800668 /* NAND header */
669 nand_page_size = mtk_nand_header_put(hdr_nand, ptr);
Ryder Lee3b975a12018-11-15 10:07:49 +0800670
Weijie Gaocadb1a82022-09-09 20:00:21 +0800671 if (nand_page_size) {
672 /* BRLYT header */
673 payload_pages = (filesize + nand_page_size - 1) /
674 nand_page_size;
675 brlyt = (struct brom_layout_header *)(ptr + nand_page_size);
676 put_brom_layout_header(brlyt, hdr_media);
677 brlyt->header_size = cpu_to_le32(2);
678 brlyt->total_size = cpu_to_le32(payload_pages);
679 brlyt->header_size_2 = brlyt->header_size;
680 brlyt->total_size_2 = brlyt->total_size;
681 brlyt->unused = cpu_to_le32(1);
682 }
Ryder Lee3b975a12018-11-15 10:07:49 +0800683
684 /* GFH header */
Weijie Gaocadb1a82022-09-09 20:00:21 +0800685 gfh = (struct gfh_header *)(ptr + hdr_nand_size);
686 put_ghf_header(gfh, filesize, hdr_nand_size, loadaddr,
687 GFH_FLASH_TYPE_NAND);
Ryder Lee3b975a12018-11-15 10:07:49 +0800688
689 /* Generate SHA256 hash */
Weijie Gaocadb1a82022-09-09 20:00:21 +0800690 put_hash((uint8_t *)gfh, filesize - hdr_nand_size - SHA256_SUM_LEN);
Ryder Lee3b975a12018-11-15 10:07:49 +0800691}
692
Weijie Gaoc561d142022-05-20 11:24:10 +0800693static void mtk_image_set_mt7621_header(void *ptr, off_t filesize,
694 uint32_t loadaddr)
695{
Simon Glassf3543e62022-09-06 20:26:52 -0600696 struct legacy_img_hdr *hdr = (struct legacy_img_hdr *)ptr;
Weijie Gaoc561d142022-05-20 11:24:10 +0800697 struct mt7621_stage1_header *shdr;
698 struct mt7621_nand_header *nhdr;
699 uint32_t datasize, crcval;
700
701 datasize = filesize - image_get_header_size();
702 nhdr = (struct mt7621_nand_header *)hdr->ih_name;
703 shdr = (struct mt7621_stage1_header *)(ptr + image_get_header_size());
704
705 shdr->ep = cpu_to_be32(loadaddr);
706 shdr->stage_size = cpu_to_be32(datasize);
707
708 image_set_magic(hdr, IH_MAGIC);
709 image_set_time(hdr, time(NULL));
710 image_set_size(hdr, datasize);
711 image_set_load(hdr, loadaddr);
712 image_set_ep(hdr, loadaddr);
713 image_set_os(hdr, IH_OS_U_BOOT);
714 image_set_arch(hdr, IH_ARCH_MIPS);
715 image_set_type(hdr, IH_TYPE_STANDALONE);
716 image_set_comp(hdr, IH_COMP_NONE);
717
718 crcval = crc32(0, (uint8_t *)shdr, datasize);
719 image_set_dcrc(hdr, crcval);
720
721 strncpy(nhdr->ih_name, "MT7621 NAND", MT7621_IH_NMLEN);
722
723 nhdr->ih_stage_offset = cpu_to_be32(image_get_header_size());
724
725 crcval = crc32be_cal(hdr, image_get_header_size());
726 nhdr->crc = cpu_to_be32(crcval);
727
728 crcval = crc32(0, (uint8_t *)hdr, image_get_header_size());
729 image_set_hcrc(hdr, crcval);
730}
731
Ryder Lee3b975a12018-11-15 10:07:49 +0800732static void mtk_image_set_header(void *ptr, struct stat *sbuf, int ifd,
733 struct image_tool_params *params)
734{
735 union lk_hdr *lk = (union lk_hdr *)ptr;
736
737 if (use_lk_hdr) {
738 lk->magic = cpu_to_le32(LK_PART_MAGIC);
739 lk->size = cpu_to_le32(sbuf->st_size - sizeof(union lk_hdr));
740 lk->loadaddr = cpu_to_le32(params->addr);
741 lk->mode = 0xffffffff; /* must be non-zero */
742 memset(lk->name, 0, sizeof(lk->name));
743 strncpy(lk->name, lk_name, sizeof(lk->name));
744 return;
745 }
746
Weijie Gaocfd48ec2021-03-09 15:52:31 +0800747 img_gen = true;
748 img_size = sbuf->st_size;
749
Weijie Gaoc561d142022-05-20 11:24:10 +0800750 if (use_mt7621_hdr) {
751 mtk_image_set_mt7621_header(ptr, sbuf->st_size, params->addr);
752 return;
753 }
754
Ryder Lee3b975a12018-11-15 10:07:49 +0800755 if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
756 mtk_image_set_nand_header(ptr, sbuf->st_size, params->addr);
757 else
758 mtk_image_set_gen_header(ptr, sbuf->st_size, params->addr);
759}
760
761U_BOOT_IMAGE_TYPE(
762 mtk_image,
763 "MediaTek BootROM Loadable Image support",
764 0,
765 NULL,
766 mtk_image_check_params,
767 mtk_image_verify_header,
768 mtk_image_print_header,
769 mtk_image_set_header,
770 NULL,
771 mtk_image_check_image_types,
772 NULL,
773 mtk_image_vrec_header
774);