1*23ba6841SJoseph Chen /* 2*23ba6841SJoseph Chen * Rockchip trust image generator 3*23ba6841SJoseph Chen * 4*23ba6841SJoseph Chen * (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd 5*23ba6841SJoseph Chen * Peter, Software Engineering, <superpeter.cai@gmail.com>. 6*23ba6841SJoseph Chen * 7*23ba6841SJoseph Chen * SPDX-License-Identifier: GPL-2.0+ 8*23ba6841SJoseph Chen */ 9*23ba6841SJoseph Chen #include <sys/stat.h> 10*23ba6841SJoseph Chen #include <u-boot/sha256.h> 11*23ba6841SJoseph Chen #include "trust_merger.h" 12*23ba6841SJoseph Chen #include "sha2.h" 13*23ba6841SJoseph Chen 14*23ba6841SJoseph Chen /* #define DEBUG */ 15*23ba6841SJoseph Chen 16*23ba6841SJoseph Chen static bool gDebug = 17*23ba6841SJoseph Chen #ifdef DEBUG 18*23ba6841SJoseph Chen true; 19*23ba6841SJoseph Chen #else 20*23ba6841SJoseph Chen false; 21*23ba6841SJoseph Chen #endif /* DEBUG */ 22*23ba6841SJoseph Chen 23*23ba6841SJoseph Chen #define LOGE(fmt, args...) fprintf(stderr, "E: [%s] " fmt, __func__, ##args) 24*23ba6841SJoseph Chen #define LOGD(fmt, args...) \ 25*23ba6841SJoseph Chen do { \ 26*23ba6841SJoseph Chen if (gDebug) \ 27*23ba6841SJoseph Chen fprintf(stderr, "D: [%s] " fmt, __func__, ##args); \ 28*23ba6841SJoseph Chen } while (0) 29*23ba6841SJoseph Chen 30*23ba6841SJoseph Chen /* trust image has g_trust_max_num backups */ 31*23ba6841SJoseph Chen static uint32_t g_trust_max_num = 2; 32*23ba6841SJoseph Chen static uint32_t g_trust_max_size = 2 * 1024 * 1024; 33*23ba6841SJoseph Chen 34*23ba6841SJoseph Chen /* config sha and rsa */ 35*23ba6841SJoseph Chen #define SHA_SEL_256 3 /* little endian */ 36*23ba6841SJoseph Chen #define SHA_SEL_256_RK 2 /* big endian: only rk3368 need it */ 37*23ba6841SJoseph Chen #define SHA_SEL_160 1 38*23ba6841SJoseph Chen #define SHA_SEL_NONE 0 39*23ba6841SJoseph Chen 40*23ba6841SJoseph Chen #define RSA_SEL_2048_PSS 3 /* only RK3326, PX30, RK3308 */ 41*23ba6841SJoseph Chen #define RSA_SEL_2048 2 /* most platforms except above PSS */ 42*23ba6841SJoseph Chen #define RSA_SEL_1024 1 43*23ba6841SJoseph Chen #define RSA_SEL_NONE 0 44*23ba6841SJoseph Chen 45*23ba6841SJoseph Chen #define is_digit(c) ((c) >= '0' && (c) <= '9') 46*23ba6841SJoseph Chen 47*23ba6841SJoseph Chen static char *gConfigPath; 48*23ba6841SJoseph Chen static OPT_T gOpts; 49*23ba6841SJoseph Chen #define BL3X_FILESIZE_MAX (512 * 1024) 50*23ba6841SJoseph Chen static uint8_t gBuf[BL3X_FILESIZE_MAX]; 51*23ba6841SJoseph Chen static bool gSubfix; 52*23ba6841SJoseph Chen static char *gLegacyPath; 53*23ba6841SJoseph Chen static char *gNewPath; 54*23ba6841SJoseph Chen static uint8_t gRSAmode = RSA_SEL_2048; 55*23ba6841SJoseph Chen static uint8_t gSHAmode = SHA_SEL_256; 56*23ba6841SJoseph Chen 57*23ba6841SJoseph Chen const uint8_t gBl3xID[BL_MAX_SEC][4] = { { 'B', 'L', '3', '0' }, 58*23ba6841SJoseph Chen { 'B', 'L', '3', '1' }, 59*23ba6841SJoseph Chen { 'B', 'L', '3', '2' }, 60*23ba6841SJoseph Chen { 'B', 'L', '3', '3' } 61*23ba6841SJoseph Chen }; 62*23ba6841SJoseph Chen 63*23ba6841SJoseph Chen static inline uint32_t getBCD(uint16_t value) 64*23ba6841SJoseph Chen { 65*23ba6841SJoseph Chen uint8_t tmp[2] = { 0 }; 66*23ba6841SJoseph Chen int i; 67*23ba6841SJoseph Chen uint32_t ret; 68*23ba6841SJoseph Chen 69*23ba6841SJoseph Chen if (value > 0xFFFF) { 70*23ba6841SJoseph Chen return 0; 71*23ba6841SJoseph Chen } 72*23ba6841SJoseph Chen 73*23ba6841SJoseph Chen for (i = 0; i < 2; i++) { 74*23ba6841SJoseph Chen tmp[i] = (((value / 10) % 10) << 4) | (value % 10); 75*23ba6841SJoseph Chen value /= 100; 76*23ba6841SJoseph Chen } 77*23ba6841SJoseph Chen ret = ((uint16_t)(tmp[1] << 8)) | tmp[0]; 78*23ba6841SJoseph Chen 79*23ba6841SJoseph Chen LOGD("ret:%x\n", ret); 80*23ba6841SJoseph Chen return ret & 0xFF; 81*23ba6841SJoseph Chen } 82*23ba6841SJoseph Chen 83*23ba6841SJoseph Chen static inline void fixPath(char *path) 84*23ba6841SJoseph Chen { 85*23ba6841SJoseph Chen int i, len = strlen(path); 86*23ba6841SJoseph Chen char tmp[MAX_LINE_LEN]; 87*23ba6841SJoseph Chen char *start, *end; 88*23ba6841SJoseph Chen 89*23ba6841SJoseph Chen for (i = 0; i < len; i++) { 90*23ba6841SJoseph Chen if (path[i] == '\\') 91*23ba6841SJoseph Chen path[i] = '/'; 92*23ba6841SJoseph Chen else if (path[i] == '\r' || path[i] == '\n') 93*23ba6841SJoseph Chen path[i] = '\0'; 94*23ba6841SJoseph Chen } 95*23ba6841SJoseph Chen 96*23ba6841SJoseph Chen if (gLegacyPath && gNewPath) { 97*23ba6841SJoseph Chen start = strstr(path, gLegacyPath); 98*23ba6841SJoseph Chen if (start) { 99*23ba6841SJoseph Chen end = start + strlen(gLegacyPath); 100*23ba6841SJoseph Chen /* Backup, so tmp can be src for strcat() */ 101*23ba6841SJoseph Chen strcpy(tmp, end); 102*23ba6841SJoseph Chen /* Terminate, so path can be dest for strcat() */ 103*23ba6841SJoseph Chen *start = '\0'; 104*23ba6841SJoseph Chen strcat(path, tmp); 105*23ba6841SJoseph Chen } 106*23ba6841SJoseph Chen } 107*23ba6841SJoseph Chen } 108*23ba6841SJoseph Chen 109*23ba6841SJoseph Chen static bool parseVersion(FILE *file) 110*23ba6841SJoseph Chen { 111*23ba6841SJoseph Chen int d = 0; 112*23ba6841SJoseph Chen 113*23ba6841SJoseph Chen if (SCANF_EAT(file) != 0) { 114*23ba6841SJoseph Chen return false; 115*23ba6841SJoseph Chen } 116*23ba6841SJoseph Chen if (fscanf(file, OPT_MAJOR "=%d", &d) != 1) 117*23ba6841SJoseph Chen return false; 118*23ba6841SJoseph Chen gOpts.major = (uint16_t) d; 119*23ba6841SJoseph Chen if (SCANF_EAT(file) != 0) { 120*23ba6841SJoseph Chen return false; 121*23ba6841SJoseph Chen } 122*23ba6841SJoseph Chen if (fscanf(file, OPT_MINOR "=%d", &d) != 1) 123*23ba6841SJoseph Chen return false; 124*23ba6841SJoseph Chen gOpts.minor = (uint16_t) d; 125*23ba6841SJoseph Chen LOGD("major:%d, minor:%d\n", gOpts.major, gOpts.minor); 126*23ba6841SJoseph Chen return true; 127*23ba6841SJoseph Chen } 128*23ba6841SJoseph Chen 129*23ba6841SJoseph Chen static bool parseBL3x(FILE *file, int bl3x_id) 130*23ba6841SJoseph Chen { 131*23ba6841SJoseph Chen int pos; 132*23ba6841SJoseph Chen int sec; 133*23ba6841SJoseph Chen char buf[MAX_LINE_LEN]; 134*23ba6841SJoseph Chen bl_entry_t *pbl3x = NULL; 135*23ba6841SJoseph Chen 136*23ba6841SJoseph Chen if (bl3x_id >= BL_MAX_SEC) { 137*23ba6841SJoseph Chen return false; 138*23ba6841SJoseph Chen } 139*23ba6841SJoseph Chen 140*23ba6841SJoseph Chen pbl3x = &gOpts.bl3x[bl3x_id]; 141*23ba6841SJoseph Chen 142*23ba6841SJoseph Chen /* SEC */ 143*23ba6841SJoseph Chen if (SCANF_EAT(file) != 0) { 144*23ba6841SJoseph Chen return false; 145*23ba6841SJoseph Chen } 146*23ba6841SJoseph Chen if (fscanf(file, OPT_SEC "=%d", &sec) != 1) { 147*23ba6841SJoseph Chen return false; 148*23ba6841SJoseph Chen } 149*23ba6841SJoseph Chen if ((gSubfix) && (bl3x_id == BL32_SEC)) { 150*23ba6841SJoseph Chen if (sec == 0) { 151*23ba6841SJoseph Chen sec = 1; 152*23ba6841SJoseph Chen printf("BL3%d adjust sec from 0 to 1\n", bl3x_id); 153*23ba6841SJoseph Chen } 154*23ba6841SJoseph Chen } 155*23ba6841SJoseph Chen pbl3x->sec = sec; 156*23ba6841SJoseph Chen LOGD("bl3%d sec: %d\n", bl3x_id, pbl3x->sec); 157*23ba6841SJoseph Chen 158*23ba6841SJoseph Chen /* PATH */ 159*23ba6841SJoseph Chen if (SCANF_EAT(file) != 0) { 160*23ba6841SJoseph Chen return false; 161*23ba6841SJoseph Chen } 162*23ba6841SJoseph Chen memset(buf, 0, MAX_LINE_LEN); 163*23ba6841SJoseph Chen if (fscanf(file, OPT_PATH "=%s", buf) != 1) { 164*23ba6841SJoseph Chen if (pbl3x->sec) 165*23ba6841SJoseph Chen return false; 166*23ba6841SJoseph Chen } else { 167*23ba6841SJoseph Chen if (strlen(buf) != 0) { 168*23ba6841SJoseph Chen fixPath(buf); 169*23ba6841SJoseph Chen strcpy(pbl3x->path, buf); 170*23ba6841SJoseph Chen LOGD("bl3%d path:%s\n", bl3x_id, pbl3x->path); 171*23ba6841SJoseph Chen } 172*23ba6841SJoseph Chen } 173*23ba6841SJoseph Chen 174*23ba6841SJoseph Chen /* ADDR */ 175*23ba6841SJoseph Chen if (SCANF_EAT(file) != 0) { 176*23ba6841SJoseph Chen return false; 177*23ba6841SJoseph Chen } 178*23ba6841SJoseph Chen memset(buf, 0, MAX_LINE_LEN); 179*23ba6841SJoseph Chen if (fscanf(file, OPT_ADDR "=%s", buf) != 1) { 180*23ba6841SJoseph Chen if (pbl3x->sec) 181*23ba6841SJoseph Chen return false; 182*23ba6841SJoseph Chen } else { 183*23ba6841SJoseph Chen if (strlen(buf) != 0) { 184*23ba6841SJoseph Chen pbl3x->addr = strtoul(buf, NULL, 16); 185*23ba6841SJoseph Chen LOGD("bl3%d addr:0x%x\n", bl3x_id, pbl3x->addr); 186*23ba6841SJoseph Chen } 187*23ba6841SJoseph Chen } 188*23ba6841SJoseph Chen 189*23ba6841SJoseph Chen pos = ftell(file); 190*23ba6841SJoseph Chen if (pos < 0) { 191*23ba6841SJoseph Chen return false; 192*23ba6841SJoseph Chen } 193*23ba6841SJoseph Chen if (SCANF_EAT(file) != 0) { 194*23ba6841SJoseph Chen return false; 195*23ba6841SJoseph Chen } 196*23ba6841SJoseph Chen 197*23ba6841SJoseph Chen return true; 198*23ba6841SJoseph Chen } 199*23ba6841SJoseph Chen 200*23ba6841SJoseph Chen static bool parseOut(FILE *file) 201*23ba6841SJoseph Chen { 202*23ba6841SJoseph Chen if (SCANF_EAT(file) != 0) { 203*23ba6841SJoseph Chen return false; 204*23ba6841SJoseph Chen } 205*23ba6841SJoseph Chen if (fscanf(file, OPT_OUT_PATH "=%[^\r^\n]", gOpts.outPath) != 1) 206*23ba6841SJoseph Chen return false; 207*23ba6841SJoseph Chen fixPath(gOpts.outPath); 208*23ba6841SJoseph Chen printf("out:%s\n", gOpts.outPath); 209*23ba6841SJoseph Chen 210*23ba6841SJoseph Chen return true; 211*23ba6841SJoseph Chen } 212*23ba6841SJoseph Chen 213*23ba6841SJoseph Chen void printOpts(FILE *out) 214*23ba6841SJoseph Chen { 215*23ba6841SJoseph Chen fprintf(out, SEC_BL30 "\n" OPT_SEC "=%d\n", gOpts.bl3x[BL30_SEC].sec); 216*23ba6841SJoseph Chen if (gOpts.bl3x[BL30_SEC].sec) { 217*23ba6841SJoseph Chen fprintf(out, OPT_PATH "=%s\n", gOpts.bl3x[BL30_SEC].path); 218*23ba6841SJoseph Chen fprintf(out, OPT_ADDR "=0x%08x\n", gOpts.bl3x[BL30_SEC].addr); 219*23ba6841SJoseph Chen } 220*23ba6841SJoseph Chen 221*23ba6841SJoseph Chen fprintf(out, SEC_BL31 "\n" OPT_SEC "=%d\n", gOpts.bl3x[BL31_SEC].sec); 222*23ba6841SJoseph Chen if (gOpts.bl3x[BL31_SEC].sec) { 223*23ba6841SJoseph Chen fprintf(out, OPT_PATH "=%s\n", gOpts.bl3x[BL31_SEC].path); 224*23ba6841SJoseph Chen fprintf(out, OPT_ADDR "=0x%08x\n", gOpts.bl3x[BL31_SEC].addr); 225*23ba6841SJoseph Chen } 226*23ba6841SJoseph Chen 227*23ba6841SJoseph Chen fprintf(out, SEC_BL32 "\n" OPT_SEC "=%d\n", gOpts.bl3x[BL32_SEC].sec); 228*23ba6841SJoseph Chen if (gOpts.bl3x[BL32_SEC].sec) { 229*23ba6841SJoseph Chen fprintf(out, OPT_PATH "=%s\n", gOpts.bl3x[BL32_SEC].path); 230*23ba6841SJoseph Chen fprintf(out, OPT_ADDR "=0x%08x\n", gOpts.bl3x[BL32_SEC].addr); 231*23ba6841SJoseph Chen } 232*23ba6841SJoseph Chen 233*23ba6841SJoseph Chen fprintf(out, SEC_BL33 "\n" OPT_SEC "=%d\n", gOpts.bl3x[BL33_SEC].sec); 234*23ba6841SJoseph Chen if (gOpts.bl3x[BL33_SEC].sec) { 235*23ba6841SJoseph Chen fprintf(out, OPT_PATH "=%s\n", gOpts.bl3x[BL33_SEC].path); 236*23ba6841SJoseph Chen fprintf(out, OPT_ADDR "=0x%08x\n", gOpts.bl3x[BL33_SEC].addr); 237*23ba6841SJoseph Chen } 238*23ba6841SJoseph Chen 239*23ba6841SJoseph Chen fprintf(out, SEC_OUT "\n" OPT_OUT_PATH "=%s\n", gOpts.outPath); 240*23ba6841SJoseph Chen } 241*23ba6841SJoseph Chen 242*23ba6841SJoseph Chen static bool parseOpts(void) 243*23ba6841SJoseph Chen { 244*23ba6841SJoseph Chen FILE *file = NULL; 245*23ba6841SJoseph Chen char *configPath = (gConfigPath == NULL) ? DEF_CONFIG_FILE : gConfigPath; 246*23ba6841SJoseph Chen bool bl30ok = false, bl31ok = false, bl32ok = false, bl33ok = false; 247*23ba6841SJoseph Chen bool outOk = false; 248*23ba6841SJoseph Chen bool versionOk = false; 249*23ba6841SJoseph Chen char buf[MAX_LINE_LEN]; 250*23ba6841SJoseph Chen bool ret = false; 251*23ba6841SJoseph Chen 252*23ba6841SJoseph Chen file = fopen(configPath, "r"); 253*23ba6841SJoseph Chen if (!file) { 254*23ba6841SJoseph Chen fprintf(stderr, "config(%s) not found!\n", configPath); 255*23ba6841SJoseph Chen if (configPath == (char *)DEF_CONFIG_FILE) { 256*23ba6841SJoseph Chen file = fopen(DEF_CONFIG_FILE, "w"); 257*23ba6841SJoseph Chen if (file) { 258*23ba6841SJoseph Chen fprintf(stderr, "create defconfig\n"); 259*23ba6841SJoseph Chen printOpts(file); 260*23ba6841SJoseph Chen } 261*23ba6841SJoseph Chen } 262*23ba6841SJoseph Chen goto end; 263*23ba6841SJoseph Chen } 264*23ba6841SJoseph Chen 265*23ba6841SJoseph Chen LOGD("start parse\n"); 266*23ba6841SJoseph Chen 267*23ba6841SJoseph Chen if (SCANF_EAT(file) != 0) { 268*23ba6841SJoseph Chen goto end; 269*23ba6841SJoseph Chen } 270*23ba6841SJoseph Chen while (fscanf(file, "%s", buf) == 1) { 271*23ba6841SJoseph Chen if (!strcmp(buf, SEC_VERSION)) { 272*23ba6841SJoseph Chen versionOk = parseVersion(file); 273*23ba6841SJoseph Chen if (!versionOk) { 274*23ba6841SJoseph Chen LOGE("parseVersion failed!\n"); 275*23ba6841SJoseph Chen goto end; 276*23ba6841SJoseph Chen } 277*23ba6841SJoseph Chen } else if (!strcmp(buf, SEC_BL30)) { 278*23ba6841SJoseph Chen bl30ok = parseBL3x(file, BL30_SEC); 279*23ba6841SJoseph Chen if (!bl30ok) { 280*23ba6841SJoseph Chen LOGE("parseBL30 failed!\n"); 281*23ba6841SJoseph Chen goto end; 282*23ba6841SJoseph Chen } 283*23ba6841SJoseph Chen } else if (!strcmp(buf, SEC_BL31)) { 284*23ba6841SJoseph Chen bl31ok = parseBL3x(file, BL31_SEC); 285*23ba6841SJoseph Chen if (!bl31ok) { 286*23ba6841SJoseph Chen LOGE("parseBL31 failed!\n"); 287*23ba6841SJoseph Chen goto end; 288*23ba6841SJoseph Chen } 289*23ba6841SJoseph Chen } else if (!strcmp(buf, SEC_BL32)) { 290*23ba6841SJoseph Chen bl32ok = parseBL3x(file, BL32_SEC); 291*23ba6841SJoseph Chen if (!bl32ok) { 292*23ba6841SJoseph Chen LOGE("parseBL32 failed!\n"); 293*23ba6841SJoseph Chen goto end; 294*23ba6841SJoseph Chen } 295*23ba6841SJoseph Chen } else if (!strcmp(buf, SEC_BL33)) { 296*23ba6841SJoseph Chen bl33ok = parseBL3x(file, BL33_SEC); 297*23ba6841SJoseph Chen if (!bl33ok) { 298*23ba6841SJoseph Chen LOGE("parseBL33 failed!\n"); 299*23ba6841SJoseph Chen goto end; 300*23ba6841SJoseph Chen } 301*23ba6841SJoseph Chen } else if (!strcmp(buf, SEC_OUT)) { 302*23ba6841SJoseph Chen outOk = parseOut(file); 303*23ba6841SJoseph Chen if (!outOk) { 304*23ba6841SJoseph Chen LOGE("parseOut failed!\n"); 305*23ba6841SJoseph Chen goto end; 306*23ba6841SJoseph Chen } 307*23ba6841SJoseph Chen } else if (buf[0] == '#') { 308*23ba6841SJoseph Chen continue; 309*23ba6841SJoseph Chen } else { 310*23ba6841SJoseph Chen LOGE("unknown sec: %s!\n", buf); 311*23ba6841SJoseph Chen goto end; 312*23ba6841SJoseph Chen } 313*23ba6841SJoseph Chen if (SCANF_EAT(file) != 0) { 314*23ba6841SJoseph Chen goto end; 315*23ba6841SJoseph Chen } 316*23ba6841SJoseph Chen } 317*23ba6841SJoseph Chen 318*23ba6841SJoseph Chen if (bl30ok && bl31ok && bl32ok && bl33ok && outOk) 319*23ba6841SJoseph Chen ret = true; 320*23ba6841SJoseph Chen end: 321*23ba6841SJoseph Chen if (file) 322*23ba6841SJoseph Chen fclose(file); 323*23ba6841SJoseph Chen 324*23ba6841SJoseph Chen return ret; 325*23ba6841SJoseph Chen } 326*23ba6841SJoseph Chen 327*23ba6841SJoseph Chen bool initOpts(void) 328*23ba6841SJoseph Chen { 329*23ba6841SJoseph Chen 330*23ba6841SJoseph Chen memset(&gOpts, 0, sizeof(gOpts)); 331*23ba6841SJoseph Chen 332*23ba6841SJoseph Chen gOpts.major = DEF_MAJOR; 333*23ba6841SJoseph Chen gOpts.minor = DEF_MINOR; 334*23ba6841SJoseph Chen 335*23ba6841SJoseph Chen memcpy(&gOpts.bl3x[BL30_SEC].id, gBl3xID[BL30_SEC], 4); 336*23ba6841SJoseph Chen strcpy(gOpts.bl3x[BL30_SEC].path, DEF_BL30_PATH); 337*23ba6841SJoseph Chen 338*23ba6841SJoseph Chen memcpy(&gOpts.bl3x[BL31_SEC].id, gBl3xID[BL31_SEC], 4); 339*23ba6841SJoseph Chen strcpy(gOpts.bl3x[BL31_SEC].path, DEF_BL31_PATH); 340*23ba6841SJoseph Chen 341*23ba6841SJoseph Chen memcpy(&gOpts.bl3x[BL32_SEC].id, gBl3xID[BL32_SEC], 4); 342*23ba6841SJoseph Chen strcpy(gOpts.bl3x[BL32_SEC].path, DEF_BL32_PATH); 343*23ba6841SJoseph Chen 344*23ba6841SJoseph Chen memcpy(&gOpts.bl3x[BL33_SEC].id, gBl3xID[BL33_SEC], 4); 345*23ba6841SJoseph Chen strcpy(gOpts.bl3x[BL33_SEC].path, DEF_BL33_PATH); 346*23ba6841SJoseph Chen 347*23ba6841SJoseph Chen strcpy(gOpts.outPath, DEF_OUT_PATH); 348*23ba6841SJoseph Chen 349*23ba6841SJoseph Chen return parseOpts(); 350*23ba6841SJoseph Chen } 351*23ba6841SJoseph Chen 352*23ba6841SJoseph Chen static inline bool getFileSize(const char *path, uint32_t *size) 353*23ba6841SJoseph Chen { 354*23ba6841SJoseph Chen struct stat st; 355*23ba6841SJoseph Chen 356*23ba6841SJoseph Chen if (stat(path, &st) < 0) 357*23ba6841SJoseph Chen return false; 358*23ba6841SJoseph Chen *size = st.st_size; 359*23ba6841SJoseph Chen LOGD("path:%s, size:%d\n", path, *size); 360*23ba6841SJoseph Chen return true; 361*23ba6841SJoseph Chen } 362*23ba6841SJoseph Chen 363*23ba6841SJoseph Chen void fill_file(FILE *file, char ch, uint32_t fill_size) 364*23ba6841SJoseph Chen { 365*23ba6841SJoseph Chen uint8_t fill_buffer[1024]; 366*23ba6841SJoseph Chen uint32_t cur_write; 367*23ba6841SJoseph Chen 368*23ba6841SJoseph Chen memset(fill_buffer, ch, 1024); 369*23ba6841SJoseph Chen while (fill_size > 0) { 370*23ba6841SJoseph Chen cur_write = (fill_size >= 1024) ? 1024 : fill_size; 371*23ba6841SJoseph Chen fwrite(fill_buffer, 1, cur_write, file); 372*23ba6841SJoseph Chen fill_size -= cur_write; 373*23ba6841SJoseph Chen } 374*23ba6841SJoseph Chen } 375*23ba6841SJoseph Chen 376*23ba6841SJoseph Chen bool filter_elf(uint32_t index, uint8_t *pMeta, uint32_t *pMetaNum, 377*23ba6841SJoseph Chen bool *bElf) 378*23ba6841SJoseph Chen { 379*23ba6841SJoseph Chen bool ret = false; 380*23ba6841SJoseph Chen FILE *file = NULL; 381*23ba6841SJoseph Chen uint8_t *file_buffer = NULL; 382*23ba6841SJoseph Chen uint32_t file_size, read_size, i; 383*23ba6841SJoseph Chen Elf32_Ehdr *pElfHeader32; 384*23ba6841SJoseph Chen Elf32_Phdr *pElfProgram32; 385*23ba6841SJoseph Chen Elf64_Ehdr *pElfHeader64; 386*23ba6841SJoseph Chen Elf64_Phdr *pElfProgram64; 387*23ba6841SJoseph Chen bl_entry_t *pEntry = (bl_entry_t *)(pMeta + sizeof(bl_entry_t) * (*pMetaNum)); 388*23ba6841SJoseph Chen LOGD("index=%d,file=%s\n", index, gOpts.bl3x[index].path); 389*23ba6841SJoseph Chen 390*23ba6841SJoseph Chen if (!getFileSize(gOpts.bl3x[index].path, &file_size)) 391*23ba6841SJoseph Chen goto exit_fileter_elf; 392*23ba6841SJoseph Chen file = fopen(gOpts.bl3x[index].path, "rb"); 393*23ba6841SJoseph Chen if (!file) { 394*23ba6841SJoseph Chen LOGE("open file(%s) failed\n", gOpts.bl3x[index].path); 395*23ba6841SJoseph Chen goto exit_fileter_elf; 396*23ba6841SJoseph Chen } 397*23ba6841SJoseph Chen file_buffer = malloc(file_size); 398*23ba6841SJoseph Chen if (!file_buffer) 399*23ba6841SJoseph Chen goto exit_fileter_elf; 400*23ba6841SJoseph Chen read_size = fread(file_buffer, 1, file_size, file); 401*23ba6841SJoseph Chen if (read_size != file_size) 402*23ba6841SJoseph Chen goto exit_fileter_elf; 403*23ba6841SJoseph Chen 404*23ba6841SJoseph Chen if (*((uint32_t *)file_buffer) != ELF_MAGIC) { 405*23ba6841SJoseph Chen ret = true; 406*23ba6841SJoseph Chen *bElf = false; 407*23ba6841SJoseph Chen goto exit_fileter_elf; 408*23ba6841SJoseph Chen } 409*23ba6841SJoseph Chen *bElf = true; 410*23ba6841SJoseph Chen if (file_buffer[5] != 1) { /* only support little endian */ 411*23ba6841SJoseph Chen goto exit_fileter_elf; 412*23ba6841SJoseph Chen } 413*23ba6841SJoseph Chen if (*((uint16_t *)(file_buffer + EI_NIDENT)) != 414*23ba6841SJoseph Chen 2) { /* only support executable case */ 415*23ba6841SJoseph Chen goto exit_fileter_elf; 416*23ba6841SJoseph Chen } 417*23ba6841SJoseph Chen 418*23ba6841SJoseph Chen if (file_buffer[4] == 2) { 419*23ba6841SJoseph Chen pElfHeader64 = (Elf64_Ehdr *)file_buffer; 420*23ba6841SJoseph Chen for (i = 0; i < pElfHeader64->e_phnum; i++) { 421*23ba6841SJoseph Chen pElfProgram64 = (Elf64_Phdr *)(file_buffer + pElfHeader64->e_phoff + 422*23ba6841SJoseph Chen i * pElfHeader64->e_phentsize); 423*23ba6841SJoseph Chen if (pElfProgram64->p_type == 1) { /* PT_LOAD */ 424*23ba6841SJoseph Chen pEntry->id = gOpts.bl3x[index].id; 425*23ba6841SJoseph Chen strcpy(pEntry->path, gOpts.bl3x[index].path); 426*23ba6841SJoseph Chen pEntry->size = (uint32_t) pElfProgram64->p_filesz; 427*23ba6841SJoseph Chen pEntry->offset = (uint32_t) pElfProgram64->p_offset; 428*23ba6841SJoseph Chen pEntry->align_size = DO_ALIGN(pEntry->size, ENTRY_ALIGN); 429*23ba6841SJoseph Chen pEntry->addr = (uint32_t) pElfProgram64->p_vaddr; 430*23ba6841SJoseph Chen if (pEntry->align_size > BL3X_FILESIZE_MAX) { 431*23ba6841SJoseph Chen LOGE("elf_file %s too large,segment=%d.\n", pEntry->path, i); 432*23ba6841SJoseph Chen goto exit_fileter_elf; 433*23ba6841SJoseph Chen } 434*23ba6841SJoseph Chen LOGD("bl3%d: filesize = %d, imagesize = %d, segment=%d\n", index, 435*23ba6841SJoseph Chen pEntry->size, pEntry->align_size, i); 436*23ba6841SJoseph Chen pEntry++; 437*23ba6841SJoseph Chen (*pMetaNum)++; 438*23ba6841SJoseph Chen } 439*23ba6841SJoseph Chen } 440*23ba6841SJoseph Chen 441*23ba6841SJoseph Chen } else { 442*23ba6841SJoseph Chen pElfHeader32 = (Elf32_Ehdr *)file_buffer; 443*23ba6841SJoseph Chen for (i = 0; i < pElfHeader32->e_phnum; i++) { 444*23ba6841SJoseph Chen pElfProgram32 = (Elf32_Phdr *)(file_buffer + pElfHeader32->e_phoff + 445*23ba6841SJoseph Chen i * pElfHeader32->e_phentsize); 446*23ba6841SJoseph Chen if (pElfProgram32->p_type == 1) { /* PT_LOAD */ 447*23ba6841SJoseph Chen pEntry->id = gOpts.bl3x[index].id; 448*23ba6841SJoseph Chen strcpy(pEntry->path, gOpts.bl3x[index].path); 449*23ba6841SJoseph Chen pEntry->size = pElfProgram32->p_filesz; 450*23ba6841SJoseph Chen pEntry->offset = pElfProgram32->p_offset; 451*23ba6841SJoseph Chen pEntry->align_size = DO_ALIGN(pEntry->size, ENTRY_ALIGN); 452*23ba6841SJoseph Chen pEntry->addr = pElfProgram32->p_vaddr; 453*23ba6841SJoseph Chen if (pEntry->align_size > BL3X_FILESIZE_MAX) { 454*23ba6841SJoseph Chen LOGE("elf_file %s too large,segment=%d.\n", pEntry->path, i); 455*23ba6841SJoseph Chen goto exit_fileter_elf; 456*23ba6841SJoseph Chen } 457*23ba6841SJoseph Chen LOGD("bl3%d: filesize = %d, imagesize = %d, segment=%d\n", index, 458*23ba6841SJoseph Chen pEntry->size, pEntry->align_size, i); 459*23ba6841SJoseph Chen pEntry++; 460*23ba6841SJoseph Chen (*pMetaNum)++; 461*23ba6841SJoseph Chen } 462*23ba6841SJoseph Chen } 463*23ba6841SJoseph Chen } 464*23ba6841SJoseph Chen ret = true; 465*23ba6841SJoseph Chen exit_fileter_elf: 466*23ba6841SJoseph Chen if (file) 467*23ba6841SJoseph Chen fclose(file); 468*23ba6841SJoseph Chen if (file_buffer) 469*23ba6841SJoseph Chen free(file_buffer); 470*23ba6841SJoseph Chen return ret; 471*23ba6841SJoseph Chen } 472*23ba6841SJoseph Chen 473*23ba6841SJoseph Chen #define SHA256_CHECK_SZ ((uint32_t)(256 * 1024)) 474*23ba6841SJoseph Chen static bool bl3xHash256(uint8_t *pHash, uint8_t *pData, uint32_t nDataSize) 475*23ba6841SJoseph Chen { 476*23ba6841SJoseph Chen uint32_t nHashSize, nHasHashSize; 477*23ba6841SJoseph Chen 478*23ba6841SJoseph Chen if (!pHash || !pData || !nDataSize) { 479*23ba6841SJoseph Chen return false; 480*23ba6841SJoseph Chen } 481*23ba6841SJoseph Chen 482*23ba6841SJoseph Chen nHasHashSize = 0; 483*23ba6841SJoseph Chen 484*23ba6841SJoseph Chen if (gSHAmode == SHA_SEL_256_RK) { 485*23ba6841SJoseph Chen sha256_ctx ctx; 486*23ba6841SJoseph Chen 487*23ba6841SJoseph Chen sha256_begin(&ctx); 488*23ba6841SJoseph Chen while (nDataSize > 0) { 489*23ba6841SJoseph Chen nHashSize = (nDataSize >= SHA256_CHECK_SZ) ? SHA256_CHECK_SZ : nDataSize; 490*23ba6841SJoseph Chen sha256_hash(&ctx, pData + nHasHashSize, nHashSize); 491*23ba6841SJoseph Chen nHasHashSize += nHashSize; 492*23ba6841SJoseph Chen nDataSize -= nHashSize; 493*23ba6841SJoseph Chen } 494*23ba6841SJoseph Chen sha256_end(&ctx, pHash); 495*23ba6841SJoseph Chen } else { 496*23ba6841SJoseph Chen sha256_context ctx; 497*23ba6841SJoseph Chen 498*23ba6841SJoseph Chen sha256_starts(&ctx); 499*23ba6841SJoseph Chen while (nDataSize > 0) { 500*23ba6841SJoseph Chen nHashSize = (nDataSize >= SHA256_CHECK_SZ) ? SHA256_CHECK_SZ : nDataSize; 501*23ba6841SJoseph Chen sha256_update(&ctx, pData + nHasHashSize, nHashSize); 502*23ba6841SJoseph Chen nHasHashSize += nHashSize; 503*23ba6841SJoseph Chen nDataSize -= nHashSize; 504*23ba6841SJoseph Chen } 505*23ba6841SJoseph Chen sha256_finish(&ctx, pHash); 506*23ba6841SJoseph Chen } 507*23ba6841SJoseph Chen return true; 508*23ba6841SJoseph Chen } 509*23ba6841SJoseph Chen 510*23ba6841SJoseph Chen static bool mergetrust(void) 511*23ba6841SJoseph Chen { 512*23ba6841SJoseph Chen FILE *outFile = NULL; 513*23ba6841SJoseph Chen uint32_t OutFileSize; 514*23ba6841SJoseph Chen uint32_t SrcFileNum, SignOffset, nComponentNum; 515*23ba6841SJoseph Chen TRUST_HEADER *pHead = NULL; 516*23ba6841SJoseph Chen COMPONENT_DATA *pComponentData = NULL; 517*23ba6841SJoseph Chen TRUST_COMPONENT *pComponent = NULL; 518*23ba6841SJoseph Chen bool ret = false, bElf; 519*23ba6841SJoseph Chen uint32_t i, n; 520*23ba6841SJoseph Chen uint8_t *outBuf = NULL, *pbuf = NULL, *pMetaBuf = NULL; 521*23ba6841SJoseph Chen bl_entry_t *pEntry = NULL; 522*23ba6841SJoseph Chen if (!initOpts()) 523*23ba6841SJoseph Chen return false; 524*23ba6841SJoseph Chen 525*23ba6841SJoseph Chen if (gDebug) { 526*23ba6841SJoseph Chen printf("---------------\nUSING CONFIG:\n"); 527*23ba6841SJoseph Chen printOpts(stdout); 528*23ba6841SJoseph Chen printf("---------------\n\n"); 529*23ba6841SJoseph Chen } 530*23ba6841SJoseph Chen pMetaBuf = malloc(sizeof(bl_entry_t) * 32); 531*23ba6841SJoseph Chen if (!pMetaBuf) { 532*23ba6841SJoseph Chen LOGE("Merge trust image: malloc buffer error.\n"); 533*23ba6841SJoseph Chen goto end; 534*23ba6841SJoseph Chen } 535*23ba6841SJoseph Chen 536*23ba6841SJoseph Chen nComponentNum = SrcFileNum = 0; 537*23ba6841SJoseph Chen for (i = BL30_SEC; i < BL_MAX_SEC; i++) { 538*23ba6841SJoseph Chen if (gOpts.bl3x[i].sec) { 539*23ba6841SJoseph Chen if (!filter_elf(i, pMetaBuf, &nComponentNum, &bElf)) { 540*23ba6841SJoseph Chen LOGE("filter_elf %s file failed\n", gOpts.bl3x[i].path); 541*23ba6841SJoseph Chen goto end; 542*23ba6841SJoseph Chen } 543*23ba6841SJoseph Chen if (!bElf) { 544*23ba6841SJoseph Chen pEntry = (bl_entry_t *)(pMetaBuf + sizeof(bl_entry_t) * nComponentNum); 545*23ba6841SJoseph Chen pEntry->id = gOpts.bl3x[i].id; 546*23ba6841SJoseph Chen strcpy(pEntry->path, gOpts.bl3x[i].path); 547*23ba6841SJoseph Chen getFileSize(pEntry->path, &pEntry->size); 548*23ba6841SJoseph Chen pEntry->offset = 0; 549*23ba6841SJoseph Chen pEntry->align_size = DO_ALIGN(pEntry->size, ENTRY_ALIGN); 550*23ba6841SJoseph Chen pEntry->addr = gOpts.bl3x[i].addr; 551*23ba6841SJoseph Chen if (pEntry->align_size > BL3X_FILESIZE_MAX) { 552*23ba6841SJoseph Chen LOGE("file %s too large.\n", gOpts.bl3x[i].path); 553*23ba6841SJoseph Chen goto end; 554*23ba6841SJoseph Chen } 555*23ba6841SJoseph Chen LOGD("bl3%d: filesize = %d, imagesize = %d\n", i, pEntry->size, 556*23ba6841SJoseph Chen pEntry->align_size); 557*23ba6841SJoseph Chen pEntry++; 558*23ba6841SJoseph Chen nComponentNum++; 559*23ba6841SJoseph Chen } 560*23ba6841SJoseph Chen 561*23ba6841SJoseph Chen } 562*23ba6841SJoseph Chen } 563*23ba6841SJoseph Chen LOGD("bl3x bin sec = %d\n", nComponentNum); 564*23ba6841SJoseph Chen 565*23ba6841SJoseph Chen /* 2048bytes for head */ 566*23ba6841SJoseph Chen memset(gBuf, 0, TRUST_HEADER_SIZE); 567*23ba6841SJoseph Chen 568*23ba6841SJoseph Chen /* Trust Head */ 569*23ba6841SJoseph Chen pHead = (TRUST_HEADER *)gBuf; 570*23ba6841SJoseph Chen memcpy(&pHead->tag, TRUST_HEAD_TAG, 4); 571*23ba6841SJoseph Chen pHead->version = (getBCD(gOpts.major) << 8) | getBCD(gOpts.minor); 572*23ba6841SJoseph Chen pHead->flags = 0; 573*23ba6841SJoseph Chen pHead->flags |= (gSHAmode << 0); 574*23ba6841SJoseph Chen pHead->flags |= (gRSAmode << 4); 575*23ba6841SJoseph Chen 576*23ba6841SJoseph Chen SignOffset = sizeof(TRUST_HEADER) + nComponentNum * sizeof(COMPONENT_DATA); 577*23ba6841SJoseph Chen LOGD("trust bin sign offset = %d\n", SignOffset); 578*23ba6841SJoseph Chen pHead->size = (nComponentNum << 16) | (SignOffset >> 2); 579*23ba6841SJoseph Chen 580*23ba6841SJoseph Chen pComponent = (TRUST_COMPONENT *)(gBuf + SignOffset + SIGNATURE_SIZE); 581*23ba6841SJoseph Chen pComponentData = (COMPONENT_DATA *)(gBuf + sizeof(TRUST_HEADER)); 582*23ba6841SJoseph Chen 583*23ba6841SJoseph Chen OutFileSize = TRUST_HEADER_SIZE; 584*23ba6841SJoseph Chen pEntry = (bl_entry_t *)pMetaBuf; 585*23ba6841SJoseph Chen for (i = 0; i < nComponentNum; i++) { 586*23ba6841SJoseph Chen /* bl3x load and run address */ 587*23ba6841SJoseph Chen pComponentData->LoadAddr = pEntry->addr; 588*23ba6841SJoseph Chen 589*23ba6841SJoseph Chen pComponent->ComponentID = pEntry->id; 590*23ba6841SJoseph Chen pComponent->StorageAddr = (OutFileSize >> 9); 591*23ba6841SJoseph Chen pComponent->ImageSize = (pEntry->align_size >> 9); 592*23ba6841SJoseph Chen 593*23ba6841SJoseph Chen LOGD("bl3%c: LoadAddr = 0x%08x, StorageAddr = %d, ImageSize = %d\n", 594*23ba6841SJoseph Chen (char)((pEntry->id & 0xFF000000) >> 24), pComponentData->LoadAddr, 595*23ba6841SJoseph Chen pComponent->StorageAddr, pComponent->ImageSize); 596*23ba6841SJoseph Chen 597*23ba6841SJoseph Chen OutFileSize += pEntry->align_size; 598*23ba6841SJoseph Chen pComponentData++; 599*23ba6841SJoseph Chen pComponent++; 600*23ba6841SJoseph Chen pEntry++; 601*23ba6841SJoseph Chen } 602*23ba6841SJoseph Chen 603*23ba6841SJoseph Chen /* create out file */ 604*23ba6841SJoseph Chen outFile = fopen(gOpts.outPath, "wb+"); 605*23ba6841SJoseph Chen if (!outFile) { 606*23ba6841SJoseph Chen LOGE("open out file(%s) failed\n", gOpts.outPath); 607*23ba6841SJoseph Chen 608*23ba6841SJoseph Chen outFile = fopen(DEF_OUT_PATH, "wb"); 609*23ba6841SJoseph Chen if (!outFile) { 610*23ba6841SJoseph Chen LOGE("open default out file:%s failed!\n", DEF_OUT_PATH); 611*23ba6841SJoseph Chen goto end; 612*23ba6841SJoseph Chen } 613*23ba6841SJoseph Chen } 614*23ba6841SJoseph Chen 615*23ba6841SJoseph Chen /* 0 for g_trust_max_num backups */ 616*23ba6841SJoseph Chen #if 0 617*23ba6841SJoseph Chen /* save trust head to out file */ 618*23ba6841SJoseph Chen if (!fwrite(gBuf, TRUST_HEADER_SIZE, 1, outFile)) 619*23ba6841SJoseph Chen goto end; 620*23ba6841SJoseph Chen 621*23ba6841SJoseph Chen /* save trust bl3x bin */ 622*23ba6841SJoseph Chen for (i = BL30_SEC; i < BL_MAX_SEC; i++) { 623*23ba6841SJoseph Chen if (gOpts.bl3x[i].sec) { 624*23ba6841SJoseph Chen FILE *inFile = fopen(gOpts.bl3x[i].path, "rb"); 625*23ba6841SJoseph Chen if (!inFile) 626*23ba6841SJoseph Chen goto end; 627*23ba6841SJoseph Chen 628*23ba6841SJoseph Chen memset(gBuf, 0, imagesize[i]); 629*23ba6841SJoseph Chen if (!fread(gBuf, filesize[i], 1, inFile)) 630*23ba6841SJoseph Chen goto end; 631*23ba6841SJoseph Chen fclose(inFile); 632*23ba6841SJoseph Chen 633*23ba6841SJoseph Chen if (!fwrite(gBuf, imagesize[i], 1, outFile)) 634*23ba6841SJoseph Chen goto end; 635*23ba6841SJoseph Chen } 636*23ba6841SJoseph Chen } 637*23ba6841SJoseph Chen #else 638*23ba6841SJoseph Chen /* check bin size */ 639*23ba6841SJoseph Chen if (OutFileSize > g_trust_max_size) { 640*23ba6841SJoseph Chen LOGE("Merge trust image: trust bin size overfull.\n"); 641*23ba6841SJoseph Chen goto end; 642*23ba6841SJoseph Chen } 643*23ba6841SJoseph Chen 644*23ba6841SJoseph Chen /* malloc buffer */ 645*23ba6841SJoseph Chen pbuf = outBuf = calloc(g_trust_max_size, g_trust_max_num); 646*23ba6841SJoseph Chen if (!outBuf) { 647*23ba6841SJoseph Chen LOGE("Merge trust image: calloc buffer error.\n"); 648*23ba6841SJoseph Chen goto end; 649*23ba6841SJoseph Chen } 650*23ba6841SJoseph Chen memset(outBuf, 0, (g_trust_max_size * g_trust_max_num)); 651*23ba6841SJoseph Chen 652*23ba6841SJoseph Chen /* save trust head data */ 653*23ba6841SJoseph Chen memcpy(pbuf, gBuf, TRUST_HEADER_SIZE); 654*23ba6841SJoseph Chen pbuf += TRUST_HEADER_SIZE; 655*23ba6841SJoseph Chen 656*23ba6841SJoseph Chen uint8_t *pHashData = NULL; 657*23ba6841SJoseph Chen pComponentData = (COMPONENT_DATA *)(outBuf + sizeof(TRUST_HEADER)); 658*23ba6841SJoseph Chen 659*23ba6841SJoseph Chen /* save trust bl3x bin */ 660*23ba6841SJoseph Chen pEntry = (bl_entry_t *)pMetaBuf; 661*23ba6841SJoseph Chen for (i = 0; i < nComponentNum; i++) { 662*23ba6841SJoseph Chen FILE *inFile = fopen(pEntry->path, "rb"); 663*23ba6841SJoseph Chen if (!inFile) 664*23ba6841SJoseph Chen goto end; 665*23ba6841SJoseph Chen 666*23ba6841SJoseph Chen memset(gBuf, 0, pEntry->align_size); 667*23ba6841SJoseph Chen fseek(inFile, pEntry->offset, SEEK_SET); 668*23ba6841SJoseph Chen if (!fread(gBuf, pEntry->size, 1, inFile)) 669*23ba6841SJoseph Chen goto end; 670*23ba6841SJoseph Chen fclose(inFile); 671*23ba6841SJoseph Chen 672*23ba6841SJoseph Chen /* bl3x bin hash256 */ 673*23ba6841SJoseph Chen pHashData = (uint8_t *)&pComponentData->HashData[0]; 674*23ba6841SJoseph Chen bl3xHash256(pHashData, gBuf, pEntry->align_size); 675*23ba6841SJoseph Chen memcpy(pbuf, gBuf, pEntry->align_size); 676*23ba6841SJoseph Chen 677*23ba6841SJoseph Chen pComponentData++; 678*23ba6841SJoseph Chen pbuf += pEntry->align_size; 679*23ba6841SJoseph Chen pEntry++; 680*23ba6841SJoseph Chen } 681*23ba6841SJoseph Chen 682*23ba6841SJoseph Chen /* copy other (g_trust_max_num - 1) backup bin */ 683*23ba6841SJoseph Chen for (n = 1; n < g_trust_max_num; n++) { 684*23ba6841SJoseph Chen memcpy(outBuf + g_trust_max_size * n, outBuf, g_trust_max_size); 685*23ba6841SJoseph Chen } 686*23ba6841SJoseph Chen 687*23ba6841SJoseph Chen /* save date to file */ 688*23ba6841SJoseph Chen if (!fwrite(outBuf, g_trust_max_size * g_trust_max_num, 1, outFile)) { 689*23ba6841SJoseph Chen LOGE("Merge trust image: write file error.\n"); 690*23ba6841SJoseph Chen goto end; 691*23ba6841SJoseph Chen } 692*23ba6841SJoseph Chen #endif 693*23ba6841SJoseph Chen 694*23ba6841SJoseph Chen ret = true; 695*23ba6841SJoseph Chen 696*23ba6841SJoseph Chen end: 697*23ba6841SJoseph Chen /* 698*23ba6841SJoseph Chen for (i = BL30_SEC; i < BL_MAX_SEC; i++) { 699*23ba6841SJoseph Chen if (gOpts.bl3x[i].sec != false) { 700*23ba6841SJoseph Chen if (gOpts.bl3x[i].is_elf) { 701*23ba6841SJoseph Chen if (stat(gOpts.bl3x[i].path, &st) >= 0) 702*23ba6841SJoseph Chen remove(gOpts.bl3x[i].path); 703*23ba6841SJoseph Chen } 704*23ba6841SJoseph Chen } 705*23ba6841SJoseph Chen } 706*23ba6841SJoseph Chen */ 707*23ba6841SJoseph Chen if (pMetaBuf) 708*23ba6841SJoseph Chen free(pMetaBuf); 709*23ba6841SJoseph Chen if (outBuf) 710*23ba6841SJoseph Chen free(outBuf); 711*23ba6841SJoseph Chen if (outFile) 712*23ba6841SJoseph Chen fclose(outFile); 713*23ba6841SJoseph Chen return ret; 714*23ba6841SJoseph Chen } 715*23ba6841SJoseph Chen 716*23ba6841SJoseph Chen static int saveDatatoFile(char *FileName, void *pBuf, uint32_t size) 717*23ba6841SJoseph Chen { 718*23ba6841SJoseph Chen FILE *OutFile = NULL; 719*23ba6841SJoseph Chen int ret = -1; 720*23ba6841SJoseph Chen 721*23ba6841SJoseph Chen OutFile = fopen(FileName, "wb"); 722*23ba6841SJoseph Chen if (!OutFile) { 723*23ba6841SJoseph Chen printf("open OutPutFlie:%s failed!\n", FileName); 724*23ba6841SJoseph Chen goto end; 725*23ba6841SJoseph Chen } 726*23ba6841SJoseph Chen if (1 != fwrite(pBuf, size, 1, OutFile)) { 727*23ba6841SJoseph Chen printf("write output file failed!\n"); 728*23ba6841SJoseph Chen goto end; 729*23ba6841SJoseph Chen } 730*23ba6841SJoseph Chen 731*23ba6841SJoseph Chen ret = 0; 732*23ba6841SJoseph Chen end: 733*23ba6841SJoseph Chen if (OutFile) 734*23ba6841SJoseph Chen fclose(OutFile); 735*23ba6841SJoseph Chen 736*23ba6841SJoseph Chen return ret; 737*23ba6841SJoseph Chen } 738*23ba6841SJoseph Chen 739*23ba6841SJoseph Chen static bool unpacktrust(char *path) 740*23ba6841SJoseph Chen { 741*23ba6841SJoseph Chen FILE *FileSrc = NULL; 742*23ba6841SJoseph Chen uint32_t FileSize; 743*23ba6841SJoseph Chen uint8_t *pBuf = NULL; 744*23ba6841SJoseph Chen uint32_t SrcFileNum, SignOffset; 745*23ba6841SJoseph Chen TRUST_HEADER *pHead = NULL; 746*23ba6841SJoseph Chen COMPONENT_DATA *pComponentData = NULL; 747*23ba6841SJoseph Chen TRUST_COMPONENT *pComponent = NULL; 748*23ba6841SJoseph Chen char str[MAX_LINE_LEN]; 749*23ba6841SJoseph Chen bool ret = false; 750*23ba6841SJoseph Chen uint32_t i; 751*23ba6841SJoseph Chen 752*23ba6841SJoseph Chen FileSrc = fopen(path, "rb"); 753*23ba6841SJoseph Chen if (FileSrc == NULL) { 754*23ba6841SJoseph Chen printf("open %s failed!\n", path); 755*23ba6841SJoseph Chen goto end; 756*23ba6841SJoseph Chen } 757*23ba6841SJoseph Chen 758*23ba6841SJoseph Chen if (getFileSize(path, &FileSize) == false) { 759*23ba6841SJoseph Chen printf("File Size failed!\n"); 760*23ba6841SJoseph Chen goto end; 761*23ba6841SJoseph Chen } 762*23ba6841SJoseph Chen printf("File Size = %d\n", FileSize); 763*23ba6841SJoseph Chen 764*23ba6841SJoseph Chen pBuf = (uint8_t *)malloc(FileSize); 765*23ba6841SJoseph Chen if (1 != fread(pBuf, FileSize, 1, FileSrc)) { 766*23ba6841SJoseph Chen printf("read input file failed!\n"); 767*23ba6841SJoseph Chen goto end; 768*23ba6841SJoseph Chen } 769*23ba6841SJoseph Chen 770*23ba6841SJoseph Chen pHead = (TRUST_HEADER *)pBuf; 771*23ba6841SJoseph Chen 772*23ba6841SJoseph Chen memcpy(str, &pHead->tag, 4); 773*23ba6841SJoseph Chen str[4] = '\0'; 774*23ba6841SJoseph Chen printf("Header Tag:%s\n", str); 775*23ba6841SJoseph Chen printf("Header version:%d\n", pHead->version); 776*23ba6841SJoseph Chen printf("Header flag:%d\n", pHead->flags); 777*23ba6841SJoseph Chen 778*23ba6841SJoseph Chen SrcFileNum = (pHead->size >> 16) & 0xffff; 779*23ba6841SJoseph Chen SignOffset = (pHead->size & 0xffff) << 2; 780*23ba6841SJoseph Chen printf("SrcFileNum:%d\n", SrcFileNum); 781*23ba6841SJoseph Chen printf("SignOffset:%d\n", SignOffset); 782*23ba6841SJoseph Chen 783*23ba6841SJoseph Chen pComponent = (TRUST_COMPONENT *)(pBuf + SignOffset + SIGNATURE_SIZE); 784*23ba6841SJoseph Chen pComponentData = (COMPONENT_DATA *)(pBuf + sizeof(TRUST_HEADER)); 785*23ba6841SJoseph Chen 786*23ba6841SJoseph Chen for (i = 0; i < SrcFileNum; i++) { 787*23ba6841SJoseph Chen printf("Component %d:\n", i); 788*23ba6841SJoseph Chen 789*23ba6841SJoseph Chen memcpy(str, &pComponent->ComponentID, 4); 790*23ba6841SJoseph Chen str[4] = '\0'; 791*23ba6841SJoseph Chen printf("ComponentID:%s\n", str); 792*23ba6841SJoseph Chen printf("StorageAddr:0x%x\n", pComponent->StorageAddr); 793*23ba6841SJoseph Chen printf("ImageSize:0x%x\n", pComponent->ImageSize); 794*23ba6841SJoseph Chen printf("LoadAddr:0x%x\n", pComponentData->LoadAddr); 795*23ba6841SJoseph Chen 796*23ba6841SJoseph Chen saveDatatoFile(str, pBuf + (pComponent->StorageAddr << 9), 797*23ba6841SJoseph Chen pComponent->ImageSize << 9); 798*23ba6841SJoseph Chen 799*23ba6841SJoseph Chen pComponentData++; 800*23ba6841SJoseph Chen pComponent++; 801*23ba6841SJoseph Chen } 802*23ba6841SJoseph Chen 803*23ba6841SJoseph Chen ret = true; 804*23ba6841SJoseph Chen end: 805*23ba6841SJoseph Chen if (FileSrc) 806*23ba6841SJoseph Chen fclose(FileSrc); 807*23ba6841SJoseph Chen if (pBuf) 808*23ba6841SJoseph Chen free(pBuf); 809*23ba6841SJoseph Chen 810*23ba6841SJoseph Chen return ret; 811*23ba6841SJoseph Chen } 812*23ba6841SJoseph Chen 813*23ba6841SJoseph Chen static void printHelp(void) 814*23ba6841SJoseph Chen { 815*23ba6841SJoseph Chen printf("Usage: trust_merger [options]... FILE\n"); 816*23ba6841SJoseph Chen printf( 817*23ba6841SJoseph Chen "Merge or unpack Rockchip's trust image (Default action is to merge.)\n"); 818*23ba6841SJoseph Chen printf("Options:\n"); 819*23ba6841SJoseph Chen printf("\t" OPT_MERGE "\t\t\tMerge trust with specified config.\n"); 820*23ba6841SJoseph Chen printf("\t" OPT_UNPACK "\t\tUnpack specified trust to current dir.\n"); 821*23ba6841SJoseph Chen printf("\t" OPT_VERBOSE "\t\tDisplay more runtime informations.\n"); 822*23ba6841SJoseph Chen printf("\t" OPT_HELP "\t\t\tDisplay this information.\n"); 823*23ba6841SJoseph Chen printf("\t" OPT_VERSION "\t\tDisplay version information.\n"); 824*23ba6841SJoseph Chen printf("\t" OPT_SUBFIX "\t\tSpec subfix.\n"); 825*23ba6841SJoseph Chen printf("\t" OPT_REPLACE "\t\tReplace some part of binary path.\n"); 826*23ba6841SJoseph Chen printf("\t" OPT_RSA "\t\t\tRSA mode.\"--rsa [mode]\", [mode] can be: " 827*23ba6841SJoseph Chen "0(none), 1(1024), 2(2048), 3(2048 pss).\n"); 828*23ba6841SJoseph Chen printf("\t" OPT_SHA 829*23ba6841SJoseph Chen "\t\t\tSHA mode.\"--sha [mode]\", [mode] can be: 0(none), 1(160), " 830*23ba6841SJoseph Chen "2(256 RK big endian), 3(256 little endian).\n"); 831*23ba6841SJoseph Chen printf("\t" OPT_SIZE "\t\t\tTrustImage size.\"--size [per image KB size] " 832*23ba6841SJoseph Chen "[copy count]\", per image must be 64KB aligned\n"); 833*23ba6841SJoseph Chen } 834*23ba6841SJoseph Chen 835*23ba6841SJoseph Chen int main(int argc, char **argv) 836*23ba6841SJoseph Chen { 837*23ba6841SJoseph Chen bool merge = true; 838*23ba6841SJoseph Chen char *optPath = NULL; 839*23ba6841SJoseph Chen int i; 840*23ba6841SJoseph Chen 841*23ba6841SJoseph Chen gConfigPath = NULL; 842*23ba6841SJoseph Chen for (i = 1; i < argc; i++) { 843*23ba6841SJoseph Chen if (!strcmp(OPT_VERBOSE, argv[i])) { 844*23ba6841SJoseph Chen gDebug = true; 845*23ba6841SJoseph Chen } else if (!strcmp(OPT_HELP, argv[i])) { 846*23ba6841SJoseph Chen printHelp(); 847*23ba6841SJoseph Chen return 0; 848*23ba6841SJoseph Chen } else if (!strcmp(OPT_VERSION, argv[i])) { 849*23ba6841SJoseph Chen printf("trust_merger (cwz@rock-chips.com)\t" VERSION "\n"); 850*23ba6841SJoseph Chen return 0; 851*23ba6841SJoseph Chen } else if (!strcmp(OPT_MERGE, argv[i])) { 852*23ba6841SJoseph Chen merge = true; 853*23ba6841SJoseph Chen } else if (!strcmp(OPT_UNPACK, argv[i])) { 854*23ba6841SJoseph Chen merge = false; 855*23ba6841SJoseph Chen } else if (!strcmp(OPT_SUBFIX, argv[i])) { 856*23ba6841SJoseph Chen gSubfix = true; 857*23ba6841SJoseph Chen printf("trust_merger: Spec subfix!\n"); 858*23ba6841SJoseph Chen } else if (!strcmp(OPT_REPLACE, argv[i])) { 859*23ba6841SJoseph Chen i++; 860*23ba6841SJoseph Chen gLegacyPath = argv[i]; 861*23ba6841SJoseph Chen i++; 862*23ba6841SJoseph Chen gNewPath = argv[i]; 863*23ba6841SJoseph Chen } else if (!strcmp(OPT_RSA, argv[i])) { 864*23ba6841SJoseph Chen i++; 865*23ba6841SJoseph Chen if (!is_digit(*(argv[i]))) { 866*23ba6841SJoseph Chen printHelp(); 867*23ba6841SJoseph Chen return -1; 868*23ba6841SJoseph Chen } 869*23ba6841SJoseph Chen gRSAmode = *(argv[i]) - '0'; 870*23ba6841SJoseph Chen LOGD("rsa mode:%d\n", gRSAmode); 871*23ba6841SJoseph Chen } else if (!strcmp(OPT_SHA, argv[i])) { 872*23ba6841SJoseph Chen i++; 873*23ba6841SJoseph Chen if (!is_digit(*(argv[i]))) { 874*23ba6841SJoseph Chen printHelp(); 875*23ba6841SJoseph Chen return -1; 876*23ba6841SJoseph Chen } 877*23ba6841SJoseph Chen gSHAmode = *(argv[i]) - '0'; 878*23ba6841SJoseph Chen LOGD("sha mode:%d\n", gSHAmode); 879*23ba6841SJoseph Chen } else if (!strcmp(OPT_SIZE, argv[i])) { 880*23ba6841SJoseph Chen /* Per trust image size */ 881*23ba6841SJoseph Chen g_trust_max_size = strtoul(argv[++i], NULL, 10); 882*23ba6841SJoseph Chen /* 883*23ba6841SJoseph Chen * Usually, it must be at 512kb align due to preloader 884*23ba6841SJoseph Chen * detects every 512kb. But some product has critial 885*23ba6841SJoseph Chen * flash size requirement, we have to make it small than 886*23ba6841SJoseph Chen * 512KB. 887*23ba6841SJoseph Chen */ 888*23ba6841SJoseph Chen if (g_trust_max_size % 64) { 889*23ba6841SJoseph Chen printHelp(); 890*23ba6841SJoseph Chen return -1; 891*23ba6841SJoseph Chen } 892*23ba6841SJoseph Chen g_trust_max_size *= 1024; /* bytes */ 893*23ba6841SJoseph Chen 894*23ba6841SJoseph Chen /* Total backup numbers */ 895*23ba6841SJoseph Chen g_trust_max_num = strtoul(argv[++i], NULL, 10); 896*23ba6841SJoseph Chen } else { 897*23ba6841SJoseph Chen if (optPath) { 898*23ba6841SJoseph Chen fprintf(stderr, "only need one path arg, but we have:\n%s\n%s.\n", 899*23ba6841SJoseph Chen optPath, argv[i]); 900*23ba6841SJoseph Chen printHelp(); 901*23ba6841SJoseph Chen return -1; 902*23ba6841SJoseph Chen } 903*23ba6841SJoseph Chen optPath = argv[i]; 904*23ba6841SJoseph Chen } 905*23ba6841SJoseph Chen } 906*23ba6841SJoseph Chen if (!merge && !optPath) { 907*23ba6841SJoseph Chen fprintf(stderr, "need set out path to unpack!\n"); 908*23ba6841SJoseph Chen printHelp(); 909*23ba6841SJoseph Chen return -1; 910*23ba6841SJoseph Chen } 911*23ba6841SJoseph Chen 912*23ba6841SJoseph Chen if (merge) { 913*23ba6841SJoseph Chen LOGD("do_merge\n"); 914*23ba6841SJoseph Chen gConfigPath = optPath; 915*23ba6841SJoseph Chen if (!mergetrust()) { 916*23ba6841SJoseph Chen fprintf(stderr, "merge failed!\n"); 917*23ba6841SJoseph Chen return -1; 918*23ba6841SJoseph Chen } 919*23ba6841SJoseph Chen printf("merge success(%s)\n", gOpts.outPath); 920*23ba6841SJoseph Chen } else { 921*23ba6841SJoseph Chen LOGD("do_unpack\n"); 922*23ba6841SJoseph Chen if (!unpacktrust(optPath)) { 923*23ba6841SJoseph Chen fprintf(stderr, "unpack failed!\n"); 924*23ba6841SJoseph Chen return -1; 925*23ba6841SJoseph Chen } 926*23ba6841SJoseph Chen printf("unpack success\n"); 927*23ba6841SJoseph Chen } 928*23ba6841SJoseph Chen 929*23ba6841SJoseph Chen return 0; 930*23ba6841SJoseph Chen } 931