13b975a14SRyder Lee // SPDX-License-Identifier: GPL-2.0+
23b975a14SRyder Lee /*
33b975a14SRyder Lee * Generate MediaTek BootROM header for SPL/U-Boot images
43b975a14SRyder Lee *
53b975a14SRyder Lee * Copyright (C) 2018 MediaTek Inc.
63b975a14SRyder Lee * Author: Weijie Gao <weijie.gao@mediatek.com>
73b975a14SRyder Lee */
83b975a14SRyder Lee
93b975a14SRyder Lee #include <image.h>
103b975a14SRyder Lee #include <u-boot/sha256.h>
113b975a14SRyder Lee #include "imagetool.h"
123b975a14SRyder Lee #include "mtk_image.h"
133b975a14SRyder Lee
143b975a14SRyder Lee /* NAND header for SPI-NAND with 2KB page + 64B spare */
153b975a14SRyder Lee static const union nand_boot_header snand_hdr_2k_64_data = {
163b975a14SRyder Lee .data = {
173b975a14SRyder Lee 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
183b975a14SRyder Lee 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
193b975a14SRyder Lee 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
203b975a14SRyder Lee 0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x40, 0x00,
213b975a14SRyder Lee 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
223b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
243b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
253b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
263b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
273b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
283b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
293b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x7B, 0xC4, 0x17, 0x9D,
303b975a14SRyder Lee 0xCA, 0x42, 0x90, 0xD0, 0x98, 0xD0, 0xE0, 0xF7,
313b975a14SRyder Lee 0xDB, 0xCD, 0x16, 0xF6, 0x03, 0x73, 0xD2, 0xB8,
323b975a14SRyder Lee 0x93, 0xB2, 0x56, 0x5A, 0x84, 0x6E, 0x00, 0x00
333b975a14SRyder Lee }
343b975a14SRyder Lee };
353b975a14SRyder Lee
363b975a14SRyder Lee /* NAND header for SPI-NAND with 2KB page + 120B/128B spare */
373b975a14SRyder Lee static const union nand_boot_header snand_hdr_2k_128_data = {
383b975a14SRyder Lee .data = {
393b975a14SRyder Lee 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
403b975a14SRyder Lee 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
413b975a14SRyder Lee 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
423b975a14SRyder Lee 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
433b975a14SRyder Lee 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
443b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
453b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
463b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
483b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
493b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
503b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
513b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x90, 0x28, 0xED, 0x13,
523b975a14SRyder Lee 0x7F, 0x12, 0x22, 0xCD, 0x3D, 0x06, 0xF1, 0xB3,
533b975a14SRyder Lee 0x6F, 0x2E, 0xD9, 0xA0, 0x9D, 0x7A, 0xBD, 0xD7,
543b975a14SRyder Lee 0xB3, 0x28, 0x3C, 0x13, 0xDB, 0x4E, 0x00, 0x00
553b975a14SRyder Lee }
563b975a14SRyder Lee };
573b975a14SRyder Lee
583b975a14SRyder Lee /* NAND header for SPI-NAND with 4KB page + 256B spare */
593b975a14SRyder Lee static const union nand_boot_header snand_hdr_4k_256_data = {
603b975a14SRyder Lee .data = {
613b975a14SRyder Lee 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
623b975a14SRyder Lee 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
633b975a14SRyder Lee 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
643b975a14SRyder Lee 0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0xE0, 0x00,
653b975a14SRyder Lee 0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
663b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
673b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
683b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
693b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
703b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
713b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
723b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
733b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x47, 0xED, 0x0E, 0xC3,
743b975a14SRyder Lee 0x83, 0xBF, 0x41, 0xD2, 0x85, 0x21, 0x97, 0x57,
753b975a14SRyder Lee 0xC4, 0x2E, 0x6B, 0x7A, 0x40, 0xE0, 0xCF, 0x8F,
763b975a14SRyder Lee 0x37, 0xBD, 0x17, 0xB6, 0xC7, 0xFE, 0x00, 0x00
773b975a14SRyder Lee }
783b975a14SRyder Lee };
793b975a14SRyder Lee
803b975a14SRyder Lee /* NAND header for Parallel NAND 1Gb with 2KB page + 64B spare */
813b975a14SRyder Lee static const union nand_boot_header nand_hdr_1gb_2k_64_data = {
823b975a14SRyder Lee .data = {
833b975a14SRyder Lee 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
843b975a14SRyder Lee 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
853b975a14SRyder Lee 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
863b975a14SRyder Lee 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
873b975a14SRyder Lee 0x40, 0x00, 0x00, 0x04, 0x0B, 0x00, 0x11, 0x00,
883b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
893b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
903b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
913b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
923b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
933b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
943b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
953b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x12, 0x28, 0x1C, 0x12,
963b975a14SRyder Lee 0x8F, 0xFD, 0xF8, 0x32, 0x6F, 0x6D, 0xCF, 0x6C,
973b975a14SRyder Lee 0xDA, 0x21, 0x70, 0x8C, 0xDA, 0x0A, 0x22, 0x82,
983b975a14SRyder Lee 0xAA, 0x59, 0xFA, 0x7C, 0x42, 0x2D, 0x00, 0x00
993b975a14SRyder Lee }
1003b975a14SRyder Lee };
1013b975a14SRyder Lee
1023b975a14SRyder Lee /* NAND header for Parallel NAND 2Gb with 2KB page + 64B spare */
1033b975a14SRyder Lee static const union nand_boot_header nand_hdr_2gb_2k_64_data = {
1043b975a14SRyder Lee .data = {
1053b975a14SRyder Lee 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
1063b975a14SRyder Lee 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
1073b975a14SRyder Lee 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
1083b975a14SRyder Lee 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
1093b975a14SRyder Lee 0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
1103b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1113b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1123b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1133b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1143b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1153b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1163b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1173b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x20, 0x9C, 0x3D, 0x2D,
1183b975a14SRyder Lee 0x7B, 0x68, 0x63, 0x52, 0x2E, 0x04, 0x63, 0xF1,
1193b975a14SRyder Lee 0x35, 0x4E, 0x44, 0x3E, 0xF8, 0xAC, 0x9B, 0x95,
1203b975a14SRyder Lee 0xAB, 0xFE, 0xE4, 0xE1, 0xD5, 0xF9, 0x00, 0x00
1213b975a14SRyder Lee }
1223b975a14SRyder Lee };
1233b975a14SRyder Lee
1243b975a14SRyder Lee /* NAND header for Parallel NAND 4Gb with 2KB page + 64B spare */
1253b975a14SRyder Lee static const union nand_boot_header nand_hdr_4gb_2k_64_data = {
1263b975a14SRyder Lee .data = {
1273b975a14SRyder Lee 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
1283b975a14SRyder Lee 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
1293b975a14SRyder Lee 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
1303b975a14SRyder Lee 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
1313b975a14SRyder Lee 0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
1323b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1333b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1343b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1353b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1363b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1373b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1383b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1393b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0xE3, 0x0F, 0x86, 0x32,
1403b975a14SRyder Lee 0x68, 0x05, 0xD9, 0xC8, 0x13, 0xDF, 0xC5, 0x0B,
1413b975a14SRyder Lee 0x35, 0x3A, 0x68, 0xA5, 0x3C, 0x0C, 0x73, 0x87,
1423b975a14SRyder Lee 0x63, 0xB0, 0xBE, 0xCC, 0x84, 0x47, 0x00, 0x00
1433b975a14SRyder Lee }
1443b975a14SRyder Lee };
1453b975a14SRyder Lee
1463b975a14SRyder Lee /* NAND header for Parallel NAND 2Gb with 2KB page + 128B spare */
1473b975a14SRyder Lee static const union nand_boot_header nand_hdr_2gb_2k_128_data = {
1483b975a14SRyder Lee .data = {
1493b975a14SRyder Lee 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
1503b975a14SRyder Lee 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
1513b975a14SRyder Lee 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
1523b975a14SRyder Lee 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
1533b975a14SRyder Lee 0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
1543b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1553b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1563b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1573b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1583b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1593b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1603b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1613b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x01, 0xA5, 0xE9, 0x5A,
1623b975a14SRyder Lee 0xDF, 0x58, 0x62, 0x41, 0xD6, 0x26, 0x77, 0xBC,
1633b975a14SRyder Lee 0x76, 0x1F, 0x27, 0x4E, 0x4F, 0x6C, 0xC3, 0xF0,
1643b975a14SRyder Lee 0x36, 0xDE, 0xD9, 0xB3, 0xFF, 0x93, 0x00, 0x00
1653b975a14SRyder Lee }
1663b975a14SRyder Lee };
1673b975a14SRyder Lee
1683b975a14SRyder Lee /* NAND header for Parallel NAND 4Gb with 2KB page + 128B spare */
1693b975a14SRyder Lee static const union nand_boot_header nand_hdr_4gb_2k_128_data = {
1703b975a14SRyder Lee .data = {
1713b975a14SRyder Lee 0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
1723b975a14SRyder Lee 0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
1733b975a14SRyder Lee 0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
1743b975a14SRyder Lee 0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
1753b975a14SRyder Lee 0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
1763b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1773b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1783b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1793b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1803b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1813b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1823b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1833b975a14SRyder Lee 0x00, 0x00, 0x00, 0x00, 0xC2, 0x36, 0x52, 0x45,
1843b975a14SRyder Lee 0xCC, 0x35, 0xD8, 0xDB, 0xEB, 0xFD, 0xD1, 0x46,
1853b975a14SRyder Lee 0x76, 0x6B, 0x0B, 0xD5, 0x8B, 0xCC, 0x2B, 0xE2,
1863b975a14SRyder Lee 0xFE, 0x90, 0x83, 0x9E, 0xAE, 0x2D, 0x00, 0x00
1873b975a14SRyder Lee }
1883b975a14SRyder Lee };
1893b975a14SRyder Lee
1903b975a14SRyder Lee static const struct nand_header_type {
1913b975a14SRyder Lee const char *name;
1923b975a14SRyder Lee const union nand_boot_header *data;
1933b975a14SRyder Lee } nand_headers[] = {
1943b975a14SRyder Lee {
1953b975a14SRyder Lee .name = "2k+64",
1963b975a14SRyder Lee .data = &snand_hdr_2k_64_data
1973b975a14SRyder Lee }, {
1983b975a14SRyder Lee .name = "2k+120",
1993b975a14SRyder Lee .data = &snand_hdr_2k_128_data
2003b975a14SRyder Lee }, {
2013b975a14SRyder Lee .name = "2k+128",
2023b975a14SRyder Lee .data = &snand_hdr_2k_128_data
2033b975a14SRyder Lee }, {
2043b975a14SRyder Lee .name = "4k+256",
2053b975a14SRyder Lee .data = &snand_hdr_4k_256_data
2063b975a14SRyder Lee }, {
2073b975a14SRyder Lee .name = "1g:2k+64",
2083b975a14SRyder Lee .data = &nand_hdr_1gb_2k_64_data
2093b975a14SRyder Lee }, {
2103b975a14SRyder Lee .name = "2g:2k+64",
2113b975a14SRyder Lee .data = &nand_hdr_2gb_2k_64_data
2123b975a14SRyder Lee }, {
2133b975a14SRyder Lee .name = "4g:2k+64",
2143b975a14SRyder Lee .data = &nand_hdr_4gb_2k_64_data
2153b975a14SRyder Lee }, {
2163b975a14SRyder Lee .name = "2g:2k+128",
2173b975a14SRyder Lee .data = &nand_hdr_2gb_2k_128_data
2183b975a14SRyder Lee }, {
2193b975a14SRyder Lee .name = "4g:2k+128",
2203b975a14SRyder Lee .data = &nand_hdr_4gb_2k_128_data
2213b975a14SRyder Lee }
2223b975a14SRyder Lee };
2233b975a14SRyder Lee
2243b975a14SRyder Lee static const struct brom_img_type {
2253b975a14SRyder Lee const char *name;
2263b975a14SRyder Lee enum brlyt_img_type type;
2273b975a14SRyder Lee } brom_images[] = {
2283b975a14SRyder Lee {
2293b975a14SRyder Lee .name = "nand",
2303b975a14SRyder Lee .type = BRLYT_TYPE_NAND
2313b975a14SRyder Lee }, {
2323b975a14SRyder Lee .name = "emmc",
2333b975a14SRyder Lee .type = BRLYT_TYPE_EMMC
2343b975a14SRyder Lee }, {
2353b975a14SRyder Lee .name = "nor",
2363b975a14SRyder Lee .type = BRLYT_TYPE_NOR
2373b975a14SRyder Lee }, {
2383b975a14SRyder Lee .name = "sdmmc",
2393b975a14SRyder Lee .type = BRLYT_TYPE_SDMMC
2403b975a14SRyder Lee }, {
2413b975a14SRyder Lee .name = "snand",
2423b975a14SRyder Lee .type = BRLYT_TYPE_SNAND
2433b975a14SRyder Lee }
2443b975a14SRyder Lee };
2453b975a14SRyder Lee
2463b975a14SRyder Lee /* Image type selected by user */
2473b975a14SRyder Lee static enum brlyt_img_type hdr_media;
2483b975a14SRyder Lee static int use_lk_hdr;
2493b975a14SRyder Lee
2503b975a14SRyder Lee /* LK image name */
2513b975a14SRyder Lee static char lk_name[32] = "U-Boot";
2523b975a14SRyder Lee
2533b975a14SRyder Lee /* NAND header selected by user */
2543b975a14SRyder Lee static const union nand_boot_header *hdr_nand;
2553b975a14SRyder Lee
2563b975a14SRyder Lee /* GFH header + 2 * 4KB pages of NAND */
2573b975a14SRyder Lee static char hdr_tmp[sizeof(struct gfh_header) + 0x2000];
2583b975a14SRyder Lee
mtk_image_check_image_types(uint8_t type)2593b975a14SRyder Lee static int mtk_image_check_image_types(uint8_t type)
2603b975a14SRyder Lee {
2613b975a14SRyder Lee if (type == IH_TYPE_MTKIMAGE)
2623b975a14SRyder Lee return EXIT_SUCCESS;
2633b975a14SRyder Lee else
2643b975a14SRyder Lee return EXIT_FAILURE;
2653b975a14SRyder Lee }
2663b975a14SRyder Lee
mtk_brom_parse_imagename(const char * imagename)2673b975a14SRyder Lee static int mtk_brom_parse_imagename(const char *imagename)
2683b975a14SRyder Lee {
2693b975a14SRyder Lee #define is_blank_char(c) \
2703b975a14SRyder Lee ((c) == '\t' || (c) == '\n' || (c) == '\r' || (c) == ' ')
2713b975a14SRyder Lee
2723b975a14SRyder Lee char *buf = strdup(imagename), *key, *val, *end, *next;
2733b975a14SRyder Lee int i;
2743b975a14SRyder Lee
2753b975a14SRyder Lee /* User passed arguments from image name */
2763b975a14SRyder Lee static const char *media = "";
2773b975a14SRyder Lee static const char *nandinfo = "";
2783b975a14SRyder Lee static const char *lk = "";
2793b975a14SRyder Lee
2803b975a14SRyder Lee key = buf;
2813b975a14SRyder Lee while (key) {
2823b975a14SRyder Lee next = strchr(key, ';');
2833b975a14SRyder Lee if (next)
2843b975a14SRyder Lee *next = 0;
2853b975a14SRyder Lee
2863b975a14SRyder Lee val = strchr(key, '=');
2873b975a14SRyder Lee if (val) {
2883b975a14SRyder Lee *val++ = 0;
2893b975a14SRyder Lee
2903b975a14SRyder Lee /* Trim key */
2913b975a14SRyder Lee while (is_blank_char(*key))
2923b975a14SRyder Lee key++;
2933b975a14SRyder Lee
2943b975a14SRyder Lee end = key + strlen(key) - 1;
2953b975a14SRyder Lee while ((end >= key) && is_blank_char(*end))
2963b975a14SRyder Lee end--;
2973b975a14SRyder Lee end++;
2983b975a14SRyder Lee
2993b975a14SRyder Lee if (is_blank_char(*end))
3003b975a14SRyder Lee *end = 0;
3013b975a14SRyder Lee
3023b975a14SRyder Lee /* Trim value */
3033b975a14SRyder Lee while (is_blank_char(*val))
3043b975a14SRyder Lee val++;
3053b975a14SRyder Lee
3063b975a14SRyder Lee end = val + strlen(val) - 1;
3073b975a14SRyder Lee while ((end >= val) && is_blank_char(*end))
3083b975a14SRyder Lee end--;
3093b975a14SRyder Lee end++;
3103b975a14SRyder Lee
3113b975a14SRyder Lee if (is_blank_char(*end))
3123b975a14SRyder Lee *end = 0;
3133b975a14SRyder Lee
3143b975a14SRyder Lee /* record user passed arguments */
3153b975a14SRyder Lee if (!strcmp(key, "media"))
3163b975a14SRyder Lee media = val;
3173b975a14SRyder Lee
3183b975a14SRyder Lee if (!strcmp(key, "nandinfo"))
3193b975a14SRyder Lee nandinfo = val;
3203b975a14SRyder Lee
3213b975a14SRyder Lee if (!strcmp(key, "lk"))
3223b975a14SRyder Lee lk = val;
3233b975a14SRyder Lee
3243b975a14SRyder Lee if (!strcmp(key, "lkname"))
325*74473ed0SAndy Shevchenko snprintf(lk_name, sizeof(lk_name), "%s", val);
3263b975a14SRyder Lee }
3273b975a14SRyder Lee
3283b975a14SRyder Lee if (next)
3293b975a14SRyder Lee key = next + 1;
3303b975a14SRyder Lee else
3313b975a14SRyder Lee break;
3323b975a14SRyder Lee }
3333b975a14SRyder Lee
3343b975a14SRyder Lee /* if user specified LK image header, skip following checks */
3353b975a14SRyder Lee if (lk && lk[0] == '1') {
3363b975a14SRyder Lee use_lk_hdr = 1;
3373b975a14SRyder Lee free(buf);
3383b975a14SRyder Lee return 0;
3393b975a14SRyder Lee }
3403b975a14SRyder Lee
3413b975a14SRyder Lee /* parse media type */
3423b975a14SRyder Lee for (i = 0; i < ARRAY_SIZE(brom_images); i++) {
3433b975a14SRyder Lee if (!strcmp(brom_images[i].name, media)) {
3443b975a14SRyder Lee hdr_media = brom_images[i].type;
3453b975a14SRyder Lee break;
3463b975a14SRyder Lee }
3473b975a14SRyder Lee }
3483b975a14SRyder Lee
3493b975a14SRyder Lee /* parse nand header type */
3503b975a14SRyder Lee for (i = 0; i < ARRAY_SIZE(nand_headers); i++) {
3513b975a14SRyder Lee if (!strcmp(nand_headers[i].name, nandinfo)) {
3523b975a14SRyder Lee hdr_nand = nand_headers[i].data;
3533b975a14SRyder Lee break;
3543b975a14SRyder Lee }
3553b975a14SRyder Lee }
3563b975a14SRyder Lee
3573b975a14SRyder Lee free(buf);
3583b975a14SRyder Lee
3593b975a14SRyder Lee if (hdr_media == BRLYT_TYPE_INVALID) {
3603b975a14SRyder Lee fprintf(stderr, "Error: media type is invalid or missing.\n");
3613b975a14SRyder Lee fprintf(stderr, " Please specify -n \"media=<type>\"\n");
3623b975a14SRyder Lee return -EINVAL;
3633b975a14SRyder Lee }
3643b975a14SRyder Lee
3653b975a14SRyder Lee if ((hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND) &&
3663b975a14SRyder Lee !hdr_nand) {
3673b975a14SRyder Lee fprintf(stderr, "Error: nand info is invalid or missing.\n");
3683b975a14SRyder Lee fprintf(stderr, " Please specify -n \"media=%s;"
3693b975a14SRyder Lee "nandinfo=<info>\"\n", media);
3703b975a14SRyder Lee return -EINVAL;
3713b975a14SRyder Lee }
3723b975a14SRyder Lee
3733b975a14SRyder Lee return 0;
3743b975a14SRyder Lee }
3753b975a14SRyder Lee
mtk_image_check_params(struct image_tool_params * params)3763b975a14SRyder Lee static int mtk_image_check_params(struct image_tool_params *params)
3773b975a14SRyder Lee {
3783b975a14SRyder Lee if (!params->addr) {
3793b975a14SRyder Lee fprintf(stderr, "Error: Load Address must be set.\n");
3803b975a14SRyder Lee return -EINVAL;
3813b975a14SRyder Lee }
3823b975a14SRyder Lee
3833b975a14SRyder Lee if (!params->imagename) {
3843b975a14SRyder Lee fprintf(stderr, "Error: Image Name must be set.\n");
3853b975a14SRyder Lee return -EINVAL;
3863b975a14SRyder Lee }
3873b975a14SRyder Lee
3883b975a14SRyder Lee return mtk_brom_parse_imagename(params->imagename);
3893b975a14SRyder Lee }
3903b975a14SRyder Lee
mtk_image_vrec_header(struct image_tool_params * params,struct image_type_params * tparams)3913b975a14SRyder Lee static int mtk_image_vrec_header(struct image_tool_params *params,
3923b975a14SRyder Lee struct image_type_params *tparams)
3933b975a14SRyder Lee {
3943b975a14SRyder Lee if (use_lk_hdr) {
3953b975a14SRyder Lee tparams->header_size = sizeof(union lk_hdr);
3963b975a14SRyder Lee tparams->hdr = &hdr_tmp;
3973b975a14SRyder Lee memset(&hdr_tmp, 0xff, tparams->header_size);
3983b975a14SRyder Lee return 0;
3993b975a14SRyder Lee }
4003b975a14SRyder Lee
4013b975a14SRyder Lee if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
4023b975a14SRyder Lee tparams->header_size = 2 * le16_to_cpu(hdr_nand->pagesize);
4033b975a14SRyder Lee else
4043b975a14SRyder Lee tparams->header_size = sizeof(struct gen_device_header);
4053b975a14SRyder Lee
4063b975a14SRyder Lee tparams->header_size += sizeof(struct gfh_header);
4073b975a14SRyder Lee tparams->hdr = &hdr_tmp;
4083b975a14SRyder Lee
4093b975a14SRyder Lee memset(&hdr_tmp, 0xff, tparams->header_size);
4103b975a14SRyder Lee
4113b975a14SRyder Lee return SHA256_SUM_LEN;
4123b975a14SRyder Lee }
4133b975a14SRyder Lee
mtk_image_verify_gen_header(const uint8_t * ptr,int print)4143b975a14SRyder Lee static int mtk_image_verify_gen_header(const uint8_t *ptr, int print)
4153b975a14SRyder Lee {
4163b975a14SRyder Lee union gen_boot_header *gbh = (union gen_boot_header *)ptr;
4173b975a14SRyder Lee struct brom_layout_header *bh;
4183b975a14SRyder Lee struct gfh_header *gfh;
4193b975a14SRyder Lee const char *bootmedia;
4203b975a14SRyder Lee
4213b975a14SRyder Lee if (!strcmp(gbh->name, SF_BOOT_NAME))
4223b975a14SRyder Lee bootmedia = "Serial NOR";
4233b975a14SRyder Lee else if (!strcmp(gbh->name, EMMC_BOOT_NAME))
4243b975a14SRyder Lee bootmedia = "eMMC";
4253b975a14SRyder Lee else if (!strcmp(gbh->name, SDMMC_BOOT_NAME))
4263b975a14SRyder Lee bootmedia = "SD/MMC";
4273b975a14SRyder Lee else
4283b975a14SRyder Lee return -1;
4293b975a14SRyder Lee
4303b975a14SRyder Lee if (print)
4313b975a14SRyder Lee printf("Boot Media: %s\n", bootmedia);
4323b975a14SRyder Lee
4333b975a14SRyder Lee if (le32_to_cpu(gbh->version) != 1 ||
4343b975a14SRyder Lee le32_to_cpu(gbh->size) != sizeof(union gen_boot_header))
4353b975a14SRyder Lee return -1;
4363b975a14SRyder Lee
4373b975a14SRyder Lee bh = (struct brom_layout_header *)(ptr + le32_to_cpu(gbh->size));
4383b975a14SRyder Lee
4393b975a14SRyder Lee if (strcmp(bh->name, BRLYT_NAME))
4403b975a14SRyder Lee return -1;
4413b975a14SRyder Lee
4423b975a14SRyder Lee if (le32_to_cpu(bh->magic) != BRLYT_MAGIC ||
4433b975a14SRyder Lee (le32_to_cpu(bh->type) != BRLYT_TYPE_NOR &&
4443b975a14SRyder Lee le32_to_cpu(bh->type) != BRLYT_TYPE_EMMC &&
4453b975a14SRyder Lee le32_to_cpu(bh->type) != BRLYT_TYPE_SDMMC))
4463b975a14SRyder Lee return -1;
4473b975a14SRyder Lee
4483b975a14SRyder Lee gfh = (struct gfh_header *)(ptr + le32_to_cpu(bh->header_size));
4493b975a14SRyder Lee
4503b975a14SRyder Lee if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
4513b975a14SRyder Lee return -1;
4523b975a14SRyder Lee
4533b975a14SRyder Lee if (le32_to_cpu(gfh->file_info.flash_type) != GFH_FLASH_TYPE_GEN)
4543b975a14SRyder Lee return -1;
4553b975a14SRyder Lee
4563b975a14SRyder Lee if (print)
4573b975a14SRyder Lee printf("Load Address: %08x\n",
4583b975a14SRyder Lee le32_to_cpu(gfh->file_info.load_addr) +
4593b975a14SRyder Lee le32_to_cpu(gfh->file_info.jump_offset));
4603b975a14SRyder Lee
4613b975a14SRyder Lee return 0;
4623b975a14SRyder Lee }
4633b975a14SRyder Lee
mtk_image_verify_nand_header(const uint8_t * ptr,int print)4643b975a14SRyder Lee static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
4653b975a14SRyder Lee {
4663b975a14SRyder Lee union nand_boot_header *nh = (union nand_boot_header *)ptr;
4673b975a14SRyder Lee struct brom_layout_header *bh;
4683b975a14SRyder Lee struct gfh_header *gfh;
4693b975a14SRyder Lee const char *bootmedia;
4703b975a14SRyder Lee
4713b975a14SRyder Lee if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh->version)) ||
4723b975a14SRyder Lee strcmp(nh->id, NAND_BOOT_ID))
4733b975a14SRyder Lee return -1;
4743b975a14SRyder Lee
4753b975a14SRyder Lee bh = (struct brom_layout_header *)(ptr + le16_to_cpu(nh->pagesize));
4763b975a14SRyder Lee
4773b975a14SRyder Lee if (strcmp(bh->name, BRLYT_NAME))
4783b975a14SRyder Lee return -1;
4793b975a14SRyder Lee
4803b975a14SRyder Lee if (le32_to_cpu(bh->magic) != BRLYT_MAGIC) {
4813b975a14SRyder Lee return -1;
4823b975a14SRyder Lee } else {
4833b975a14SRyder Lee if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND)
4843b975a14SRyder Lee bootmedia = "Parallel NAND";
4853b975a14SRyder Lee else if (le32_to_cpu(bh->type) == BRLYT_TYPE_SNAND)
4863b975a14SRyder Lee bootmedia = "Serial NAND";
4873b975a14SRyder Lee else
4883b975a14SRyder Lee return -1;
4893b975a14SRyder Lee }
4903b975a14SRyder Lee
4913b975a14SRyder Lee if (print) {
4923b975a14SRyder Lee printf("Boot Media: %s\n", bootmedia);
4933b975a14SRyder Lee
4943b975a14SRyder Lee if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND) {
4953b975a14SRyder Lee uint64_t capacity =
4963b975a14SRyder Lee (uint64_t)le16_to_cpu(nh->numblocks) *
4973b975a14SRyder Lee (uint64_t)le16_to_cpu(nh->pages_of_block) *
4983b975a14SRyder Lee (uint64_t)le16_to_cpu(nh->pagesize) * 8;
4993b975a14SRyder Lee printf("Capacity: %dGb\n",
5003b975a14SRyder Lee (uint32_t)(capacity >> 30));
5013b975a14SRyder Lee }
5023b975a14SRyder Lee
5033b975a14SRyder Lee if (le16_to_cpu(nh->pagesize) >= 1024)
5043b975a14SRyder Lee printf("Page Size: %dKB\n",
5053b975a14SRyder Lee le16_to_cpu(nh->pagesize) >> 10);
5063b975a14SRyder Lee else
5073b975a14SRyder Lee printf("Page Size: %dB\n",
5083b975a14SRyder Lee le16_to_cpu(nh->pagesize));
5093b975a14SRyder Lee
5103b975a14SRyder Lee printf("Spare Size: %dB\n", le16_to_cpu(nh->oobsize));
5113b975a14SRyder Lee }
5123b975a14SRyder Lee
5133b975a14SRyder Lee gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(nh->pagesize));
5143b975a14SRyder Lee
5153b975a14SRyder Lee if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
5163b975a14SRyder Lee return -1;
5173b975a14SRyder Lee
5183b975a14SRyder Lee if (le32_to_cpu(gfh->file_info.flash_type) != GFH_FLASH_TYPE_NAND)
5193b975a14SRyder Lee return -1;
5203b975a14SRyder Lee
5213b975a14SRyder Lee if (print)
5223b975a14SRyder Lee printf("Load Address: %08x\n",
5233b975a14SRyder Lee le32_to_cpu(gfh->file_info.load_addr) +
5243b975a14SRyder Lee le32_to_cpu(gfh->file_info.jump_offset));
5253b975a14SRyder Lee
5263b975a14SRyder Lee return 0;
5273b975a14SRyder Lee }
5283b975a14SRyder Lee
mtk_image_verify_header(unsigned char * ptr,int image_size,struct image_tool_params * params)5293b975a14SRyder Lee static int mtk_image_verify_header(unsigned char *ptr, int image_size,
5303b975a14SRyder Lee struct image_tool_params *params)
5313b975a14SRyder Lee {
5323b975a14SRyder Lee union lk_hdr *lk = (union lk_hdr *)ptr;
5333b975a14SRyder Lee
5343b975a14SRyder Lee /* nothing to verify for LK image header */
5353b975a14SRyder Lee if (le32_to_cpu(lk->magic) == LK_PART_MAGIC)
5363b975a14SRyder Lee return 0;
5373b975a14SRyder Lee
5383b975a14SRyder Lee if (!strcmp((char *)ptr, NAND_BOOT_NAME))
5393b975a14SRyder Lee return mtk_image_verify_nand_header(ptr, 0);
5403b975a14SRyder Lee else
5413b975a14SRyder Lee return mtk_image_verify_gen_header(ptr, 0);
5423b975a14SRyder Lee
5433b975a14SRyder Lee return -1;
5443b975a14SRyder Lee }
5453b975a14SRyder Lee
mtk_image_print_header(const void * ptr)5463b975a14SRyder Lee static void mtk_image_print_header(const void *ptr)
5473b975a14SRyder Lee {
5483b975a14SRyder Lee union lk_hdr *lk = (union lk_hdr *)ptr;
5493b975a14SRyder Lee
5503b975a14SRyder Lee if (le32_to_cpu(lk->magic) == LK_PART_MAGIC) {
5513b975a14SRyder Lee printf("Image Type: MediaTek LK Image\n");
5523b975a14SRyder Lee printf("Load Address: %08x\n", le32_to_cpu(lk->loadaddr));
5533b975a14SRyder Lee return;
5543b975a14SRyder Lee }
5553b975a14SRyder Lee
5563b975a14SRyder Lee printf("Image Type: MediaTek BootROM Loadable Image\n");
5573b975a14SRyder Lee
5583b975a14SRyder Lee if (!strcmp((char *)ptr, NAND_BOOT_NAME))
5593b975a14SRyder Lee mtk_image_verify_nand_header(ptr, 1);
5603b975a14SRyder Lee else
5613b975a14SRyder Lee mtk_image_verify_gen_header(ptr, 1);
5623b975a14SRyder Lee }
5633b975a14SRyder Lee
put_brom_layout_header(struct brom_layout_header * hdr,int type)5643b975a14SRyder Lee static void put_brom_layout_header(struct brom_layout_header *hdr, int type)
5653b975a14SRyder Lee {
5663b975a14SRyder Lee strncpy(hdr->name, BRLYT_NAME, sizeof(hdr->name));
5673b975a14SRyder Lee hdr->version = cpu_to_le32(1);
5683b975a14SRyder Lee hdr->magic = cpu_to_le32(BRLYT_MAGIC);
5693b975a14SRyder Lee hdr->type = cpu_to_le32(type);
5703b975a14SRyder Lee }
5713b975a14SRyder Lee
put_ghf_common_header(struct gfh_common_header * gfh,int size,int type,int ver)5723b975a14SRyder Lee static void put_ghf_common_header(struct gfh_common_header *gfh, int size,
5733b975a14SRyder Lee int type, int ver)
5743b975a14SRyder Lee {
5753b975a14SRyder Lee memcpy(gfh->magic, GFH_HEADER_MAGIC, sizeof(gfh->magic));
5763b975a14SRyder Lee gfh->version = ver;
5773b975a14SRyder Lee gfh->size = cpu_to_le16(size);
5783b975a14SRyder Lee gfh->type = cpu_to_le16(type);
5793b975a14SRyder Lee }
5803b975a14SRyder Lee
put_ghf_header(struct gfh_header * gfh,int file_size,int dev_hdr_size,int load_addr,int flash_type)5813b975a14SRyder Lee static void put_ghf_header(struct gfh_header *gfh, int file_size,
5823b975a14SRyder Lee int dev_hdr_size, int load_addr, int flash_type)
5833b975a14SRyder Lee {
5843b975a14SRyder Lee memset(gfh, 0, sizeof(struct gfh_header));
5853b975a14SRyder Lee
5863b975a14SRyder Lee /* GFH_FILE_INFO header */
5873b975a14SRyder Lee put_ghf_common_header(&gfh->file_info.gfh, sizeof(gfh->file_info),
5883b975a14SRyder Lee GFH_TYPE_FILE_INFO, 1);
5893b975a14SRyder Lee strncpy(gfh->file_info.name, GFH_FILE_INFO_NAME,
5903b975a14SRyder Lee sizeof(gfh->file_info.name));
5913b975a14SRyder Lee gfh->file_info.unused = cpu_to_le32(1);
5923b975a14SRyder Lee gfh->file_info.file_type = cpu_to_le16(1);
5933b975a14SRyder Lee gfh->file_info.flash_type = flash_type;
5943b975a14SRyder Lee gfh->file_info.sig_type = GFH_SIG_TYPE_SHA256;
5953b975a14SRyder Lee gfh->file_info.load_addr = cpu_to_le32(load_addr - sizeof(*gfh));
5963b975a14SRyder Lee gfh->file_info.total_size = cpu_to_le32(file_size - dev_hdr_size);
5973b975a14SRyder Lee gfh->file_info.max_size = cpu_to_le32(file_size);
5983b975a14SRyder Lee gfh->file_info.hdr_size = sizeof(*gfh);
5993b975a14SRyder Lee gfh->file_info.sig_size = SHA256_SUM_LEN;
6003b975a14SRyder Lee gfh->file_info.jump_offset = sizeof(*gfh);
6013b975a14SRyder Lee gfh->file_info.processed = cpu_to_le32(1);
6023b975a14SRyder Lee
6033b975a14SRyder Lee /* GFH_BL_INFO header */
6043b975a14SRyder Lee put_ghf_common_header(&gfh->bl_info.gfh, sizeof(gfh->bl_info),
6053b975a14SRyder Lee GFH_TYPE_BL_INFO, 1);
6063b975a14SRyder Lee gfh->bl_info.attr = cpu_to_le32(1);
6073b975a14SRyder Lee
6083b975a14SRyder Lee /* GFH_BROM_CFG header */
6093b975a14SRyder Lee put_ghf_common_header(&gfh->brom_cfg.gfh, sizeof(gfh->brom_cfg),
6103b975a14SRyder Lee GFH_TYPE_BROM_CFG, 3);
6113b975a14SRyder Lee gfh->brom_cfg.cfg_bits = cpu_to_le32(
6123b975a14SRyder Lee GFH_BROM_CFG_USBDL_AUTO_DETECT_DIS |
6133b975a14SRyder Lee GFH_BROM_CFG_USBDL_BY_KCOL0_TIMEOUT_EN |
6143b975a14SRyder Lee GFH_BROM_CFG_USBDL_BY_FLAG_TIMEOUT_EN);
6153b975a14SRyder Lee gfh->brom_cfg.usbdl_by_kcol0_timeout_ms = cpu_to_le32(5000);
6163b975a14SRyder Lee
6173b975a14SRyder Lee /* GFH_BL_SEC_KEY header */
6183b975a14SRyder Lee put_ghf_common_header(&gfh->bl_sec_key.gfh, sizeof(gfh->bl_sec_key),
6193b975a14SRyder Lee GFH_TYPE_BL_SEC_KEY, 1);
6203b975a14SRyder Lee
6213b975a14SRyder Lee /* GFH_ANTI_CLONE header */
6223b975a14SRyder Lee put_ghf_common_header(&gfh->anti_clone.gfh, sizeof(gfh->anti_clone),
6233b975a14SRyder Lee GFH_TYPE_ANTI_CLONE, 1);
6243b975a14SRyder Lee gfh->anti_clone.ac_offset = cpu_to_le32(0x10);
6253b975a14SRyder Lee gfh->anti_clone.ac_len = cpu_to_le32(0x80);
6263b975a14SRyder Lee
6273b975a14SRyder Lee /* GFH_BROM_SEC_CFG header */
6283b975a14SRyder Lee put_ghf_common_header(&gfh->brom_sec_cfg.gfh,
6293b975a14SRyder Lee sizeof(gfh->brom_sec_cfg),
6303b975a14SRyder Lee GFH_TYPE_BROM_SEC_CFG, 1);
6313b975a14SRyder Lee gfh->brom_sec_cfg.cfg_bits =
6323b975a14SRyder Lee cpu_to_le32(BROM_SEC_CFG_JTAG_EN | BROM_SEC_CFG_UART_EN);
6333b975a14SRyder Lee }
6343b975a14SRyder Lee
put_hash(uint8_t * buff,int size)6353b975a14SRyder Lee static void put_hash(uint8_t *buff, int size)
6363b975a14SRyder Lee {
6373b975a14SRyder Lee sha256_context ctx;
6383b975a14SRyder Lee
6393b975a14SRyder Lee sha256_starts(&ctx);
6403b975a14SRyder Lee sha256_update(&ctx, buff, size);
6413b975a14SRyder Lee sha256_finish(&ctx, buff + size);
6423b975a14SRyder Lee }
6433b975a14SRyder Lee
mtk_image_set_gen_header(void * ptr,off_t filesize,uint32_t loadaddr)6443b975a14SRyder Lee static void mtk_image_set_gen_header(void *ptr, off_t filesize,
6453b975a14SRyder Lee uint32_t loadaddr)
6463b975a14SRyder Lee {
6473b975a14SRyder Lee struct gen_device_header *hdr = (struct gen_device_header *)ptr;
6483b975a14SRyder Lee struct gfh_header *gfh;
6493b975a14SRyder Lee const char *bootname = NULL;
6503b975a14SRyder Lee
6513b975a14SRyder Lee if (hdr_media == BRLYT_TYPE_NOR)
6523b975a14SRyder Lee bootname = SF_BOOT_NAME;
6533b975a14SRyder Lee else if (hdr_media == BRLYT_TYPE_EMMC)
6543b975a14SRyder Lee bootname = EMMC_BOOT_NAME;
6553b975a14SRyder Lee else if (hdr_media == BRLYT_TYPE_SDMMC)
6563b975a14SRyder Lee bootname = SDMMC_BOOT_NAME;
6573b975a14SRyder Lee
6583b975a14SRyder Lee /* Generic device header */
659*74473ed0SAndy Shevchenko snprintf(hdr->boot.name, sizeof(hdr->boot.name), "%s", bootname);
6603b975a14SRyder Lee hdr->boot.version = cpu_to_le32(1);
6613b975a14SRyder Lee hdr->boot.size = cpu_to_le32(sizeof(hdr->boot));
6623b975a14SRyder Lee
6633b975a14SRyder Lee /* BRLYT header */
6643b975a14SRyder Lee put_brom_layout_header(&hdr->brlyt, hdr_media);
6653b975a14SRyder Lee hdr->brlyt.header_size = cpu_to_le32(sizeof(struct gen_device_header));
6663b975a14SRyder Lee hdr->brlyt.total_size = cpu_to_le32(filesize);
6673b975a14SRyder Lee hdr->brlyt.header_size_2 = hdr->brlyt.header_size;
6683b975a14SRyder Lee hdr->brlyt.total_size_2 = hdr->brlyt.total_size;
6693b975a14SRyder Lee
6703b975a14SRyder Lee /* GFH header */
6713b975a14SRyder Lee gfh = (struct gfh_header *)(ptr + sizeof(struct gen_device_header));
6723b975a14SRyder Lee put_ghf_header(gfh, filesize, sizeof(struct gen_device_header),
6733b975a14SRyder Lee loadaddr, GFH_FLASH_TYPE_GEN);
6743b975a14SRyder Lee
6753b975a14SRyder Lee /* Generate SHA256 hash */
6763b975a14SRyder Lee put_hash((uint8_t *)gfh,
6773b975a14SRyder Lee filesize - sizeof(struct gen_device_header) - SHA256_SUM_LEN);
6783b975a14SRyder Lee }
6793b975a14SRyder Lee
mtk_image_set_nand_header(void * ptr,off_t filesize,uint32_t loadaddr)6803b975a14SRyder Lee static void mtk_image_set_nand_header(void *ptr, off_t filesize,
6813b975a14SRyder Lee uint32_t loadaddr)
6823b975a14SRyder Lee {
6833b975a14SRyder Lee union nand_boot_header *nh = (union nand_boot_header *)ptr;
6843b975a14SRyder Lee struct brom_layout_header *brlyt;
6853b975a14SRyder Lee struct gfh_header *gfh;
6863b975a14SRyder Lee uint32_t payload_pages;
6873b975a14SRyder Lee int i;
6883b975a14SRyder Lee
6893b975a14SRyder Lee /* NAND device header, repeat 4 times */
6903b975a14SRyder Lee for (i = 0; i < 4; i++)
6913b975a14SRyder Lee memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header));
6923b975a14SRyder Lee
6933b975a14SRyder Lee /* BRLYT header */
6943b975a14SRyder Lee payload_pages = (filesize + le16_to_cpu(hdr_nand->pagesize) - 1) /
6953b975a14SRyder Lee le16_to_cpu(hdr_nand->pagesize);
6963b975a14SRyder Lee brlyt = (struct brom_layout_header *)
6973b975a14SRyder Lee (ptr + le16_to_cpu(hdr_nand->pagesize));
6983b975a14SRyder Lee put_brom_layout_header(brlyt, hdr_media);
6993b975a14SRyder Lee brlyt->header_size = cpu_to_le32(2);
7003b975a14SRyder Lee brlyt->total_size = cpu_to_le32(payload_pages);
7013b975a14SRyder Lee brlyt->header_size_2 = brlyt->header_size;
7023b975a14SRyder Lee brlyt->total_size_2 = brlyt->total_size;
7033b975a14SRyder Lee brlyt->unused = cpu_to_le32(1);
7043b975a14SRyder Lee
7053b975a14SRyder Lee /* GFH header */
7063b975a14SRyder Lee gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(hdr_nand->pagesize));
7073b975a14SRyder Lee put_ghf_header(gfh, filesize, 2 * le16_to_cpu(hdr_nand->pagesize),
7083b975a14SRyder Lee loadaddr, GFH_FLASH_TYPE_NAND);
7093b975a14SRyder Lee
7103b975a14SRyder Lee /* Generate SHA256 hash */
7113b975a14SRyder Lee put_hash((uint8_t *)gfh,
7123b975a14SRyder Lee filesize - 2 * le16_to_cpu(hdr_nand->pagesize) - SHA256_SUM_LEN);
7133b975a14SRyder Lee }
7143b975a14SRyder Lee
mtk_image_set_header(void * ptr,struct stat * sbuf,int ifd,struct image_tool_params * params)7153b975a14SRyder Lee static void mtk_image_set_header(void *ptr, struct stat *sbuf, int ifd,
7163b975a14SRyder Lee struct image_tool_params *params)
7173b975a14SRyder Lee {
7183b975a14SRyder Lee union lk_hdr *lk = (union lk_hdr *)ptr;
7193b975a14SRyder Lee
7203b975a14SRyder Lee if (use_lk_hdr) {
7213b975a14SRyder Lee lk->magic = cpu_to_le32(LK_PART_MAGIC);
7223b975a14SRyder Lee lk->size = cpu_to_le32(sbuf->st_size - sizeof(union lk_hdr));
7233b975a14SRyder Lee lk->loadaddr = cpu_to_le32(params->addr);
7243b975a14SRyder Lee lk->mode = 0xffffffff; /* must be non-zero */
7253b975a14SRyder Lee memset(lk->name, 0, sizeof(lk->name));
7263b975a14SRyder Lee strncpy(lk->name, lk_name, sizeof(lk->name));
7273b975a14SRyder Lee return;
7283b975a14SRyder Lee }
7293b975a14SRyder Lee
7303b975a14SRyder Lee if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
7313b975a14SRyder Lee mtk_image_set_nand_header(ptr, sbuf->st_size, params->addr);
7323b975a14SRyder Lee else
7333b975a14SRyder Lee mtk_image_set_gen_header(ptr, sbuf->st_size, params->addr);
7343b975a14SRyder Lee }
7353b975a14SRyder Lee
7363b975a14SRyder Lee U_BOOT_IMAGE_TYPE(
7373b975a14SRyder Lee mtk_image,
7383b975a14SRyder Lee "MediaTek BootROM Loadable Image support",
7393b975a14SRyder Lee 0,
7403b975a14SRyder Lee NULL,
7413b975a14SRyder Lee mtk_image_check_params,
7423b975a14SRyder Lee mtk_image_verify_header,
7433b975a14SRyder Lee mtk_image_print_header,
7443b975a14SRyder Lee mtk_image_set_header,
7453b975a14SRyder Lee NULL,
7463b975a14SRyder Lee mtk_image_check_image_types,
7473b975a14SRyder Lee NULL,
7483b975a14SRyder Lee mtk_image_vrec_header
7493b975a14SRyder Lee );
750