123ba6841SJoseph Chen /* 223ba6841SJoseph Chen * Rockchip trust image generator 323ba6841SJoseph Chen * 423ba6841SJoseph Chen * (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd 523ba6841SJoseph Chen * Peter, Software Engineering, <superpeter.cai@gmail.com>. 623ba6841SJoseph Chen * 723ba6841SJoseph Chen * SPDX-License-Identifier: GPL-2.0+ 823ba6841SJoseph Chen */ 923ba6841SJoseph Chen #include <sys/stat.h> 1023ba6841SJoseph Chen #include <u-boot/sha256.h> 1123ba6841SJoseph Chen #include "trust_merger.h" 1223ba6841SJoseph Chen #include "sha2.h" 1323ba6841SJoseph Chen 1423ba6841SJoseph Chen /* #define DEBUG */ 1523ba6841SJoseph Chen 1623ba6841SJoseph Chen static bool gDebug = 1723ba6841SJoseph Chen #ifdef DEBUG 1823ba6841SJoseph Chen true; 1923ba6841SJoseph Chen #else 2023ba6841SJoseph Chen false; 2123ba6841SJoseph Chen #endif /* DEBUG */ 2223ba6841SJoseph Chen 2323ba6841SJoseph Chen #define LOGE(fmt, args...) fprintf(stderr, "E: [%s] " fmt, __func__, ##args) 2423ba6841SJoseph Chen #define LOGD(fmt, args...) \ 2523ba6841SJoseph Chen do { \ 2623ba6841SJoseph Chen if (gDebug) \ 2723ba6841SJoseph Chen fprintf(stderr, "D: [%s] " fmt, __func__, ##args); \ 2823ba6841SJoseph Chen } while (0) 2923ba6841SJoseph Chen 3023ba6841SJoseph Chen /* trust image has g_trust_max_num backups */ 3123ba6841SJoseph Chen static uint32_t g_trust_max_num = 2; 3223ba6841SJoseph Chen static uint32_t g_trust_max_size = 2 * 1024 * 1024; 3323ba6841SJoseph Chen 3423ba6841SJoseph Chen /* config sha and rsa */ 3523ba6841SJoseph Chen #define SHA_SEL_256 3 /* little endian */ 3623ba6841SJoseph Chen #define SHA_SEL_256_RK 2 /* big endian: only rk3368 need it */ 3723ba6841SJoseph Chen #define SHA_SEL_160 1 3823ba6841SJoseph Chen #define SHA_SEL_NONE 0 3923ba6841SJoseph Chen 4023ba6841SJoseph Chen #define RSA_SEL_2048_PSS 3 /* only RK3326, PX30, RK3308 */ 4123ba6841SJoseph Chen #define RSA_SEL_2048 2 /* most platforms except above PSS */ 4223ba6841SJoseph Chen #define RSA_SEL_1024 1 4323ba6841SJoseph Chen #define RSA_SEL_NONE 0 4423ba6841SJoseph Chen 4523ba6841SJoseph Chen #define is_digit(c) ((c) >= '0' && (c) <= '9') 4623ba6841SJoseph Chen 4723ba6841SJoseph Chen static char *gConfigPath; 4823ba6841SJoseph Chen static OPT_T gOpts; 4923ba6841SJoseph Chen #define BL3X_FILESIZE_MAX (512 * 1024) 5023ba6841SJoseph Chen static uint8_t gBuf[BL3X_FILESIZE_MAX]; 5123ba6841SJoseph Chen static bool gSubfix; 5223ba6841SJoseph Chen static char *gLegacyPath; 5323ba6841SJoseph Chen static char *gNewPath; 54*e311da24SJoseph Chen static char *gPrePath; 5523ba6841SJoseph Chen static uint8_t gRSAmode = RSA_SEL_2048; 5623ba6841SJoseph Chen static uint8_t gSHAmode = SHA_SEL_256; 5775828958SJoseph Chen static bool gIgnoreBL32; 5823ba6841SJoseph Chen 5923ba6841SJoseph Chen const uint8_t gBl3xID[BL_MAX_SEC][4] = { { 'B', 'L', '3', '0' }, 6023ba6841SJoseph Chen { 'B', 'L', '3', '1' }, 6123ba6841SJoseph Chen { 'B', 'L', '3', '2' }, 6223ba6841SJoseph Chen { 'B', 'L', '3', '3' } 6323ba6841SJoseph Chen }; 6423ba6841SJoseph Chen 6523ba6841SJoseph Chen static inline uint32_t getBCD(uint16_t value) 6623ba6841SJoseph Chen { 6723ba6841SJoseph Chen uint8_t tmp[2] = { 0 }; 6823ba6841SJoseph Chen int i; 6923ba6841SJoseph Chen uint32_t ret; 7023ba6841SJoseph Chen 7123ba6841SJoseph Chen if (value > 0xFFFF) { 7223ba6841SJoseph Chen return 0; 7323ba6841SJoseph Chen } 7423ba6841SJoseph Chen 7523ba6841SJoseph Chen for (i = 0; i < 2; i++) { 7623ba6841SJoseph Chen tmp[i] = (((value / 10) % 10) << 4) | (value % 10); 7723ba6841SJoseph Chen value /= 100; 7823ba6841SJoseph Chen } 7923ba6841SJoseph Chen ret = ((uint16_t)(tmp[1] << 8)) | tmp[0]; 8023ba6841SJoseph Chen 8123ba6841SJoseph Chen LOGD("ret:%x\n", ret); 8223ba6841SJoseph Chen return ret & 0xFF; 8323ba6841SJoseph Chen } 8423ba6841SJoseph Chen 8523ba6841SJoseph Chen static inline void fixPath(char *path) 8623ba6841SJoseph Chen { 8723ba6841SJoseph Chen int i, len = strlen(path); 8823ba6841SJoseph Chen char tmp[MAX_LINE_LEN]; 8923ba6841SJoseph Chen char *start, *end; 9023ba6841SJoseph Chen 9123ba6841SJoseph Chen for (i = 0; i < len; i++) { 9223ba6841SJoseph Chen if (path[i] == '\\') 9323ba6841SJoseph Chen path[i] = '/'; 9423ba6841SJoseph Chen else if (path[i] == '\r' || path[i] == '\n') 9523ba6841SJoseph Chen path[i] = '\0'; 9623ba6841SJoseph Chen } 9723ba6841SJoseph Chen 9823ba6841SJoseph Chen if (gLegacyPath && gNewPath) { 9923ba6841SJoseph Chen start = strstr(path, gLegacyPath); 10023ba6841SJoseph Chen if (start) { 10123ba6841SJoseph Chen end = start + strlen(gLegacyPath); 10223ba6841SJoseph Chen /* Backup, so tmp can be src for strcat() */ 10323ba6841SJoseph Chen strcpy(tmp, end); 10423ba6841SJoseph Chen /* Terminate, so path can be dest for strcat() */ 10523ba6841SJoseph Chen *start = '\0'; 10645c2a034SJoseph Chen strcat(path, gNewPath); 10723ba6841SJoseph Chen strcat(path, tmp); 1089ad3008aSJoseph Chen } else { 1099ad3008aSJoseph Chen strcpy(tmp, path); 1109ad3008aSJoseph Chen strcpy(path, gNewPath); 1119ad3008aSJoseph Chen strcat(path, tmp); 11223ba6841SJoseph Chen } 113*e311da24SJoseph Chen } else if (gPrePath) { 114*e311da24SJoseph Chen strcpy(tmp, path); 115*e311da24SJoseph Chen strcpy(path, gPrePath); 116*e311da24SJoseph Chen strcat(path, tmp); 11723ba6841SJoseph Chen } 11823ba6841SJoseph Chen } 11923ba6841SJoseph Chen 12023ba6841SJoseph Chen static bool parseVersion(FILE *file) 12123ba6841SJoseph Chen { 12223ba6841SJoseph Chen int d = 0; 12323ba6841SJoseph Chen 12423ba6841SJoseph Chen if (SCANF_EAT(file) != 0) { 12523ba6841SJoseph Chen return false; 12623ba6841SJoseph Chen } 12723ba6841SJoseph Chen if (fscanf(file, OPT_MAJOR "=%d", &d) != 1) 12823ba6841SJoseph Chen return false; 12923ba6841SJoseph Chen gOpts.major = (uint16_t) d; 13023ba6841SJoseph Chen if (SCANF_EAT(file) != 0) { 13123ba6841SJoseph Chen return false; 13223ba6841SJoseph Chen } 13323ba6841SJoseph Chen if (fscanf(file, OPT_MINOR "=%d", &d) != 1) 13423ba6841SJoseph Chen return false; 13523ba6841SJoseph Chen gOpts.minor = (uint16_t) d; 13623ba6841SJoseph Chen LOGD("major:%d, minor:%d\n", gOpts.major, gOpts.minor); 13723ba6841SJoseph Chen return true; 13823ba6841SJoseph Chen } 13923ba6841SJoseph Chen 14023ba6841SJoseph Chen static bool parseBL3x(FILE *file, int bl3x_id) 14123ba6841SJoseph Chen { 14223ba6841SJoseph Chen int pos; 14323ba6841SJoseph Chen int sec; 14423ba6841SJoseph Chen char buf[MAX_LINE_LEN]; 14523ba6841SJoseph Chen bl_entry_t *pbl3x = NULL; 14623ba6841SJoseph Chen 14723ba6841SJoseph Chen if (bl3x_id >= BL_MAX_SEC) { 14823ba6841SJoseph Chen return false; 14923ba6841SJoseph Chen } 15023ba6841SJoseph Chen 15123ba6841SJoseph Chen pbl3x = &gOpts.bl3x[bl3x_id]; 15223ba6841SJoseph Chen 15323ba6841SJoseph Chen /* SEC */ 15423ba6841SJoseph Chen if (SCANF_EAT(file) != 0) { 15523ba6841SJoseph Chen return false; 15623ba6841SJoseph Chen } 15723ba6841SJoseph Chen if (fscanf(file, OPT_SEC "=%d", &sec) != 1) { 15823ba6841SJoseph Chen return false; 15923ba6841SJoseph Chen } 16023ba6841SJoseph Chen if ((gSubfix) && (bl3x_id == BL32_SEC)) { 16123ba6841SJoseph Chen if (sec == 0) { 16223ba6841SJoseph Chen sec = 1; 16323ba6841SJoseph Chen printf("BL3%d adjust sec from 0 to 1\n", bl3x_id); 16423ba6841SJoseph Chen } 16575828958SJoseph Chen } else if (gIgnoreBL32 && (bl3x_id == BL32_SEC)) { 16675828958SJoseph Chen if (sec == 1) { 16775828958SJoseph Chen sec = 0; 16875828958SJoseph Chen printf("BL3%d adjust sec from 1 to 0\n", bl3x_id); 16975828958SJoseph Chen } 17023ba6841SJoseph Chen } 17123ba6841SJoseph Chen pbl3x->sec = sec; 17223ba6841SJoseph Chen LOGD("bl3%d sec: %d\n", bl3x_id, pbl3x->sec); 17323ba6841SJoseph Chen 17423ba6841SJoseph Chen /* PATH */ 17523ba6841SJoseph Chen if (SCANF_EAT(file) != 0) { 17623ba6841SJoseph Chen return false; 17723ba6841SJoseph Chen } 17823ba6841SJoseph Chen memset(buf, 0, MAX_LINE_LEN); 17923ba6841SJoseph Chen if (fscanf(file, OPT_PATH "=%s", buf) != 1) { 18023ba6841SJoseph Chen if (pbl3x->sec) 18123ba6841SJoseph Chen return false; 18223ba6841SJoseph Chen } else { 18323ba6841SJoseph Chen if (strlen(buf) != 0) { 18423ba6841SJoseph Chen fixPath(buf); 18523ba6841SJoseph Chen strcpy(pbl3x->path, buf); 18623ba6841SJoseph Chen LOGD("bl3%d path:%s\n", bl3x_id, pbl3x->path); 18723ba6841SJoseph Chen } 18823ba6841SJoseph Chen } 18923ba6841SJoseph Chen 19023ba6841SJoseph Chen /* ADDR */ 19123ba6841SJoseph Chen if (SCANF_EAT(file) != 0) { 19223ba6841SJoseph Chen return false; 19323ba6841SJoseph Chen } 19423ba6841SJoseph Chen memset(buf, 0, MAX_LINE_LEN); 19523ba6841SJoseph Chen if (fscanf(file, OPT_ADDR "=%s", buf) != 1) { 19623ba6841SJoseph Chen if (pbl3x->sec) 19723ba6841SJoseph Chen return false; 19823ba6841SJoseph Chen } else { 19923ba6841SJoseph Chen if (strlen(buf) != 0) { 20023ba6841SJoseph Chen pbl3x->addr = strtoul(buf, NULL, 16); 20123ba6841SJoseph Chen LOGD("bl3%d addr:0x%x\n", bl3x_id, pbl3x->addr); 20223ba6841SJoseph Chen } 20323ba6841SJoseph Chen } 20423ba6841SJoseph Chen 20523ba6841SJoseph Chen pos = ftell(file); 20623ba6841SJoseph Chen if (pos < 0) { 20723ba6841SJoseph Chen return false; 20823ba6841SJoseph Chen } 20923ba6841SJoseph Chen if (SCANF_EAT(file) != 0) { 21023ba6841SJoseph Chen return false; 21123ba6841SJoseph Chen } 21223ba6841SJoseph Chen 21323ba6841SJoseph Chen return true; 21423ba6841SJoseph Chen } 21523ba6841SJoseph Chen 21623ba6841SJoseph Chen static bool parseOut(FILE *file) 21723ba6841SJoseph Chen { 21823ba6841SJoseph Chen if (SCANF_EAT(file) != 0) { 21923ba6841SJoseph Chen return false; 22023ba6841SJoseph Chen } 22123ba6841SJoseph Chen if (fscanf(file, OPT_OUT_PATH "=%[^\r^\n]", gOpts.outPath) != 1) 22223ba6841SJoseph Chen return false; 22323ba6841SJoseph Chen printf("out:%s\n", gOpts.outPath); 22423ba6841SJoseph Chen 22523ba6841SJoseph Chen return true; 22623ba6841SJoseph Chen } 22723ba6841SJoseph Chen 22823ba6841SJoseph Chen void printOpts(FILE *out) 22923ba6841SJoseph Chen { 23023ba6841SJoseph Chen fprintf(out, SEC_BL30 "\n" OPT_SEC "=%d\n", gOpts.bl3x[BL30_SEC].sec); 23123ba6841SJoseph Chen if (gOpts.bl3x[BL30_SEC].sec) { 23223ba6841SJoseph Chen fprintf(out, OPT_PATH "=%s\n", gOpts.bl3x[BL30_SEC].path); 23323ba6841SJoseph Chen fprintf(out, OPT_ADDR "=0x%08x\n", gOpts.bl3x[BL30_SEC].addr); 23423ba6841SJoseph Chen } 23523ba6841SJoseph Chen 23623ba6841SJoseph Chen fprintf(out, SEC_BL31 "\n" OPT_SEC "=%d\n", gOpts.bl3x[BL31_SEC].sec); 23723ba6841SJoseph Chen if (gOpts.bl3x[BL31_SEC].sec) { 23823ba6841SJoseph Chen fprintf(out, OPT_PATH "=%s\n", gOpts.bl3x[BL31_SEC].path); 23923ba6841SJoseph Chen fprintf(out, OPT_ADDR "=0x%08x\n", gOpts.bl3x[BL31_SEC].addr); 24023ba6841SJoseph Chen } 24123ba6841SJoseph Chen 24223ba6841SJoseph Chen fprintf(out, SEC_BL32 "\n" OPT_SEC "=%d\n", gOpts.bl3x[BL32_SEC].sec); 24323ba6841SJoseph Chen if (gOpts.bl3x[BL32_SEC].sec) { 24423ba6841SJoseph Chen fprintf(out, OPT_PATH "=%s\n", gOpts.bl3x[BL32_SEC].path); 24523ba6841SJoseph Chen fprintf(out, OPT_ADDR "=0x%08x\n", gOpts.bl3x[BL32_SEC].addr); 24623ba6841SJoseph Chen } 24723ba6841SJoseph Chen 24823ba6841SJoseph Chen fprintf(out, SEC_BL33 "\n" OPT_SEC "=%d\n", gOpts.bl3x[BL33_SEC].sec); 24923ba6841SJoseph Chen if (gOpts.bl3x[BL33_SEC].sec) { 25023ba6841SJoseph Chen fprintf(out, OPT_PATH "=%s\n", gOpts.bl3x[BL33_SEC].path); 25123ba6841SJoseph Chen fprintf(out, OPT_ADDR "=0x%08x\n", gOpts.bl3x[BL33_SEC].addr); 25223ba6841SJoseph Chen } 25323ba6841SJoseph Chen 25423ba6841SJoseph Chen fprintf(out, SEC_OUT "\n" OPT_OUT_PATH "=%s\n", gOpts.outPath); 25523ba6841SJoseph Chen } 25623ba6841SJoseph Chen 25723ba6841SJoseph Chen static bool parseOpts(void) 25823ba6841SJoseph Chen { 25923ba6841SJoseph Chen FILE *file = NULL; 26023ba6841SJoseph Chen char *configPath = (gConfigPath == NULL) ? DEF_CONFIG_FILE : gConfigPath; 26123ba6841SJoseph Chen bool bl30ok = false, bl31ok = false, bl32ok = false, bl33ok = false; 26223ba6841SJoseph Chen bool outOk = false; 26323ba6841SJoseph Chen bool versionOk = false; 26423ba6841SJoseph Chen char buf[MAX_LINE_LEN]; 26523ba6841SJoseph Chen bool ret = false; 26623ba6841SJoseph Chen 26723ba6841SJoseph Chen file = fopen(configPath, "r"); 26823ba6841SJoseph Chen if (!file) { 26923ba6841SJoseph Chen fprintf(stderr, "config(%s) not found!\n", configPath); 27023ba6841SJoseph Chen if (configPath == (char *)DEF_CONFIG_FILE) { 27123ba6841SJoseph Chen file = fopen(DEF_CONFIG_FILE, "w"); 27223ba6841SJoseph Chen if (file) { 27323ba6841SJoseph Chen fprintf(stderr, "create defconfig\n"); 27423ba6841SJoseph Chen printOpts(file); 27523ba6841SJoseph Chen } 27623ba6841SJoseph Chen } 27723ba6841SJoseph Chen goto end; 27823ba6841SJoseph Chen } 27923ba6841SJoseph Chen 28023ba6841SJoseph Chen LOGD("start parse\n"); 28123ba6841SJoseph Chen 28223ba6841SJoseph Chen if (SCANF_EAT(file) != 0) { 28323ba6841SJoseph Chen goto end; 28423ba6841SJoseph Chen } 28523ba6841SJoseph Chen while (fscanf(file, "%s", buf) == 1) { 28623ba6841SJoseph Chen if (!strcmp(buf, SEC_VERSION)) { 28723ba6841SJoseph Chen versionOk = parseVersion(file); 28823ba6841SJoseph Chen if (!versionOk) { 28923ba6841SJoseph Chen LOGE("parseVersion failed!\n"); 29023ba6841SJoseph Chen goto end; 29123ba6841SJoseph Chen } 29223ba6841SJoseph Chen } else if (!strcmp(buf, SEC_BL30)) { 29323ba6841SJoseph Chen bl30ok = parseBL3x(file, BL30_SEC); 29423ba6841SJoseph Chen if (!bl30ok) { 29523ba6841SJoseph Chen LOGE("parseBL30 failed!\n"); 29623ba6841SJoseph Chen goto end; 29723ba6841SJoseph Chen } 29823ba6841SJoseph Chen } else if (!strcmp(buf, SEC_BL31)) { 29923ba6841SJoseph Chen bl31ok = parseBL3x(file, BL31_SEC); 30023ba6841SJoseph Chen if (!bl31ok) { 30123ba6841SJoseph Chen LOGE("parseBL31 failed!\n"); 30223ba6841SJoseph Chen goto end; 30323ba6841SJoseph Chen } 30423ba6841SJoseph Chen } else if (!strcmp(buf, SEC_BL32)) { 30523ba6841SJoseph Chen bl32ok = parseBL3x(file, BL32_SEC); 30623ba6841SJoseph Chen if (!bl32ok) { 30723ba6841SJoseph Chen LOGE("parseBL32 failed!\n"); 30823ba6841SJoseph Chen goto end; 30923ba6841SJoseph Chen } 31023ba6841SJoseph Chen } else if (!strcmp(buf, SEC_BL33)) { 31123ba6841SJoseph Chen bl33ok = parseBL3x(file, BL33_SEC); 31223ba6841SJoseph Chen if (!bl33ok) { 31323ba6841SJoseph Chen LOGE("parseBL33 failed!\n"); 31423ba6841SJoseph Chen goto end; 31523ba6841SJoseph Chen } 31623ba6841SJoseph Chen } else if (!strcmp(buf, SEC_OUT)) { 31723ba6841SJoseph Chen outOk = parseOut(file); 31823ba6841SJoseph Chen if (!outOk) { 31923ba6841SJoseph Chen LOGE("parseOut failed!\n"); 32023ba6841SJoseph Chen goto end; 32123ba6841SJoseph Chen } 32223ba6841SJoseph Chen } else if (buf[0] == '#') { 32323ba6841SJoseph Chen continue; 32423ba6841SJoseph Chen } else { 32523ba6841SJoseph Chen LOGE("unknown sec: %s!\n", buf); 32623ba6841SJoseph Chen goto end; 32723ba6841SJoseph Chen } 32823ba6841SJoseph Chen if (SCANF_EAT(file) != 0) { 32923ba6841SJoseph Chen goto end; 33023ba6841SJoseph Chen } 33123ba6841SJoseph Chen } 33223ba6841SJoseph Chen 33323ba6841SJoseph Chen if (bl30ok && bl31ok && bl32ok && bl33ok && outOk) 33423ba6841SJoseph Chen ret = true; 33523ba6841SJoseph Chen end: 33623ba6841SJoseph Chen if (file) 33723ba6841SJoseph Chen fclose(file); 33823ba6841SJoseph Chen 33923ba6841SJoseph Chen return ret; 34023ba6841SJoseph Chen } 34123ba6841SJoseph Chen 34223ba6841SJoseph Chen bool initOpts(void) 34323ba6841SJoseph Chen { 34423ba6841SJoseph Chen 34523ba6841SJoseph Chen memset(&gOpts, 0, sizeof(gOpts)); 34623ba6841SJoseph Chen 34723ba6841SJoseph Chen gOpts.major = DEF_MAJOR; 34823ba6841SJoseph Chen gOpts.minor = DEF_MINOR; 34923ba6841SJoseph Chen 35023ba6841SJoseph Chen memcpy(&gOpts.bl3x[BL30_SEC].id, gBl3xID[BL30_SEC], 4); 35123ba6841SJoseph Chen strcpy(gOpts.bl3x[BL30_SEC].path, DEF_BL30_PATH); 35223ba6841SJoseph Chen 35323ba6841SJoseph Chen memcpy(&gOpts.bl3x[BL31_SEC].id, gBl3xID[BL31_SEC], 4); 35423ba6841SJoseph Chen strcpy(gOpts.bl3x[BL31_SEC].path, DEF_BL31_PATH); 35523ba6841SJoseph Chen 35623ba6841SJoseph Chen memcpy(&gOpts.bl3x[BL32_SEC].id, gBl3xID[BL32_SEC], 4); 35723ba6841SJoseph Chen strcpy(gOpts.bl3x[BL32_SEC].path, DEF_BL32_PATH); 35823ba6841SJoseph Chen 35923ba6841SJoseph Chen memcpy(&gOpts.bl3x[BL33_SEC].id, gBl3xID[BL33_SEC], 4); 36023ba6841SJoseph Chen strcpy(gOpts.bl3x[BL33_SEC].path, DEF_BL33_PATH); 36123ba6841SJoseph Chen 36223ba6841SJoseph Chen strcpy(gOpts.outPath, DEF_OUT_PATH); 36323ba6841SJoseph Chen 36423ba6841SJoseph Chen return parseOpts(); 36523ba6841SJoseph Chen } 36623ba6841SJoseph Chen 36723ba6841SJoseph Chen static inline bool getFileSize(const char *path, uint32_t *size) 36823ba6841SJoseph Chen { 36923ba6841SJoseph Chen struct stat st; 37023ba6841SJoseph Chen 37123ba6841SJoseph Chen if (stat(path, &st) < 0) 37223ba6841SJoseph Chen return false; 37323ba6841SJoseph Chen *size = st.st_size; 37423ba6841SJoseph Chen LOGD("path:%s, size:%d\n", path, *size); 37523ba6841SJoseph Chen return true; 37623ba6841SJoseph Chen } 37723ba6841SJoseph Chen 37823ba6841SJoseph Chen void fill_file(FILE *file, char ch, uint32_t fill_size) 37923ba6841SJoseph Chen { 38023ba6841SJoseph Chen uint8_t fill_buffer[1024]; 38123ba6841SJoseph Chen uint32_t cur_write; 38223ba6841SJoseph Chen 38323ba6841SJoseph Chen memset(fill_buffer, ch, 1024); 38423ba6841SJoseph Chen while (fill_size > 0) { 38523ba6841SJoseph Chen cur_write = (fill_size >= 1024) ? 1024 : fill_size; 38623ba6841SJoseph Chen fwrite(fill_buffer, 1, cur_write, file); 38723ba6841SJoseph Chen fill_size -= cur_write; 38823ba6841SJoseph Chen } 38923ba6841SJoseph Chen } 39023ba6841SJoseph Chen 39123ba6841SJoseph Chen bool filter_elf(uint32_t index, uint8_t *pMeta, uint32_t *pMetaNum, 39223ba6841SJoseph Chen bool *bElf) 39323ba6841SJoseph Chen { 39423ba6841SJoseph Chen bool ret = false; 39523ba6841SJoseph Chen FILE *file = NULL; 39623ba6841SJoseph Chen uint8_t *file_buffer = NULL; 39723ba6841SJoseph Chen uint32_t file_size, read_size, i; 39823ba6841SJoseph Chen Elf32_Ehdr *pElfHeader32; 39923ba6841SJoseph Chen Elf32_Phdr *pElfProgram32; 40023ba6841SJoseph Chen Elf64_Ehdr *pElfHeader64; 40123ba6841SJoseph Chen Elf64_Phdr *pElfProgram64; 40223ba6841SJoseph Chen bl_entry_t *pEntry = (bl_entry_t *)(pMeta + sizeof(bl_entry_t) * (*pMetaNum)); 40323ba6841SJoseph Chen LOGD("index=%d,file=%s\n", index, gOpts.bl3x[index].path); 40423ba6841SJoseph Chen 40523ba6841SJoseph Chen if (!getFileSize(gOpts.bl3x[index].path, &file_size)) 40623ba6841SJoseph Chen goto exit_fileter_elf; 40723ba6841SJoseph Chen file = fopen(gOpts.bl3x[index].path, "rb"); 40823ba6841SJoseph Chen if (!file) { 40923ba6841SJoseph Chen LOGE("open file(%s) failed\n", gOpts.bl3x[index].path); 41023ba6841SJoseph Chen goto exit_fileter_elf; 41123ba6841SJoseph Chen } 41223ba6841SJoseph Chen file_buffer = malloc(file_size); 41323ba6841SJoseph Chen if (!file_buffer) 41423ba6841SJoseph Chen goto exit_fileter_elf; 41523ba6841SJoseph Chen read_size = fread(file_buffer, 1, file_size, file); 41623ba6841SJoseph Chen if (read_size != file_size) 41723ba6841SJoseph Chen goto exit_fileter_elf; 41823ba6841SJoseph Chen 41923ba6841SJoseph Chen if (*((uint32_t *)file_buffer) != ELF_MAGIC) { 42023ba6841SJoseph Chen ret = true; 42123ba6841SJoseph Chen *bElf = false; 42223ba6841SJoseph Chen goto exit_fileter_elf; 42323ba6841SJoseph Chen } 42423ba6841SJoseph Chen *bElf = true; 42523ba6841SJoseph Chen if (file_buffer[5] != 1) { /* only support little endian */ 42623ba6841SJoseph Chen goto exit_fileter_elf; 42723ba6841SJoseph Chen } 42823ba6841SJoseph Chen if (*((uint16_t *)(file_buffer + EI_NIDENT)) != 42923ba6841SJoseph Chen 2) { /* only support executable case */ 43023ba6841SJoseph Chen goto exit_fileter_elf; 43123ba6841SJoseph Chen } 43223ba6841SJoseph Chen 43323ba6841SJoseph Chen if (file_buffer[4] == 2) { 43423ba6841SJoseph Chen pElfHeader64 = (Elf64_Ehdr *)file_buffer; 43523ba6841SJoseph Chen for (i = 0; i < pElfHeader64->e_phnum; i++) { 43623ba6841SJoseph Chen pElfProgram64 = (Elf64_Phdr *)(file_buffer + pElfHeader64->e_phoff + 43723ba6841SJoseph Chen i * pElfHeader64->e_phentsize); 43823ba6841SJoseph Chen if (pElfProgram64->p_type == 1) { /* PT_LOAD */ 43923ba6841SJoseph Chen pEntry->id = gOpts.bl3x[index].id; 44023ba6841SJoseph Chen strcpy(pEntry->path, gOpts.bl3x[index].path); 44123ba6841SJoseph Chen pEntry->size = (uint32_t) pElfProgram64->p_filesz; 44223ba6841SJoseph Chen pEntry->offset = (uint32_t) pElfProgram64->p_offset; 44323ba6841SJoseph Chen pEntry->align_size = DO_ALIGN(pEntry->size, ENTRY_ALIGN); 44423ba6841SJoseph Chen pEntry->addr = (uint32_t) pElfProgram64->p_vaddr; 44523ba6841SJoseph Chen if (pEntry->align_size > BL3X_FILESIZE_MAX) { 44623ba6841SJoseph Chen LOGE("elf_file %s too large,segment=%d.\n", pEntry->path, i); 44723ba6841SJoseph Chen goto exit_fileter_elf; 44823ba6841SJoseph Chen } 44923ba6841SJoseph Chen LOGD("bl3%d: filesize = %d, imagesize = %d, segment=%d\n", index, 45023ba6841SJoseph Chen pEntry->size, pEntry->align_size, i); 45123ba6841SJoseph Chen pEntry++; 45223ba6841SJoseph Chen (*pMetaNum)++; 45323ba6841SJoseph Chen } 45423ba6841SJoseph Chen } 45523ba6841SJoseph Chen 45623ba6841SJoseph Chen } else { 45723ba6841SJoseph Chen pElfHeader32 = (Elf32_Ehdr *)file_buffer; 45823ba6841SJoseph Chen for (i = 0; i < pElfHeader32->e_phnum; i++) { 45923ba6841SJoseph Chen pElfProgram32 = (Elf32_Phdr *)(file_buffer + pElfHeader32->e_phoff + 46023ba6841SJoseph Chen i * pElfHeader32->e_phentsize); 46123ba6841SJoseph Chen if (pElfProgram32->p_type == 1) { /* PT_LOAD */ 46223ba6841SJoseph Chen pEntry->id = gOpts.bl3x[index].id; 46323ba6841SJoseph Chen strcpy(pEntry->path, gOpts.bl3x[index].path); 46423ba6841SJoseph Chen pEntry->size = pElfProgram32->p_filesz; 46523ba6841SJoseph Chen pEntry->offset = pElfProgram32->p_offset; 46623ba6841SJoseph Chen pEntry->align_size = DO_ALIGN(pEntry->size, ENTRY_ALIGN); 46723ba6841SJoseph Chen pEntry->addr = pElfProgram32->p_vaddr; 46823ba6841SJoseph Chen if (pEntry->align_size > BL3X_FILESIZE_MAX) { 46923ba6841SJoseph Chen LOGE("elf_file %s too large,segment=%d.\n", pEntry->path, i); 47023ba6841SJoseph Chen goto exit_fileter_elf; 47123ba6841SJoseph Chen } 47223ba6841SJoseph Chen LOGD("bl3%d: filesize = %d, imagesize = %d, segment=%d\n", index, 47323ba6841SJoseph Chen pEntry->size, pEntry->align_size, i); 47423ba6841SJoseph Chen pEntry++; 47523ba6841SJoseph Chen (*pMetaNum)++; 47623ba6841SJoseph Chen } 47723ba6841SJoseph Chen } 47823ba6841SJoseph Chen } 47923ba6841SJoseph Chen ret = true; 48023ba6841SJoseph Chen exit_fileter_elf: 48123ba6841SJoseph Chen if (file) 48223ba6841SJoseph Chen fclose(file); 48323ba6841SJoseph Chen if (file_buffer) 48423ba6841SJoseph Chen free(file_buffer); 48523ba6841SJoseph Chen return ret; 48623ba6841SJoseph Chen } 48723ba6841SJoseph Chen 48823ba6841SJoseph Chen #define SHA256_CHECK_SZ ((uint32_t)(256 * 1024)) 48923ba6841SJoseph Chen static bool bl3xHash256(uint8_t *pHash, uint8_t *pData, uint32_t nDataSize) 49023ba6841SJoseph Chen { 49123ba6841SJoseph Chen uint32_t nHashSize, nHasHashSize; 49223ba6841SJoseph Chen 49323ba6841SJoseph Chen if (!pHash || !pData || !nDataSize) { 49423ba6841SJoseph Chen return false; 49523ba6841SJoseph Chen } 49623ba6841SJoseph Chen 49723ba6841SJoseph Chen nHasHashSize = 0; 49823ba6841SJoseph Chen 49923ba6841SJoseph Chen if (gSHAmode == SHA_SEL_256_RK) { 50023ba6841SJoseph Chen sha256_ctx ctx; 50123ba6841SJoseph Chen 50223ba6841SJoseph Chen sha256_begin(&ctx); 50323ba6841SJoseph Chen while (nDataSize > 0) { 50423ba6841SJoseph Chen nHashSize = (nDataSize >= SHA256_CHECK_SZ) ? SHA256_CHECK_SZ : nDataSize; 50523ba6841SJoseph Chen sha256_hash(&ctx, pData + nHasHashSize, nHashSize); 50623ba6841SJoseph Chen nHasHashSize += nHashSize; 50723ba6841SJoseph Chen nDataSize -= nHashSize; 50823ba6841SJoseph Chen } 50923ba6841SJoseph Chen sha256_end(&ctx, pHash); 51023ba6841SJoseph Chen } else { 51123ba6841SJoseph Chen sha256_context ctx; 51223ba6841SJoseph Chen 51323ba6841SJoseph Chen sha256_starts(&ctx); 51423ba6841SJoseph Chen while (nDataSize > 0) { 51523ba6841SJoseph Chen nHashSize = (nDataSize >= SHA256_CHECK_SZ) ? SHA256_CHECK_SZ : nDataSize; 51623ba6841SJoseph Chen sha256_update(&ctx, pData + nHasHashSize, nHashSize); 51723ba6841SJoseph Chen nHasHashSize += nHashSize; 51823ba6841SJoseph Chen nDataSize -= nHashSize; 51923ba6841SJoseph Chen } 52023ba6841SJoseph Chen sha256_finish(&ctx, pHash); 52123ba6841SJoseph Chen } 52223ba6841SJoseph Chen return true; 52323ba6841SJoseph Chen } 52423ba6841SJoseph Chen 52523ba6841SJoseph Chen static bool mergetrust(void) 52623ba6841SJoseph Chen { 52723ba6841SJoseph Chen FILE *outFile = NULL; 52823ba6841SJoseph Chen uint32_t OutFileSize; 52923ba6841SJoseph Chen uint32_t SrcFileNum, SignOffset, nComponentNum; 53023ba6841SJoseph Chen TRUST_HEADER *pHead = NULL; 53123ba6841SJoseph Chen COMPONENT_DATA *pComponentData = NULL; 53223ba6841SJoseph Chen TRUST_COMPONENT *pComponent = NULL; 53323ba6841SJoseph Chen bool ret = false, bElf; 53423ba6841SJoseph Chen uint32_t i, n; 53523ba6841SJoseph Chen uint8_t *outBuf = NULL, *pbuf = NULL, *pMetaBuf = NULL; 53623ba6841SJoseph Chen bl_entry_t *pEntry = NULL; 53723ba6841SJoseph Chen if (!initOpts()) 53823ba6841SJoseph Chen return false; 53923ba6841SJoseph Chen 54023ba6841SJoseph Chen if (gDebug) { 54123ba6841SJoseph Chen printf("---------------\nUSING CONFIG:\n"); 54223ba6841SJoseph Chen printOpts(stdout); 54323ba6841SJoseph Chen printf("---------------\n\n"); 54423ba6841SJoseph Chen } 54523ba6841SJoseph Chen pMetaBuf = malloc(sizeof(bl_entry_t) * 32); 54623ba6841SJoseph Chen if (!pMetaBuf) { 54723ba6841SJoseph Chen LOGE("Merge trust image: malloc buffer error.\n"); 54823ba6841SJoseph Chen goto end; 54923ba6841SJoseph Chen } 55023ba6841SJoseph Chen 55123ba6841SJoseph Chen nComponentNum = SrcFileNum = 0; 55223ba6841SJoseph Chen for (i = BL30_SEC; i < BL_MAX_SEC; i++) { 55323ba6841SJoseph Chen if (gOpts.bl3x[i].sec) { 55423ba6841SJoseph Chen if (!filter_elf(i, pMetaBuf, &nComponentNum, &bElf)) { 55523ba6841SJoseph Chen LOGE("filter_elf %s file failed\n", gOpts.bl3x[i].path); 55623ba6841SJoseph Chen goto end; 55723ba6841SJoseph Chen } 55823ba6841SJoseph Chen if (!bElf) { 55923ba6841SJoseph Chen pEntry = (bl_entry_t *)(pMetaBuf + sizeof(bl_entry_t) * nComponentNum); 56023ba6841SJoseph Chen pEntry->id = gOpts.bl3x[i].id; 56123ba6841SJoseph Chen strcpy(pEntry->path, gOpts.bl3x[i].path); 56223ba6841SJoseph Chen getFileSize(pEntry->path, &pEntry->size); 56323ba6841SJoseph Chen pEntry->offset = 0; 56423ba6841SJoseph Chen pEntry->align_size = DO_ALIGN(pEntry->size, ENTRY_ALIGN); 56523ba6841SJoseph Chen pEntry->addr = gOpts.bl3x[i].addr; 56623ba6841SJoseph Chen if (pEntry->align_size > BL3X_FILESIZE_MAX) { 56723ba6841SJoseph Chen LOGE("file %s too large.\n", gOpts.bl3x[i].path); 56823ba6841SJoseph Chen goto end; 56923ba6841SJoseph Chen } 57023ba6841SJoseph Chen LOGD("bl3%d: filesize = %d, imagesize = %d\n", i, pEntry->size, 57123ba6841SJoseph Chen pEntry->align_size); 57223ba6841SJoseph Chen pEntry++; 57323ba6841SJoseph Chen nComponentNum++; 57423ba6841SJoseph Chen } 57523ba6841SJoseph Chen 57623ba6841SJoseph Chen } 57723ba6841SJoseph Chen } 57823ba6841SJoseph Chen LOGD("bl3x bin sec = %d\n", nComponentNum); 57923ba6841SJoseph Chen 58023ba6841SJoseph Chen /* 2048bytes for head */ 58123ba6841SJoseph Chen memset(gBuf, 0, TRUST_HEADER_SIZE); 58223ba6841SJoseph Chen 58323ba6841SJoseph Chen /* Trust Head */ 58423ba6841SJoseph Chen pHead = (TRUST_HEADER *)gBuf; 58523ba6841SJoseph Chen memcpy(&pHead->tag, TRUST_HEAD_TAG, 4); 58623ba6841SJoseph Chen pHead->version = (getBCD(gOpts.major) << 8) | getBCD(gOpts.minor); 58723ba6841SJoseph Chen pHead->flags = 0; 58823ba6841SJoseph Chen pHead->flags |= (gSHAmode << 0); 58923ba6841SJoseph Chen pHead->flags |= (gRSAmode << 4); 59023ba6841SJoseph Chen 59123ba6841SJoseph Chen SignOffset = sizeof(TRUST_HEADER) + nComponentNum * sizeof(COMPONENT_DATA); 59223ba6841SJoseph Chen LOGD("trust bin sign offset = %d\n", SignOffset); 59323ba6841SJoseph Chen pHead->size = (nComponentNum << 16) | (SignOffset >> 2); 59423ba6841SJoseph Chen 59523ba6841SJoseph Chen pComponent = (TRUST_COMPONENT *)(gBuf + SignOffset + SIGNATURE_SIZE); 59623ba6841SJoseph Chen pComponentData = (COMPONENT_DATA *)(gBuf + sizeof(TRUST_HEADER)); 59723ba6841SJoseph Chen 59823ba6841SJoseph Chen OutFileSize = TRUST_HEADER_SIZE; 59923ba6841SJoseph Chen pEntry = (bl_entry_t *)pMetaBuf; 60023ba6841SJoseph Chen for (i = 0; i < nComponentNum; i++) { 60123ba6841SJoseph Chen /* bl3x load and run address */ 60223ba6841SJoseph Chen pComponentData->LoadAddr = pEntry->addr; 60323ba6841SJoseph Chen 60423ba6841SJoseph Chen pComponent->ComponentID = pEntry->id; 60523ba6841SJoseph Chen pComponent->StorageAddr = (OutFileSize >> 9); 60623ba6841SJoseph Chen pComponent->ImageSize = (pEntry->align_size >> 9); 60723ba6841SJoseph Chen 60823ba6841SJoseph Chen LOGD("bl3%c: LoadAddr = 0x%08x, StorageAddr = %d, ImageSize = %d\n", 60923ba6841SJoseph Chen (char)((pEntry->id & 0xFF000000) >> 24), pComponentData->LoadAddr, 61023ba6841SJoseph Chen pComponent->StorageAddr, pComponent->ImageSize); 61123ba6841SJoseph Chen 61223ba6841SJoseph Chen OutFileSize += pEntry->align_size; 61323ba6841SJoseph Chen pComponentData++; 61423ba6841SJoseph Chen pComponent++; 61523ba6841SJoseph Chen pEntry++; 61623ba6841SJoseph Chen } 61723ba6841SJoseph Chen 61823ba6841SJoseph Chen /* create out file */ 61923ba6841SJoseph Chen outFile = fopen(gOpts.outPath, "wb+"); 62023ba6841SJoseph Chen if (!outFile) { 62123ba6841SJoseph Chen LOGE("open out file(%s) failed\n", gOpts.outPath); 62223ba6841SJoseph Chen 62323ba6841SJoseph Chen outFile = fopen(DEF_OUT_PATH, "wb"); 62423ba6841SJoseph Chen if (!outFile) { 62523ba6841SJoseph Chen LOGE("open default out file:%s failed!\n", DEF_OUT_PATH); 62623ba6841SJoseph Chen goto end; 62723ba6841SJoseph Chen } 62823ba6841SJoseph Chen } 62923ba6841SJoseph Chen 63023ba6841SJoseph Chen /* 0 for g_trust_max_num backups */ 63123ba6841SJoseph Chen #if 0 63223ba6841SJoseph Chen /* save trust head to out file */ 63323ba6841SJoseph Chen if (!fwrite(gBuf, TRUST_HEADER_SIZE, 1, outFile)) 63423ba6841SJoseph Chen goto end; 63523ba6841SJoseph Chen 63623ba6841SJoseph Chen /* save trust bl3x bin */ 63723ba6841SJoseph Chen for (i = BL30_SEC; i < BL_MAX_SEC; i++) { 63823ba6841SJoseph Chen if (gOpts.bl3x[i].sec) { 63923ba6841SJoseph Chen FILE *inFile = fopen(gOpts.bl3x[i].path, "rb"); 64023ba6841SJoseph Chen if (!inFile) 64123ba6841SJoseph Chen goto end; 64223ba6841SJoseph Chen 64323ba6841SJoseph Chen memset(gBuf, 0, imagesize[i]); 64423ba6841SJoseph Chen if (!fread(gBuf, filesize[i], 1, inFile)) 64523ba6841SJoseph Chen goto end; 64623ba6841SJoseph Chen fclose(inFile); 64723ba6841SJoseph Chen 64823ba6841SJoseph Chen if (!fwrite(gBuf, imagesize[i], 1, outFile)) 64923ba6841SJoseph Chen goto end; 65023ba6841SJoseph Chen } 65123ba6841SJoseph Chen } 65223ba6841SJoseph Chen #else 65323ba6841SJoseph Chen /* check bin size */ 65423ba6841SJoseph Chen if (OutFileSize > g_trust_max_size) { 65523ba6841SJoseph Chen LOGE("Merge trust image: trust bin size overfull.\n"); 65623ba6841SJoseph Chen goto end; 65723ba6841SJoseph Chen } 65823ba6841SJoseph Chen 65923ba6841SJoseph Chen /* malloc buffer */ 66023ba6841SJoseph Chen pbuf = outBuf = calloc(g_trust_max_size, g_trust_max_num); 66123ba6841SJoseph Chen if (!outBuf) { 66223ba6841SJoseph Chen LOGE("Merge trust image: calloc buffer error.\n"); 66323ba6841SJoseph Chen goto end; 66423ba6841SJoseph Chen } 66523ba6841SJoseph Chen memset(outBuf, 0, (g_trust_max_size * g_trust_max_num)); 66623ba6841SJoseph Chen 66723ba6841SJoseph Chen /* save trust head data */ 66823ba6841SJoseph Chen memcpy(pbuf, gBuf, TRUST_HEADER_SIZE); 66923ba6841SJoseph Chen pbuf += TRUST_HEADER_SIZE; 67023ba6841SJoseph Chen 67123ba6841SJoseph Chen uint8_t *pHashData = NULL; 67223ba6841SJoseph Chen pComponentData = (COMPONENT_DATA *)(outBuf + sizeof(TRUST_HEADER)); 67323ba6841SJoseph Chen 67423ba6841SJoseph Chen /* save trust bl3x bin */ 67523ba6841SJoseph Chen pEntry = (bl_entry_t *)pMetaBuf; 67623ba6841SJoseph Chen for (i = 0; i < nComponentNum; i++) { 67723ba6841SJoseph Chen FILE *inFile = fopen(pEntry->path, "rb"); 67823ba6841SJoseph Chen if (!inFile) 67923ba6841SJoseph Chen goto end; 68023ba6841SJoseph Chen 68123ba6841SJoseph Chen memset(gBuf, 0, pEntry->align_size); 68223ba6841SJoseph Chen fseek(inFile, pEntry->offset, SEEK_SET); 68323ba6841SJoseph Chen if (!fread(gBuf, pEntry->size, 1, inFile)) 68423ba6841SJoseph Chen goto end; 68523ba6841SJoseph Chen fclose(inFile); 68623ba6841SJoseph Chen 68723ba6841SJoseph Chen /* bl3x bin hash256 */ 68823ba6841SJoseph Chen pHashData = (uint8_t *)&pComponentData->HashData[0]; 68923ba6841SJoseph Chen bl3xHash256(pHashData, gBuf, pEntry->align_size); 69023ba6841SJoseph Chen memcpy(pbuf, gBuf, pEntry->align_size); 69123ba6841SJoseph Chen 69223ba6841SJoseph Chen pComponentData++; 69323ba6841SJoseph Chen pbuf += pEntry->align_size; 69423ba6841SJoseph Chen pEntry++; 69523ba6841SJoseph Chen } 69623ba6841SJoseph Chen 69723ba6841SJoseph Chen /* copy other (g_trust_max_num - 1) backup bin */ 69823ba6841SJoseph Chen for (n = 1; n < g_trust_max_num; n++) { 69923ba6841SJoseph Chen memcpy(outBuf + g_trust_max_size * n, outBuf, g_trust_max_size); 70023ba6841SJoseph Chen } 70123ba6841SJoseph Chen 70223ba6841SJoseph Chen /* save date to file */ 70323ba6841SJoseph Chen if (!fwrite(outBuf, g_trust_max_size * g_trust_max_num, 1, outFile)) { 70423ba6841SJoseph Chen LOGE("Merge trust image: write file error.\n"); 70523ba6841SJoseph Chen goto end; 70623ba6841SJoseph Chen } 70723ba6841SJoseph Chen #endif 70823ba6841SJoseph Chen 70923ba6841SJoseph Chen ret = true; 71023ba6841SJoseph Chen 71123ba6841SJoseph Chen end: 71223ba6841SJoseph Chen /* 71323ba6841SJoseph Chen for (i = BL30_SEC; i < BL_MAX_SEC; i++) { 71423ba6841SJoseph Chen if (gOpts.bl3x[i].sec != false) { 71523ba6841SJoseph Chen if (gOpts.bl3x[i].is_elf) { 71623ba6841SJoseph Chen if (stat(gOpts.bl3x[i].path, &st) >= 0) 71723ba6841SJoseph Chen remove(gOpts.bl3x[i].path); 71823ba6841SJoseph Chen } 71923ba6841SJoseph Chen } 72023ba6841SJoseph Chen } 72123ba6841SJoseph Chen */ 72223ba6841SJoseph Chen if (pMetaBuf) 72323ba6841SJoseph Chen free(pMetaBuf); 72423ba6841SJoseph Chen if (outBuf) 72523ba6841SJoseph Chen free(outBuf); 72623ba6841SJoseph Chen if (outFile) 72723ba6841SJoseph Chen fclose(outFile); 72823ba6841SJoseph Chen return ret; 72923ba6841SJoseph Chen } 73023ba6841SJoseph Chen 73123ba6841SJoseph Chen static int saveDatatoFile(char *FileName, void *pBuf, uint32_t size) 73223ba6841SJoseph Chen { 73323ba6841SJoseph Chen FILE *OutFile = NULL; 73423ba6841SJoseph Chen int ret = -1; 73523ba6841SJoseph Chen 73623ba6841SJoseph Chen OutFile = fopen(FileName, "wb"); 73723ba6841SJoseph Chen if (!OutFile) { 73823ba6841SJoseph Chen printf("open OutPutFlie:%s failed!\n", FileName); 73923ba6841SJoseph Chen goto end; 74023ba6841SJoseph Chen } 74123ba6841SJoseph Chen if (1 != fwrite(pBuf, size, 1, OutFile)) { 74223ba6841SJoseph Chen printf("write output file failed!\n"); 74323ba6841SJoseph Chen goto end; 74423ba6841SJoseph Chen } 74523ba6841SJoseph Chen 74623ba6841SJoseph Chen ret = 0; 74723ba6841SJoseph Chen end: 74823ba6841SJoseph Chen if (OutFile) 74923ba6841SJoseph Chen fclose(OutFile); 75023ba6841SJoseph Chen 75123ba6841SJoseph Chen return ret; 75223ba6841SJoseph Chen } 75323ba6841SJoseph Chen 75423ba6841SJoseph Chen static bool unpacktrust(char *path) 75523ba6841SJoseph Chen { 75623ba6841SJoseph Chen FILE *FileSrc = NULL; 75723ba6841SJoseph Chen uint32_t FileSize; 75823ba6841SJoseph Chen uint8_t *pBuf = NULL; 75923ba6841SJoseph Chen uint32_t SrcFileNum, SignOffset; 76023ba6841SJoseph Chen TRUST_HEADER *pHead = NULL; 76123ba6841SJoseph Chen COMPONENT_DATA *pComponentData = NULL; 76223ba6841SJoseph Chen TRUST_COMPONENT *pComponent = NULL; 76323ba6841SJoseph Chen char str[MAX_LINE_LEN]; 76423ba6841SJoseph Chen bool ret = false; 76523ba6841SJoseph Chen uint32_t i; 76623ba6841SJoseph Chen 76723ba6841SJoseph Chen FileSrc = fopen(path, "rb"); 76823ba6841SJoseph Chen if (FileSrc == NULL) { 76923ba6841SJoseph Chen printf("open %s failed!\n", path); 77023ba6841SJoseph Chen goto end; 77123ba6841SJoseph Chen } 77223ba6841SJoseph Chen 77323ba6841SJoseph Chen if (getFileSize(path, &FileSize) == false) { 77423ba6841SJoseph Chen printf("File Size failed!\n"); 77523ba6841SJoseph Chen goto end; 77623ba6841SJoseph Chen } 77723ba6841SJoseph Chen printf("File Size = %d\n", FileSize); 77823ba6841SJoseph Chen 77923ba6841SJoseph Chen pBuf = (uint8_t *)malloc(FileSize); 78023ba6841SJoseph Chen if (1 != fread(pBuf, FileSize, 1, FileSrc)) { 78123ba6841SJoseph Chen printf("read input file failed!\n"); 78223ba6841SJoseph Chen goto end; 78323ba6841SJoseph Chen } 78423ba6841SJoseph Chen 78523ba6841SJoseph Chen pHead = (TRUST_HEADER *)pBuf; 78623ba6841SJoseph Chen 78723ba6841SJoseph Chen memcpy(str, &pHead->tag, 4); 78823ba6841SJoseph Chen str[4] = '\0'; 78923ba6841SJoseph Chen printf("Header Tag:%s\n", str); 79023ba6841SJoseph Chen printf("Header version:%d\n", pHead->version); 79123ba6841SJoseph Chen printf("Header flag:%d\n", pHead->flags); 79223ba6841SJoseph Chen 79323ba6841SJoseph Chen SrcFileNum = (pHead->size >> 16) & 0xffff; 79423ba6841SJoseph Chen SignOffset = (pHead->size & 0xffff) << 2; 79523ba6841SJoseph Chen printf("SrcFileNum:%d\n", SrcFileNum); 79623ba6841SJoseph Chen printf("SignOffset:%d\n", SignOffset); 79723ba6841SJoseph Chen 79823ba6841SJoseph Chen pComponent = (TRUST_COMPONENT *)(pBuf + SignOffset + SIGNATURE_SIZE); 79923ba6841SJoseph Chen pComponentData = (COMPONENT_DATA *)(pBuf + sizeof(TRUST_HEADER)); 80023ba6841SJoseph Chen 80123ba6841SJoseph Chen for (i = 0; i < SrcFileNum; i++) { 80223ba6841SJoseph Chen printf("Component %d:\n", i); 80323ba6841SJoseph Chen 80423ba6841SJoseph Chen memcpy(str, &pComponent->ComponentID, 4); 80523ba6841SJoseph Chen str[4] = '\0'; 80623ba6841SJoseph Chen printf("ComponentID:%s\n", str); 80723ba6841SJoseph Chen printf("StorageAddr:0x%x\n", pComponent->StorageAddr); 80823ba6841SJoseph Chen printf("ImageSize:0x%x\n", pComponent->ImageSize); 80923ba6841SJoseph Chen printf("LoadAddr:0x%x\n", pComponentData->LoadAddr); 81023ba6841SJoseph Chen 81123ba6841SJoseph Chen saveDatatoFile(str, pBuf + (pComponent->StorageAddr << 9), 81223ba6841SJoseph Chen pComponent->ImageSize << 9); 81323ba6841SJoseph Chen 81423ba6841SJoseph Chen pComponentData++; 81523ba6841SJoseph Chen pComponent++; 81623ba6841SJoseph Chen } 81723ba6841SJoseph Chen 81823ba6841SJoseph Chen ret = true; 81923ba6841SJoseph Chen end: 82023ba6841SJoseph Chen if (FileSrc) 82123ba6841SJoseph Chen fclose(FileSrc); 82223ba6841SJoseph Chen if (pBuf) 82323ba6841SJoseph Chen free(pBuf); 82423ba6841SJoseph Chen 82523ba6841SJoseph Chen return ret; 82623ba6841SJoseph Chen } 82723ba6841SJoseph Chen 82823ba6841SJoseph Chen static void printHelp(void) 82923ba6841SJoseph Chen { 83023ba6841SJoseph Chen printf("Usage: trust_merger [options]... FILE\n"); 83123ba6841SJoseph Chen printf( 83223ba6841SJoseph Chen "Merge or unpack Rockchip's trust image (Default action is to merge.)\n"); 83323ba6841SJoseph Chen printf("Options:\n"); 83423ba6841SJoseph Chen printf("\t" OPT_MERGE "\t\t\tMerge trust with specified config.\n"); 83523ba6841SJoseph Chen printf("\t" OPT_UNPACK "\t\tUnpack specified trust to current dir.\n"); 83623ba6841SJoseph Chen printf("\t" OPT_VERBOSE "\t\tDisplay more runtime informations.\n"); 83723ba6841SJoseph Chen printf("\t" OPT_HELP "\t\t\tDisplay this information.\n"); 83823ba6841SJoseph Chen printf("\t" OPT_VERSION "\t\tDisplay version information.\n"); 83923ba6841SJoseph Chen printf("\t" OPT_SUBFIX "\t\tSpec subfix.\n"); 84023ba6841SJoseph Chen printf("\t" OPT_REPLACE "\t\tReplace some part of binary path.\n"); 841*e311da24SJoseph Chen printf("\t" OPT_PREPATH "\t\tAdd prefix path of binary path.\n"); 84223ba6841SJoseph Chen printf("\t" OPT_RSA "\t\t\tRSA mode.\"--rsa [mode]\", [mode] can be: " 84323ba6841SJoseph Chen "0(none), 1(1024), 2(2048), 3(2048 pss).\n"); 84423ba6841SJoseph Chen printf("\t" OPT_SHA 84523ba6841SJoseph Chen "\t\t\tSHA mode.\"--sha [mode]\", [mode] can be: 0(none), 1(160), " 84623ba6841SJoseph Chen "2(256 RK big endian), 3(256 little endian).\n"); 84723ba6841SJoseph Chen printf("\t" OPT_SIZE "\t\t\tTrustImage size.\"--size [per image KB size] " 84823ba6841SJoseph Chen "[copy count]\", per image must be 64KB aligned\n"); 84923ba6841SJoseph Chen } 85023ba6841SJoseph Chen 85123ba6841SJoseph Chen int main(int argc, char **argv) 85223ba6841SJoseph Chen { 85323ba6841SJoseph Chen bool merge = true; 85423ba6841SJoseph Chen char *optPath = NULL; 85523ba6841SJoseph Chen int i; 85623ba6841SJoseph Chen 85723ba6841SJoseph Chen gConfigPath = NULL; 85823ba6841SJoseph Chen for (i = 1; i < argc; i++) { 85923ba6841SJoseph Chen if (!strcmp(OPT_VERBOSE, argv[i])) { 86023ba6841SJoseph Chen gDebug = true; 86123ba6841SJoseph Chen } else if (!strcmp(OPT_HELP, argv[i])) { 86223ba6841SJoseph Chen printHelp(); 86323ba6841SJoseph Chen return 0; 86423ba6841SJoseph Chen } else if (!strcmp(OPT_VERSION, argv[i])) { 86523ba6841SJoseph Chen printf("trust_merger (cwz@rock-chips.com)\t" VERSION "\n"); 86623ba6841SJoseph Chen return 0; 86723ba6841SJoseph Chen } else if (!strcmp(OPT_MERGE, argv[i])) { 86823ba6841SJoseph Chen merge = true; 86923ba6841SJoseph Chen } else if (!strcmp(OPT_UNPACK, argv[i])) { 87023ba6841SJoseph Chen merge = false; 87123ba6841SJoseph Chen } else if (!strcmp(OPT_SUBFIX, argv[i])) { 87223ba6841SJoseph Chen gSubfix = true; 87323ba6841SJoseph Chen printf("trust_merger: Spec subfix!\n"); 87423ba6841SJoseph Chen } else if (!strcmp(OPT_REPLACE, argv[i])) { 87523ba6841SJoseph Chen i++; 87623ba6841SJoseph Chen gLegacyPath = argv[i]; 87723ba6841SJoseph Chen i++; 87823ba6841SJoseph Chen gNewPath = argv[i]; 879*e311da24SJoseph Chen } else if (!strcmp(OPT_PREPATH, argv[i])) { 880*e311da24SJoseph Chen i++; 881*e311da24SJoseph Chen gPrePath = argv[i]; 88223ba6841SJoseph Chen } else if (!strcmp(OPT_RSA, argv[i])) { 88323ba6841SJoseph Chen i++; 88423ba6841SJoseph Chen if (!is_digit(*(argv[i]))) { 88523ba6841SJoseph Chen printHelp(); 88623ba6841SJoseph Chen return -1; 88723ba6841SJoseph Chen } 88823ba6841SJoseph Chen gRSAmode = *(argv[i]) - '0'; 88923ba6841SJoseph Chen LOGD("rsa mode:%d\n", gRSAmode); 89023ba6841SJoseph Chen } else if (!strcmp(OPT_SHA, argv[i])) { 89123ba6841SJoseph Chen i++; 89223ba6841SJoseph Chen if (!is_digit(*(argv[i]))) { 89323ba6841SJoseph Chen printHelp(); 89423ba6841SJoseph Chen return -1; 89523ba6841SJoseph Chen } 89623ba6841SJoseph Chen gSHAmode = *(argv[i]) - '0'; 89723ba6841SJoseph Chen LOGD("sha mode:%d\n", gSHAmode); 89823ba6841SJoseph Chen } else if (!strcmp(OPT_SIZE, argv[i])) { 89923ba6841SJoseph Chen /* Per trust image size */ 90023ba6841SJoseph Chen g_trust_max_size = strtoul(argv[++i], NULL, 10); 90123ba6841SJoseph Chen /* 90223ba6841SJoseph Chen * Usually, it must be at 512kb align due to preloader 90323ba6841SJoseph Chen * detects every 512kb. But some product has critial 90423ba6841SJoseph Chen * flash size requirement, we have to make it small than 90523ba6841SJoseph Chen * 512KB. 90623ba6841SJoseph Chen */ 90723ba6841SJoseph Chen if (g_trust_max_size % 64) { 90823ba6841SJoseph Chen printHelp(); 90923ba6841SJoseph Chen return -1; 91023ba6841SJoseph Chen } 91123ba6841SJoseph Chen g_trust_max_size *= 1024; /* bytes */ 91223ba6841SJoseph Chen 91323ba6841SJoseph Chen /* Total backup numbers */ 91423ba6841SJoseph Chen g_trust_max_num = strtoul(argv[++i], NULL, 10); 91575828958SJoseph Chen } else if (!strcmp(OPT_IGNORE_BL32, argv[i])) { 91675828958SJoseph Chen gIgnoreBL32 = true; 91723ba6841SJoseph Chen } else { 91823ba6841SJoseph Chen if (optPath) { 91923ba6841SJoseph Chen fprintf(stderr, "only need one path arg, but we have:\n%s\n%s.\n", 92023ba6841SJoseph Chen optPath, argv[i]); 92123ba6841SJoseph Chen printHelp(); 92223ba6841SJoseph Chen return -1; 92323ba6841SJoseph Chen } 92423ba6841SJoseph Chen optPath = argv[i]; 92523ba6841SJoseph Chen } 92623ba6841SJoseph Chen } 92723ba6841SJoseph Chen if (!merge && !optPath) { 92823ba6841SJoseph Chen fprintf(stderr, "need set out path to unpack!\n"); 92923ba6841SJoseph Chen printHelp(); 93023ba6841SJoseph Chen return -1; 93123ba6841SJoseph Chen } 93223ba6841SJoseph Chen 93323ba6841SJoseph Chen if (merge) { 93423ba6841SJoseph Chen LOGD("do_merge\n"); 93523ba6841SJoseph Chen gConfigPath = optPath; 93623ba6841SJoseph Chen if (!mergetrust()) { 93723ba6841SJoseph Chen fprintf(stderr, "merge failed!\n"); 93823ba6841SJoseph Chen return -1; 93923ba6841SJoseph Chen } 94023ba6841SJoseph Chen printf("merge success(%s)\n", gOpts.outPath); 94123ba6841SJoseph Chen } else { 94223ba6841SJoseph Chen LOGD("do_unpack\n"); 94323ba6841SJoseph Chen if (!unpacktrust(optPath)) { 94423ba6841SJoseph Chen fprintf(stderr, "unpack failed!\n"); 94523ba6841SJoseph Chen return -1; 94623ba6841SJoseph Chen } 94723ba6841SJoseph Chen printf("unpack success\n"); 94823ba6841SJoseph Chen } 94923ba6841SJoseph Chen 95023ba6841SJoseph Chen return 0; 95123ba6841SJoseph Chen } 952