Skip to content

Commit c561d14

Browse files
hackpascaldanielschwierzeck
authored andcommitted
tools: mtk_image: add support for MT7621 NAND images
The BootROM of MT7621 requires a image header for SPL to record its size and load address when booting from NAND. To create such an image, one can use the following command line: mkimage -T mtk_image -a 0x80200000 -e 0x80200000 -n "mt7621=1" -d u-boot-spl-ddr.bin u-boot-spl-ddr.img Reviewed-by: Daniel Schwierzeck <[email protected]> Signed-off-by: Weijie Gao <[email protected]>
1 parent 4620e8a commit c561d14

File tree

2 files changed

+206
-0
lines changed

2 files changed

+206
-0
lines changed

tools/mtk_image.c

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
* Author: Weijie Gao <[email protected]>
77
*/
88

9+
#include <time.h>
910
#include <image.h>
11+
#include <u-boot/crc.h>
1012
#include <u-boot/sha256.h>
1113
#include "imagetool.h"
1214
#include "mtk_image.h"
@@ -251,17 +253,45 @@ static uint32_t img_size;
251253
static enum brlyt_img_type hdr_media;
252254
static uint32_t hdr_offset;
253255
static int use_lk_hdr;
256+
static int use_mt7621_hdr;
254257
static bool is_arm64_image;
255258

256259
/* LK image name */
257260
static char lk_name[32] = "U-Boot";
258261

262+
/* CRC32 normal table required by MT7621 image */
263+
static uint32_t crc32tbl[256];
264+
259265
/* NAND header selected by user */
260266
static const union nand_boot_header *hdr_nand;
261267

262268
/* GFH header + 2 * 4KB pages of NAND */
263269
static char hdr_tmp[sizeof(struct gfh_header) + 0x2000];
264270

271+
static 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+
282+
static 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+
265295
static int mtk_image_check_image_types(uint8_t type)
266296
{
267297
if (type == IH_TYPE_MTKIMAGE)
@@ -283,6 +313,7 @@ static int mtk_brom_parse_imagename(const char *imagename)
283313
static const char *hdr_offs = "";
284314
static const char *nandinfo = "";
285315
static const char *lk = "";
316+
static const char *mt7621 = "";
286317
static const char *arm64_param = "";
287318

288319
key = buf;
@@ -332,6 +363,9 @@ static int mtk_brom_parse_imagename(const char *imagename)
332363
if (!strcmp(key, "lk"))
333364
lk = val;
334365

366+
if (!strcmp(key, "mt7621"))
367+
mt7621 = val;
368+
335369
if (!strcmp(key, "lkname"))
336370
snprintf(lk_name, sizeof(lk_name), "%s", val);
337371

@@ -352,6 +386,13 @@ static int mtk_brom_parse_imagename(const char *imagename)
352386
return 0;
353387
}
354388

389+
/* 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+
355396
/* parse media type */
356397
for (i = 0; i < ARRAY_SIZE(brom_images); i++) {
357398
if (!strcmp(brom_images[i].name, media)) {
@@ -419,6 +460,13 @@ static int mtk_image_vrec_header(struct image_tool_params *params,
419460
return 0;
420461
}
421462

463+
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+
422470
if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
423471
tparams->header_size = 2 * le16_to_cpu(hdr_nand->pagesize);
424472
else
@@ -579,9 +627,90 @@ static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
579627
return 0;
580628
}
581629

630+
static 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+
648+
static 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+
582710
static int mtk_image_verify_header(unsigned char *ptr, int image_size,
583711
struct image_tool_params *params)
584712
{
713+
image_header_t *hdr = (image_header_t *)ptr;
585714
union lk_hdr *lk = (union lk_hdr *)ptr;
586715

587716
/* nothing to verify for LK image header */
@@ -590,6 +719,9 @@ static int mtk_image_verify_header(unsigned char *ptr, int image_size,
590719

591720
img_size = image_size;
592721

722+
if (image_get_magic(hdr) == IH_MAGIC)
723+
return mtk_image_verify_mt7621_header(ptr, 0);
724+
593725
if (!strcmp((char *)ptr, NAND_BOOT_NAME))
594726
return mtk_image_verify_nand_header(ptr, 0);
595727
else
@@ -600,6 +732,7 @@ static int mtk_image_verify_header(unsigned char *ptr, int image_size,
600732

601733
static void mtk_image_print_header(const void *ptr)
602734
{
735+
image_header_t *hdr = (image_header_t *)ptr;
603736
union lk_hdr *lk = (union lk_hdr *)ptr;
604737

605738
if (le32_to_cpu(lk->magic) == LK_PART_MAGIC) {
@@ -610,6 +743,11 @@ static void mtk_image_print_header(const void *ptr)
610743

611744
printf("Image Type: MediaTek BootROM Loadable Image\n");
612745

746+
if (image_get_magic(hdr) == IH_MAGIC) {
747+
mtk_image_verify_mt7621_header(ptr, 1);
748+
return;
749+
}
750+
613751
if (!strcmp((char *)ptr, NAND_BOOT_NAME))
614752
mtk_image_verify_nand_header(ptr, 1);
615753
else
@@ -773,6 +911,45 @@ static void mtk_image_set_nand_header(void *ptr, off_t filesize,
773911
filesize - 2 * le16_to_cpu(hdr_nand->pagesize) - SHA256_SUM_LEN);
774912
}
775913

914+
static 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+
776953
static void mtk_image_set_header(void *ptr, struct stat *sbuf, int ifd,
777954
struct image_tool_params *params)
778955
{
@@ -791,6 +968,11 @@ static void mtk_image_set_header(void *ptr, struct stat *sbuf, int ifd,
791968
img_gen = true;
792969
img_size = sbuf->st_size;
793970

971+
if (use_mt7621_hdr) {
972+
mtk_image_set_mt7621_header(ptr, sbuf->st_size, params->addr);
973+
return;
974+
}
975+
794976
if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
795977
mtk_image_set_nand_header(ptr, sbuf->st_size, params->addr);
796978
else

tools/mtk_image.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,4 +200,28 @@ union lk_hdr {
200200

201201
#define LK_PART_MAGIC 0x58881688
202202

203+
/* MT7621 NAND SPL image header */
204+
205+
#define MT7621_IH_NMLEN 12
206+
#define MT7621_IH_CRC_POLYNOMIAL 0x04c11db7
207+
208+
struct mt7621_nand_header {
209+
char ih_name[MT7621_IH_NMLEN];
210+
uint32_t nand_ac_timing;
211+
uint32_t ih_stage_offset;
212+
uint32_t ih_bootloader_offset;
213+
uint32_t nand_info_1_data;
214+
uint32_t crc;
215+
};
216+
217+
struct mt7621_stage1_header {
218+
uint32_t jump_insn[2];
219+
uint32_t ep;
220+
uint32_t stage_size;
221+
uint32_t has_stage2;
222+
uint32_t next_ep;
223+
uint32_t next_size;
224+
uint32_t next_offset;
225+
};
226+
203227
#endif /* _MTK_IMAGE_H */

0 commit comments

Comments
 (0)