1*bce88370SMarek Vasut /* 2*bce88370SMarek Vasut * Freescale i.MX23/i.MX28 SB image generator 3*bce88370SMarek Vasut * 4*bce88370SMarek Vasut * Copyright (C) 2012-2013 Marek Vasut <marex@denx.de> 5*bce88370SMarek Vasut * 6*bce88370SMarek Vasut * SPDX-License-Identifier: GPL-2.0+ 7*bce88370SMarek Vasut */ 8*bce88370SMarek Vasut 9*bce88370SMarek Vasut #ifdef CONFIG_MXS 10*bce88370SMarek Vasut 11*bce88370SMarek Vasut #include <errno.h> 12*bce88370SMarek Vasut #include <fcntl.h> 13*bce88370SMarek Vasut #include <stdio.h> 14*bce88370SMarek Vasut #include <string.h> 15*bce88370SMarek Vasut #include <unistd.h> 16*bce88370SMarek Vasut #include <limits.h> 17*bce88370SMarek Vasut 18*bce88370SMarek Vasut #include <openssl/evp.h> 19*bce88370SMarek Vasut 20*bce88370SMarek Vasut #include "mkimage.h" 21*bce88370SMarek Vasut #include "mxsimage.h" 22*bce88370SMarek Vasut #include <image.h> 23*bce88370SMarek Vasut 24*bce88370SMarek Vasut 25*bce88370SMarek Vasut /* 26*bce88370SMarek Vasut * DCD block 27*bce88370SMarek Vasut * |-Write to address command block 28*bce88370SMarek Vasut * | 0xf00 == 0xf33d 29*bce88370SMarek Vasut * | 0xba2 == 0xb33f 30*bce88370SMarek Vasut * |-ORR address with mask command block 31*bce88370SMarek Vasut * | 0xf00 |= 0x1337 32*bce88370SMarek Vasut * |-Write to address command block 33*bce88370SMarek Vasut * | 0xba2 == 0xd00d 34*bce88370SMarek Vasut * : 35*bce88370SMarek Vasut */ 36*bce88370SMarek Vasut #define SB_HAB_DCD_WRITE 0xccUL 37*bce88370SMarek Vasut #define SB_HAB_DCD_CHECK 0xcfUL 38*bce88370SMarek Vasut #define SB_HAB_DCD_NOOP 0xc0UL 39*bce88370SMarek Vasut #define SB_HAB_DCD_MASK_BIT (1 << 3) 40*bce88370SMarek Vasut #define SB_HAB_DCD_SET_BIT (1 << 4) 41*bce88370SMarek Vasut 42*bce88370SMarek Vasut /* Addr.n = Value.n */ 43*bce88370SMarek Vasut #define SB_DCD_WRITE \ 44*bce88370SMarek Vasut (SB_HAB_DCD_WRITE << 24) 45*bce88370SMarek Vasut /* Addr.n &= ~Value.n */ 46*bce88370SMarek Vasut #define SB_DCD_ANDC \ 47*bce88370SMarek Vasut ((SB_HAB_DCD_WRITE << 24) | SB_HAB_DCD_SET_BIT) 48*bce88370SMarek Vasut /* Addr.n |= Value.n */ 49*bce88370SMarek Vasut #define SB_DCD_ORR \ 50*bce88370SMarek Vasut ((SB_HAB_DCD_WRITE << 24) | SB_HAB_DCD_SET_BIT | SB_HAB_DCD_MASK_BIT) 51*bce88370SMarek Vasut /* (Addr.n & Value.n) == 0 */ 52*bce88370SMarek Vasut #define SB_DCD_CHK_EQZ \ 53*bce88370SMarek Vasut (SB_HAB_DCD_CHECK << 24) 54*bce88370SMarek Vasut /* (Addr.n & Value.n) == Value.n */ 55*bce88370SMarek Vasut #define SB_DCD_CHK_EQ \ 56*bce88370SMarek Vasut ((SB_HAB_DCD_CHECK << 24) | SB_HAB_DCD_SET_BIT) 57*bce88370SMarek Vasut /* (Addr.n & Value.n) != Value.n */ 58*bce88370SMarek Vasut #define SB_DCD_CHK_NEQ \ 59*bce88370SMarek Vasut ((SB_HAB_DCD_CHECK << 24) | SB_HAB_DCD_MASK_BIT) 60*bce88370SMarek Vasut /* (Addr.n & Value.n) != 0 */ 61*bce88370SMarek Vasut #define SB_DCD_CHK_NEZ \ 62*bce88370SMarek Vasut ((SB_HAB_DCD_CHECK << 24) | SB_HAB_DCD_SET_BIT | SB_HAB_DCD_MASK_BIT) 63*bce88370SMarek Vasut /* NOP */ 64*bce88370SMarek Vasut #define SB_DCD_NOOP \ 65*bce88370SMarek Vasut (SB_HAB_DCD_NOOP << 24) 66*bce88370SMarek Vasut 67*bce88370SMarek Vasut struct sb_dcd_ctx { 68*bce88370SMarek Vasut struct sb_dcd_ctx *dcd; 69*bce88370SMarek Vasut 70*bce88370SMarek Vasut uint32_t id; 71*bce88370SMarek Vasut 72*bce88370SMarek Vasut /* The DCD block. */ 73*bce88370SMarek Vasut uint32_t *payload; 74*bce88370SMarek Vasut /* Size of the whole DCD block. */ 75*bce88370SMarek Vasut uint32_t size; 76*bce88370SMarek Vasut 77*bce88370SMarek Vasut /* Pointer to previous DCD command block. */ 78*bce88370SMarek Vasut uint32_t *prev_dcd_head; 79*bce88370SMarek Vasut }; 80*bce88370SMarek Vasut 81*bce88370SMarek Vasut /* 82*bce88370SMarek Vasut * IMAGE 83*bce88370SMarek Vasut * |-SECTION 84*bce88370SMarek Vasut * | |-CMD 85*bce88370SMarek Vasut * | |-CMD 86*bce88370SMarek Vasut * | `-CMD 87*bce88370SMarek Vasut * |-SECTION 88*bce88370SMarek Vasut * | |-CMD 89*bce88370SMarek Vasut * : : 90*bce88370SMarek Vasut */ 91*bce88370SMarek Vasut struct sb_cmd_list { 92*bce88370SMarek Vasut char *cmd; 93*bce88370SMarek Vasut size_t len; 94*bce88370SMarek Vasut unsigned int lineno; 95*bce88370SMarek Vasut }; 96*bce88370SMarek Vasut 97*bce88370SMarek Vasut struct sb_cmd_ctx { 98*bce88370SMarek Vasut uint32_t size; 99*bce88370SMarek Vasut 100*bce88370SMarek Vasut struct sb_cmd_ctx *cmd; 101*bce88370SMarek Vasut 102*bce88370SMarek Vasut uint8_t *data; 103*bce88370SMarek Vasut uint32_t length; 104*bce88370SMarek Vasut 105*bce88370SMarek Vasut struct sb_command payload; 106*bce88370SMarek Vasut struct sb_command c_payload; 107*bce88370SMarek Vasut }; 108*bce88370SMarek Vasut 109*bce88370SMarek Vasut struct sb_section_ctx { 110*bce88370SMarek Vasut uint32_t size; 111*bce88370SMarek Vasut 112*bce88370SMarek Vasut /* Section flags */ 113*bce88370SMarek Vasut unsigned int boot:1; 114*bce88370SMarek Vasut 115*bce88370SMarek Vasut struct sb_section_ctx *sect; 116*bce88370SMarek Vasut 117*bce88370SMarek Vasut struct sb_cmd_ctx *cmd_head; 118*bce88370SMarek Vasut struct sb_cmd_ctx *cmd_tail; 119*bce88370SMarek Vasut 120*bce88370SMarek Vasut struct sb_sections_header payload; 121*bce88370SMarek Vasut }; 122*bce88370SMarek Vasut 123*bce88370SMarek Vasut struct sb_image_ctx { 124*bce88370SMarek Vasut unsigned int in_section:1; 125*bce88370SMarek Vasut unsigned int in_dcd:1; 126*bce88370SMarek Vasut /* Image configuration */ 127*bce88370SMarek Vasut unsigned int verbose_boot:1; 128*bce88370SMarek Vasut unsigned int silent_dump:1; 129*bce88370SMarek Vasut char *input_filename; 130*bce88370SMarek Vasut char *output_filename; 131*bce88370SMarek Vasut char *cfg_filename; 132*bce88370SMarek Vasut uint8_t image_key[16]; 133*bce88370SMarek Vasut 134*bce88370SMarek Vasut /* Number of section in the image */ 135*bce88370SMarek Vasut unsigned int sect_count; 136*bce88370SMarek Vasut /* Bootable section */ 137*bce88370SMarek Vasut unsigned int sect_boot; 138*bce88370SMarek Vasut unsigned int sect_boot_found:1; 139*bce88370SMarek Vasut 140*bce88370SMarek Vasut struct sb_section_ctx *sect_head; 141*bce88370SMarek Vasut struct sb_section_ctx *sect_tail; 142*bce88370SMarek Vasut 143*bce88370SMarek Vasut struct sb_dcd_ctx *dcd_head; 144*bce88370SMarek Vasut struct sb_dcd_ctx *dcd_tail; 145*bce88370SMarek Vasut 146*bce88370SMarek Vasut EVP_CIPHER_CTX cipher_ctx; 147*bce88370SMarek Vasut EVP_MD_CTX md_ctx; 148*bce88370SMarek Vasut uint8_t digest[32]; 149*bce88370SMarek Vasut struct sb_key_dictionary_key sb_dict_key; 150*bce88370SMarek Vasut 151*bce88370SMarek Vasut struct sb_boot_image_header payload; 152*bce88370SMarek Vasut }; 153*bce88370SMarek Vasut 154*bce88370SMarek Vasut /* 155*bce88370SMarek Vasut * Instruction semantics: 156*bce88370SMarek Vasut * NOOP 157*bce88370SMarek Vasut * TAG [LAST] 158*bce88370SMarek Vasut * LOAD address file 159*bce88370SMarek Vasut * LOAD IVT address IVT_entry_point 160*bce88370SMarek Vasut * FILL address pattern length 161*bce88370SMarek Vasut * JUMP [HAB] address [r0_arg] 162*bce88370SMarek Vasut * CALL [HAB] address [r0_arg] 163*bce88370SMarek Vasut * MODE mode 164*bce88370SMarek Vasut * For i.MX23, mode = USB/I2C/SPI1_FLASH/SPI2_FLASH/NAND_BCH 165*bce88370SMarek Vasut * JTAG/SPI3_EEPROM/SD_SSP0/SD_SSP1 166*bce88370SMarek Vasut * For i.MX28, mode = USB/I2C/SPI2_FLASH/SPI3_FLASH/NAND_BCH 167*bce88370SMarek Vasut * JTAG/SPI2_EEPROM/SD_SSP0/SD_SSP1 168*bce88370SMarek Vasut */ 169*bce88370SMarek Vasut 170*bce88370SMarek Vasut /* 171*bce88370SMarek Vasut * AES libcrypto 172*bce88370SMarek Vasut */ 173*bce88370SMarek Vasut static int sb_aes_init(struct sb_image_ctx *ictx, uint8_t *iv, int enc) 174*bce88370SMarek Vasut { 175*bce88370SMarek Vasut EVP_CIPHER_CTX *ctx = &ictx->cipher_ctx; 176*bce88370SMarek Vasut int ret; 177*bce88370SMarek Vasut 178*bce88370SMarek Vasut /* If there is no init vector, init vector is all zeroes. */ 179*bce88370SMarek Vasut if (!iv) 180*bce88370SMarek Vasut iv = ictx->image_key; 181*bce88370SMarek Vasut 182*bce88370SMarek Vasut EVP_CIPHER_CTX_init(ctx); 183*bce88370SMarek Vasut ret = EVP_CipherInit(ctx, EVP_aes_128_cbc(), ictx->image_key, iv, enc); 184*bce88370SMarek Vasut if (ret == 1) 185*bce88370SMarek Vasut EVP_CIPHER_CTX_set_padding(ctx, 0); 186*bce88370SMarek Vasut return ret; 187*bce88370SMarek Vasut } 188*bce88370SMarek Vasut 189*bce88370SMarek Vasut static int sb_aes_crypt(struct sb_image_ctx *ictx, uint8_t *in_data, 190*bce88370SMarek Vasut uint8_t *out_data, int in_len) 191*bce88370SMarek Vasut { 192*bce88370SMarek Vasut EVP_CIPHER_CTX *ctx = &ictx->cipher_ctx; 193*bce88370SMarek Vasut int ret, outlen; 194*bce88370SMarek Vasut uint8_t *outbuf; 195*bce88370SMarek Vasut 196*bce88370SMarek Vasut outbuf = malloc(in_len); 197*bce88370SMarek Vasut if (!outbuf) 198*bce88370SMarek Vasut return -ENOMEM; 199*bce88370SMarek Vasut memset(outbuf, 0, sizeof(in_len)); 200*bce88370SMarek Vasut 201*bce88370SMarek Vasut ret = EVP_CipherUpdate(ctx, outbuf, &outlen, in_data, in_len); 202*bce88370SMarek Vasut if (!ret) { 203*bce88370SMarek Vasut ret = -EINVAL; 204*bce88370SMarek Vasut goto err; 205*bce88370SMarek Vasut } 206*bce88370SMarek Vasut 207*bce88370SMarek Vasut if (out_data) 208*bce88370SMarek Vasut memcpy(out_data, outbuf, outlen); 209*bce88370SMarek Vasut 210*bce88370SMarek Vasut err: 211*bce88370SMarek Vasut free(outbuf); 212*bce88370SMarek Vasut return ret; 213*bce88370SMarek Vasut } 214*bce88370SMarek Vasut 215*bce88370SMarek Vasut static int sb_aes_deinit(EVP_CIPHER_CTX *ctx) 216*bce88370SMarek Vasut { 217*bce88370SMarek Vasut return EVP_CIPHER_CTX_cleanup(ctx); 218*bce88370SMarek Vasut } 219*bce88370SMarek Vasut 220*bce88370SMarek Vasut static int sb_aes_reinit(struct sb_image_ctx *ictx, int enc) 221*bce88370SMarek Vasut { 222*bce88370SMarek Vasut int ret; 223*bce88370SMarek Vasut EVP_CIPHER_CTX *ctx = &ictx->cipher_ctx; 224*bce88370SMarek Vasut struct sb_boot_image_header *sb_header = &ictx->payload; 225*bce88370SMarek Vasut uint8_t *iv = sb_header->iv; 226*bce88370SMarek Vasut 227*bce88370SMarek Vasut ret = sb_aes_deinit(ctx); 228*bce88370SMarek Vasut if (!ret) 229*bce88370SMarek Vasut return ret; 230*bce88370SMarek Vasut return sb_aes_init(ictx, iv, enc); 231*bce88370SMarek Vasut } 232*bce88370SMarek Vasut 233*bce88370SMarek Vasut /* 234*bce88370SMarek Vasut * CRC32 235*bce88370SMarek Vasut */ 236*bce88370SMarek Vasut static uint32_t crc32(uint8_t *data, uint32_t len) 237*bce88370SMarek Vasut { 238*bce88370SMarek Vasut const uint32_t poly = 0x04c11db7; 239*bce88370SMarek Vasut uint32_t crc32 = 0xffffffff; 240*bce88370SMarek Vasut unsigned int byte, bit; 241*bce88370SMarek Vasut 242*bce88370SMarek Vasut for (byte = 0; byte < len; byte++) { 243*bce88370SMarek Vasut crc32 ^= data[byte] << 24; 244*bce88370SMarek Vasut 245*bce88370SMarek Vasut for (bit = 8; bit > 0; bit--) { 246*bce88370SMarek Vasut if (crc32 & (1UL << 31)) 247*bce88370SMarek Vasut crc32 = (crc32 << 1) ^ poly; 248*bce88370SMarek Vasut else 249*bce88370SMarek Vasut crc32 = (crc32 << 1); 250*bce88370SMarek Vasut } 251*bce88370SMarek Vasut } 252*bce88370SMarek Vasut 253*bce88370SMarek Vasut return crc32; 254*bce88370SMarek Vasut } 255*bce88370SMarek Vasut 256*bce88370SMarek Vasut /* 257*bce88370SMarek Vasut * Debug 258*bce88370SMarek Vasut */ 259*bce88370SMarek Vasut static void soprintf(struct sb_image_ctx *ictx, const char *fmt, ...) 260*bce88370SMarek Vasut { 261*bce88370SMarek Vasut va_list ap; 262*bce88370SMarek Vasut 263*bce88370SMarek Vasut if (ictx->silent_dump) 264*bce88370SMarek Vasut return; 265*bce88370SMarek Vasut 266*bce88370SMarek Vasut va_start(ap, fmt); 267*bce88370SMarek Vasut vfprintf(stdout, fmt, ap); 268*bce88370SMarek Vasut va_end(ap); 269*bce88370SMarek Vasut } 270*bce88370SMarek Vasut 271*bce88370SMarek Vasut /* 272*bce88370SMarek Vasut * Code 273*bce88370SMarek Vasut */ 274*bce88370SMarek Vasut static time_t sb_get_timestamp(void) 275*bce88370SMarek Vasut { 276*bce88370SMarek Vasut struct tm time_2000 = { 277*bce88370SMarek Vasut .tm_yday = 1, /* Jan. 1st */ 278*bce88370SMarek Vasut .tm_year = 100, /* 2000 */ 279*bce88370SMarek Vasut }; 280*bce88370SMarek Vasut time_t seconds_to_2000 = mktime(&time_2000); 281*bce88370SMarek Vasut time_t seconds_to_now = time(NULL); 282*bce88370SMarek Vasut 283*bce88370SMarek Vasut return seconds_to_now - seconds_to_2000; 284*bce88370SMarek Vasut } 285*bce88370SMarek Vasut 286*bce88370SMarek Vasut static int sb_get_time(time_t time, struct tm *tm) 287*bce88370SMarek Vasut { 288*bce88370SMarek Vasut struct tm time_2000 = { 289*bce88370SMarek Vasut .tm_yday = 1, /* Jan. 1st */ 290*bce88370SMarek Vasut .tm_year = 0, /* 1900 */ 291*bce88370SMarek Vasut }; 292*bce88370SMarek Vasut const time_t seconds_to_2000 = mktime(&time_2000); 293*bce88370SMarek Vasut const time_t seconds_to_now = seconds_to_2000 + time; 294*bce88370SMarek Vasut struct tm *ret; 295*bce88370SMarek Vasut ret = gmtime_r(&seconds_to_now, tm); 296*bce88370SMarek Vasut return ret ? 0 : -EINVAL; 297*bce88370SMarek Vasut } 298*bce88370SMarek Vasut 299*bce88370SMarek Vasut static void sb_encrypt_sb_header(struct sb_image_ctx *ictx) 300*bce88370SMarek Vasut { 301*bce88370SMarek Vasut EVP_MD_CTX *md_ctx = &ictx->md_ctx; 302*bce88370SMarek Vasut struct sb_boot_image_header *sb_header = &ictx->payload; 303*bce88370SMarek Vasut uint8_t *sb_header_ptr = (uint8_t *)sb_header; 304*bce88370SMarek Vasut 305*bce88370SMarek Vasut /* Encrypt the header, compute the digest. */ 306*bce88370SMarek Vasut sb_aes_crypt(ictx, sb_header_ptr, NULL, sizeof(*sb_header)); 307*bce88370SMarek Vasut EVP_DigestUpdate(md_ctx, sb_header_ptr, sizeof(*sb_header)); 308*bce88370SMarek Vasut } 309*bce88370SMarek Vasut 310*bce88370SMarek Vasut static void sb_encrypt_sb_sections_header(struct sb_image_ctx *ictx) 311*bce88370SMarek Vasut { 312*bce88370SMarek Vasut EVP_MD_CTX *md_ctx = &ictx->md_ctx; 313*bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_head; 314*bce88370SMarek Vasut struct sb_sections_header *shdr; 315*bce88370SMarek Vasut uint8_t *sb_sections_header_ptr; 316*bce88370SMarek Vasut const int size = sizeof(*shdr); 317*bce88370SMarek Vasut 318*bce88370SMarek Vasut while (sctx) { 319*bce88370SMarek Vasut shdr = &sctx->payload; 320*bce88370SMarek Vasut sb_sections_header_ptr = (uint8_t *)shdr; 321*bce88370SMarek Vasut 322*bce88370SMarek Vasut sb_aes_crypt(ictx, sb_sections_header_ptr, 323*bce88370SMarek Vasut ictx->sb_dict_key.cbc_mac, size); 324*bce88370SMarek Vasut EVP_DigestUpdate(md_ctx, sb_sections_header_ptr, size); 325*bce88370SMarek Vasut 326*bce88370SMarek Vasut sctx = sctx->sect; 327*bce88370SMarek Vasut }; 328*bce88370SMarek Vasut } 329*bce88370SMarek Vasut 330*bce88370SMarek Vasut static void sb_encrypt_key_dictionary_key(struct sb_image_ctx *ictx) 331*bce88370SMarek Vasut { 332*bce88370SMarek Vasut EVP_MD_CTX *md_ctx = &ictx->md_ctx; 333*bce88370SMarek Vasut 334*bce88370SMarek Vasut sb_aes_crypt(ictx, ictx->image_key, ictx->sb_dict_key.key, 335*bce88370SMarek Vasut sizeof(ictx->sb_dict_key.key)); 336*bce88370SMarek Vasut EVP_DigestUpdate(md_ctx, &ictx->sb_dict_key, sizeof(ictx->sb_dict_key)); 337*bce88370SMarek Vasut } 338*bce88370SMarek Vasut 339*bce88370SMarek Vasut static void sb_decrypt_key_dictionary_key(struct sb_image_ctx *ictx) 340*bce88370SMarek Vasut { 341*bce88370SMarek Vasut EVP_MD_CTX *md_ctx = &ictx->md_ctx; 342*bce88370SMarek Vasut 343*bce88370SMarek Vasut EVP_DigestUpdate(md_ctx, &ictx->sb_dict_key, sizeof(ictx->sb_dict_key)); 344*bce88370SMarek Vasut sb_aes_crypt(ictx, ictx->sb_dict_key.key, ictx->image_key, 345*bce88370SMarek Vasut sizeof(ictx->sb_dict_key.key)); 346*bce88370SMarek Vasut } 347*bce88370SMarek Vasut 348*bce88370SMarek Vasut static void sb_encrypt_tag(struct sb_image_ctx *ictx, 349*bce88370SMarek Vasut struct sb_cmd_ctx *cctx) 350*bce88370SMarek Vasut { 351*bce88370SMarek Vasut EVP_MD_CTX *md_ctx = &ictx->md_ctx; 352*bce88370SMarek Vasut struct sb_command *cmd = &cctx->payload; 353*bce88370SMarek Vasut 354*bce88370SMarek Vasut sb_aes_crypt(ictx, (uint8_t *)cmd, 355*bce88370SMarek Vasut (uint8_t *)&cctx->c_payload, sizeof(*cmd)); 356*bce88370SMarek Vasut EVP_DigestUpdate(md_ctx, &cctx->c_payload, sizeof(*cmd)); 357*bce88370SMarek Vasut } 358*bce88370SMarek Vasut 359*bce88370SMarek Vasut static int sb_encrypt_image(struct sb_image_ctx *ictx) 360*bce88370SMarek Vasut { 361*bce88370SMarek Vasut /* Start image-wide crypto. */ 362*bce88370SMarek Vasut EVP_MD_CTX_init(&ictx->md_ctx); 363*bce88370SMarek Vasut EVP_DigestInit(&ictx->md_ctx, EVP_sha1()); 364*bce88370SMarek Vasut 365*bce88370SMarek Vasut /* 366*bce88370SMarek Vasut * SB image header. 367*bce88370SMarek Vasut */ 368*bce88370SMarek Vasut sb_aes_init(ictx, NULL, 1); 369*bce88370SMarek Vasut sb_encrypt_sb_header(ictx); 370*bce88370SMarek Vasut 371*bce88370SMarek Vasut /* 372*bce88370SMarek Vasut * SB sections header. 373*bce88370SMarek Vasut */ 374*bce88370SMarek Vasut sb_encrypt_sb_sections_header(ictx); 375*bce88370SMarek Vasut 376*bce88370SMarek Vasut /* 377*bce88370SMarek Vasut * Key dictionary. 378*bce88370SMarek Vasut */ 379*bce88370SMarek Vasut sb_aes_reinit(ictx, 1); 380*bce88370SMarek Vasut sb_encrypt_key_dictionary_key(ictx); 381*bce88370SMarek Vasut 382*bce88370SMarek Vasut /* 383*bce88370SMarek Vasut * Section tags. 384*bce88370SMarek Vasut */ 385*bce88370SMarek Vasut struct sb_cmd_ctx *cctx; 386*bce88370SMarek Vasut struct sb_command *ccmd; 387*bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_head; 388*bce88370SMarek Vasut 389*bce88370SMarek Vasut while (sctx) { 390*bce88370SMarek Vasut cctx = sctx->cmd_head; 391*bce88370SMarek Vasut 392*bce88370SMarek Vasut sb_aes_reinit(ictx, 1); 393*bce88370SMarek Vasut 394*bce88370SMarek Vasut while (cctx) { 395*bce88370SMarek Vasut ccmd = &cctx->payload; 396*bce88370SMarek Vasut 397*bce88370SMarek Vasut sb_encrypt_tag(ictx, cctx); 398*bce88370SMarek Vasut 399*bce88370SMarek Vasut if (ccmd->header.tag == ROM_TAG_CMD) { 400*bce88370SMarek Vasut sb_aes_reinit(ictx, 1); 401*bce88370SMarek Vasut } else if (ccmd->header.tag == ROM_LOAD_CMD) { 402*bce88370SMarek Vasut sb_aes_crypt(ictx, cctx->data, cctx->data, 403*bce88370SMarek Vasut cctx->length); 404*bce88370SMarek Vasut EVP_DigestUpdate(&ictx->md_ctx, cctx->data, 405*bce88370SMarek Vasut cctx->length); 406*bce88370SMarek Vasut } 407*bce88370SMarek Vasut 408*bce88370SMarek Vasut cctx = cctx->cmd; 409*bce88370SMarek Vasut } 410*bce88370SMarek Vasut 411*bce88370SMarek Vasut sctx = sctx->sect; 412*bce88370SMarek Vasut }; 413*bce88370SMarek Vasut 414*bce88370SMarek Vasut /* 415*bce88370SMarek Vasut * Dump the SHA1 of the whole image. 416*bce88370SMarek Vasut */ 417*bce88370SMarek Vasut sb_aes_reinit(ictx, 1); 418*bce88370SMarek Vasut 419*bce88370SMarek Vasut EVP_DigestFinal(&ictx->md_ctx, ictx->digest, NULL); 420*bce88370SMarek Vasut sb_aes_crypt(ictx, ictx->digest, ictx->digest, sizeof(ictx->digest)); 421*bce88370SMarek Vasut 422*bce88370SMarek Vasut /* Stop the encryption session. */ 423*bce88370SMarek Vasut sb_aes_deinit(&ictx->cipher_ctx); 424*bce88370SMarek Vasut 425*bce88370SMarek Vasut return 0; 426*bce88370SMarek Vasut } 427*bce88370SMarek Vasut 428*bce88370SMarek Vasut static int sb_load_file(struct sb_cmd_ctx *cctx, char *filename) 429*bce88370SMarek Vasut { 430*bce88370SMarek Vasut long real_size, roundup_size; 431*bce88370SMarek Vasut uint8_t *data; 432*bce88370SMarek Vasut long ret; 433*bce88370SMarek Vasut unsigned long size; 434*bce88370SMarek Vasut FILE *fp; 435*bce88370SMarek Vasut 436*bce88370SMarek Vasut if (!filename) { 437*bce88370SMarek Vasut fprintf(stderr, "ERR: Missing filename!\n"); 438*bce88370SMarek Vasut return -EINVAL; 439*bce88370SMarek Vasut } 440*bce88370SMarek Vasut 441*bce88370SMarek Vasut fp = fopen(filename, "r"); 442*bce88370SMarek Vasut if (!fp) 443*bce88370SMarek Vasut goto err_open; 444*bce88370SMarek Vasut 445*bce88370SMarek Vasut ret = fseek(fp, 0, SEEK_END); 446*bce88370SMarek Vasut if (ret < 0) 447*bce88370SMarek Vasut goto err_file; 448*bce88370SMarek Vasut 449*bce88370SMarek Vasut real_size = ftell(fp); 450*bce88370SMarek Vasut if (real_size < 0) 451*bce88370SMarek Vasut goto err_file; 452*bce88370SMarek Vasut 453*bce88370SMarek Vasut ret = fseek(fp, 0, SEEK_SET); 454*bce88370SMarek Vasut if (ret < 0) 455*bce88370SMarek Vasut goto err_file; 456*bce88370SMarek Vasut 457*bce88370SMarek Vasut roundup_size = roundup(real_size, SB_BLOCK_SIZE); 458*bce88370SMarek Vasut data = calloc(1, roundup_size); 459*bce88370SMarek Vasut if (!data) 460*bce88370SMarek Vasut goto err_file; 461*bce88370SMarek Vasut 462*bce88370SMarek Vasut size = fread(data, 1, real_size, fp); 463*bce88370SMarek Vasut if (size != (unsigned long)real_size) 464*bce88370SMarek Vasut goto err_alloc; 465*bce88370SMarek Vasut 466*bce88370SMarek Vasut cctx->data = data; 467*bce88370SMarek Vasut cctx->length = roundup_size; 468*bce88370SMarek Vasut 469*bce88370SMarek Vasut fclose(fp); 470*bce88370SMarek Vasut return 0; 471*bce88370SMarek Vasut 472*bce88370SMarek Vasut err_alloc: 473*bce88370SMarek Vasut free(data); 474*bce88370SMarek Vasut err_file: 475*bce88370SMarek Vasut fclose(fp); 476*bce88370SMarek Vasut err_open: 477*bce88370SMarek Vasut fprintf(stderr, "ERR: Failed to load file \"%s\"\n", filename); 478*bce88370SMarek Vasut return -EINVAL; 479*bce88370SMarek Vasut } 480*bce88370SMarek Vasut 481*bce88370SMarek Vasut static uint8_t sb_command_checksum(struct sb_command *inst) 482*bce88370SMarek Vasut { 483*bce88370SMarek Vasut uint8_t *inst_ptr = (uint8_t *)inst; 484*bce88370SMarek Vasut uint8_t csum = 0; 485*bce88370SMarek Vasut unsigned int i; 486*bce88370SMarek Vasut 487*bce88370SMarek Vasut for (i = 0; i < sizeof(struct sb_command); i++) 488*bce88370SMarek Vasut csum += inst_ptr[i]; 489*bce88370SMarek Vasut 490*bce88370SMarek Vasut return csum; 491*bce88370SMarek Vasut } 492*bce88370SMarek Vasut 493*bce88370SMarek Vasut static int sb_token_to_long(char *tok, uint32_t *rid) 494*bce88370SMarek Vasut { 495*bce88370SMarek Vasut char *endptr; 496*bce88370SMarek Vasut unsigned long id; 497*bce88370SMarek Vasut 498*bce88370SMarek Vasut if (tok[0] != '0' || tok[1] != 'x') { 499*bce88370SMarek Vasut fprintf(stderr, "ERR: Invalid hexadecimal number!\n"); 500*bce88370SMarek Vasut return -EINVAL; 501*bce88370SMarek Vasut } 502*bce88370SMarek Vasut 503*bce88370SMarek Vasut tok += 2; 504*bce88370SMarek Vasut 505*bce88370SMarek Vasut id = strtoul(tok, &endptr, 16); 506*bce88370SMarek Vasut if ((errno == ERANGE && id == ULONG_MAX) || (errno != 0 && id == 0)) { 507*bce88370SMarek Vasut fprintf(stderr, "ERR: Value can't be decoded!\n"); 508*bce88370SMarek Vasut return -EINVAL; 509*bce88370SMarek Vasut } 510*bce88370SMarek Vasut 511*bce88370SMarek Vasut /* Check for 32-bit overflow. */ 512*bce88370SMarek Vasut if (id > 0xffffffff) { 513*bce88370SMarek Vasut fprintf(stderr, "ERR: Value too big!\n"); 514*bce88370SMarek Vasut return -EINVAL; 515*bce88370SMarek Vasut } 516*bce88370SMarek Vasut 517*bce88370SMarek Vasut if (endptr == tok) { 518*bce88370SMarek Vasut fprintf(stderr, "ERR: Deformed value!\n"); 519*bce88370SMarek Vasut return -EINVAL; 520*bce88370SMarek Vasut } 521*bce88370SMarek Vasut 522*bce88370SMarek Vasut *rid = (uint32_t)id; 523*bce88370SMarek Vasut return 0; 524*bce88370SMarek Vasut } 525*bce88370SMarek Vasut 526*bce88370SMarek Vasut static int sb_grow_dcd(struct sb_dcd_ctx *dctx, unsigned int inc_size) 527*bce88370SMarek Vasut { 528*bce88370SMarek Vasut uint32_t *tmp; 529*bce88370SMarek Vasut 530*bce88370SMarek Vasut if (!inc_size) 531*bce88370SMarek Vasut return 0; 532*bce88370SMarek Vasut 533*bce88370SMarek Vasut dctx->size += inc_size; 534*bce88370SMarek Vasut tmp = realloc(dctx->payload, dctx->size); 535*bce88370SMarek Vasut if (!tmp) 536*bce88370SMarek Vasut return -ENOMEM; 537*bce88370SMarek Vasut 538*bce88370SMarek Vasut dctx->payload = tmp; 539*bce88370SMarek Vasut 540*bce88370SMarek Vasut /* Assemble and update the HAB DCD header. */ 541*bce88370SMarek Vasut dctx->payload[0] = htonl((SB_HAB_DCD_TAG << 24) | 542*bce88370SMarek Vasut (dctx->size << 8) | 543*bce88370SMarek Vasut SB_HAB_VERSION); 544*bce88370SMarek Vasut 545*bce88370SMarek Vasut return 0; 546*bce88370SMarek Vasut } 547*bce88370SMarek Vasut 548*bce88370SMarek Vasut static int sb_build_dcd(struct sb_image_ctx *ictx, struct sb_cmd_list *cmd) 549*bce88370SMarek Vasut { 550*bce88370SMarek Vasut struct sb_dcd_ctx *dctx; 551*bce88370SMarek Vasut 552*bce88370SMarek Vasut char *tok; 553*bce88370SMarek Vasut uint32_t id; 554*bce88370SMarek Vasut int ret; 555*bce88370SMarek Vasut 556*bce88370SMarek Vasut dctx = calloc(1, sizeof(*dctx)); 557*bce88370SMarek Vasut if (!dctx) 558*bce88370SMarek Vasut return -ENOMEM; 559*bce88370SMarek Vasut 560*bce88370SMarek Vasut ret = sb_grow_dcd(dctx, 4); 561*bce88370SMarek Vasut if (ret) 562*bce88370SMarek Vasut goto err_dcd; 563*bce88370SMarek Vasut 564*bce88370SMarek Vasut /* Read DCD block number. */ 565*bce88370SMarek Vasut tok = strtok(cmd->cmd, " "); 566*bce88370SMarek Vasut if (!tok) { 567*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: DCD block without number!\n", 568*bce88370SMarek Vasut cmd->lineno); 569*bce88370SMarek Vasut ret = -EINVAL; 570*bce88370SMarek Vasut goto err_dcd; 571*bce88370SMarek Vasut } 572*bce88370SMarek Vasut 573*bce88370SMarek Vasut /* Parse the DCD block number. */ 574*bce88370SMarek Vasut ret = sb_token_to_long(tok, &id); 575*bce88370SMarek Vasut if (ret) { 576*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Malformed DCD block number!\n", 577*bce88370SMarek Vasut cmd->lineno); 578*bce88370SMarek Vasut goto err_dcd; 579*bce88370SMarek Vasut } 580*bce88370SMarek Vasut 581*bce88370SMarek Vasut dctx->id = id; 582*bce88370SMarek Vasut 583*bce88370SMarek Vasut /* 584*bce88370SMarek Vasut * The DCD block is now constructed. Append it to the list. 585*bce88370SMarek Vasut * WARNING: The DCD size is still not computed and will be 586*bce88370SMarek Vasut * updated while parsing it's commands. 587*bce88370SMarek Vasut */ 588*bce88370SMarek Vasut if (!ictx->dcd_head) { 589*bce88370SMarek Vasut ictx->dcd_head = dctx; 590*bce88370SMarek Vasut ictx->dcd_tail = dctx; 591*bce88370SMarek Vasut } else { 592*bce88370SMarek Vasut ictx->dcd_tail->dcd = dctx; 593*bce88370SMarek Vasut ictx->dcd_tail = dctx; 594*bce88370SMarek Vasut } 595*bce88370SMarek Vasut 596*bce88370SMarek Vasut return 0; 597*bce88370SMarek Vasut 598*bce88370SMarek Vasut err_dcd: 599*bce88370SMarek Vasut free(dctx->payload); 600*bce88370SMarek Vasut free(dctx); 601*bce88370SMarek Vasut return ret; 602*bce88370SMarek Vasut } 603*bce88370SMarek Vasut 604*bce88370SMarek Vasut static int sb_build_dcd_block(struct sb_image_ctx *ictx, 605*bce88370SMarek Vasut struct sb_cmd_list *cmd, 606*bce88370SMarek Vasut uint32_t type) 607*bce88370SMarek Vasut { 608*bce88370SMarek Vasut char *tok; 609*bce88370SMarek Vasut uint32_t address, value, length; 610*bce88370SMarek Vasut int ret; 611*bce88370SMarek Vasut 612*bce88370SMarek Vasut struct sb_dcd_ctx *dctx = ictx->dcd_tail; 613*bce88370SMarek Vasut uint32_t *dcd; 614*bce88370SMarek Vasut 615*bce88370SMarek Vasut if (dctx->prev_dcd_head && (type != SB_DCD_NOOP) && 616*bce88370SMarek Vasut ((dctx->prev_dcd_head[0] & 0xff0000ff) == type)) { 617*bce88370SMarek Vasut /* Same instruction as before, just append it. */ 618*bce88370SMarek Vasut ret = sb_grow_dcd(dctx, 8); 619*bce88370SMarek Vasut if (ret) 620*bce88370SMarek Vasut return ret; 621*bce88370SMarek Vasut } else if (type == SB_DCD_NOOP) { 622*bce88370SMarek Vasut ret = sb_grow_dcd(dctx, 4); 623*bce88370SMarek Vasut if (ret) 624*bce88370SMarek Vasut return ret; 625*bce88370SMarek Vasut 626*bce88370SMarek Vasut /* Update DCD command block pointer. */ 627*bce88370SMarek Vasut dctx->prev_dcd_head = dctx->payload + 628*bce88370SMarek Vasut dctx->size / sizeof(*dctx->payload) - 1; 629*bce88370SMarek Vasut 630*bce88370SMarek Vasut /* NOOP has only 4 bytes and no payload. */ 631*bce88370SMarek Vasut goto noop; 632*bce88370SMarek Vasut } else { 633*bce88370SMarek Vasut /* 634*bce88370SMarek Vasut * Either a different instruction block started now 635*bce88370SMarek Vasut * or this is the first instruction block. 636*bce88370SMarek Vasut */ 637*bce88370SMarek Vasut ret = sb_grow_dcd(dctx, 12); 638*bce88370SMarek Vasut if (ret) 639*bce88370SMarek Vasut return ret; 640*bce88370SMarek Vasut 641*bce88370SMarek Vasut /* Update DCD command block pointer. */ 642*bce88370SMarek Vasut dctx->prev_dcd_head = dctx->payload + 643*bce88370SMarek Vasut dctx->size / sizeof(*dctx->payload) - 3; 644*bce88370SMarek Vasut } 645*bce88370SMarek Vasut 646*bce88370SMarek Vasut dcd = dctx->payload + dctx->size / sizeof(*dctx->payload) - 2; 647*bce88370SMarek Vasut 648*bce88370SMarek Vasut /* 649*bce88370SMarek Vasut * Prepare the command. 650*bce88370SMarek Vasut */ 651*bce88370SMarek Vasut tok = strtok(cmd->cmd, " "); 652*bce88370SMarek Vasut if (!tok) { 653*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Missing DCD address!\n", 654*bce88370SMarek Vasut cmd->lineno); 655*bce88370SMarek Vasut ret = -EINVAL; 656*bce88370SMarek Vasut goto err; 657*bce88370SMarek Vasut } 658*bce88370SMarek Vasut 659*bce88370SMarek Vasut /* Read DCD destination address. */ 660*bce88370SMarek Vasut ret = sb_token_to_long(tok, &address); 661*bce88370SMarek Vasut if (ret) { 662*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Incorrect DCD address!\n", 663*bce88370SMarek Vasut cmd->lineno); 664*bce88370SMarek Vasut goto err; 665*bce88370SMarek Vasut } 666*bce88370SMarek Vasut 667*bce88370SMarek Vasut tok = strtok(NULL, " "); 668*bce88370SMarek Vasut if (!tok) { 669*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Missing DCD value!\n", 670*bce88370SMarek Vasut cmd->lineno); 671*bce88370SMarek Vasut ret = -EINVAL; 672*bce88370SMarek Vasut goto err; 673*bce88370SMarek Vasut } 674*bce88370SMarek Vasut 675*bce88370SMarek Vasut /* Read DCD operation value. */ 676*bce88370SMarek Vasut ret = sb_token_to_long(tok, &value); 677*bce88370SMarek Vasut if (ret) { 678*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Incorrect DCD value!\n", 679*bce88370SMarek Vasut cmd->lineno); 680*bce88370SMarek Vasut goto err; 681*bce88370SMarek Vasut } 682*bce88370SMarek Vasut 683*bce88370SMarek Vasut /* Fill in the new DCD entry. */ 684*bce88370SMarek Vasut dcd[0] = htonl(address); 685*bce88370SMarek Vasut dcd[1] = htonl(value); 686*bce88370SMarek Vasut 687*bce88370SMarek Vasut noop: 688*bce88370SMarek Vasut /* Update the DCD command block. */ 689*bce88370SMarek Vasut length = dctx->size - 690*bce88370SMarek Vasut ((dctx->prev_dcd_head - dctx->payload) * 691*bce88370SMarek Vasut sizeof(*dctx->payload)); 692*bce88370SMarek Vasut dctx->prev_dcd_head[0] = htonl(type | (length << 8)); 693*bce88370SMarek Vasut 694*bce88370SMarek Vasut err: 695*bce88370SMarek Vasut return ret; 696*bce88370SMarek Vasut } 697*bce88370SMarek Vasut 698*bce88370SMarek Vasut static int sb_build_section(struct sb_image_ctx *ictx, struct sb_cmd_list *cmd) 699*bce88370SMarek Vasut { 700*bce88370SMarek Vasut struct sb_section_ctx *sctx; 701*bce88370SMarek Vasut struct sb_sections_header *shdr; 702*bce88370SMarek Vasut char *tok; 703*bce88370SMarek Vasut uint32_t bootable = 0; 704*bce88370SMarek Vasut uint32_t id; 705*bce88370SMarek Vasut int ret; 706*bce88370SMarek Vasut 707*bce88370SMarek Vasut sctx = calloc(1, sizeof(*sctx)); 708*bce88370SMarek Vasut if (!sctx) 709*bce88370SMarek Vasut return -ENOMEM; 710*bce88370SMarek Vasut 711*bce88370SMarek Vasut /* Read section number. */ 712*bce88370SMarek Vasut tok = strtok(cmd->cmd, " "); 713*bce88370SMarek Vasut if (!tok) { 714*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Section without number!\n", 715*bce88370SMarek Vasut cmd->lineno); 716*bce88370SMarek Vasut ret = -EINVAL; 717*bce88370SMarek Vasut goto err_sect; 718*bce88370SMarek Vasut } 719*bce88370SMarek Vasut 720*bce88370SMarek Vasut /* Parse the section number. */ 721*bce88370SMarek Vasut ret = sb_token_to_long(tok, &id); 722*bce88370SMarek Vasut if (ret) { 723*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Malformed section number!\n", 724*bce88370SMarek Vasut cmd->lineno); 725*bce88370SMarek Vasut goto err_sect; 726*bce88370SMarek Vasut } 727*bce88370SMarek Vasut 728*bce88370SMarek Vasut /* Read section's BOOTABLE flag. */ 729*bce88370SMarek Vasut tok = strtok(NULL, " "); 730*bce88370SMarek Vasut if (tok && (strlen(tok) == 8) && !strncmp(tok, "BOOTABLE", 8)) 731*bce88370SMarek Vasut bootable = SB_SECTION_FLAG_BOOTABLE; 732*bce88370SMarek Vasut 733*bce88370SMarek Vasut sctx->boot = bootable; 734*bce88370SMarek Vasut 735*bce88370SMarek Vasut shdr = &sctx->payload; 736*bce88370SMarek Vasut shdr->section_number = id; 737*bce88370SMarek Vasut shdr->section_flags = bootable; 738*bce88370SMarek Vasut 739*bce88370SMarek Vasut /* 740*bce88370SMarek Vasut * The section is now constructed. Append it to the list. 741*bce88370SMarek Vasut * WARNING: The section size is still not computed and will 742*bce88370SMarek Vasut * be updated while parsing it's commands. 743*bce88370SMarek Vasut */ 744*bce88370SMarek Vasut ictx->sect_count++; 745*bce88370SMarek Vasut 746*bce88370SMarek Vasut /* Mark that this section is bootable one. */ 747*bce88370SMarek Vasut if (bootable) { 748*bce88370SMarek Vasut if (ictx->sect_boot_found) { 749*bce88370SMarek Vasut fprintf(stderr, 750*bce88370SMarek Vasut "#%i WARN: Multiple bootable section!\n", 751*bce88370SMarek Vasut cmd->lineno); 752*bce88370SMarek Vasut } else { 753*bce88370SMarek Vasut ictx->sect_boot = id; 754*bce88370SMarek Vasut ictx->sect_boot_found = 1; 755*bce88370SMarek Vasut } 756*bce88370SMarek Vasut } 757*bce88370SMarek Vasut 758*bce88370SMarek Vasut if (!ictx->sect_head) { 759*bce88370SMarek Vasut ictx->sect_head = sctx; 760*bce88370SMarek Vasut ictx->sect_tail = sctx; 761*bce88370SMarek Vasut } else { 762*bce88370SMarek Vasut ictx->sect_tail->sect = sctx; 763*bce88370SMarek Vasut ictx->sect_tail = sctx; 764*bce88370SMarek Vasut } 765*bce88370SMarek Vasut 766*bce88370SMarek Vasut return 0; 767*bce88370SMarek Vasut 768*bce88370SMarek Vasut err_sect: 769*bce88370SMarek Vasut free(sctx); 770*bce88370SMarek Vasut return ret; 771*bce88370SMarek Vasut } 772*bce88370SMarek Vasut 773*bce88370SMarek Vasut static int sb_build_command_nop(struct sb_image_ctx *ictx) 774*bce88370SMarek Vasut { 775*bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_tail; 776*bce88370SMarek Vasut struct sb_cmd_ctx *cctx; 777*bce88370SMarek Vasut struct sb_command *ccmd; 778*bce88370SMarek Vasut 779*bce88370SMarek Vasut cctx = calloc(1, sizeof(*cctx)); 780*bce88370SMarek Vasut if (!cctx) 781*bce88370SMarek Vasut return -ENOMEM; 782*bce88370SMarek Vasut 783*bce88370SMarek Vasut ccmd = &cctx->payload; 784*bce88370SMarek Vasut 785*bce88370SMarek Vasut /* 786*bce88370SMarek Vasut * Construct the command. 787*bce88370SMarek Vasut */ 788*bce88370SMarek Vasut ccmd->header.checksum = 0x5a; 789*bce88370SMarek Vasut ccmd->header.tag = ROM_NOP_CMD; 790*bce88370SMarek Vasut 791*bce88370SMarek Vasut cctx->size = sizeof(*ccmd); 792*bce88370SMarek Vasut 793*bce88370SMarek Vasut /* 794*bce88370SMarek Vasut * Append the command to the last section. 795*bce88370SMarek Vasut */ 796*bce88370SMarek Vasut if (!sctx->cmd_head) { 797*bce88370SMarek Vasut sctx->cmd_head = cctx; 798*bce88370SMarek Vasut sctx->cmd_tail = cctx; 799*bce88370SMarek Vasut } else { 800*bce88370SMarek Vasut sctx->cmd_tail->cmd = cctx; 801*bce88370SMarek Vasut sctx->cmd_tail = cctx; 802*bce88370SMarek Vasut } 803*bce88370SMarek Vasut 804*bce88370SMarek Vasut return 0; 805*bce88370SMarek Vasut } 806*bce88370SMarek Vasut 807*bce88370SMarek Vasut static int sb_build_command_tag(struct sb_image_ctx *ictx, 808*bce88370SMarek Vasut struct sb_cmd_list *cmd) 809*bce88370SMarek Vasut { 810*bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_tail; 811*bce88370SMarek Vasut struct sb_cmd_ctx *cctx; 812*bce88370SMarek Vasut struct sb_command *ccmd; 813*bce88370SMarek Vasut char *tok; 814*bce88370SMarek Vasut 815*bce88370SMarek Vasut cctx = calloc(1, sizeof(*cctx)); 816*bce88370SMarek Vasut if (!cctx) 817*bce88370SMarek Vasut return -ENOMEM; 818*bce88370SMarek Vasut 819*bce88370SMarek Vasut ccmd = &cctx->payload; 820*bce88370SMarek Vasut 821*bce88370SMarek Vasut /* 822*bce88370SMarek Vasut * Prepare the command. 823*bce88370SMarek Vasut */ 824*bce88370SMarek Vasut /* Check for the LAST keyword. */ 825*bce88370SMarek Vasut tok = strtok(cmd->cmd, " "); 826*bce88370SMarek Vasut if (tok && !strcmp(tok, "LAST")) 827*bce88370SMarek Vasut ccmd->header.flags = ROM_TAG_CMD_FLAG_ROM_LAST_TAG; 828*bce88370SMarek Vasut 829*bce88370SMarek Vasut /* 830*bce88370SMarek Vasut * Construct the command. 831*bce88370SMarek Vasut */ 832*bce88370SMarek Vasut ccmd->header.checksum = 0x5a; 833*bce88370SMarek Vasut ccmd->header.tag = ROM_TAG_CMD; 834*bce88370SMarek Vasut 835*bce88370SMarek Vasut cctx->size = sizeof(*ccmd); 836*bce88370SMarek Vasut 837*bce88370SMarek Vasut /* 838*bce88370SMarek Vasut * Append the command to the last section. 839*bce88370SMarek Vasut */ 840*bce88370SMarek Vasut if (!sctx->cmd_head) { 841*bce88370SMarek Vasut sctx->cmd_head = cctx; 842*bce88370SMarek Vasut sctx->cmd_tail = cctx; 843*bce88370SMarek Vasut } else { 844*bce88370SMarek Vasut sctx->cmd_tail->cmd = cctx; 845*bce88370SMarek Vasut sctx->cmd_tail = cctx; 846*bce88370SMarek Vasut } 847*bce88370SMarek Vasut 848*bce88370SMarek Vasut return 0; 849*bce88370SMarek Vasut } 850*bce88370SMarek Vasut 851*bce88370SMarek Vasut static int sb_build_command_load(struct sb_image_ctx *ictx, 852*bce88370SMarek Vasut struct sb_cmd_list *cmd) 853*bce88370SMarek Vasut { 854*bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_tail; 855*bce88370SMarek Vasut struct sb_cmd_ctx *cctx; 856*bce88370SMarek Vasut struct sb_command *ccmd; 857*bce88370SMarek Vasut char *tok; 858*bce88370SMarek Vasut int ret, is_ivt = 0, is_dcd = 0; 859*bce88370SMarek Vasut uint32_t dest, dcd = 0; 860*bce88370SMarek Vasut 861*bce88370SMarek Vasut cctx = calloc(1, sizeof(*cctx)); 862*bce88370SMarek Vasut if (!cctx) 863*bce88370SMarek Vasut return -ENOMEM; 864*bce88370SMarek Vasut 865*bce88370SMarek Vasut ccmd = &cctx->payload; 866*bce88370SMarek Vasut 867*bce88370SMarek Vasut /* 868*bce88370SMarek Vasut * Prepare the command. 869*bce88370SMarek Vasut */ 870*bce88370SMarek Vasut tok = strtok(cmd->cmd, " "); 871*bce88370SMarek Vasut if (!tok) { 872*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Missing LOAD address or 'IVT'!\n", 873*bce88370SMarek Vasut cmd->lineno); 874*bce88370SMarek Vasut ret = -EINVAL; 875*bce88370SMarek Vasut goto err; 876*bce88370SMarek Vasut } 877*bce88370SMarek Vasut 878*bce88370SMarek Vasut /* Check for "IVT" flag. */ 879*bce88370SMarek Vasut if (!strcmp(tok, "IVT")) 880*bce88370SMarek Vasut is_ivt = 1; 881*bce88370SMarek Vasut if (!strcmp(tok, "DCD")) 882*bce88370SMarek Vasut is_dcd = 1; 883*bce88370SMarek Vasut if (is_ivt || is_dcd) { 884*bce88370SMarek Vasut tok = strtok(NULL, " "); 885*bce88370SMarek Vasut if (!tok) { 886*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Missing LOAD address!\n", 887*bce88370SMarek Vasut cmd->lineno); 888*bce88370SMarek Vasut ret = -EINVAL; 889*bce88370SMarek Vasut goto err; 890*bce88370SMarek Vasut } 891*bce88370SMarek Vasut } 892*bce88370SMarek Vasut 893*bce88370SMarek Vasut /* Read load destination address. */ 894*bce88370SMarek Vasut ret = sb_token_to_long(tok, &dest); 895*bce88370SMarek Vasut if (ret) { 896*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Incorrect LOAD address!\n", 897*bce88370SMarek Vasut cmd->lineno); 898*bce88370SMarek Vasut goto err; 899*bce88370SMarek Vasut } 900*bce88370SMarek Vasut 901*bce88370SMarek Vasut /* Read filename or IVT entrypoint or DCD block ID. */ 902*bce88370SMarek Vasut tok = strtok(NULL, " "); 903*bce88370SMarek Vasut if (!tok) { 904*bce88370SMarek Vasut fprintf(stderr, 905*bce88370SMarek Vasut "#%i ERR: Missing LOAD filename or IVT ep or DCD block ID!\n", 906*bce88370SMarek Vasut cmd->lineno); 907*bce88370SMarek Vasut ret = -EINVAL; 908*bce88370SMarek Vasut goto err; 909*bce88370SMarek Vasut } 910*bce88370SMarek Vasut 911*bce88370SMarek Vasut if (is_ivt) { 912*bce88370SMarek Vasut /* Handle IVT. */ 913*bce88370SMarek Vasut struct sb_ivt_header *ivt; 914*bce88370SMarek Vasut uint32_t ivtep; 915*bce88370SMarek Vasut ret = sb_token_to_long(tok, &ivtep); 916*bce88370SMarek Vasut 917*bce88370SMarek Vasut if (ret) { 918*bce88370SMarek Vasut fprintf(stderr, 919*bce88370SMarek Vasut "#%i ERR: Incorrect IVT entry point!\n", 920*bce88370SMarek Vasut cmd->lineno); 921*bce88370SMarek Vasut goto err; 922*bce88370SMarek Vasut } 923*bce88370SMarek Vasut 924*bce88370SMarek Vasut ivt = calloc(1, sizeof(*ivt)); 925*bce88370SMarek Vasut if (!ivt) { 926*bce88370SMarek Vasut ret = -ENOMEM; 927*bce88370SMarek Vasut goto err; 928*bce88370SMarek Vasut } 929*bce88370SMarek Vasut 930*bce88370SMarek Vasut ivt->header = sb_hab_ivt_header(); 931*bce88370SMarek Vasut ivt->entry = ivtep; 932*bce88370SMarek Vasut ivt->self = dest; 933*bce88370SMarek Vasut 934*bce88370SMarek Vasut cctx->data = (uint8_t *)ivt; 935*bce88370SMarek Vasut cctx->length = sizeof(*ivt); 936*bce88370SMarek Vasut } else if (is_dcd) { 937*bce88370SMarek Vasut struct sb_dcd_ctx *dctx = ictx->dcd_head; 938*bce88370SMarek Vasut uint32_t dcdid; 939*bce88370SMarek Vasut uint8_t *payload; 940*bce88370SMarek Vasut uint32_t asize; 941*bce88370SMarek Vasut ret = sb_token_to_long(tok, &dcdid); 942*bce88370SMarek Vasut 943*bce88370SMarek Vasut if (ret) { 944*bce88370SMarek Vasut fprintf(stderr, 945*bce88370SMarek Vasut "#%i ERR: Incorrect DCD block ID!\n", 946*bce88370SMarek Vasut cmd->lineno); 947*bce88370SMarek Vasut goto err; 948*bce88370SMarek Vasut } 949*bce88370SMarek Vasut 950*bce88370SMarek Vasut while (dctx) { 951*bce88370SMarek Vasut if (dctx->id == dcdid) 952*bce88370SMarek Vasut break; 953*bce88370SMarek Vasut dctx = dctx->dcd; 954*bce88370SMarek Vasut } 955*bce88370SMarek Vasut 956*bce88370SMarek Vasut if (!dctx) { 957*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: DCD block %08x not found!\n", 958*bce88370SMarek Vasut cmd->lineno, dcdid); 959*bce88370SMarek Vasut goto err; 960*bce88370SMarek Vasut } 961*bce88370SMarek Vasut 962*bce88370SMarek Vasut asize = roundup(dctx->size, SB_BLOCK_SIZE); 963*bce88370SMarek Vasut payload = calloc(1, asize); 964*bce88370SMarek Vasut if (!payload) { 965*bce88370SMarek Vasut ret = -ENOMEM; 966*bce88370SMarek Vasut goto err; 967*bce88370SMarek Vasut } 968*bce88370SMarek Vasut 969*bce88370SMarek Vasut memcpy(payload, dctx->payload, dctx->size); 970*bce88370SMarek Vasut 971*bce88370SMarek Vasut cctx->data = payload; 972*bce88370SMarek Vasut cctx->length = asize; 973*bce88370SMarek Vasut 974*bce88370SMarek Vasut /* Set the Load DCD flag. */ 975*bce88370SMarek Vasut dcd = ROM_LOAD_CMD_FLAG_DCD_LOAD; 976*bce88370SMarek Vasut } else { 977*bce88370SMarek Vasut /* Regular LOAD of a file. */ 978*bce88370SMarek Vasut ret = sb_load_file(cctx, tok); 979*bce88370SMarek Vasut if (ret) { 980*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Cannot load '%s'!\n", 981*bce88370SMarek Vasut cmd->lineno, tok); 982*bce88370SMarek Vasut goto err; 983*bce88370SMarek Vasut } 984*bce88370SMarek Vasut } 985*bce88370SMarek Vasut 986*bce88370SMarek Vasut if (cctx->length & (SB_BLOCK_SIZE - 1)) { 987*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Unaligned payload!\n", 988*bce88370SMarek Vasut cmd->lineno); 989*bce88370SMarek Vasut } 990*bce88370SMarek Vasut 991*bce88370SMarek Vasut /* 992*bce88370SMarek Vasut * Construct the command. 993*bce88370SMarek Vasut */ 994*bce88370SMarek Vasut ccmd->header.checksum = 0x5a; 995*bce88370SMarek Vasut ccmd->header.tag = ROM_LOAD_CMD; 996*bce88370SMarek Vasut ccmd->header.flags = dcd; 997*bce88370SMarek Vasut 998*bce88370SMarek Vasut ccmd->load.address = dest; 999*bce88370SMarek Vasut ccmd->load.count = cctx->length; 1000*bce88370SMarek Vasut ccmd->load.crc32 = crc32(cctx->data, cctx->length); 1001*bce88370SMarek Vasut 1002*bce88370SMarek Vasut cctx->size = sizeof(*ccmd) + cctx->length; 1003*bce88370SMarek Vasut 1004*bce88370SMarek Vasut /* 1005*bce88370SMarek Vasut * Append the command to the last section. 1006*bce88370SMarek Vasut */ 1007*bce88370SMarek Vasut if (!sctx->cmd_head) { 1008*bce88370SMarek Vasut sctx->cmd_head = cctx; 1009*bce88370SMarek Vasut sctx->cmd_tail = cctx; 1010*bce88370SMarek Vasut } else { 1011*bce88370SMarek Vasut sctx->cmd_tail->cmd = cctx; 1012*bce88370SMarek Vasut sctx->cmd_tail = cctx; 1013*bce88370SMarek Vasut } 1014*bce88370SMarek Vasut 1015*bce88370SMarek Vasut return 0; 1016*bce88370SMarek Vasut 1017*bce88370SMarek Vasut err: 1018*bce88370SMarek Vasut free(cctx); 1019*bce88370SMarek Vasut return ret; 1020*bce88370SMarek Vasut } 1021*bce88370SMarek Vasut 1022*bce88370SMarek Vasut static int sb_build_command_fill(struct sb_image_ctx *ictx, 1023*bce88370SMarek Vasut struct sb_cmd_list *cmd) 1024*bce88370SMarek Vasut { 1025*bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_tail; 1026*bce88370SMarek Vasut struct sb_cmd_ctx *cctx; 1027*bce88370SMarek Vasut struct sb_command *ccmd; 1028*bce88370SMarek Vasut char *tok; 1029*bce88370SMarek Vasut uint32_t address, pattern, length; 1030*bce88370SMarek Vasut int ret; 1031*bce88370SMarek Vasut 1032*bce88370SMarek Vasut cctx = calloc(1, sizeof(*cctx)); 1033*bce88370SMarek Vasut if (!cctx) 1034*bce88370SMarek Vasut return -ENOMEM; 1035*bce88370SMarek Vasut 1036*bce88370SMarek Vasut ccmd = &cctx->payload; 1037*bce88370SMarek Vasut 1038*bce88370SMarek Vasut /* 1039*bce88370SMarek Vasut * Prepare the command. 1040*bce88370SMarek Vasut */ 1041*bce88370SMarek Vasut tok = strtok(cmd->cmd, " "); 1042*bce88370SMarek Vasut if (!tok) { 1043*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Missing FILL address!\n", 1044*bce88370SMarek Vasut cmd->lineno); 1045*bce88370SMarek Vasut ret = -EINVAL; 1046*bce88370SMarek Vasut goto err; 1047*bce88370SMarek Vasut } 1048*bce88370SMarek Vasut 1049*bce88370SMarek Vasut /* Read fill destination address. */ 1050*bce88370SMarek Vasut ret = sb_token_to_long(tok, &address); 1051*bce88370SMarek Vasut if (ret) { 1052*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Incorrect FILL address!\n", 1053*bce88370SMarek Vasut cmd->lineno); 1054*bce88370SMarek Vasut goto err; 1055*bce88370SMarek Vasut } 1056*bce88370SMarek Vasut 1057*bce88370SMarek Vasut tok = strtok(NULL, " "); 1058*bce88370SMarek Vasut if (!tok) { 1059*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Missing FILL pattern!\n", 1060*bce88370SMarek Vasut cmd->lineno); 1061*bce88370SMarek Vasut ret = -EINVAL; 1062*bce88370SMarek Vasut goto err; 1063*bce88370SMarek Vasut } 1064*bce88370SMarek Vasut 1065*bce88370SMarek Vasut /* Read fill pattern address. */ 1066*bce88370SMarek Vasut ret = sb_token_to_long(tok, &pattern); 1067*bce88370SMarek Vasut if (ret) { 1068*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Incorrect FILL pattern!\n", 1069*bce88370SMarek Vasut cmd->lineno); 1070*bce88370SMarek Vasut goto err; 1071*bce88370SMarek Vasut } 1072*bce88370SMarek Vasut 1073*bce88370SMarek Vasut tok = strtok(NULL, " "); 1074*bce88370SMarek Vasut if (!tok) { 1075*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Missing FILL length!\n", 1076*bce88370SMarek Vasut cmd->lineno); 1077*bce88370SMarek Vasut ret = -EINVAL; 1078*bce88370SMarek Vasut goto err; 1079*bce88370SMarek Vasut } 1080*bce88370SMarek Vasut 1081*bce88370SMarek Vasut /* Read fill pattern address. */ 1082*bce88370SMarek Vasut ret = sb_token_to_long(tok, &length); 1083*bce88370SMarek Vasut if (ret) { 1084*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Incorrect FILL length!\n", 1085*bce88370SMarek Vasut cmd->lineno); 1086*bce88370SMarek Vasut goto err; 1087*bce88370SMarek Vasut } 1088*bce88370SMarek Vasut 1089*bce88370SMarek Vasut /* 1090*bce88370SMarek Vasut * Construct the command. 1091*bce88370SMarek Vasut */ 1092*bce88370SMarek Vasut ccmd->header.checksum = 0x5a; 1093*bce88370SMarek Vasut ccmd->header.tag = ROM_FILL_CMD; 1094*bce88370SMarek Vasut 1095*bce88370SMarek Vasut ccmd->fill.address = address; 1096*bce88370SMarek Vasut ccmd->fill.count = length; 1097*bce88370SMarek Vasut ccmd->fill.pattern = pattern; 1098*bce88370SMarek Vasut 1099*bce88370SMarek Vasut cctx->size = sizeof(*ccmd); 1100*bce88370SMarek Vasut 1101*bce88370SMarek Vasut /* 1102*bce88370SMarek Vasut * Append the command to the last section. 1103*bce88370SMarek Vasut */ 1104*bce88370SMarek Vasut if (!sctx->cmd_head) { 1105*bce88370SMarek Vasut sctx->cmd_head = cctx; 1106*bce88370SMarek Vasut sctx->cmd_tail = cctx; 1107*bce88370SMarek Vasut } else { 1108*bce88370SMarek Vasut sctx->cmd_tail->cmd = cctx; 1109*bce88370SMarek Vasut sctx->cmd_tail = cctx; 1110*bce88370SMarek Vasut } 1111*bce88370SMarek Vasut 1112*bce88370SMarek Vasut return 0; 1113*bce88370SMarek Vasut 1114*bce88370SMarek Vasut err: 1115*bce88370SMarek Vasut free(cctx); 1116*bce88370SMarek Vasut return ret; 1117*bce88370SMarek Vasut } 1118*bce88370SMarek Vasut 1119*bce88370SMarek Vasut static int sb_build_command_jump_call(struct sb_image_ctx *ictx, 1120*bce88370SMarek Vasut struct sb_cmd_list *cmd, 1121*bce88370SMarek Vasut unsigned int is_call) 1122*bce88370SMarek Vasut { 1123*bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_tail; 1124*bce88370SMarek Vasut struct sb_cmd_ctx *cctx; 1125*bce88370SMarek Vasut struct sb_command *ccmd; 1126*bce88370SMarek Vasut char *tok; 1127*bce88370SMarek Vasut uint32_t dest, arg = 0x0; 1128*bce88370SMarek Vasut uint32_t hab = 0; 1129*bce88370SMarek Vasut int ret; 1130*bce88370SMarek Vasut const char *cmdname = is_call ? "CALL" : "JUMP"; 1131*bce88370SMarek Vasut 1132*bce88370SMarek Vasut cctx = calloc(1, sizeof(*cctx)); 1133*bce88370SMarek Vasut if (!cctx) 1134*bce88370SMarek Vasut return -ENOMEM; 1135*bce88370SMarek Vasut 1136*bce88370SMarek Vasut ccmd = &cctx->payload; 1137*bce88370SMarek Vasut 1138*bce88370SMarek Vasut /* 1139*bce88370SMarek Vasut * Prepare the command. 1140*bce88370SMarek Vasut */ 1141*bce88370SMarek Vasut tok = strtok(cmd->cmd, " "); 1142*bce88370SMarek Vasut if (!tok) { 1143*bce88370SMarek Vasut fprintf(stderr, 1144*bce88370SMarek Vasut "#%i ERR: Missing %s address or 'HAB'!\n", 1145*bce88370SMarek Vasut cmd->lineno, cmdname); 1146*bce88370SMarek Vasut ret = -EINVAL; 1147*bce88370SMarek Vasut goto err; 1148*bce88370SMarek Vasut } 1149*bce88370SMarek Vasut 1150*bce88370SMarek Vasut /* Check for "HAB" flag. */ 1151*bce88370SMarek Vasut if (!strcmp(tok, "HAB")) { 1152*bce88370SMarek Vasut hab = is_call ? ROM_CALL_CMD_FLAG_HAB : ROM_JUMP_CMD_FLAG_HAB; 1153*bce88370SMarek Vasut tok = strtok(NULL, " "); 1154*bce88370SMarek Vasut if (!tok) { 1155*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Missing %s address!\n", 1156*bce88370SMarek Vasut cmd->lineno, cmdname); 1157*bce88370SMarek Vasut ret = -EINVAL; 1158*bce88370SMarek Vasut goto err; 1159*bce88370SMarek Vasut } 1160*bce88370SMarek Vasut } 1161*bce88370SMarek Vasut /* Read load destination address. */ 1162*bce88370SMarek Vasut ret = sb_token_to_long(tok, &dest); 1163*bce88370SMarek Vasut if (ret) { 1164*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Incorrect %s address!\n", 1165*bce88370SMarek Vasut cmd->lineno, cmdname); 1166*bce88370SMarek Vasut goto err; 1167*bce88370SMarek Vasut } 1168*bce88370SMarek Vasut 1169*bce88370SMarek Vasut tok = strtok(NULL, " "); 1170*bce88370SMarek Vasut if (tok) { 1171*bce88370SMarek Vasut ret = sb_token_to_long(tok, &arg); 1172*bce88370SMarek Vasut if (ret) { 1173*bce88370SMarek Vasut fprintf(stderr, 1174*bce88370SMarek Vasut "#%i ERR: Incorrect %s argument!\n", 1175*bce88370SMarek Vasut cmd->lineno, cmdname); 1176*bce88370SMarek Vasut goto err; 1177*bce88370SMarek Vasut } 1178*bce88370SMarek Vasut } 1179*bce88370SMarek Vasut 1180*bce88370SMarek Vasut /* 1181*bce88370SMarek Vasut * Construct the command. 1182*bce88370SMarek Vasut */ 1183*bce88370SMarek Vasut ccmd->header.checksum = 0x5a; 1184*bce88370SMarek Vasut ccmd->header.tag = is_call ? ROM_CALL_CMD : ROM_JUMP_CMD; 1185*bce88370SMarek Vasut ccmd->header.flags = hab; 1186*bce88370SMarek Vasut 1187*bce88370SMarek Vasut ccmd->call.address = dest; 1188*bce88370SMarek Vasut ccmd->call.argument = arg; 1189*bce88370SMarek Vasut 1190*bce88370SMarek Vasut cctx->size = sizeof(*ccmd); 1191*bce88370SMarek Vasut 1192*bce88370SMarek Vasut /* 1193*bce88370SMarek Vasut * Append the command to the last section. 1194*bce88370SMarek Vasut */ 1195*bce88370SMarek Vasut if (!sctx->cmd_head) { 1196*bce88370SMarek Vasut sctx->cmd_head = cctx; 1197*bce88370SMarek Vasut sctx->cmd_tail = cctx; 1198*bce88370SMarek Vasut } else { 1199*bce88370SMarek Vasut sctx->cmd_tail->cmd = cctx; 1200*bce88370SMarek Vasut sctx->cmd_tail = cctx; 1201*bce88370SMarek Vasut } 1202*bce88370SMarek Vasut 1203*bce88370SMarek Vasut return 0; 1204*bce88370SMarek Vasut 1205*bce88370SMarek Vasut err: 1206*bce88370SMarek Vasut free(cctx); 1207*bce88370SMarek Vasut return ret; 1208*bce88370SMarek Vasut } 1209*bce88370SMarek Vasut 1210*bce88370SMarek Vasut static int sb_build_command_jump(struct sb_image_ctx *ictx, 1211*bce88370SMarek Vasut struct sb_cmd_list *cmd) 1212*bce88370SMarek Vasut { 1213*bce88370SMarek Vasut return sb_build_command_jump_call(ictx, cmd, 0); 1214*bce88370SMarek Vasut } 1215*bce88370SMarek Vasut 1216*bce88370SMarek Vasut static int sb_build_command_call(struct sb_image_ctx *ictx, 1217*bce88370SMarek Vasut struct sb_cmd_list *cmd) 1218*bce88370SMarek Vasut { 1219*bce88370SMarek Vasut return sb_build_command_jump_call(ictx, cmd, 1); 1220*bce88370SMarek Vasut } 1221*bce88370SMarek Vasut 1222*bce88370SMarek Vasut static int sb_build_command_mode(struct sb_image_ctx *ictx, 1223*bce88370SMarek Vasut struct sb_cmd_list *cmd) 1224*bce88370SMarek Vasut { 1225*bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_tail; 1226*bce88370SMarek Vasut struct sb_cmd_ctx *cctx; 1227*bce88370SMarek Vasut struct sb_command *ccmd; 1228*bce88370SMarek Vasut char *tok; 1229*bce88370SMarek Vasut int ret; 1230*bce88370SMarek Vasut unsigned int i; 1231*bce88370SMarek Vasut uint32_t mode = 0xffffffff; 1232*bce88370SMarek Vasut 1233*bce88370SMarek Vasut cctx = calloc(1, sizeof(*cctx)); 1234*bce88370SMarek Vasut if (!cctx) 1235*bce88370SMarek Vasut return -ENOMEM; 1236*bce88370SMarek Vasut 1237*bce88370SMarek Vasut ccmd = &cctx->payload; 1238*bce88370SMarek Vasut 1239*bce88370SMarek Vasut /* 1240*bce88370SMarek Vasut * Prepare the command. 1241*bce88370SMarek Vasut */ 1242*bce88370SMarek Vasut tok = strtok(cmd->cmd, " "); 1243*bce88370SMarek Vasut if (!tok) { 1244*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Missing MODE boot mode argument!\n", 1245*bce88370SMarek Vasut cmd->lineno); 1246*bce88370SMarek Vasut ret = -EINVAL; 1247*bce88370SMarek Vasut goto err; 1248*bce88370SMarek Vasut } 1249*bce88370SMarek Vasut 1250*bce88370SMarek Vasut for (i = 0; i < ARRAY_SIZE(modetable); i++) { 1251*bce88370SMarek Vasut if (!strcmp(tok, modetable[i].name)) { 1252*bce88370SMarek Vasut mode = modetable[i].mode; 1253*bce88370SMarek Vasut break; 1254*bce88370SMarek Vasut } 1255*bce88370SMarek Vasut 1256*bce88370SMarek Vasut if (!modetable[i].altname) 1257*bce88370SMarek Vasut continue; 1258*bce88370SMarek Vasut 1259*bce88370SMarek Vasut if (!strcmp(tok, modetable[i].altname)) { 1260*bce88370SMarek Vasut mode = modetable[i].mode; 1261*bce88370SMarek Vasut break; 1262*bce88370SMarek Vasut } 1263*bce88370SMarek Vasut } 1264*bce88370SMarek Vasut 1265*bce88370SMarek Vasut if (mode == 0xffffffff) { 1266*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Invalid MODE boot mode argument!\n", 1267*bce88370SMarek Vasut cmd->lineno); 1268*bce88370SMarek Vasut ret = -EINVAL; 1269*bce88370SMarek Vasut goto err; 1270*bce88370SMarek Vasut } 1271*bce88370SMarek Vasut 1272*bce88370SMarek Vasut /* 1273*bce88370SMarek Vasut * Construct the command. 1274*bce88370SMarek Vasut */ 1275*bce88370SMarek Vasut ccmd->header.checksum = 0x5a; 1276*bce88370SMarek Vasut ccmd->header.tag = ROM_MODE_CMD; 1277*bce88370SMarek Vasut 1278*bce88370SMarek Vasut ccmd->mode.mode = mode; 1279*bce88370SMarek Vasut 1280*bce88370SMarek Vasut cctx->size = sizeof(*ccmd); 1281*bce88370SMarek Vasut 1282*bce88370SMarek Vasut /* 1283*bce88370SMarek Vasut * Append the command to the last section. 1284*bce88370SMarek Vasut */ 1285*bce88370SMarek Vasut if (!sctx->cmd_head) { 1286*bce88370SMarek Vasut sctx->cmd_head = cctx; 1287*bce88370SMarek Vasut sctx->cmd_tail = cctx; 1288*bce88370SMarek Vasut } else { 1289*bce88370SMarek Vasut sctx->cmd_tail->cmd = cctx; 1290*bce88370SMarek Vasut sctx->cmd_tail = cctx; 1291*bce88370SMarek Vasut } 1292*bce88370SMarek Vasut 1293*bce88370SMarek Vasut return 0; 1294*bce88370SMarek Vasut 1295*bce88370SMarek Vasut err: 1296*bce88370SMarek Vasut free(cctx); 1297*bce88370SMarek Vasut return ret; 1298*bce88370SMarek Vasut } 1299*bce88370SMarek Vasut 1300*bce88370SMarek Vasut static int sb_prefill_image_header(struct sb_image_ctx *ictx) 1301*bce88370SMarek Vasut { 1302*bce88370SMarek Vasut struct sb_boot_image_header *hdr = &ictx->payload; 1303*bce88370SMarek Vasut 1304*bce88370SMarek Vasut /* Fill signatures */ 1305*bce88370SMarek Vasut memcpy(hdr->signature1, "STMP", 4); 1306*bce88370SMarek Vasut memcpy(hdr->signature2, "sgtl", 4); 1307*bce88370SMarek Vasut 1308*bce88370SMarek Vasut /* SB Image version 1.1 */ 1309*bce88370SMarek Vasut hdr->major_version = SB_VERSION_MAJOR; 1310*bce88370SMarek Vasut hdr->minor_version = SB_VERSION_MINOR; 1311*bce88370SMarek Vasut 1312*bce88370SMarek Vasut /* Boot image major version */ 1313*bce88370SMarek Vasut hdr->product_version.major = htons(0x999); 1314*bce88370SMarek Vasut hdr->product_version.minor = htons(0x999); 1315*bce88370SMarek Vasut hdr->product_version.revision = htons(0x999); 1316*bce88370SMarek Vasut /* Boot image major version */ 1317*bce88370SMarek Vasut hdr->component_version.major = htons(0x999); 1318*bce88370SMarek Vasut hdr->component_version.minor = htons(0x999); 1319*bce88370SMarek Vasut hdr->component_version.revision = htons(0x999); 1320*bce88370SMarek Vasut 1321*bce88370SMarek Vasut /* Drive tag must be 0x0 for i.MX23 */ 1322*bce88370SMarek Vasut hdr->drive_tag = 0; 1323*bce88370SMarek Vasut 1324*bce88370SMarek Vasut hdr->header_blocks = 1325*bce88370SMarek Vasut sizeof(struct sb_boot_image_header) / SB_BLOCK_SIZE; 1326*bce88370SMarek Vasut hdr->section_header_size = 1327*bce88370SMarek Vasut sizeof(struct sb_sections_header) / SB_BLOCK_SIZE; 1328*bce88370SMarek Vasut hdr->timestamp_us = sb_get_timestamp() * 1000000; 1329*bce88370SMarek Vasut 1330*bce88370SMarek Vasut /* FIXME -- add proper config option */ 1331*bce88370SMarek Vasut hdr->flags = ictx->verbose_boot ? SB_IMAGE_FLAG_VERBOSE : 0, 1332*bce88370SMarek Vasut 1333*bce88370SMarek Vasut /* FIXME -- We support only default key */ 1334*bce88370SMarek Vasut hdr->key_count = 1; 1335*bce88370SMarek Vasut 1336*bce88370SMarek Vasut return 0; 1337*bce88370SMarek Vasut } 1338*bce88370SMarek Vasut 1339*bce88370SMarek Vasut static int sb_postfill_image_header(struct sb_image_ctx *ictx) 1340*bce88370SMarek Vasut { 1341*bce88370SMarek Vasut struct sb_boot_image_header *hdr = &ictx->payload; 1342*bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_head; 1343*bce88370SMarek Vasut uint32_t kd_size, sections_blocks; 1344*bce88370SMarek Vasut EVP_MD_CTX md_ctx; 1345*bce88370SMarek Vasut 1346*bce88370SMarek Vasut /* The main SB header size in blocks. */ 1347*bce88370SMarek Vasut hdr->image_blocks = hdr->header_blocks; 1348*bce88370SMarek Vasut 1349*bce88370SMarek Vasut /* Size of the key dictionary, which has single zero entry. */ 1350*bce88370SMarek Vasut kd_size = hdr->key_count * sizeof(struct sb_key_dictionary_key); 1351*bce88370SMarek Vasut hdr->image_blocks += kd_size / SB_BLOCK_SIZE; 1352*bce88370SMarek Vasut 1353*bce88370SMarek Vasut /* Now count the payloads. */ 1354*bce88370SMarek Vasut hdr->section_count = ictx->sect_count; 1355*bce88370SMarek Vasut while (sctx) { 1356*bce88370SMarek Vasut hdr->image_blocks += sctx->size / SB_BLOCK_SIZE; 1357*bce88370SMarek Vasut sctx = sctx->sect; 1358*bce88370SMarek Vasut } 1359*bce88370SMarek Vasut 1360*bce88370SMarek Vasut if (!ictx->sect_boot_found) { 1361*bce88370SMarek Vasut fprintf(stderr, "ERR: No bootable section selected!\n"); 1362*bce88370SMarek Vasut return -EINVAL; 1363*bce88370SMarek Vasut } 1364*bce88370SMarek Vasut hdr->first_boot_section_id = ictx->sect_boot; 1365*bce88370SMarek Vasut 1366*bce88370SMarek Vasut /* The n * SB section size in blocks. */ 1367*bce88370SMarek Vasut sections_blocks = hdr->section_count * hdr->section_header_size; 1368*bce88370SMarek Vasut hdr->image_blocks += sections_blocks; 1369*bce88370SMarek Vasut 1370*bce88370SMarek Vasut /* Key dictionary offset. */ 1371*bce88370SMarek Vasut hdr->key_dictionary_block = hdr->header_blocks + sections_blocks; 1372*bce88370SMarek Vasut 1373*bce88370SMarek Vasut /* Digest of the whole image. */ 1374*bce88370SMarek Vasut hdr->image_blocks += 2; 1375*bce88370SMarek Vasut 1376*bce88370SMarek Vasut /* Pointer past the dictionary. */ 1377*bce88370SMarek Vasut hdr->first_boot_tag_block = 1378*bce88370SMarek Vasut hdr->key_dictionary_block + kd_size / SB_BLOCK_SIZE; 1379*bce88370SMarek Vasut 1380*bce88370SMarek Vasut /* Compute header digest. */ 1381*bce88370SMarek Vasut EVP_MD_CTX_init(&md_ctx); 1382*bce88370SMarek Vasut 1383*bce88370SMarek Vasut EVP_DigestInit(&md_ctx, EVP_sha1()); 1384*bce88370SMarek Vasut EVP_DigestUpdate(&md_ctx, hdr->signature1, 1385*bce88370SMarek Vasut sizeof(struct sb_boot_image_header) - 1386*bce88370SMarek Vasut sizeof(hdr->digest)); 1387*bce88370SMarek Vasut EVP_DigestFinal(&md_ctx, hdr->digest, NULL); 1388*bce88370SMarek Vasut 1389*bce88370SMarek Vasut return 0; 1390*bce88370SMarek Vasut } 1391*bce88370SMarek Vasut 1392*bce88370SMarek Vasut static int sb_fixup_sections_and_tags(struct sb_image_ctx *ictx) 1393*bce88370SMarek Vasut { 1394*bce88370SMarek Vasut /* Fixup the placement of sections. */ 1395*bce88370SMarek Vasut struct sb_boot_image_header *ihdr = &ictx->payload; 1396*bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_head; 1397*bce88370SMarek Vasut struct sb_sections_header *shdr; 1398*bce88370SMarek Vasut struct sb_cmd_ctx *cctx; 1399*bce88370SMarek Vasut struct sb_command *ccmd; 1400*bce88370SMarek Vasut uint32_t offset = ihdr->first_boot_tag_block; 1401*bce88370SMarek Vasut 1402*bce88370SMarek Vasut while (sctx) { 1403*bce88370SMarek Vasut shdr = &sctx->payload; 1404*bce88370SMarek Vasut 1405*bce88370SMarek Vasut /* Fill in the section TAG offset. */ 1406*bce88370SMarek Vasut shdr->section_offset = offset + 1; 1407*bce88370SMarek Vasut offset += shdr->section_size; 1408*bce88370SMarek Vasut 1409*bce88370SMarek Vasut /* Section length is measured from the TAG block. */ 1410*bce88370SMarek Vasut shdr->section_size--; 1411*bce88370SMarek Vasut 1412*bce88370SMarek Vasut /* Fixup the TAG command. */ 1413*bce88370SMarek Vasut cctx = sctx->cmd_head; 1414*bce88370SMarek Vasut while (cctx) { 1415*bce88370SMarek Vasut ccmd = &cctx->payload; 1416*bce88370SMarek Vasut if (ccmd->header.tag == ROM_TAG_CMD) { 1417*bce88370SMarek Vasut ccmd->tag.section_number = shdr->section_number; 1418*bce88370SMarek Vasut ccmd->tag.section_length = shdr->section_size; 1419*bce88370SMarek Vasut ccmd->tag.section_flags = shdr->section_flags; 1420*bce88370SMarek Vasut } 1421*bce88370SMarek Vasut 1422*bce88370SMarek Vasut /* Update the command checksum. */ 1423*bce88370SMarek Vasut ccmd->header.checksum = sb_command_checksum(ccmd); 1424*bce88370SMarek Vasut 1425*bce88370SMarek Vasut cctx = cctx->cmd; 1426*bce88370SMarek Vasut } 1427*bce88370SMarek Vasut 1428*bce88370SMarek Vasut sctx = sctx->sect; 1429*bce88370SMarek Vasut } 1430*bce88370SMarek Vasut 1431*bce88370SMarek Vasut return 0; 1432*bce88370SMarek Vasut } 1433*bce88370SMarek Vasut 1434*bce88370SMarek Vasut static int sb_parse_line(struct sb_image_ctx *ictx, struct sb_cmd_list *cmd) 1435*bce88370SMarek Vasut { 1436*bce88370SMarek Vasut char *tok; 1437*bce88370SMarek Vasut char *line = cmd->cmd; 1438*bce88370SMarek Vasut char *rptr; 1439*bce88370SMarek Vasut int ret; 1440*bce88370SMarek Vasut 1441*bce88370SMarek Vasut /* Analyze the identifier on this line first. */ 1442*bce88370SMarek Vasut tok = strtok_r(line, " ", &rptr); 1443*bce88370SMarek Vasut if (!tok || (strlen(tok) == 0)) { 1444*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Invalid line!\n", cmd->lineno); 1445*bce88370SMarek Vasut return -EINVAL; 1446*bce88370SMarek Vasut } 1447*bce88370SMarek Vasut 1448*bce88370SMarek Vasut cmd->cmd = rptr; 1449*bce88370SMarek Vasut 1450*bce88370SMarek Vasut /* DCD */ 1451*bce88370SMarek Vasut if (!strcmp(tok, "DCD")) { 1452*bce88370SMarek Vasut ictx->in_section = 0; 1453*bce88370SMarek Vasut ictx->in_dcd = 1; 1454*bce88370SMarek Vasut sb_build_dcd(ictx, cmd); 1455*bce88370SMarek Vasut return 0; 1456*bce88370SMarek Vasut } 1457*bce88370SMarek Vasut 1458*bce88370SMarek Vasut /* Section */ 1459*bce88370SMarek Vasut if (!strcmp(tok, "SECTION")) { 1460*bce88370SMarek Vasut ictx->in_section = 1; 1461*bce88370SMarek Vasut ictx->in_dcd = 0; 1462*bce88370SMarek Vasut sb_build_section(ictx, cmd); 1463*bce88370SMarek Vasut return 0; 1464*bce88370SMarek Vasut } 1465*bce88370SMarek Vasut 1466*bce88370SMarek Vasut if (!ictx->in_section && !ictx->in_dcd) { 1467*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Data outside of a section!\n", 1468*bce88370SMarek Vasut cmd->lineno); 1469*bce88370SMarek Vasut return -EINVAL; 1470*bce88370SMarek Vasut } 1471*bce88370SMarek Vasut 1472*bce88370SMarek Vasut if (ictx->in_section) { 1473*bce88370SMarek Vasut /* Section commands */ 1474*bce88370SMarek Vasut if (!strcmp(tok, "NOP")) { 1475*bce88370SMarek Vasut ret = sb_build_command_nop(ictx); 1476*bce88370SMarek Vasut } else if (!strcmp(tok, "TAG")) { 1477*bce88370SMarek Vasut ret = sb_build_command_tag(ictx, cmd); 1478*bce88370SMarek Vasut } else if (!strcmp(tok, "LOAD")) { 1479*bce88370SMarek Vasut ret = sb_build_command_load(ictx, cmd); 1480*bce88370SMarek Vasut } else if (!strcmp(tok, "FILL")) { 1481*bce88370SMarek Vasut ret = sb_build_command_fill(ictx, cmd); 1482*bce88370SMarek Vasut } else if (!strcmp(tok, "JUMP")) { 1483*bce88370SMarek Vasut ret = sb_build_command_jump(ictx, cmd); 1484*bce88370SMarek Vasut } else if (!strcmp(tok, "CALL")) { 1485*bce88370SMarek Vasut ret = sb_build_command_call(ictx, cmd); 1486*bce88370SMarek Vasut } else if (!strcmp(tok, "MODE")) { 1487*bce88370SMarek Vasut ret = sb_build_command_mode(ictx, cmd); 1488*bce88370SMarek Vasut } else { 1489*bce88370SMarek Vasut fprintf(stderr, 1490*bce88370SMarek Vasut "#%i ERR: Unsupported instruction '%s'!\n", 1491*bce88370SMarek Vasut cmd->lineno, tok); 1492*bce88370SMarek Vasut return -ENOTSUP; 1493*bce88370SMarek Vasut } 1494*bce88370SMarek Vasut } else if (ictx->in_dcd) { 1495*bce88370SMarek Vasut char *lptr; 1496*bce88370SMarek Vasut uint32_t ilen = '1'; 1497*bce88370SMarek Vasut 1498*bce88370SMarek Vasut tok = strtok_r(tok, ".", &lptr); 1499*bce88370SMarek Vasut if (!tok || (strlen(tok) == 0) || (lptr && strlen(lptr) != 1)) { 1500*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Invalid line!\n", 1501*bce88370SMarek Vasut cmd->lineno); 1502*bce88370SMarek Vasut return -EINVAL; 1503*bce88370SMarek Vasut } 1504*bce88370SMarek Vasut 1505*bce88370SMarek Vasut if (lptr && 1506*bce88370SMarek Vasut (lptr[0] != '1' && lptr[0] != '2' && lptr[0] != '4')) { 1507*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Invalid instruction width!\n", 1508*bce88370SMarek Vasut cmd->lineno); 1509*bce88370SMarek Vasut return -EINVAL; 1510*bce88370SMarek Vasut } 1511*bce88370SMarek Vasut 1512*bce88370SMarek Vasut if (lptr) 1513*bce88370SMarek Vasut ilen = lptr[0] - '1'; 1514*bce88370SMarek Vasut 1515*bce88370SMarek Vasut /* DCD commands */ 1516*bce88370SMarek Vasut if (!strcmp(tok, "WRITE")) { 1517*bce88370SMarek Vasut ret = sb_build_dcd_block(ictx, cmd, 1518*bce88370SMarek Vasut SB_DCD_WRITE | ilen); 1519*bce88370SMarek Vasut } else if (!strcmp(tok, "ANDC")) { 1520*bce88370SMarek Vasut ret = sb_build_dcd_block(ictx, cmd, 1521*bce88370SMarek Vasut SB_DCD_ANDC | ilen); 1522*bce88370SMarek Vasut } else if (!strcmp(tok, "ORR")) { 1523*bce88370SMarek Vasut ret = sb_build_dcd_block(ictx, cmd, 1524*bce88370SMarek Vasut SB_DCD_ORR | ilen); 1525*bce88370SMarek Vasut } else if (!strcmp(tok, "EQZ")) { 1526*bce88370SMarek Vasut ret = sb_build_dcd_block(ictx, cmd, 1527*bce88370SMarek Vasut SB_DCD_CHK_EQZ | ilen); 1528*bce88370SMarek Vasut } else if (!strcmp(tok, "EQ")) { 1529*bce88370SMarek Vasut ret = sb_build_dcd_block(ictx, cmd, 1530*bce88370SMarek Vasut SB_DCD_CHK_EQ | ilen); 1531*bce88370SMarek Vasut } else if (!strcmp(tok, "NEQ")) { 1532*bce88370SMarek Vasut ret = sb_build_dcd_block(ictx, cmd, 1533*bce88370SMarek Vasut SB_DCD_CHK_NEQ | ilen); 1534*bce88370SMarek Vasut } else if (!strcmp(tok, "NEZ")) { 1535*bce88370SMarek Vasut ret = sb_build_dcd_block(ictx, cmd, 1536*bce88370SMarek Vasut SB_DCD_CHK_NEZ | ilen); 1537*bce88370SMarek Vasut } else if (!strcmp(tok, "NOOP")) { 1538*bce88370SMarek Vasut ret = sb_build_dcd_block(ictx, cmd, SB_DCD_NOOP); 1539*bce88370SMarek Vasut } else { 1540*bce88370SMarek Vasut fprintf(stderr, 1541*bce88370SMarek Vasut "#%i ERR: Unsupported instruction '%s'!\n", 1542*bce88370SMarek Vasut cmd->lineno, tok); 1543*bce88370SMarek Vasut return -ENOTSUP; 1544*bce88370SMarek Vasut } 1545*bce88370SMarek Vasut } else { 1546*bce88370SMarek Vasut fprintf(stderr, "#%i ERR: Unsupported instruction '%s'!\n", 1547*bce88370SMarek Vasut cmd->lineno, tok); 1548*bce88370SMarek Vasut return -ENOTSUP; 1549*bce88370SMarek Vasut } 1550*bce88370SMarek Vasut 1551*bce88370SMarek Vasut /* 1552*bce88370SMarek Vasut * Here we have at least one section with one command, otherwise we 1553*bce88370SMarek Vasut * would have failed already higher above. 1554*bce88370SMarek Vasut * 1555*bce88370SMarek Vasut * FIXME -- should the updating happen here ? 1556*bce88370SMarek Vasut */ 1557*bce88370SMarek Vasut if (ictx->in_section && !ret) { 1558*bce88370SMarek Vasut ictx->sect_tail->size += ictx->sect_tail->cmd_tail->size; 1559*bce88370SMarek Vasut ictx->sect_tail->payload.section_size = 1560*bce88370SMarek Vasut ictx->sect_tail->size / SB_BLOCK_SIZE; 1561*bce88370SMarek Vasut } 1562*bce88370SMarek Vasut 1563*bce88370SMarek Vasut return ret; 1564*bce88370SMarek Vasut } 1565*bce88370SMarek Vasut 1566*bce88370SMarek Vasut static int sb_load_cmdfile(struct sb_image_ctx *ictx) 1567*bce88370SMarek Vasut { 1568*bce88370SMarek Vasut struct sb_cmd_list cmd; 1569*bce88370SMarek Vasut int lineno = 1; 1570*bce88370SMarek Vasut FILE *fp; 1571*bce88370SMarek Vasut char *line = NULL; 1572*bce88370SMarek Vasut ssize_t rlen; 1573*bce88370SMarek Vasut size_t len; 1574*bce88370SMarek Vasut 1575*bce88370SMarek Vasut fp = fopen(ictx->cfg_filename, "r"); 1576*bce88370SMarek Vasut if (!fp) 1577*bce88370SMarek Vasut goto err_file; 1578*bce88370SMarek Vasut 1579*bce88370SMarek Vasut while ((rlen = getline(&line, &len, fp)) > 0) { 1580*bce88370SMarek Vasut memset(&cmd, 0, sizeof(cmd)); 1581*bce88370SMarek Vasut 1582*bce88370SMarek Vasut /* Strip the trailing newline. */ 1583*bce88370SMarek Vasut line[rlen - 1] = '\0'; 1584*bce88370SMarek Vasut 1585*bce88370SMarek Vasut cmd.cmd = line; 1586*bce88370SMarek Vasut cmd.len = rlen; 1587*bce88370SMarek Vasut cmd.lineno = lineno++; 1588*bce88370SMarek Vasut 1589*bce88370SMarek Vasut sb_parse_line(ictx, &cmd); 1590*bce88370SMarek Vasut } 1591*bce88370SMarek Vasut 1592*bce88370SMarek Vasut free(line); 1593*bce88370SMarek Vasut 1594*bce88370SMarek Vasut fclose(fp); 1595*bce88370SMarek Vasut 1596*bce88370SMarek Vasut return 0; 1597*bce88370SMarek Vasut 1598*bce88370SMarek Vasut err_file: 1599*bce88370SMarek Vasut fclose(fp); 1600*bce88370SMarek Vasut fprintf(stderr, "ERR: Failed to load file \"%s\"\n", 1601*bce88370SMarek Vasut ictx->cfg_filename); 1602*bce88370SMarek Vasut return -EINVAL; 1603*bce88370SMarek Vasut } 1604*bce88370SMarek Vasut 1605*bce88370SMarek Vasut static int sb_build_tree_from_cfg(struct sb_image_ctx *ictx) 1606*bce88370SMarek Vasut { 1607*bce88370SMarek Vasut int ret; 1608*bce88370SMarek Vasut 1609*bce88370SMarek Vasut ret = sb_load_cmdfile(ictx); 1610*bce88370SMarek Vasut if (ret) 1611*bce88370SMarek Vasut return ret; 1612*bce88370SMarek Vasut 1613*bce88370SMarek Vasut ret = sb_prefill_image_header(ictx); 1614*bce88370SMarek Vasut if (ret) 1615*bce88370SMarek Vasut return ret; 1616*bce88370SMarek Vasut 1617*bce88370SMarek Vasut ret = sb_postfill_image_header(ictx); 1618*bce88370SMarek Vasut if (ret) 1619*bce88370SMarek Vasut return ret; 1620*bce88370SMarek Vasut 1621*bce88370SMarek Vasut ret = sb_fixup_sections_and_tags(ictx); 1622*bce88370SMarek Vasut if (ret) 1623*bce88370SMarek Vasut return ret; 1624*bce88370SMarek Vasut 1625*bce88370SMarek Vasut return 0; 1626*bce88370SMarek Vasut } 1627*bce88370SMarek Vasut 1628*bce88370SMarek Vasut static int sb_verify_image_header(struct sb_image_ctx *ictx, 1629*bce88370SMarek Vasut FILE *fp, long fsize) 1630*bce88370SMarek Vasut { 1631*bce88370SMarek Vasut /* Verify static fields in the image header. */ 1632*bce88370SMarek Vasut struct sb_boot_image_header *hdr = &ictx->payload; 1633*bce88370SMarek Vasut const char *stat[2] = { "[PASS]", "[FAIL]" }; 1634*bce88370SMarek Vasut struct tm tm; 1635*bce88370SMarek Vasut int sz, ret = 0; 1636*bce88370SMarek Vasut unsigned char digest[20]; 1637*bce88370SMarek Vasut EVP_MD_CTX md_ctx; 1638*bce88370SMarek Vasut unsigned long size; 1639*bce88370SMarek Vasut 1640*bce88370SMarek Vasut /* Start image-wide crypto. */ 1641*bce88370SMarek Vasut EVP_MD_CTX_init(&ictx->md_ctx); 1642*bce88370SMarek Vasut EVP_DigestInit(&ictx->md_ctx, EVP_sha1()); 1643*bce88370SMarek Vasut 1644*bce88370SMarek Vasut soprintf(ictx, "---------- Verifying SB Image Header ----------\n"); 1645*bce88370SMarek Vasut 1646*bce88370SMarek Vasut size = fread(&ictx->payload, 1, sizeof(ictx->payload), fp); 1647*bce88370SMarek Vasut if (size != sizeof(ictx->payload)) { 1648*bce88370SMarek Vasut fprintf(stderr, "ERR: SB image header too short!\n"); 1649*bce88370SMarek Vasut return -EINVAL; 1650*bce88370SMarek Vasut } 1651*bce88370SMarek Vasut 1652*bce88370SMarek Vasut /* Compute header digest. */ 1653*bce88370SMarek Vasut EVP_MD_CTX_init(&md_ctx); 1654*bce88370SMarek Vasut EVP_DigestInit(&md_ctx, EVP_sha1()); 1655*bce88370SMarek Vasut EVP_DigestUpdate(&md_ctx, hdr->signature1, 1656*bce88370SMarek Vasut sizeof(struct sb_boot_image_header) - 1657*bce88370SMarek Vasut sizeof(hdr->digest)); 1658*bce88370SMarek Vasut EVP_DigestFinal(&md_ctx, digest, NULL); 1659*bce88370SMarek Vasut 1660*bce88370SMarek Vasut sb_aes_init(ictx, NULL, 1); 1661*bce88370SMarek Vasut sb_encrypt_sb_header(ictx); 1662*bce88370SMarek Vasut 1663*bce88370SMarek Vasut if (memcmp(digest, hdr->digest, 20)) 1664*bce88370SMarek Vasut ret = -EINVAL; 1665*bce88370SMarek Vasut soprintf(ictx, "%s Image header checksum: %s\n", stat[!!ret], 1666*bce88370SMarek Vasut ret ? "BAD" : "OK"); 1667*bce88370SMarek Vasut if (ret) 1668*bce88370SMarek Vasut return ret; 1669*bce88370SMarek Vasut 1670*bce88370SMarek Vasut if (memcmp(hdr->signature1, "STMP", 4) || 1671*bce88370SMarek Vasut memcmp(hdr->signature2, "sgtl", 4)) 1672*bce88370SMarek Vasut ret = -EINVAL; 1673*bce88370SMarek Vasut soprintf(ictx, "%s Signatures: '%.4s' '%.4s'\n", 1674*bce88370SMarek Vasut stat[!!ret], hdr->signature1, hdr->signature2); 1675*bce88370SMarek Vasut if (ret) 1676*bce88370SMarek Vasut return ret; 1677*bce88370SMarek Vasut 1678*bce88370SMarek Vasut if ((hdr->major_version != SB_VERSION_MAJOR) || 1679*bce88370SMarek Vasut ((hdr->minor_version != 1) && (hdr->minor_version != 2))) 1680*bce88370SMarek Vasut ret = -EINVAL; 1681*bce88370SMarek Vasut soprintf(ictx, "%s Image version: v%i.%i\n", stat[!!ret], 1682*bce88370SMarek Vasut hdr->major_version, hdr->minor_version); 1683*bce88370SMarek Vasut if (ret) 1684*bce88370SMarek Vasut return ret; 1685*bce88370SMarek Vasut 1686*bce88370SMarek Vasut ret = sb_get_time(hdr->timestamp_us / 1000000, &tm); 1687*bce88370SMarek Vasut soprintf(ictx, 1688*bce88370SMarek Vasut "%s Creation time: %02i:%02i:%02i %02i/%02i/%04i\n", 1689*bce88370SMarek Vasut stat[!!ret], tm.tm_hour, tm.tm_min, tm.tm_sec, 1690*bce88370SMarek Vasut tm.tm_mday, tm.tm_mon, tm.tm_year + 2000); 1691*bce88370SMarek Vasut if (ret) 1692*bce88370SMarek Vasut return ret; 1693*bce88370SMarek Vasut 1694*bce88370SMarek Vasut soprintf(ictx, "%s Product version: %x.%x.%x\n", stat[0], 1695*bce88370SMarek Vasut ntohs(hdr->product_version.major), 1696*bce88370SMarek Vasut ntohs(hdr->product_version.minor), 1697*bce88370SMarek Vasut ntohs(hdr->product_version.revision)); 1698*bce88370SMarek Vasut soprintf(ictx, "%s Component version: %x.%x.%x\n", stat[0], 1699*bce88370SMarek Vasut ntohs(hdr->component_version.major), 1700*bce88370SMarek Vasut ntohs(hdr->component_version.minor), 1701*bce88370SMarek Vasut ntohs(hdr->component_version.revision)); 1702*bce88370SMarek Vasut 1703*bce88370SMarek Vasut if (hdr->flags & ~SB_IMAGE_FLAG_VERBOSE) 1704*bce88370SMarek Vasut ret = -EINVAL; 1705*bce88370SMarek Vasut soprintf(ictx, "%s Image flags: %s\n", stat[!!ret], 1706*bce88370SMarek Vasut hdr->flags & SB_IMAGE_FLAG_VERBOSE ? "Verbose_boot" : ""); 1707*bce88370SMarek Vasut if (ret) 1708*bce88370SMarek Vasut return ret; 1709*bce88370SMarek Vasut 1710*bce88370SMarek Vasut if (hdr->drive_tag != 0) 1711*bce88370SMarek Vasut ret = -EINVAL; 1712*bce88370SMarek Vasut soprintf(ictx, "%s Drive tag: %i\n", stat[!!ret], 1713*bce88370SMarek Vasut hdr->drive_tag); 1714*bce88370SMarek Vasut if (ret) 1715*bce88370SMarek Vasut return ret; 1716*bce88370SMarek Vasut 1717*bce88370SMarek Vasut sz = sizeof(struct sb_boot_image_header) / SB_BLOCK_SIZE; 1718*bce88370SMarek Vasut if (hdr->header_blocks != sz) 1719*bce88370SMarek Vasut ret = -EINVAL; 1720*bce88370SMarek Vasut soprintf(ictx, "%s Image header size (blocks): %i\n", stat[!!ret], 1721*bce88370SMarek Vasut hdr->header_blocks); 1722*bce88370SMarek Vasut if (ret) 1723*bce88370SMarek Vasut return ret; 1724*bce88370SMarek Vasut 1725*bce88370SMarek Vasut sz = sizeof(struct sb_sections_header) / SB_BLOCK_SIZE; 1726*bce88370SMarek Vasut if (hdr->section_header_size != sz) 1727*bce88370SMarek Vasut ret = -EINVAL; 1728*bce88370SMarek Vasut soprintf(ictx, "%s Section header size (blocks): %i\n", stat[!!ret], 1729*bce88370SMarek Vasut hdr->section_header_size); 1730*bce88370SMarek Vasut if (ret) 1731*bce88370SMarek Vasut return ret; 1732*bce88370SMarek Vasut 1733*bce88370SMarek Vasut soprintf(ictx, "%s Sections count: %i\n", stat[!!ret], 1734*bce88370SMarek Vasut hdr->section_count); 1735*bce88370SMarek Vasut soprintf(ictx, "%s First bootable section %i\n", stat[!!ret], 1736*bce88370SMarek Vasut hdr->first_boot_section_id); 1737*bce88370SMarek Vasut 1738*bce88370SMarek Vasut if (hdr->image_blocks != fsize / SB_BLOCK_SIZE) 1739*bce88370SMarek Vasut ret = -EINVAL; 1740*bce88370SMarek Vasut soprintf(ictx, "%s Image size (blocks): %i\n", stat[!!ret], 1741*bce88370SMarek Vasut hdr->image_blocks); 1742*bce88370SMarek Vasut if (ret) 1743*bce88370SMarek Vasut return ret; 1744*bce88370SMarek Vasut 1745*bce88370SMarek Vasut sz = hdr->header_blocks + hdr->section_header_size * hdr->section_count; 1746*bce88370SMarek Vasut if (hdr->key_dictionary_block != sz) 1747*bce88370SMarek Vasut ret = -EINVAL; 1748*bce88370SMarek Vasut soprintf(ictx, "%s Key dict offset (blocks): %i\n", stat[!!ret], 1749*bce88370SMarek Vasut hdr->key_dictionary_block); 1750*bce88370SMarek Vasut if (ret) 1751*bce88370SMarek Vasut return ret; 1752*bce88370SMarek Vasut 1753*bce88370SMarek Vasut if (hdr->key_count != 1) 1754*bce88370SMarek Vasut ret = -EINVAL; 1755*bce88370SMarek Vasut soprintf(ictx, "%s Number of encryption keys: %i\n", stat[!!ret], 1756*bce88370SMarek Vasut hdr->key_count); 1757*bce88370SMarek Vasut if (ret) 1758*bce88370SMarek Vasut return ret; 1759*bce88370SMarek Vasut 1760*bce88370SMarek Vasut sz = hdr->header_blocks + hdr->section_header_size * hdr->section_count; 1761*bce88370SMarek Vasut sz += hdr->key_count * 1762*bce88370SMarek Vasut sizeof(struct sb_key_dictionary_key) / SB_BLOCK_SIZE; 1763*bce88370SMarek Vasut if (hdr->first_boot_tag_block != (unsigned)sz) 1764*bce88370SMarek Vasut ret = -EINVAL; 1765*bce88370SMarek Vasut soprintf(ictx, "%s First TAG block (blocks): %i\n", stat[!!ret], 1766*bce88370SMarek Vasut hdr->first_boot_tag_block); 1767*bce88370SMarek Vasut if (ret) 1768*bce88370SMarek Vasut return ret; 1769*bce88370SMarek Vasut 1770*bce88370SMarek Vasut return 0; 1771*bce88370SMarek Vasut } 1772*bce88370SMarek Vasut 1773*bce88370SMarek Vasut static void sb_decrypt_tag(struct sb_image_ctx *ictx, 1774*bce88370SMarek Vasut struct sb_cmd_ctx *cctx) 1775*bce88370SMarek Vasut { 1776*bce88370SMarek Vasut EVP_MD_CTX *md_ctx = &ictx->md_ctx; 1777*bce88370SMarek Vasut struct sb_command *cmd = &cctx->payload; 1778*bce88370SMarek Vasut 1779*bce88370SMarek Vasut sb_aes_crypt(ictx, (uint8_t *)&cctx->c_payload, 1780*bce88370SMarek Vasut (uint8_t *)&cctx->payload, sizeof(*cmd)); 1781*bce88370SMarek Vasut EVP_DigestUpdate(md_ctx, &cctx->c_payload, sizeof(*cmd)); 1782*bce88370SMarek Vasut } 1783*bce88370SMarek Vasut 1784*bce88370SMarek Vasut static int sb_verify_command(struct sb_image_ctx *ictx, 1785*bce88370SMarek Vasut struct sb_cmd_ctx *cctx, FILE *fp, 1786*bce88370SMarek Vasut unsigned long *tsize) 1787*bce88370SMarek Vasut { 1788*bce88370SMarek Vasut struct sb_command *ccmd = &cctx->payload; 1789*bce88370SMarek Vasut unsigned long size, asize; 1790*bce88370SMarek Vasut char *csum, *flag = ""; 1791*bce88370SMarek Vasut int ret; 1792*bce88370SMarek Vasut unsigned int i; 1793*bce88370SMarek Vasut uint8_t csn, csc = ccmd->header.checksum; 1794*bce88370SMarek Vasut ccmd->header.checksum = 0x5a; 1795*bce88370SMarek Vasut csn = sb_command_checksum(ccmd); 1796*bce88370SMarek Vasut ccmd->header.checksum = csc; 1797*bce88370SMarek Vasut 1798*bce88370SMarek Vasut if (csc == csn) 1799*bce88370SMarek Vasut ret = 0; 1800*bce88370SMarek Vasut else 1801*bce88370SMarek Vasut ret = -EINVAL; 1802*bce88370SMarek Vasut csum = ret ? "checksum BAD" : "checksum OK"; 1803*bce88370SMarek Vasut 1804*bce88370SMarek Vasut switch (ccmd->header.tag) { 1805*bce88370SMarek Vasut case ROM_NOP_CMD: 1806*bce88370SMarek Vasut soprintf(ictx, " NOOP # %s\n", csum); 1807*bce88370SMarek Vasut return ret; 1808*bce88370SMarek Vasut case ROM_TAG_CMD: 1809*bce88370SMarek Vasut if (ccmd->header.flags & ROM_TAG_CMD_FLAG_ROM_LAST_TAG) 1810*bce88370SMarek Vasut flag = "LAST"; 1811*bce88370SMarek Vasut soprintf(ictx, " TAG %s # %s\n", flag, csum); 1812*bce88370SMarek Vasut sb_aes_reinit(ictx, 0); 1813*bce88370SMarek Vasut return ret; 1814*bce88370SMarek Vasut case ROM_LOAD_CMD: 1815*bce88370SMarek Vasut soprintf(ictx, " LOAD addr=0x%08x length=0x%08x # %s\n", 1816*bce88370SMarek Vasut ccmd->load.address, ccmd->load.count, csum); 1817*bce88370SMarek Vasut 1818*bce88370SMarek Vasut cctx->length = ccmd->load.count; 1819*bce88370SMarek Vasut asize = roundup(cctx->length, SB_BLOCK_SIZE); 1820*bce88370SMarek Vasut cctx->data = malloc(asize); 1821*bce88370SMarek Vasut if (!cctx->data) 1822*bce88370SMarek Vasut return -ENOMEM; 1823*bce88370SMarek Vasut 1824*bce88370SMarek Vasut size = fread(cctx->data, 1, asize, fp); 1825*bce88370SMarek Vasut if (size != asize) { 1826*bce88370SMarek Vasut fprintf(stderr, 1827*bce88370SMarek Vasut "ERR: SB LOAD command payload too short!\n"); 1828*bce88370SMarek Vasut return -EINVAL; 1829*bce88370SMarek Vasut } 1830*bce88370SMarek Vasut 1831*bce88370SMarek Vasut *tsize += size; 1832*bce88370SMarek Vasut 1833*bce88370SMarek Vasut EVP_DigestUpdate(&ictx->md_ctx, cctx->data, asize); 1834*bce88370SMarek Vasut sb_aes_crypt(ictx, cctx->data, cctx->data, asize); 1835*bce88370SMarek Vasut 1836*bce88370SMarek Vasut if (ccmd->load.crc32 != crc32(cctx->data, asize)) { 1837*bce88370SMarek Vasut fprintf(stderr, 1838*bce88370SMarek Vasut "ERR: SB LOAD command payload CRC32 invalid!\n"); 1839*bce88370SMarek Vasut return -EINVAL; 1840*bce88370SMarek Vasut } 1841*bce88370SMarek Vasut return 0; 1842*bce88370SMarek Vasut case ROM_FILL_CMD: 1843*bce88370SMarek Vasut soprintf(ictx, 1844*bce88370SMarek Vasut " FILL addr=0x%08x length=0x%08x pattern=0x%08x # %s\n", 1845*bce88370SMarek Vasut ccmd->fill.address, ccmd->fill.count, 1846*bce88370SMarek Vasut ccmd->fill.pattern, csum); 1847*bce88370SMarek Vasut return 0; 1848*bce88370SMarek Vasut case ROM_JUMP_CMD: 1849*bce88370SMarek Vasut if (ccmd->header.flags & ROM_JUMP_CMD_FLAG_HAB) 1850*bce88370SMarek Vasut flag = " HAB"; 1851*bce88370SMarek Vasut soprintf(ictx, 1852*bce88370SMarek Vasut " JUMP%s addr=0x%08x r0_arg=0x%08x # %s\n", 1853*bce88370SMarek Vasut flag, ccmd->fill.address, ccmd->jump.argument, csum); 1854*bce88370SMarek Vasut return 0; 1855*bce88370SMarek Vasut case ROM_CALL_CMD: 1856*bce88370SMarek Vasut if (ccmd->header.flags & ROM_CALL_CMD_FLAG_HAB) 1857*bce88370SMarek Vasut flag = " HAB"; 1858*bce88370SMarek Vasut soprintf(ictx, 1859*bce88370SMarek Vasut " CALL%s addr=0x%08x r0_arg=0x%08x # %s\n", 1860*bce88370SMarek Vasut flag, ccmd->fill.address, ccmd->jump.argument, csum); 1861*bce88370SMarek Vasut return 0; 1862*bce88370SMarek Vasut case ROM_MODE_CMD: 1863*bce88370SMarek Vasut for (i = 0; i < ARRAY_SIZE(modetable); i++) { 1864*bce88370SMarek Vasut if (ccmd->mode.mode == modetable[i].mode) { 1865*bce88370SMarek Vasut soprintf(ictx, " MODE %s # %s\n", 1866*bce88370SMarek Vasut modetable[i].name, csum); 1867*bce88370SMarek Vasut break; 1868*bce88370SMarek Vasut } 1869*bce88370SMarek Vasut } 1870*bce88370SMarek Vasut fprintf(stderr, " MODE !INVALID! # %s\n", csum); 1871*bce88370SMarek Vasut return 0; 1872*bce88370SMarek Vasut } 1873*bce88370SMarek Vasut 1874*bce88370SMarek Vasut return ret; 1875*bce88370SMarek Vasut } 1876*bce88370SMarek Vasut 1877*bce88370SMarek Vasut static int sb_verify_commands(struct sb_image_ctx *ictx, 1878*bce88370SMarek Vasut struct sb_section_ctx *sctx, FILE *fp) 1879*bce88370SMarek Vasut { 1880*bce88370SMarek Vasut unsigned long size, tsize = 0; 1881*bce88370SMarek Vasut struct sb_cmd_ctx *cctx; 1882*bce88370SMarek Vasut int ret; 1883*bce88370SMarek Vasut 1884*bce88370SMarek Vasut sb_aes_reinit(ictx, 0); 1885*bce88370SMarek Vasut 1886*bce88370SMarek Vasut while (tsize < sctx->size) { 1887*bce88370SMarek Vasut cctx = calloc(1, sizeof(*cctx)); 1888*bce88370SMarek Vasut if (!cctx) 1889*bce88370SMarek Vasut return -ENOMEM; 1890*bce88370SMarek Vasut if (!sctx->cmd_head) { 1891*bce88370SMarek Vasut sctx->cmd_head = cctx; 1892*bce88370SMarek Vasut sctx->cmd_tail = cctx; 1893*bce88370SMarek Vasut } else { 1894*bce88370SMarek Vasut sctx->cmd_tail->cmd = cctx; 1895*bce88370SMarek Vasut sctx->cmd_tail = cctx; 1896*bce88370SMarek Vasut } 1897*bce88370SMarek Vasut 1898*bce88370SMarek Vasut size = fread(&cctx->c_payload, 1, sizeof(cctx->c_payload), fp); 1899*bce88370SMarek Vasut if (size != sizeof(cctx->c_payload)) { 1900*bce88370SMarek Vasut fprintf(stderr, "ERR: SB command header too short!\n"); 1901*bce88370SMarek Vasut return -EINVAL; 1902*bce88370SMarek Vasut } 1903*bce88370SMarek Vasut 1904*bce88370SMarek Vasut tsize += size; 1905*bce88370SMarek Vasut 1906*bce88370SMarek Vasut sb_decrypt_tag(ictx, cctx); 1907*bce88370SMarek Vasut 1908*bce88370SMarek Vasut ret = sb_verify_command(ictx, cctx, fp, &tsize); 1909*bce88370SMarek Vasut if (ret) 1910*bce88370SMarek Vasut return -EINVAL; 1911*bce88370SMarek Vasut } 1912*bce88370SMarek Vasut 1913*bce88370SMarek Vasut return 0; 1914*bce88370SMarek Vasut } 1915*bce88370SMarek Vasut 1916*bce88370SMarek Vasut static int sb_verify_sections_cmds(struct sb_image_ctx *ictx, FILE *fp) 1917*bce88370SMarek Vasut { 1918*bce88370SMarek Vasut struct sb_boot_image_header *hdr = &ictx->payload; 1919*bce88370SMarek Vasut struct sb_sections_header *shdr; 1920*bce88370SMarek Vasut unsigned int i; 1921*bce88370SMarek Vasut int ret; 1922*bce88370SMarek Vasut struct sb_section_ctx *sctx; 1923*bce88370SMarek Vasut unsigned long size; 1924*bce88370SMarek Vasut char *bootable = ""; 1925*bce88370SMarek Vasut 1926*bce88370SMarek Vasut soprintf(ictx, "----- Verifying SB Sections and Commands -----\n"); 1927*bce88370SMarek Vasut 1928*bce88370SMarek Vasut for (i = 0; i < hdr->section_count; i++) { 1929*bce88370SMarek Vasut sctx = calloc(1, sizeof(*sctx)); 1930*bce88370SMarek Vasut if (!sctx) 1931*bce88370SMarek Vasut return -ENOMEM; 1932*bce88370SMarek Vasut if (!ictx->sect_head) { 1933*bce88370SMarek Vasut ictx->sect_head = sctx; 1934*bce88370SMarek Vasut ictx->sect_tail = sctx; 1935*bce88370SMarek Vasut } else { 1936*bce88370SMarek Vasut ictx->sect_tail->sect = sctx; 1937*bce88370SMarek Vasut ictx->sect_tail = sctx; 1938*bce88370SMarek Vasut } 1939*bce88370SMarek Vasut 1940*bce88370SMarek Vasut size = fread(&sctx->payload, 1, sizeof(sctx->payload), fp); 1941*bce88370SMarek Vasut if (size != sizeof(sctx->payload)) { 1942*bce88370SMarek Vasut fprintf(stderr, "ERR: SB section header too short!\n"); 1943*bce88370SMarek Vasut return -EINVAL; 1944*bce88370SMarek Vasut } 1945*bce88370SMarek Vasut } 1946*bce88370SMarek Vasut 1947*bce88370SMarek Vasut size = fread(&ictx->sb_dict_key, 1, sizeof(ictx->sb_dict_key), fp); 1948*bce88370SMarek Vasut if (size != sizeof(ictx->sb_dict_key)) { 1949*bce88370SMarek Vasut fprintf(stderr, "ERR: SB key dictionary too short!\n"); 1950*bce88370SMarek Vasut return -EINVAL; 1951*bce88370SMarek Vasut } 1952*bce88370SMarek Vasut 1953*bce88370SMarek Vasut sb_encrypt_sb_sections_header(ictx); 1954*bce88370SMarek Vasut sb_aes_reinit(ictx, 0); 1955*bce88370SMarek Vasut sb_decrypt_key_dictionary_key(ictx); 1956*bce88370SMarek Vasut 1957*bce88370SMarek Vasut sb_aes_reinit(ictx, 0); 1958*bce88370SMarek Vasut 1959*bce88370SMarek Vasut sctx = ictx->sect_head; 1960*bce88370SMarek Vasut while (sctx) { 1961*bce88370SMarek Vasut shdr = &sctx->payload; 1962*bce88370SMarek Vasut 1963*bce88370SMarek Vasut if (shdr->section_flags & SB_SECTION_FLAG_BOOTABLE) { 1964*bce88370SMarek Vasut sctx->boot = 1; 1965*bce88370SMarek Vasut bootable = " BOOTABLE"; 1966*bce88370SMarek Vasut } 1967*bce88370SMarek Vasut 1968*bce88370SMarek Vasut sctx->size = (shdr->section_size * SB_BLOCK_SIZE) + 1969*bce88370SMarek Vasut sizeof(struct sb_command); 1970*bce88370SMarek Vasut soprintf(ictx, "SECTION 0x%x%s # size = %i bytes\n", 1971*bce88370SMarek Vasut shdr->section_number, bootable, sctx->size); 1972*bce88370SMarek Vasut 1973*bce88370SMarek Vasut if (shdr->section_flags & ~SB_SECTION_FLAG_BOOTABLE) 1974*bce88370SMarek Vasut fprintf(stderr, " WARN: Unknown section flag(s) %08x\n", 1975*bce88370SMarek Vasut shdr->section_flags); 1976*bce88370SMarek Vasut 1977*bce88370SMarek Vasut if ((shdr->section_flags & SB_SECTION_FLAG_BOOTABLE) && 1978*bce88370SMarek Vasut (hdr->first_boot_section_id != shdr->section_number)) { 1979*bce88370SMarek Vasut fprintf(stderr, 1980*bce88370SMarek Vasut " WARN: Bootable section does ID not match image header ID!\n"); 1981*bce88370SMarek Vasut } 1982*bce88370SMarek Vasut 1983*bce88370SMarek Vasut ret = sb_verify_commands(ictx, sctx, fp); 1984*bce88370SMarek Vasut if (ret) 1985*bce88370SMarek Vasut return ret; 1986*bce88370SMarek Vasut 1987*bce88370SMarek Vasut sctx = sctx->sect; 1988*bce88370SMarek Vasut } 1989*bce88370SMarek Vasut 1990*bce88370SMarek Vasut /* 1991*bce88370SMarek Vasut * FIXME IDEA: 1992*bce88370SMarek Vasut * check if the first TAG command is at sctx->section_offset 1993*bce88370SMarek Vasut */ 1994*bce88370SMarek Vasut return 0; 1995*bce88370SMarek Vasut } 1996*bce88370SMarek Vasut 1997*bce88370SMarek Vasut static int sb_verify_image_end(struct sb_image_ctx *ictx, 1998*bce88370SMarek Vasut FILE *fp, off_t filesz) 1999*bce88370SMarek Vasut { 2000*bce88370SMarek Vasut uint8_t digest[32]; 2001*bce88370SMarek Vasut unsigned long size; 2002*bce88370SMarek Vasut off_t pos; 2003*bce88370SMarek Vasut int ret; 2004*bce88370SMarek Vasut 2005*bce88370SMarek Vasut soprintf(ictx, "------------- Verifying image end -------------\n"); 2006*bce88370SMarek Vasut 2007*bce88370SMarek Vasut size = fread(digest, 1, sizeof(digest), fp); 2008*bce88370SMarek Vasut if (size != sizeof(digest)) { 2009*bce88370SMarek Vasut fprintf(stderr, "ERR: SB key dictionary too short!\n"); 2010*bce88370SMarek Vasut return -EINVAL; 2011*bce88370SMarek Vasut } 2012*bce88370SMarek Vasut 2013*bce88370SMarek Vasut pos = ftell(fp); 2014*bce88370SMarek Vasut if (pos != filesz) { 2015*bce88370SMarek Vasut fprintf(stderr, "ERR: Trailing data past the image!\n"); 2016*bce88370SMarek Vasut return -EINVAL; 2017*bce88370SMarek Vasut } 2018*bce88370SMarek Vasut 2019*bce88370SMarek Vasut /* Check the image digest. */ 2020*bce88370SMarek Vasut EVP_DigestFinal(&ictx->md_ctx, ictx->digest, NULL); 2021*bce88370SMarek Vasut 2022*bce88370SMarek Vasut /* Decrypt the image digest from the input image. */ 2023*bce88370SMarek Vasut sb_aes_reinit(ictx, 0); 2024*bce88370SMarek Vasut sb_aes_crypt(ictx, digest, digest, sizeof(digest)); 2025*bce88370SMarek Vasut 2026*bce88370SMarek Vasut /* Check all of 20 bytes of the SHA1 hash. */ 2027*bce88370SMarek Vasut ret = memcmp(digest, ictx->digest, 20) ? -EINVAL : 0; 2028*bce88370SMarek Vasut 2029*bce88370SMarek Vasut if (ret) 2030*bce88370SMarek Vasut soprintf(ictx, "[FAIL] Full-image checksum: BAD\n"); 2031*bce88370SMarek Vasut else 2032*bce88370SMarek Vasut soprintf(ictx, "[PASS] Full-image checksum: OK\n"); 2033*bce88370SMarek Vasut 2034*bce88370SMarek Vasut return ret; 2035*bce88370SMarek Vasut } 2036*bce88370SMarek Vasut 2037*bce88370SMarek Vasut 2038*bce88370SMarek Vasut static int sb_build_tree_from_img(struct sb_image_ctx *ictx) 2039*bce88370SMarek Vasut { 2040*bce88370SMarek Vasut long filesize; 2041*bce88370SMarek Vasut int ret; 2042*bce88370SMarek Vasut FILE *fp; 2043*bce88370SMarek Vasut 2044*bce88370SMarek Vasut if (!ictx->input_filename) { 2045*bce88370SMarek Vasut fprintf(stderr, "ERR: Missing filename!\n"); 2046*bce88370SMarek Vasut return -EINVAL; 2047*bce88370SMarek Vasut } 2048*bce88370SMarek Vasut 2049*bce88370SMarek Vasut fp = fopen(ictx->input_filename, "r"); 2050*bce88370SMarek Vasut if (!fp) 2051*bce88370SMarek Vasut goto err_open; 2052*bce88370SMarek Vasut 2053*bce88370SMarek Vasut ret = fseek(fp, 0, SEEK_END); 2054*bce88370SMarek Vasut if (ret < 0) 2055*bce88370SMarek Vasut goto err_file; 2056*bce88370SMarek Vasut 2057*bce88370SMarek Vasut filesize = ftell(fp); 2058*bce88370SMarek Vasut if (filesize < 0) 2059*bce88370SMarek Vasut goto err_file; 2060*bce88370SMarek Vasut 2061*bce88370SMarek Vasut ret = fseek(fp, 0, SEEK_SET); 2062*bce88370SMarek Vasut if (ret < 0) 2063*bce88370SMarek Vasut goto err_file; 2064*bce88370SMarek Vasut 2065*bce88370SMarek Vasut if (filesize < (signed)sizeof(ictx->payload)) { 2066*bce88370SMarek Vasut fprintf(stderr, "ERR: File too short!\n"); 2067*bce88370SMarek Vasut goto err_file; 2068*bce88370SMarek Vasut } 2069*bce88370SMarek Vasut 2070*bce88370SMarek Vasut if (filesize & (SB_BLOCK_SIZE - 1)) { 2071*bce88370SMarek Vasut fprintf(stderr, "ERR: The file is not aligned!\n"); 2072*bce88370SMarek Vasut goto err_file; 2073*bce88370SMarek Vasut } 2074*bce88370SMarek Vasut 2075*bce88370SMarek Vasut /* Load and verify image header */ 2076*bce88370SMarek Vasut ret = sb_verify_image_header(ictx, fp, filesize); 2077*bce88370SMarek Vasut if (ret) 2078*bce88370SMarek Vasut goto err_verify; 2079*bce88370SMarek Vasut 2080*bce88370SMarek Vasut /* Load and verify sections and commands */ 2081*bce88370SMarek Vasut ret = sb_verify_sections_cmds(ictx, fp); 2082*bce88370SMarek Vasut if (ret) 2083*bce88370SMarek Vasut goto err_verify; 2084*bce88370SMarek Vasut 2085*bce88370SMarek Vasut ret = sb_verify_image_end(ictx, fp, filesize); 2086*bce88370SMarek Vasut if (ret) 2087*bce88370SMarek Vasut goto err_verify; 2088*bce88370SMarek Vasut 2089*bce88370SMarek Vasut ret = 0; 2090*bce88370SMarek Vasut 2091*bce88370SMarek Vasut err_verify: 2092*bce88370SMarek Vasut soprintf(ictx, "-------------------- Result -------------------\n"); 2093*bce88370SMarek Vasut soprintf(ictx, "Verification %s\n", ret ? "FAILED" : "PASSED"); 2094*bce88370SMarek Vasut 2095*bce88370SMarek Vasut /* Stop the encryption session. */ 2096*bce88370SMarek Vasut sb_aes_deinit(&ictx->cipher_ctx); 2097*bce88370SMarek Vasut 2098*bce88370SMarek Vasut fclose(fp); 2099*bce88370SMarek Vasut return ret; 2100*bce88370SMarek Vasut 2101*bce88370SMarek Vasut err_file: 2102*bce88370SMarek Vasut fclose(fp); 2103*bce88370SMarek Vasut err_open: 2104*bce88370SMarek Vasut fprintf(stderr, "ERR: Failed to load file \"%s\"\n", 2105*bce88370SMarek Vasut ictx->input_filename); 2106*bce88370SMarek Vasut return -EINVAL; 2107*bce88370SMarek Vasut } 2108*bce88370SMarek Vasut 2109*bce88370SMarek Vasut static void sb_free_image(struct sb_image_ctx *ictx) 2110*bce88370SMarek Vasut { 2111*bce88370SMarek Vasut struct sb_section_ctx *sctx = ictx->sect_head, *s_head; 2112*bce88370SMarek Vasut struct sb_dcd_ctx *dctx = ictx->dcd_head, *d_head; 2113*bce88370SMarek Vasut struct sb_cmd_ctx *cctx, *c_head; 2114*bce88370SMarek Vasut 2115*bce88370SMarek Vasut while (sctx) { 2116*bce88370SMarek Vasut s_head = sctx; 2117*bce88370SMarek Vasut c_head = sctx->cmd_head; 2118*bce88370SMarek Vasut 2119*bce88370SMarek Vasut while (c_head) { 2120*bce88370SMarek Vasut cctx = c_head; 2121*bce88370SMarek Vasut c_head = c_head->cmd; 2122*bce88370SMarek Vasut if (cctx->data) 2123*bce88370SMarek Vasut free(cctx->data); 2124*bce88370SMarek Vasut free(cctx); 2125*bce88370SMarek Vasut } 2126*bce88370SMarek Vasut 2127*bce88370SMarek Vasut sctx = sctx->sect; 2128*bce88370SMarek Vasut free(s_head); 2129*bce88370SMarek Vasut } 2130*bce88370SMarek Vasut 2131*bce88370SMarek Vasut while (dctx) { 2132*bce88370SMarek Vasut d_head = dctx; 2133*bce88370SMarek Vasut dctx = dctx->dcd; 2134*bce88370SMarek Vasut free(d_head->payload); 2135*bce88370SMarek Vasut free(d_head); 2136*bce88370SMarek Vasut } 2137*bce88370SMarek Vasut } 2138*bce88370SMarek Vasut 2139*bce88370SMarek Vasut /* 2140*bce88370SMarek Vasut * MXSSB-MKIMAGE glue code. 2141*bce88370SMarek Vasut */ 2142*bce88370SMarek Vasut static int mxsimage_check_image_types(uint8_t type) 2143*bce88370SMarek Vasut { 2144*bce88370SMarek Vasut if (type == IH_TYPE_MXSIMAGE) 2145*bce88370SMarek Vasut return EXIT_SUCCESS; 2146*bce88370SMarek Vasut else 2147*bce88370SMarek Vasut return EXIT_FAILURE; 2148*bce88370SMarek Vasut } 2149*bce88370SMarek Vasut 2150*bce88370SMarek Vasut static void mxsimage_set_header(void *ptr, struct stat *sbuf, int ifd, 2151*bce88370SMarek Vasut struct mkimage_params *params) 2152*bce88370SMarek Vasut { 2153*bce88370SMarek Vasut } 2154*bce88370SMarek Vasut 2155*bce88370SMarek Vasut int mxsimage_check_params(struct mkimage_params *params) 2156*bce88370SMarek Vasut { 2157*bce88370SMarek Vasut if (!params) 2158*bce88370SMarek Vasut return -1; 2159*bce88370SMarek Vasut if (!strlen(params->imagename)) { 2160*bce88370SMarek Vasut fprintf(stderr, 2161*bce88370SMarek Vasut "Error: %s - Configuration file not specified, it is needed for mxsimage generation\n", 2162*bce88370SMarek Vasut params->cmdname); 2163*bce88370SMarek Vasut return -1; 2164*bce88370SMarek Vasut } 2165*bce88370SMarek Vasut 2166*bce88370SMarek Vasut /* 2167*bce88370SMarek Vasut * Check parameters: 2168*bce88370SMarek Vasut * XIP is not allowed and verify that incompatible 2169*bce88370SMarek Vasut * parameters are not sent at the same time 2170*bce88370SMarek Vasut * For example, if list is required a data image must not be provided 2171*bce88370SMarek Vasut */ 2172*bce88370SMarek Vasut return (params->dflag && (params->fflag || params->lflag)) || 2173*bce88370SMarek Vasut (params->fflag && (params->dflag || params->lflag)) || 2174*bce88370SMarek Vasut (params->lflag && (params->dflag || params->fflag)) || 2175*bce88370SMarek Vasut (params->xflag) || !(strlen(params->imagename)); 2176*bce88370SMarek Vasut } 2177*bce88370SMarek Vasut 2178*bce88370SMarek Vasut static int mxsimage_verify_print_header(char *file, int silent) 2179*bce88370SMarek Vasut { 2180*bce88370SMarek Vasut int ret; 2181*bce88370SMarek Vasut struct sb_image_ctx ctx; 2182*bce88370SMarek Vasut 2183*bce88370SMarek Vasut memset(&ctx, 0, sizeof(ctx)); 2184*bce88370SMarek Vasut 2185*bce88370SMarek Vasut ctx.input_filename = file; 2186*bce88370SMarek Vasut ctx.silent_dump = silent; 2187*bce88370SMarek Vasut 2188*bce88370SMarek Vasut ret = sb_build_tree_from_img(&ctx); 2189*bce88370SMarek Vasut sb_free_image(&ctx); 2190*bce88370SMarek Vasut 2191*bce88370SMarek Vasut return ret; 2192*bce88370SMarek Vasut } 2193*bce88370SMarek Vasut 2194*bce88370SMarek Vasut char *imagefile; 2195*bce88370SMarek Vasut static int mxsimage_verify_header(unsigned char *ptr, int image_size, 2196*bce88370SMarek Vasut struct mkimage_params *params) 2197*bce88370SMarek Vasut { 2198*bce88370SMarek Vasut struct sb_boot_image_header *hdr; 2199*bce88370SMarek Vasut 2200*bce88370SMarek Vasut if (!ptr) 2201*bce88370SMarek Vasut return -EINVAL; 2202*bce88370SMarek Vasut 2203*bce88370SMarek Vasut hdr = (struct sb_boot_image_header *)ptr; 2204*bce88370SMarek Vasut 2205*bce88370SMarek Vasut /* 2206*bce88370SMarek Vasut * Check if the header contains the MXS image signatures, 2207*bce88370SMarek Vasut * if so, do a full-image verification. 2208*bce88370SMarek Vasut */ 2209*bce88370SMarek Vasut if (memcmp(hdr->signature1, "STMP", 4) || 2210*bce88370SMarek Vasut memcmp(hdr->signature2, "sgtl", 4)) 2211*bce88370SMarek Vasut return -EINVAL; 2212*bce88370SMarek Vasut 2213*bce88370SMarek Vasut imagefile = params->imagefile; 2214*bce88370SMarek Vasut 2215*bce88370SMarek Vasut return mxsimage_verify_print_header(params->imagefile, 1); 2216*bce88370SMarek Vasut } 2217*bce88370SMarek Vasut 2218*bce88370SMarek Vasut static void mxsimage_print_header(const void *hdr) 2219*bce88370SMarek Vasut { 2220*bce88370SMarek Vasut if (imagefile) 2221*bce88370SMarek Vasut mxsimage_verify_print_header(imagefile, 0); 2222*bce88370SMarek Vasut } 2223*bce88370SMarek Vasut 2224*bce88370SMarek Vasut static int sb_build_image(struct sb_image_ctx *ictx, 2225*bce88370SMarek Vasut struct image_type_params *tparams) 2226*bce88370SMarek Vasut { 2227*bce88370SMarek Vasut struct sb_boot_image_header *sb_header = &ictx->payload; 2228*bce88370SMarek Vasut struct sb_section_ctx *sctx; 2229*bce88370SMarek Vasut struct sb_cmd_ctx *cctx; 2230*bce88370SMarek Vasut struct sb_command *ccmd; 2231*bce88370SMarek Vasut struct sb_key_dictionary_key *sb_dict_key = &ictx->sb_dict_key; 2232*bce88370SMarek Vasut 2233*bce88370SMarek Vasut uint8_t *image, *iptr; 2234*bce88370SMarek Vasut 2235*bce88370SMarek Vasut /* Calculate image size. */ 2236*bce88370SMarek Vasut uint32_t size = sizeof(*sb_header) + 2237*bce88370SMarek Vasut ictx->sect_count * sizeof(struct sb_sections_header) + 2238*bce88370SMarek Vasut sizeof(*sb_dict_key) + sizeof(ictx->digest); 2239*bce88370SMarek Vasut 2240*bce88370SMarek Vasut sctx = ictx->sect_head; 2241*bce88370SMarek Vasut while (sctx) { 2242*bce88370SMarek Vasut size += sctx->size; 2243*bce88370SMarek Vasut sctx = sctx->sect; 2244*bce88370SMarek Vasut }; 2245*bce88370SMarek Vasut 2246*bce88370SMarek Vasut image = malloc(size); 2247*bce88370SMarek Vasut if (!image) 2248*bce88370SMarek Vasut return -ENOMEM; 2249*bce88370SMarek Vasut iptr = image; 2250*bce88370SMarek Vasut 2251*bce88370SMarek Vasut memcpy(iptr, sb_header, sizeof(*sb_header)); 2252*bce88370SMarek Vasut iptr += sizeof(*sb_header); 2253*bce88370SMarek Vasut 2254*bce88370SMarek Vasut sctx = ictx->sect_head; 2255*bce88370SMarek Vasut while (sctx) { 2256*bce88370SMarek Vasut memcpy(iptr, &sctx->payload, sizeof(struct sb_sections_header)); 2257*bce88370SMarek Vasut iptr += sizeof(struct sb_sections_header); 2258*bce88370SMarek Vasut sctx = sctx->sect; 2259*bce88370SMarek Vasut }; 2260*bce88370SMarek Vasut 2261*bce88370SMarek Vasut memcpy(iptr, sb_dict_key, sizeof(*sb_dict_key)); 2262*bce88370SMarek Vasut iptr += sizeof(*sb_dict_key); 2263*bce88370SMarek Vasut 2264*bce88370SMarek Vasut sctx = ictx->sect_head; 2265*bce88370SMarek Vasut while (sctx) { 2266*bce88370SMarek Vasut cctx = sctx->cmd_head; 2267*bce88370SMarek Vasut while (cctx) { 2268*bce88370SMarek Vasut ccmd = &cctx->payload; 2269*bce88370SMarek Vasut 2270*bce88370SMarek Vasut memcpy(iptr, &cctx->c_payload, sizeof(cctx->payload)); 2271*bce88370SMarek Vasut iptr += sizeof(cctx->payload); 2272*bce88370SMarek Vasut 2273*bce88370SMarek Vasut if (ccmd->header.tag == ROM_LOAD_CMD) { 2274*bce88370SMarek Vasut memcpy(iptr, cctx->data, cctx->length); 2275*bce88370SMarek Vasut iptr += cctx->length; 2276*bce88370SMarek Vasut } 2277*bce88370SMarek Vasut 2278*bce88370SMarek Vasut cctx = cctx->cmd; 2279*bce88370SMarek Vasut } 2280*bce88370SMarek Vasut 2281*bce88370SMarek Vasut sctx = sctx->sect; 2282*bce88370SMarek Vasut }; 2283*bce88370SMarek Vasut 2284*bce88370SMarek Vasut memcpy(iptr, ictx->digest, sizeof(ictx->digest)); 2285*bce88370SMarek Vasut iptr += sizeof(ictx->digest); 2286*bce88370SMarek Vasut 2287*bce88370SMarek Vasut /* Configure the mkimage */ 2288*bce88370SMarek Vasut tparams->hdr = image; 2289*bce88370SMarek Vasut tparams->header_size = size; 2290*bce88370SMarek Vasut 2291*bce88370SMarek Vasut return 0; 2292*bce88370SMarek Vasut } 2293*bce88370SMarek Vasut 2294*bce88370SMarek Vasut static int mxsimage_generate(struct mkimage_params *params, 2295*bce88370SMarek Vasut struct image_type_params *tparams) 2296*bce88370SMarek Vasut { 2297*bce88370SMarek Vasut int ret; 2298*bce88370SMarek Vasut struct sb_image_ctx ctx; 2299*bce88370SMarek Vasut 2300*bce88370SMarek Vasut /* Do not copy the U-Boot image! */ 2301*bce88370SMarek Vasut params->skipcpy = 1; 2302*bce88370SMarek Vasut 2303*bce88370SMarek Vasut memset(&ctx, 0, sizeof(ctx)); 2304*bce88370SMarek Vasut 2305*bce88370SMarek Vasut ctx.cfg_filename = params->imagename; 2306*bce88370SMarek Vasut ctx.output_filename = params->imagefile; 2307*bce88370SMarek Vasut ctx.verbose_boot = 1; 2308*bce88370SMarek Vasut 2309*bce88370SMarek Vasut ret = sb_build_tree_from_cfg(&ctx); 2310*bce88370SMarek Vasut if (ret) 2311*bce88370SMarek Vasut goto fail; 2312*bce88370SMarek Vasut 2313*bce88370SMarek Vasut ret = sb_encrypt_image(&ctx); 2314*bce88370SMarek Vasut if (!ret) 2315*bce88370SMarek Vasut ret = sb_build_image(&ctx, tparams); 2316*bce88370SMarek Vasut 2317*bce88370SMarek Vasut fail: 2318*bce88370SMarek Vasut sb_free_image(&ctx); 2319*bce88370SMarek Vasut 2320*bce88370SMarek Vasut return ret; 2321*bce88370SMarek Vasut } 2322*bce88370SMarek Vasut 2323*bce88370SMarek Vasut /* 2324*bce88370SMarek Vasut * mxsimage parameters 2325*bce88370SMarek Vasut */ 2326*bce88370SMarek Vasut static struct image_type_params mxsimage_params = { 2327*bce88370SMarek Vasut .name = "Freescale MXS Boot Image support", 2328*bce88370SMarek Vasut .header_size = 0, 2329*bce88370SMarek Vasut .hdr = NULL, 2330*bce88370SMarek Vasut .check_image_type = mxsimage_check_image_types, 2331*bce88370SMarek Vasut .verify_header = mxsimage_verify_header, 2332*bce88370SMarek Vasut .print_header = mxsimage_print_header, 2333*bce88370SMarek Vasut .set_header = mxsimage_set_header, 2334*bce88370SMarek Vasut .check_params = mxsimage_check_params, 2335*bce88370SMarek Vasut .vrec_header = mxsimage_generate, 2336*bce88370SMarek Vasut }; 2337*bce88370SMarek Vasut 2338*bce88370SMarek Vasut void init_mxs_image_type(void) 2339*bce88370SMarek Vasut { 2340*bce88370SMarek Vasut mkimage_register(&mxsimage_params); 2341*bce88370SMarek Vasut } 2342*bce88370SMarek Vasut 2343*bce88370SMarek Vasut #else 2344*bce88370SMarek Vasut void init_mxs_image_type(void) 2345*bce88370SMarek Vasut { 2346*bce88370SMarek Vasut } 2347*bce88370SMarek Vasut #endif 2348