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/* Indicates whether we're generating or verifying */
 247static bool img_gen;
 248static uint32_t img_size;
 249
 250/* Image type selected by user */
 251static enum brlyt_img_type hdr_media;
 252static uint32_t hdr_offset;
 253static int use_lk_hdr;
 254static bool is_arm64_image;
 255
 256/* LK image name */
 257static char lk_name[32] = "U-Boot";
 258
 259/* NAND header selected by user */
 260static const union nand_boot_header *hdr_nand;
 261
 262/* GFH header + 2 * 4KB pages of NAND */
 263static char hdr_tmp[sizeof(struct gfh_header) + 0x2000];
 264
 265static int mtk_image_check_image_types(uint8_t type)
 266{
 267        if (type == IH_TYPE_MTKIMAGE)
 268                return EXIT_SUCCESS;
 269        else
 270                return EXIT_FAILURE;
 271}
 272
 273static int mtk_brom_parse_imagename(const char *imagename)
 274{
 275#define is_blank_char(c) \
 276        ((c) == '\t' || (c) == '\n' || (c) == '\r' || (c) == ' ')
 277
 278        char *buf = strdup(imagename), *key, *val, *end, *next;
 279        int i;
 280
 281        /* User passed arguments from image name */
 282        static const char *media = "";
 283        static const char *hdr_offs = "";
 284        static const char *nandinfo = "";
 285        static const char *lk = "";
 286        static const char *arm64_param = "";
 287
 288        key = buf;
 289        while (key) {
 290                next = strchr(key, ';');
 291                if (next)
 292                        *next = 0;
 293
 294                val = strchr(key, '=');
 295                if (val) {
 296                        *val++ = 0;
 297
 298                        /* Trim key */
 299                        while (is_blank_char(*key))
 300                                key++;
 301
 302                        end = key + strlen(key) - 1;
 303                        while ((end >= key) && is_blank_char(*end))
 304                                end--;
 305                        end++;
 306
 307                        if (is_blank_char(*end))
 308                                *end = 0;
 309
 310                        /* Trim value */
 311                        while (is_blank_char(*val))
 312                                val++;
 313
 314                        end = val + strlen(val) - 1;
 315                        while ((end >= val) && is_blank_char(*end))
 316                                end--;
 317                        end++;
 318
 319                        if (is_blank_char(*end))
 320                                *end = 0;
 321
 322                        /* record user passed arguments */
 323                        if (!strcmp(key, "media"))
 324                                media = val;
 325
 326                        if (!strcmp(key, "hdroffset"))
 327                                hdr_offs = val;
 328
 329                        if (!strcmp(key, "nandinfo"))
 330                                nandinfo = val;
 331
 332                        if (!strcmp(key, "lk"))
 333                                lk = val;
 334
 335                        if (!strcmp(key, "lkname"))
 336                                snprintf(lk_name, sizeof(lk_name), "%s", val);
 337
 338                        if (!strcmp(key, "arm64"))
 339                                arm64_param = val;
 340                }
 341
 342                if (next)
 343                        key = next + 1;
 344                else
 345                        break;
 346        }
 347
 348        /* if user specified LK image header, skip following checks */
 349        if (lk && lk[0] == '1') {
 350                use_lk_hdr = 1;
 351                free(buf);
 352                return 0;
 353        }
 354
 355        /* parse media type */
 356        for (i = 0; i < ARRAY_SIZE(brom_images); i++) {
 357                if (!strcmp(brom_images[i].name, media)) {
 358                        hdr_media = brom_images[i].type;
 359                        break;
 360                }
 361        }
 362
 363        /* parse nand header type */
 364        for (i = 0; i < ARRAY_SIZE(nand_headers); i++) {
 365                if (!strcmp(nand_headers[i].name, nandinfo)) {
 366                        hdr_nand = nand_headers[i].data;
 367                        break;
 368                }
 369        }
 370
 371        /* parse device header offset */
 372        if (hdr_offs && hdr_offs[0])
 373                hdr_offset = strtoul(hdr_offs, NULL, 0);
 374
 375        if (arm64_param && arm64_param[0] == '1')
 376                is_arm64_image = true;
 377
 378        free(buf);
 379
 380        if (hdr_media == BRLYT_TYPE_INVALID) {
 381                fprintf(stderr, "Error: media type is invalid or missing.\n");
 382                fprintf(stderr, "       Please specify -n \"media=<type>\"\n");
 383                return -EINVAL;
 384        }
 385
 386        if ((hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND) &&
 387            !hdr_nand) {
 388                fprintf(stderr, "Error: nand info is invalid or missing.\n");
 389                fprintf(stderr, "       Please specify -n \"media=%s;"
 390                                "nandinfo=<info>\"\n", media);
 391                return -EINVAL;
 392        }
 393
 394        return 0;
 395}
 396
 397static int mtk_image_check_params(struct image_tool_params *params)
 398{
 399        if (!params->addr) {
 400                fprintf(stderr, "Error: Load Address must be set.\n");
 401                return -EINVAL;
 402        }
 403
 404        if (!params->imagename) {
 405                fprintf(stderr, "Error: Image Name must be set.\n");
 406                return -EINVAL;
 407        }
 408
 409        return mtk_brom_parse_imagename(params->imagename);
 410}
 411
 412static int mtk_image_vrec_header(struct image_tool_params *params,
 413                                 struct image_type_params *tparams)
 414{
 415        if (use_lk_hdr) {
 416                tparams->header_size = sizeof(union lk_hdr);
 417                tparams->hdr = &hdr_tmp;
 418                memset(&hdr_tmp, 0xff, tparams->header_size);
 419                return 0;
 420        }
 421
 422        if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
 423                tparams->header_size = 2 * le16_to_cpu(hdr_nand->pagesize);
 424        else
 425                tparams->header_size = sizeof(struct gen_device_header);
 426
 427        tparams->header_size += sizeof(struct gfh_header);
 428        tparams->hdr = &hdr_tmp;
 429
 430        memset(&hdr_tmp, 0xff, tparams->header_size);
 431
 432        return SHA256_SUM_LEN;
 433}
 434
 435static int mtk_image_verify_gen_header(const uint8_t *ptr, int print)
 436{
 437        union gen_boot_header *gbh = (union gen_boot_header *)ptr;
 438        uint32_t gfh_offset, total_size, devh_size;
 439        struct brom_layout_header *bh;
 440        struct gfh_header *gfh;
 441        const char *bootmedia;
 442
 443        if (!strcmp(gbh->name, SF_BOOT_NAME))
 444                bootmedia = "Serial NOR";
 445        else if (!strcmp(gbh->name, EMMC_BOOT_NAME))
 446                bootmedia = "eMMC";
 447        else if (!strcmp(gbh->name, SDMMC_BOOT_NAME))
 448                bootmedia = "SD/MMC";
 449        else
 450                return -1;
 451
 452        if (print)
 453                printf("Boot Media:   %s\n", bootmedia);
 454
 455        if (le32_to_cpu(gbh->version) != 1 ||
 456            le32_to_cpu(gbh->size) != sizeof(union gen_boot_header))
 457                return -1;
 458
 459        bh = (struct brom_layout_header *)(ptr + le32_to_cpu(gbh->size));
 460
 461        if (strcmp(bh->name, BRLYT_NAME))
 462                return -1;
 463
 464        if (le32_to_cpu(bh->magic) != BRLYT_MAGIC ||
 465            (le32_to_cpu(bh->type) != BRLYT_TYPE_NOR &&
 466            le32_to_cpu(bh->type) != BRLYT_TYPE_EMMC &&
 467            le32_to_cpu(bh->type) != BRLYT_TYPE_SDMMC))
 468                return -1;
 469
 470        devh_size = sizeof(struct gen_device_header);
 471
 472        if (img_gen) {
 473                gfh_offset = devh_size;
 474        } else {
 475                gfh_offset = le32_to_cpu(bh->header_size);
 476
 477                if (gfh_offset + sizeof(struct gfh_header) > img_size) {
 478                        /*
 479                         * This may happen if the hdr_offset used to generate
 480                         * this image is not zero.
 481                         * Since device header size is not fixed, we can't
 482                         * cover all possible cases.
 483                         * Assuming the image is valid only if the real
 484                         * device header size equals to devh_size.
 485                         */
 486                        total_size = le32_to_cpu(bh->total_size);
 487
 488                        if (total_size - gfh_offset > img_size - devh_size)
 489                                return -1;
 490
 491                        gfh_offset = devh_size;
 492                }
 493        }
 494
 495        gfh = (struct gfh_header *)(ptr + gfh_offset);
 496
 497        if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
 498                return -1;
 499
 500        if (le32_to_cpu(gfh->file_info.flash_type) != GFH_FLASH_TYPE_GEN)
 501                return -1;
 502
 503        if (print)
 504                printf("Load Address: %08x\n",
 505                       le32_to_cpu(gfh->file_info.load_addr) +
 506                       le32_to_cpu(gfh->file_info.jump_offset));
 507
 508        if (print)
 509                printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM");
 510
 511        return 0;
 512}
 513
 514static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
 515{
 516        union nand_boot_header *nh = (union nand_boot_header *)ptr;
 517        struct brom_layout_header *bh;
 518        struct gfh_header *gfh;
 519        const char *bootmedia;
 520
 521        if (strncmp(nh->version, NAND_BOOT_VERSION, sizeof(nh->version)) ||
 522            strcmp(nh->id, NAND_BOOT_ID))
 523                return -1;
 524
 525        bh = (struct brom_layout_header *)(ptr + le16_to_cpu(nh->pagesize));
 526
 527        if (strcmp(bh->name, BRLYT_NAME))
 528                return -1;
 529
 530        if (le32_to_cpu(bh->magic) != BRLYT_MAGIC) {
 531                return -1;
 532        } else {
 533                if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND)
 534                        bootmedia = "Parallel NAND";
 535                else if (le32_to_cpu(bh->type) == BRLYT_TYPE_SNAND)
 536                        bootmedia = "Serial NAND";
 537                else
 538                        return -1;
 539        }
 540
 541        if (print) {
 542                printf("Boot Media: %s\n", bootmedia);
 543
 544                if (le32_to_cpu(bh->type) == BRLYT_TYPE_NAND) {
 545                        uint64_t capacity =
 546                                (uint64_t)le16_to_cpu(nh->numblocks) *
 547                                (uint64_t)le16_to_cpu(nh->pages_of_block) *
 548                                (uint64_t)le16_to_cpu(nh->pagesize) * 8;
 549                        printf("Capacity:     %dGb\n",
 550                               (uint32_t)(capacity >> 30));
 551                }
 552
 553                if (le16_to_cpu(nh->pagesize) >= 1024)
 554                        printf("Page Size:    %dKB\n",
 555                               le16_to_cpu(nh->pagesize) >> 10);
 556                else
 557                        printf("Page Size:    %dB\n",
 558                               le16_to_cpu(nh->pagesize));
 559
 560                printf("Spare Size:   %dB\n", le16_to_cpu(nh->oobsize));
 561        }
 562
 563        gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(nh->pagesize));
 564
 565        if (strcmp(gfh->file_info.name, GFH_FILE_INFO_NAME))
 566                return -1;
 567
 568        if (le32_to_cpu(gfh->file_info.flash_type) != GFH_FLASH_TYPE_NAND)
 569                return -1;
 570
 571        if (print)
 572                printf("Load Address: %08x\n",
 573                       le32_to_cpu(gfh->file_info.load_addr) +
 574                       le32_to_cpu(gfh->file_info.jump_offset));
 575
 576        if (print)
 577                printf("Architecture: %s\n", is_arm64_image ? "ARM64" : "ARM");
 578
 579        return 0;
 580}
 581
 582static int mtk_image_verify_header(unsigned char *ptr, int image_size,
 583                                   struct image_tool_params *params)
 584{
 585        union lk_hdr *lk = (union lk_hdr *)ptr;
 586
 587        /* nothing to verify for LK image header */
 588        if (le32_to_cpu(lk->magic) == LK_PART_MAGIC)
 589                return 0;
 590
 591        img_size = image_size;
 592
 593        if (!strcmp((char *)ptr, NAND_BOOT_NAME))
 594                return mtk_image_verify_nand_header(ptr, 0);
 595        else
 596                return mtk_image_verify_gen_header(ptr, 0);
 597
 598        return -1;
 599}
 600
 601static void mtk_image_print_header(const void *ptr)
 602{
 603        union lk_hdr *lk = (union lk_hdr *)ptr;
 604
 605        if (le32_to_cpu(lk->magic) == LK_PART_MAGIC) {
 606                printf("Image Type:   MediaTek LK Image\n");
 607                printf("Load Address: %08x\n", le32_to_cpu(lk->loadaddr));
 608                return;
 609        }
 610
 611        printf("Image Type:   MediaTek BootROM Loadable Image\n");
 612
 613        if (!strcmp((char *)ptr, NAND_BOOT_NAME))
 614                mtk_image_verify_nand_header(ptr, 1);
 615        else
 616                mtk_image_verify_gen_header(ptr, 1);
 617}
 618
 619static void put_brom_layout_header(struct brom_layout_header *hdr, int type)
 620{
 621        strncpy(hdr->name, BRLYT_NAME, sizeof(hdr->name));
 622        hdr->version = cpu_to_le32(1);
 623        hdr->magic = cpu_to_le32(BRLYT_MAGIC);
 624        hdr->type = cpu_to_le32(type);
 625}
 626
 627static void put_ghf_common_header(struct gfh_common_header *gfh, int size,
 628                                  int type, int ver)
 629{
 630        memcpy(gfh->magic, GFH_HEADER_MAGIC, sizeof(gfh->magic));
 631        gfh->version = ver;
 632        gfh->size = cpu_to_le16(size);
 633        gfh->type = cpu_to_le16(type);
 634}
 635
 636static void put_ghf_header(struct gfh_header *gfh, int file_size,
 637                           int dev_hdr_size, int load_addr, int flash_type)
 638{
 639        uint32_t cfg_bits;
 640
 641        memset(gfh, 0, sizeof(struct gfh_header));
 642
 643        /* GFH_FILE_INFO header */
 644        put_ghf_common_header(&gfh->file_info.gfh, sizeof(gfh->file_info),
 645                              GFH_TYPE_FILE_INFO, 1);
 646        strncpy(gfh->file_info.name, GFH_FILE_INFO_NAME,
 647                sizeof(gfh->file_info.name));
 648        gfh->file_info.unused = cpu_to_le32(1);
 649        gfh->file_info.file_type = cpu_to_le16(1);
 650        gfh->file_info.flash_type = flash_type;
 651        gfh->file_info.sig_type = GFH_SIG_TYPE_SHA256;
 652        gfh->file_info.load_addr = cpu_to_le32(load_addr - sizeof(*gfh));
 653        gfh->file_info.total_size = cpu_to_le32(file_size - dev_hdr_size);
 654        gfh->file_info.max_size = cpu_to_le32(file_size);
 655        gfh->file_info.hdr_size = sizeof(*gfh);
 656        gfh->file_info.sig_size = SHA256_SUM_LEN;
 657        gfh->file_info.jump_offset = sizeof(*gfh);
 658        gfh->file_info.processed = cpu_to_le32(1);
 659
 660        /* GFH_BL_INFO header */
 661        put_ghf_common_header(&gfh->bl_info.gfh, sizeof(gfh->bl_info),
 662                              GFH_TYPE_BL_INFO, 1);
 663        gfh->bl_info.attr = cpu_to_le32(1);
 664
 665        /* GFH_BROM_CFG header */
 666        put_ghf_common_header(&gfh->brom_cfg.gfh, sizeof(gfh->brom_cfg),
 667                              GFH_TYPE_BROM_CFG, 3);
 668        cfg_bits = GFH_BROM_CFG_USBDL_AUTO_DETECT_DIS |
 669                   GFH_BROM_CFG_USBDL_BY_KCOL0_TIMEOUT_EN |
 670                   GFH_BROM_CFG_USBDL_BY_FLAG_TIMEOUT_EN;
 671        gfh->brom_cfg.usbdl_by_kcol0_timeout_ms = cpu_to_le32(5000);
 672        if (is_arm64_image) {
 673                gfh->brom_cfg.jump_bl_arm64 = GFH_BROM_CFG_JUMP_BL_ARM64;
 674                cfg_bits |= GFH_BROM_CFG_JUMP_BL_ARM64_EN;
 675        }
 676        gfh->brom_cfg.cfg_bits = cpu_to_le32(cfg_bits);
 677
 678        /* GFH_BL_SEC_KEY header */
 679        put_ghf_common_header(&gfh->bl_sec_key.gfh, sizeof(gfh->bl_sec_key),
 680                              GFH_TYPE_BL_SEC_KEY, 1);
 681
 682        /* GFH_ANTI_CLONE header */
 683        put_ghf_common_header(&gfh->anti_clone.gfh, sizeof(gfh->anti_clone),
 684                              GFH_TYPE_ANTI_CLONE, 1);
 685        gfh->anti_clone.ac_offset = cpu_to_le32(0x10);
 686        gfh->anti_clone.ac_len = cpu_to_le32(0x80);
 687
 688        /* GFH_BROM_SEC_CFG header */
 689        put_ghf_common_header(&gfh->brom_sec_cfg.gfh,
 690                              sizeof(gfh->brom_sec_cfg),
 691                              GFH_TYPE_BROM_SEC_CFG, 1);
 692        gfh->brom_sec_cfg.cfg_bits =
 693                cpu_to_le32(BROM_SEC_CFG_JTAG_EN | BROM_SEC_CFG_UART_EN);
 694}
 695
 696static void put_hash(uint8_t *buff, int size)
 697{
 698        sha256_context ctx;
 699
 700        sha256_starts(&ctx);
 701        sha256_update(&ctx, buff, size);
 702        sha256_finish(&ctx, buff + size);
 703}
 704
 705static void mtk_image_set_gen_header(void *ptr, off_t filesize,
 706                                     uint32_t loadaddr)
 707{
 708        struct gen_device_header *hdr = (struct gen_device_header *)ptr;
 709        struct gfh_header *gfh;
 710        const char *bootname = NULL;
 711
 712        if (hdr_media == BRLYT_TYPE_NOR)
 713                bootname = SF_BOOT_NAME;
 714        else if (hdr_media == BRLYT_TYPE_EMMC)
 715                bootname = EMMC_BOOT_NAME;
 716        else if (hdr_media == BRLYT_TYPE_SDMMC)
 717                bootname = SDMMC_BOOT_NAME;
 718
 719        /* Generic device header */
 720        snprintf(hdr->boot.name, sizeof(hdr->boot.name), "%s", bootname);
 721        hdr->boot.version = cpu_to_le32(1);
 722        hdr->boot.size = cpu_to_le32(sizeof(hdr->boot));
 723
 724        /* BRLYT header */
 725        put_brom_layout_header(&hdr->brlyt, hdr_media);
 726        hdr->brlyt.header_size = cpu_to_le32(hdr_offset + sizeof(*hdr));
 727        hdr->brlyt.total_size = cpu_to_le32(hdr_offset + filesize);
 728        hdr->brlyt.header_size_2 = hdr->brlyt.header_size;
 729        hdr->brlyt.total_size_2 = hdr->brlyt.total_size;
 730
 731        /* GFH header */
 732        gfh = (struct gfh_header *)(ptr + sizeof(struct gen_device_header));
 733        put_ghf_header(gfh, filesize, sizeof(struct gen_device_header),
 734                       loadaddr, GFH_FLASH_TYPE_GEN);
 735
 736        /* Generate SHA256 hash */
 737        put_hash((uint8_t *)gfh,
 738                 filesize - sizeof(struct gen_device_header) - SHA256_SUM_LEN);
 739}
 740
 741static void mtk_image_set_nand_header(void *ptr, off_t filesize,
 742                                      uint32_t loadaddr)
 743{
 744        union nand_boot_header *nh = (union nand_boot_header *)ptr;
 745        struct brom_layout_header *brlyt;
 746        struct gfh_header *gfh;
 747        uint32_t payload_pages;
 748        int i;
 749
 750        /* NAND device header, repeat 4 times */
 751        for (i = 0; i < 4; i++)
 752                memcpy(nh + i, hdr_nand, sizeof(union nand_boot_header));
 753
 754        /* BRLYT header */
 755        payload_pages = (filesize + le16_to_cpu(hdr_nand->pagesize) - 1) /
 756                        le16_to_cpu(hdr_nand->pagesize);
 757        brlyt = (struct brom_layout_header *)
 758                (ptr + le16_to_cpu(hdr_nand->pagesize));
 759        put_brom_layout_header(brlyt, hdr_media);
 760        brlyt->header_size = cpu_to_le32(2);
 761        brlyt->total_size = cpu_to_le32(payload_pages);
 762        brlyt->header_size_2 = brlyt->header_size;
 763        brlyt->total_size_2 = brlyt->total_size;
 764        brlyt->unused = cpu_to_le32(1);
 765
 766        /* GFH header */
 767        gfh = (struct gfh_header *)(ptr + 2 * le16_to_cpu(hdr_nand->pagesize));
 768        put_ghf_header(gfh, filesize, 2 * le16_to_cpu(hdr_nand->pagesize),
 769                       loadaddr, GFH_FLASH_TYPE_NAND);
 770
 771        /* Generate SHA256 hash */
 772        put_hash((uint8_t *)gfh,
 773                 filesize - 2 * le16_to_cpu(hdr_nand->pagesize) - SHA256_SUM_LEN);
 774}
 775
 776static void mtk_image_set_header(void *ptr, struct stat *sbuf, int ifd,
 777                                 struct image_tool_params *params)
 778{
 779        union lk_hdr *lk = (union lk_hdr *)ptr;
 780
 781        if (use_lk_hdr) {
 782                lk->magic = cpu_to_le32(LK_PART_MAGIC);
 783                lk->size = cpu_to_le32(sbuf->st_size - sizeof(union lk_hdr));
 784                lk->loadaddr = cpu_to_le32(params->addr);
 785                lk->mode = 0xffffffff; /* must be non-zero */
 786                memset(lk->name, 0, sizeof(lk->name));
 787                strncpy(lk->name, lk_name, sizeof(lk->name));
 788                return;
 789        }
 790
 791        img_gen = true;
 792        img_size = sbuf->st_size;
 793
 794        if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
 795                mtk_image_set_nand_header(ptr, sbuf->st_size, params->addr);
 796        else
 797                mtk_image_set_gen_header(ptr, sbuf->st_size, params->addr);
 798}
 799
 800U_BOOT_IMAGE_TYPE(
 801        mtk_image,
 802        "MediaTek BootROM Loadable Image support",
 803        0,
 804        NULL,
 805        mtk_image_check_params,
 806        mtk_image_verify_header,
 807        mtk_image_print_header,
 808        mtk_image_set_header,
 809        NULL,
 810        mtk_image_check_image_types,
 811        NULL,
 812        mtk_image_vrec_header
 813);
 814