uboot/tools/mtk_image.c
<<
>>
Prefs
   1// 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
   9#include <image.h>
  10#include <u-boot/sha256.h>
  11#include "imagetool.h"
  12#include "mtk_image.h"
  13
  14/* NAND header for SPI-NAND with 2KB page + 64B spare */
  15static const union nand_boot_header snand_hdr_2k_64_data = {
  16        .data = {
  17                0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
  18                0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
  19                0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
  20                0x00, 0x00, 0x00, 0x08, 0x03, 0x00, 0x40, 0x00,
  21                0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
  22                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  23                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x7B, 0xC4, 0x17, 0x9D,
  30                0xCA, 0x42, 0x90, 0xD0, 0x98, 0xD0, 0xE0, 0xF7,
  31                0xDB, 0xCD, 0x16, 0xF6, 0x03, 0x73, 0xD2, 0xB8,
  32                0x93, 0xB2, 0x56, 0x5A, 0x84, 0x6E, 0x00, 0x00
  33        }
  34};
  35
  36/* NAND header for SPI-NAND with 2KB page + 120B/128B spare */
  37static const union nand_boot_header snand_hdr_2k_128_data = {
  38        .data = {
  39                0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
  40                0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
  41                0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
  42                0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
  43                0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
  44                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  45                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x90, 0x28, 0xED, 0x13,
  52                0x7F, 0x12, 0x22, 0xCD, 0x3D, 0x06, 0xF1, 0xB3,
  53                0x6F, 0x2E, 0xD9, 0xA0, 0x9D, 0x7A, 0xBD, 0xD7,
  54                0xB3, 0x28, 0x3C, 0x13, 0xDB, 0x4E, 0x00, 0x00
  55        }
  56};
  57
  58/* NAND header for SPI-NAND with 4KB page + 256B spare */
  59static const union nand_boot_header snand_hdr_4k_256_data = {
  60        .data = {
  61                0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
  62                0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
  63                0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
  64                0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0xE0, 0x00,
  65                0x40, 0x00, 0x00, 0x08, 0x10, 0x00, 0x16, 0x00,
  66                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  67                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x47, 0xED, 0x0E, 0xC3,
  74                0x83, 0xBF, 0x41, 0xD2, 0x85, 0x21, 0x97, 0x57,
  75                0xC4, 0x2E, 0x6B, 0x7A, 0x40, 0xE0, 0xCF, 0x8F,
  76                0x37, 0xBD, 0x17, 0xB6, 0xC7, 0xFE, 0x00, 0x00
  77        }
  78};
  79
  80/* NAND header for Parallel NAND 1Gb with 2KB page + 64B spare */
  81static const union nand_boot_header nand_hdr_1gb_2k_64_data = {
  82        .data = {
  83                0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
  84                0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
  85                0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
  86                0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
  87                0x40, 0x00, 0x00, 0x04, 0x0B, 0x00, 0x11, 0x00,
  88                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  89                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x12, 0x28, 0x1C, 0x12,
  96                0x8F, 0xFD, 0xF8, 0x32, 0x6F, 0x6D, 0xCF, 0x6C,
  97                0xDA, 0x21, 0x70, 0x8C, 0xDA, 0x0A, 0x22, 0x82,
  98                0xAA, 0x59, 0xFA, 0x7C, 0x42, 0x2D, 0x00, 0x00
  99        }
 100};
 101
 102/* NAND header for Parallel NAND 2Gb with 2KB page + 64B spare */
 103static const union nand_boot_header nand_hdr_2gb_2k_64_data = {
 104        .data = {
 105                0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
 106                0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
 107                0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
 108                0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
 109                0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
 110                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 111                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x20, 0x9C, 0x3D, 0x2D,
 118                0x7B, 0x68, 0x63, 0x52, 0x2E, 0x04, 0x63, 0xF1,
 119                0x35, 0x4E, 0x44, 0x3E, 0xF8, 0xAC, 0x9B, 0x95,
 120                0xAB, 0xFE, 0xE4, 0xE1, 0xD5, 0xF9, 0x00, 0x00
 121        }
 122};
 123
 124/* NAND header for Parallel NAND 4Gb with 2KB page + 64B spare */
 125static const union nand_boot_header nand_hdr_4gb_2k_64_data = {
 126        .data = {
 127                0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
 128                0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
 129                0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
 130                0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x40, 0x00,
 131                0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
 132                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 133                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xE3, 0x0F, 0x86, 0x32,
 140                0x68, 0x05, 0xD9, 0xC8, 0x13, 0xDF, 0xC5, 0x0B,
 141                0x35, 0x3A, 0x68, 0xA5, 0x3C, 0x0C, 0x73, 0x87,
 142                0x63, 0xB0, 0xBE, 0xCC, 0x84, 0x47, 0x00, 0x00
 143        }
 144};
 145
 146/* NAND header for Parallel NAND 2Gb with 2KB page + 128B spare */
 147static const union nand_boot_header nand_hdr_2gb_2k_128_data = {
 148        .data = {
 149                0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
 150                0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
 151                0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
 152                0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
 153                0x40, 0x00, 0x00, 0x08, 0x0B, 0x00, 0x11, 0x00,
 154                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 155                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x01, 0xA5, 0xE9, 0x5A,
 162                0xDF, 0x58, 0x62, 0x41, 0xD6, 0x26, 0x77, 0xBC,
 163                0x76, 0x1F, 0x27, 0x4E, 0x4F, 0x6C, 0xC3, 0xF0,
 164                0x36, 0xDE, 0xD9, 0xB3, 0xFF, 0x93, 0x00, 0x00
 165        }
 166};
 167
 168/* NAND header for Parallel NAND 4Gb with 2KB page + 128B spare */
 169static const union nand_boot_header nand_hdr_4gb_2k_128_data = {
 170        .data = {
 171                0x42, 0x4F, 0x4F, 0x54, 0x4C, 0x4F, 0x41, 0x44,
 172                0x45, 0x52, 0x21, 0x00, 0x56, 0x30, 0x30, 0x36,
 173                0x4E, 0x46, 0x49, 0x49, 0x4E, 0x46, 0x4F, 0x00,
 174                0x00, 0x00, 0x00, 0x08, 0x05, 0x00, 0x70, 0x00,
 175                0x40, 0x00, 0x00, 0x10, 0x0B, 0x00, 0x11, 0x00,
 176                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 177                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xC2, 0x36, 0x52, 0x45,
 184                0xCC, 0x35, 0xD8, 0xDB, 0xEB, 0xFD, 0xD1, 0x46,
 185                0x76, 0x6B, 0x0B, 0xD5, 0x8B, 0xCC, 0x2B, 0xE2,
 186                0xFE, 0x90, 0x83, 0x9E, 0xAE, 0x2D, 0x00, 0x00
 187        }
 188};
 189
 190static const struct nand_header_type {
 191        const char *name;
 192        const union nand_boot_header *data;
 193} nand_headers[] = {
 194        {
 195                .name = "2k+64",
 196                .data = &snand_hdr_2k_64_data
 197        }, {
 198                .name = "2k+120",
 199                .data = &snand_hdr_2k_128_data
 200        }, {
 201                .name = "2k+128",
 202                .data = &snand_hdr_2k_128_data
 203        }, {
 204                .name = "4k+256",
 205                .data = &snand_hdr_4k_256_data
 206        }, {
 207                .name = "1g:2k+64",
 208                .data = &nand_hdr_1gb_2k_64_data
 209        }, {
 210                .name = "2g:2k+64",
 211                .data = &nand_hdr_2gb_2k_64_data
 212        }, {
 213                .name = "4g:2k+64",
 214                .data = &nand_hdr_4gb_2k_64_data
 215        }, {
 216                .name = "2g:2k+128",
 217                .data = &nand_hdr_2gb_2k_128_data
 218        }, {
 219                .name = "4g:2k+128",
 220                .data = &nand_hdr_4gb_2k_128_data
 221        }
 222};
 223
 224static const struct brom_img_type {
 225        const char *name;
 226        enum brlyt_img_type type;
 227} brom_images[] = {
 228        {
 229                .name = "nand",
 230                .type = BRLYT_TYPE_NAND
 231        }, {
 232                .name = "emmc",
 233                .type = BRLYT_TYPE_EMMC
 234        }, {
 235                .name = "nor",
 236                .type = BRLYT_TYPE_NOR
 237        }, {
 238                .name = "sdmmc",
 239                .type = BRLYT_TYPE_SDMMC
 240        }, {
 241                .name = "snand",
 242                .type = BRLYT_TYPE_SNAND
 243        }
 244};
 245
 246/* Image type selected by user */
 247static enum brlyt_img_type hdr_media;
 248static int use_lk_hdr;
 249
 250/* LK image name */
 251static char lk_name[32] = "U-Boot";
 252
 253/* NAND header selected by user */
 254static const union nand_boot_header *hdr_nand;
 255
 256/* GFH header + 2 * 4KB pages of NAND */
 257static char hdr_tmp[sizeof(struct gfh_header) + 0x2000];
 258
 259static int mtk_image_check_image_types(uint8_t type)
 260{
 261        if (type == IH_TYPE_MTKIMAGE)
 262                return EXIT_SUCCESS;
 263        else
 264                return EXIT_FAILURE;
 265}
 266
 267static int mtk_brom_parse_imagename(const char *imagename)
 268{
 269#define is_blank_char(c) \
 270        ((c) == '\t' || (c) == '\n' || (c) == '\r' || (c) == ' ')
 271
 272        char *buf = strdup(imagename), *key, *val, *end, *next;
 273        int i;
 274
 275        /* User passed arguments from image name */
 276        static const char *media = "";
 277        static const char *nandinfo = "";
 278        static const char *lk = "";
 279
 280        key = buf;
 281        while (key) {
 282                next = strchr(key, ';');
 283                if (next)
 284                        *next = 0;
 285
 286                val = strchr(key, '=');
 287                if (val) {
 288                        *val++ = 0;
 289
 290                        /* Trim key */
 291                        while (is_blank_char(*key))
 292                                key++;
 293
 294                        end = key + strlen(key) - 1;
 295                        while ((end >= key) && is_blank_char(*end))
 296                                end--;
 297                        end++;
 298
 299                        if (is_blank_char(*end))
 300                                *end = 0;
 301
 302                        /* Trim value */
 303                        while (is_blank_char(*val))
 304                                val++;
 305
 306                        end = val + strlen(val) - 1;
 307                        while ((end >= val) && is_blank_char(*end))
 308                                end--;
 309                        end++;
 310
 311                        if (is_blank_char(*end))
 312                                *end = 0;
 313
 314                        /* record user passed arguments */
 315                        if (!strcmp(key, "media"))
 316                                media = val;
 317
 318                        if (!strcmp(key, "nandinfo"))
 319                                nandinfo = val;
 320
 321                        if (!strcmp(key, "lk"))
 322                                lk = val;
 323
 324                        if (!strcmp(key, "lkname"))
 325                                snprintf(lk_name, sizeof(lk_name), "%s", val);
 326                }
 327
 328                if (next)
 329                        key = next + 1;
 330                else
 331                        break;
 332        }
 333
 334        /* if user specified LK image header, skip following checks */
 335        if (lk && lk[0] == '1') {
 336                use_lk_hdr = 1;
 337                free(buf);
 338                return 0;
 339        }
 340
 341        /* parse media type */
 342        for (i = 0; i < ARRAY_SIZE(brom_images); i++) {
 343                if (!strcmp(brom_images[i].name, media)) {
 344                        hdr_media = brom_images[i].type;
 345                        break;
 346                }
 347        }
 348
 349        /* parse nand header type */
 350        for (i = 0; i < ARRAY_SIZE(nand_headers); i++) {
 351                if (!strcmp(nand_headers[i].name, nandinfo)) {
 352                        hdr_nand = nand_headers[i].data;
 353                        break;
 354                }
 355        }
 356
 357        free(buf);
 358
 359        if (hdr_media == BRLYT_TYPE_INVALID) {
 360                fprintf(stderr, "Error: media type is invalid or missing.\n");
 361                fprintf(stderr, "       Please specify -n \"media=<type>\"\n");
 362                return -EINVAL;
 363        }
 364
 365        if ((hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND) &&
 366            !hdr_nand) {
 367                fprintf(stderr, "Error: nand info is invalid or missing.\n");
 368                fprintf(stderr, "       Please specify -n \"media=%s;"
 369                                "nandinfo=<info>\"\n", media);
 370                return -EINVAL;
 371        }
 372
 373        return 0;
 374}
 375
 376static int mtk_image_check_params(struct image_tool_params *params)
 377{
 378        if (!params->addr) {
 379                fprintf(stderr, "Error: Load Address must be set.\n");
 380                return -EINVAL;
 381        }
 382
 383        if (!params->imagename) {
 384                fprintf(stderr, "Error: Image Name must be set.\n");
 385                return -EINVAL;
 386        }
 387
 388        return mtk_brom_parse_imagename(params->imagename);
 389}
 390
 391static int mtk_image_vrec_header(struct image_tool_params *params,
 392                                 struct image_type_params *tparams)
 393{
 394        if (use_lk_hdr) {
 395                tparams->header_size = sizeof(union lk_hdr);
 396                tparams->hdr = &hdr_tmp;
 397                memset(&hdr_tmp, 0xff, tparams->header_size);
 398                return 0;
 399        }
 400
 401        if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
 402                tparams->header_size = 2 * le16_to_cpu(hdr_nand->pagesize);
 403        else
 404                tparams->header_size = sizeof(struct gen_device_header);
 405
 406        tparams->header_size += sizeof(struct gfh_header);
 407        tparams->hdr = &hdr_tmp;
 408
 409        memset(&hdr_tmp, 0xff, tparams->header_size);
 410
 411        return SHA256_SUM_LEN;
 412}
 413
 414static int mtk_image_verify_gen_header(const uint8_t *ptr, int print)
 415{
 416        union gen_boot_header *gbh = (union gen_boot_header *)ptr;
 417        struct brom_layout_header *bh;
 418        struct gfh_header *gfh;
 419        const char *bootmedia;
 420
 421        if (!strcmp(gbh->name, SF_BOOT_NAME))
 422                bootmedia = "Serial NOR";
 423        else if (!strcmp(gbh->name, EMMC_BOOT_NAME))
 424                bootmedia = "eMMC";
 425        else if (!strcmp(gbh->name, SDMMC_BOOT_NAME))
 426                bootmedia = "SD/MMC";
 427        else
 428                return -1;
 429
 430        if (print)
 431                printf("Boot Media:   %s\n", bootmedia);
 432
 433        if (le32_to_cpu(gbh->version) != 1 ||
 434            le32_to_cpu(gbh->size) != sizeof(union gen_boot_header))
 435                return -1;
 436
 437        bh = (struct brom_layout_header *)(ptr + le32_to_cpu(gbh->size));
 438
 439        if (strcmp(bh->name, BRLYT_NAME))
 440                return -1;
 441
 442        if (le32_to_cpu(bh->magic) != BRLYT_MAGIC ||
 443            (le32_to_cpu(bh->type) != BRLYT_TYPE_NOR &&
 444            le32_to_cpu(bh->type) != BRLYT_TYPE_EMMC &&
 445            le32_to_cpu(bh->type) != BRLYT_TYPE_SDMMC))
 446                return -1;
 447
 448        gfh = (struct gfh_header *)(ptr + le32_to_cpu(bh->header_size));
 449
 450        if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
 451                return -1;
 452
 453        if (le32_to_cpu(gfh->file_info.flash_type) != GFH_FLASH_TYPE_GEN)
 454                return -1;
 455
 456        if (print)
 457                printf("Load Address: %08x\n",
 458                       le32_to_cpu(gfh->file_info.load_addr) +
 459                       le32_to_cpu(gfh->file_info.jump_offset));
 460
 461        return 0;
 462}
 463
 464static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
 465{
 466        union nand_boot_header *nh = (union nand_boot_header *)ptr;
 467        struct brom_layout_header *bh;
 468        struct gfh_header *gfh;
 469        const char *bootmedia;
 470
 471        if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh->version)) ||
 472            strcmp(nh->id, NAND_BOOT_ID))
 473                return -1;
 474
 475        bh = (struct brom_layout_header *)(ptr + le16_to_cpu(nh->pagesize));
 476
 477        if (strcmp(bh->name, BRLYT_NAME))
 478                return -1;
 479
 480        if (le32_to_cpu(bh->magic) != BRLYT_MAGIC) {
 481                return -1;
 482        } else {
 483                if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND)
 484                        bootmedia = "Parallel NAND";
 485                else if (le32_to_cpu(bh->type) == BRLYT_TYPE_SNAND)
 486                        bootmedia = "Serial NAND";
 487                else
 488                        return -1;
 489        }
 490
 491        if (print) {
 492                printf("Boot Media: %s\n", bootmedia);
 493
 494                if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND) {
 495                        uint64_t capacity =
 496                                (uint64_t)le16_to_cpu(nh->numblocks) *
 497                                (uint64_t)le16_to_cpu(nh->pages_of_block) *
 498                                (uint64_t)le16_to_cpu(nh->pagesize) * 8;
 499                        printf("Capacity:     %dGb\n",
 500                               (uint32_t)(capacity >> 30));
 501                }
 502
 503                if (le16_to_cpu(nh->pagesize) >= 1024)
 504                        printf("Page Size:    %dKB\n",
 505                               le16_to_cpu(nh->pagesize) >> 10);
 506                else
 507                        printf("Page Size:    %dB\n",
 508                               le16_to_cpu(nh->pagesize));
 509
 510                printf("Spare Size:   %dB\n", le16_to_cpu(nh->oobsize));
 511        }
 512
 513        gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(nh->pagesize));
 514
 515        if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
 516                return -1;
 517
 518        if (le32_to_cpu(gfh->file_info.flash_type) != GFH_FLASH_TYPE_NAND)
 519                return -1;
 520
 521        if (print)
 522                printf("Load Address: %08x\n",
 523                       le32_to_cpu(gfh->file_info.load_addr) +
 524                       le32_to_cpu(gfh->file_info.jump_offset));
 525
 526        return 0;
 527}
 528
 529static int mtk_image_verify_header(unsigned char *ptr, int image_size,
 530                                   struct image_tool_params *params)
 531{
 532        union lk_hdr *lk = (union lk_hdr *)ptr;
 533
 534        /* nothing to verify for LK image header */
 535        if (le32_to_cpu(lk->magic) == LK_PART_MAGIC)
 536                return 0;
 537
 538        if (!strcmp((char *)ptr, NAND_BOOT_NAME))
 539                return mtk_image_verify_nand_header(ptr, 0);
 540        else
 541                return mtk_image_verify_gen_header(ptr, 0);
 542
 543        return -1;
 544}
 545
 546static void mtk_image_print_header(const void *ptr)
 547{
 548        union lk_hdr *lk = (union lk_hdr *)ptr;
 549
 550        if (le32_to_cpu(lk->magic) == LK_PART_MAGIC) {
 551                printf("Image Type:   MediaTek LK Image\n");
 552                printf("Load Address: %08x\n", le32_to_cpu(lk->loadaddr));
 553                return;
 554        }
 555
 556        printf("Image Type:   MediaTek BootROM Loadable Image\n");
 557
 558        if (!strcmp((char *)ptr, NAND_BOOT_NAME))
 559                mtk_image_verify_nand_header(ptr, 1);
 560        else
 561                mtk_image_verify_gen_header(ptr, 1);
 562}
 563
 564static void put_brom_layout_header(struct brom_layout_header *hdr, int type)
 565{
 566        strncpy(hdr->name, BRLYT_NAME, sizeof(hdr->name));
 567        hdr->version = cpu_to_le32(1);
 568        hdr->magic = cpu_to_le32(BRLYT_MAGIC);
 569        hdr->type = cpu_to_le32(type);
 570}
 571
 572static void put_ghf_common_header(struct gfh_common_header *gfh, int size,
 573                                  int type, int ver)
 574{
 575        memcpy(gfh->magic, GFH_HEADER_MAGIC, sizeof(gfh->magic));
 576        gfh->version = ver;
 577        gfh->size = cpu_to_le16(size);
 578        gfh->type = cpu_to_le16(type);
 579}
 580
 581static void put_ghf_header(struct gfh_header *gfh, int file_size,
 582                           int dev_hdr_size, int load_addr, int flash_type)
 583{
 584        memset(gfh, 0, sizeof(struct gfh_header));
 585
 586        /* GFH_FILE_INFO header */
 587        put_ghf_common_header(&gfh->file_info.gfh, sizeof(gfh->file_info),
 588                              GFH_TYPE_FILE_INFO, 1);
 589        strncpy(gfh->file_info.name, GFH_FILE_INFO_NAME,
 590                sizeof(gfh->file_info.name));
 591        gfh->file_info.unused = cpu_to_le32(1);
 592        gfh->file_info.file_type = cpu_to_le16(1);
 593        gfh->file_info.flash_type = flash_type;
 594        gfh->file_info.sig_type = GFH_SIG_TYPE_SHA256;
 595        gfh->file_info.load_addr = cpu_to_le32(load_addr - sizeof(*gfh));
 596        gfh->file_info.total_size = cpu_to_le32(file_size - dev_hdr_size);
 597        gfh->file_info.max_size = cpu_to_le32(file_size);
 598        gfh->file_info.hdr_size = sizeof(*gfh);
 599        gfh->file_info.sig_size = SHA256_SUM_LEN;
 600        gfh->file_info.jump_offset = sizeof(*gfh);
 601        gfh->file_info.processed = cpu_to_le32(1);
 602
 603        /* GFH_BL_INFO header */
 604        put_ghf_common_header(&gfh->bl_info.gfh, sizeof(gfh->bl_info),
 605                              GFH_TYPE_BL_INFO, 1);
 606        gfh->bl_info.attr = cpu_to_le32(1);
 607
 608        /* GFH_BROM_CFG header */
 609        put_ghf_common_header(&gfh->brom_cfg.gfh, sizeof(gfh->brom_cfg),
 610                              GFH_TYPE_BROM_CFG, 3);
 611        gfh->brom_cfg.cfg_bits = cpu_to_le32(
 612                GFH_BROM_CFG_USBDL_AUTO_DETECT_DIS |
 613                GFH_BROM_CFG_USBDL_BY_KCOL0_TIMEOUT_EN |
 614                GFH_BROM_CFG_USBDL_BY_FLAG_TIMEOUT_EN);
 615        gfh->brom_cfg.usbdl_by_kcol0_timeout_ms = cpu_to_le32(5000);
 616
 617        /* GFH_BL_SEC_KEY header */
 618        put_ghf_common_header(&gfh->bl_sec_key.gfh, sizeof(gfh->bl_sec_key),
 619                              GFH_TYPE_BL_SEC_KEY, 1);
 620
 621        /* GFH_ANTI_CLONE header */
 622        put_ghf_common_header(&gfh->anti_clone.gfh, sizeof(gfh->anti_clone),
 623                              GFH_TYPE_ANTI_CLONE, 1);
 624        gfh->anti_clone.ac_offset = cpu_to_le32(0x10);
 625        gfh->anti_clone.ac_len = cpu_to_le32(0x80);
 626
 627        /* GFH_BROM_SEC_CFG header */
 628        put_ghf_common_header(&gfh->brom_sec_cfg.gfh,
 629                              sizeof(gfh->brom_sec_cfg),
 630                              GFH_TYPE_BROM_SEC_CFG, 1);
 631        gfh->brom_sec_cfg.cfg_bits =
 632                cpu_to_le32(BROM_SEC_CFG_JTAG_EN | BROM_SEC_CFG_UART_EN);
 633}
 634
 635static void put_hash(uint8_t *buff, int size)
 636{
 637        sha256_context ctx;
 638
 639        sha256_starts(&ctx);
 640        sha256_update(&ctx, buff, size);
 641        sha256_finish(&ctx, buff + size);
 642}
 643
 644static void mtk_image_set_gen_header(void *ptr, off_t filesize,
 645                                     uint32_t loadaddr)
 646{
 647        struct gen_device_header *hdr = (struct gen_device_header *)ptr;
 648        struct gfh_header *gfh;
 649        const char *bootname = NULL;
 650
 651        if (hdr_media == BRLYT_TYPE_NOR)
 652                bootname = SF_BOOT_NAME;
 653        else if (hdr_media == BRLYT_TYPE_EMMC)
 654                bootname = EMMC_BOOT_NAME;
 655        else if (hdr_media == BRLYT_TYPE_SDMMC)
 656                bootname = SDMMC_BOOT_NAME;
 657
 658        /* Generic device header */
 659        snprintf(hdr->boot.name, sizeof(hdr->boot.name), "%s", bootname);
 660        hdr->boot.version = cpu_to_le32(1);
 661        hdr->boot.size = cpu_to_le32(sizeof(hdr->boot));
 662
 663        /* BRLYT header */
 664        put_brom_layout_header(&hdr->brlyt, hdr_media);
 665        hdr->brlyt.header_size = cpu_to_le32(sizeof(struct gen_device_header));
 666        hdr->brlyt.total_size = cpu_to_le32(filesize);
 667        hdr->brlyt.header_size_2 = hdr->brlyt.header_size;
 668        hdr->brlyt.total_size_2 = hdr->brlyt.total_size;
 669
 670        /* GFH header */
 671        gfh = (struct gfh_header *)(ptr + sizeof(struct gen_device_header));
 672        put_ghf_header(gfh, filesize, sizeof(struct gen_device_header),
 673                       loadaddr, GFH_FLASH_TYPE_GEN);
 674
 675        /* Generate SHA256 hash */
 676        put_hash((uint8_t *)gfh,
 677                 filesize - sizeof(struct gen_device_header) - SHA256_SUM_LEN);
 678}
 679
 680static void mtk_image_set_nand_header(void *ptr, off_t filesize,
 681                                      uint32_t loadaddr)
 682{
 683        union nand_boot_header *nh = (union nand_boot_header *)ptr;
 684        struct brom_layout_header *brlyt;
 685        struct gfh_header *gfh;
 686        uint32_t payload_pages;
 687        int i;
 688
 689        /* NAND device header, repeat 4 times */
 690        for (i = 0; i < 4; i++)
 691                memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header));
 692
 693        /* BRLYT header */
 694        payload_pages = (filesize + le16_to_cpu(hdr_nand->pagesize) - 1) /
 695                        le16_to_cpu(hdr_nand->pagesize);
 696        brlyt = (struct brom_layout_header *)
 697                (ptr + le16_to_cpu(hdr_nand->pagesize));
 698        put_brom_layout_header(brlyt, hdr_media);
 699        brlyt->header_size = cpu_to_le32(2);
 700        brlyt->total_size = cpu_to_le32(payload_pages);
 701        brlyt->header_size_2 = brlyt->header_size;
 702        brlyt->total_size_2 = brlyt->total_size;
 703        brlyt->unused = cpu_to_le32(1);
 704
 705        /* GFH header */
 706        gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(hdr_nand->pagesize));
 707        put_ghf_header(gfh, filesize, 2 * le16_to_cpu(hdr_nand->pagesize),
 708                       loadaddr, GFH_FLASH_TYPE_NAND);
 709
 710        /* Generate SHA256 hash */
 711        put_hash((uint8_t *)gfh,
 712                 filesize - 2 * le16_to_cpu(hdr_nand->pagesize) - SHA256_SUM_LEN);
 713}
 714
 715static void mtk_image_set_header(void *ptr, struct stat *sbuf, int ifd,
 716                                 struct image_tool_params *params)
 717{
 718        union lk_hdr *lk = (union lk_hdr *)ptr;
 719
 720        if (use_lk_hdr) {
 721                lk->magic = cpu_to_le32(LK_PART_MAGIC);
 722                lk->size = cpu_to_le32(sbuf->st_size - sizeof(union lk_hdr));
 723                lk->loadaddr = cpu_to_le32(params->addr);
 724                lk->mode = 0xffffffff; /* must be non-zero */
 725                memset(lk->name, 0, sizeof(lk->name));
 726                strncpy(lk->name, lk_name, sizeof(lk->name));
 727                return;
 728        }
 729
 730        if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
 731                mtk_image_set_nand_header(ptr, sbuf->st_size, params->addr);
 732        else
 733                mtk_image_set_gen_header(ptr, sbuf->st_size, params->addr);
 734}
 735
 736U_BOOT_IMAGE_TYPE(
 737        mtk_image,
 738        "MediaTek BootROM Loadable Image support",
 739        0,
 740        NULL,
 741        mtk_image_check_params,
 742        mtk_image_verify_header,
 743        mtk_image_print_header,
 744        mtk_image_set_header,
 745        NULL,
 746        mtk_image_check_image_types,
 747        NULL,
 748        mtk_image_vrec_header
 749);
 750