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