From 78884ef4bafbcdb297daf3d3da7adf84677908d7 Mon Sep 17 00:00:00 2001 From: Eddie Cai Date: Mon, 17 Apr 2017 18:42:08 +0800 Subject: [PATCH] main: add pack and unpack boot loader support pack and unpack boot loader is very helpful when debug boot loader. we should support it in rkdeveloptool. Signed-off-by: Eddie Cai --- boot_merger.h | 154 ++++++++++ config.ini | 19 ++ main.cpp | 776 +++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 948 insertions(+), 1 deletion(-) create mode 100755 boot_merger.h diff --git a/boot_merger.h b/boot_merger.h new file mode 100755 index 0000000..bc1a572 --- /dev/null +++ b/boot_merger.h @@ -0,0 +1,154 @@ +/* + * (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#ifndef BOOT_MERGER_H +#define BOOT_MERGER_H + +#include +#include +#include +#include +#include + + + +#define SCANF_EAT(in) fscanf(in, "%*[ \r\n\t/]")//, gEat) +#define MAX_LINE_LEN 256 + +typedef char line_t[MAX_LINE_LEN]; + + + +#define DEF_CONFIG_FILE "config.ini" + +#define DEF_MAJOR 0 +#define DEF_MINOR 3 +#define DEF_CHIP "RK30" +#define DEF_CODE471_NUM 1 +#define DEF_CODE472_NUM 1 +#define DEF_CODE471_SLEEP 0 +#define DEF_CODE472_SLEEP 0 +#define DEF_CODE471_PATH "rk3288_ddr_400MHZ_v1.01.bin" +#define DEF_CODE472_PATH "rk3288_usbplug_v2.32.bin" +#define DEF_LOADER_NUM 2 +#define DEF_LOADER0 "FlashData" +#define DEF_LOADER0_PATH "rk3288_ddr_400MHZ_v1.01.bin" +#define DEF_LOADER1 "FlashBoot" +#define DEF_LOADER1_PATH "u-boot.bin" +#define DEF_OUT_PATH "rk3288_bootloader_test.bin" + +#define OUT_SUBFIX ".bin" + +#define SEC_CHIP "[CHIP_NAME]" +#define SEC_VERSION "[VERSION]" +#define SEC_471 "[CODE471_OPTION]" +#define SEC_472 "[CODE472_OPTION]" +#define SEC_LOADER "[LOADER_OPTION]" +#define SEC_OUT "[OUTPUT]" + +#define OPT_NAME "NAME" +#define OPT_MAJOR "MAJOR" +#define OPT_MINOR "MINOR" +#define OPT_NUM "NUM" +#define OPT_LOADER_NUM "LOADERCOUNT" +#define OPT_PATH "Path" +#define OPT_SLEEP "Sleep" +#define OPT_LOADER_NAME "LOADER" +#define OPT_OUT_PATH "PATH" + +typedef struct { + char name[MAX_LINE_LEN]; + char path[MAX_LINE_LEN]; +} name_entry; + +typedef struct { + int major; + int minor; + char chip[MAX_LINE_LEN]; + int code471Sleep; + int code472Sleep; + int code471Num; + int code472Num; + line_t* code471Path; + line_t* code472Path; + int loaderNum; + name_entry* loader; + char outPath[MAX_LINE_LEN]; +} options; + + +#define TAG 0x544F4F42 +#define MERGER_VERSION 0x01030000 +#define SMALL_PACKET 512 + +#define MAX_NAME_LEN 20 +#define MAX_MERGE_SIZE (1024 << 10) + +#define SEC_CHIP_TYPES "[CHIP_TYPES]" + +#define CHIP_RK28 "RK28" +#define CHIP_RK281X "RK281X" +#define CHIP_RKPANDA "RKPANDA" +#define CHIP_RK27 "RK27" +#define CHIP_RKNANO "RKNANO" +#define CHIP_RKSMART "RKSMART" +#define CHIP_RKCROWN "RKCROWN" +#define CHIP_RKCAYMAN "RKCAYMAN" +#define CHIP_RK29 "RK29" +#define CHIP_RK292X "RK292X" +#define CHIP_RK30 "RK30" +#define CHIP_RK30B "RK30B" +#define CHIP_RK31 "RK31" +#define CHIP_RK32 "RK32" + +typedef enum { + ENTRY_471 =1, + ENTRY_472 =2, + ENTRY_LOADER =4, +} rk_entry_type; + +#pragma pack(1) +typedef struct { + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; +} rk_time; + +#define BOOT_RESERVED_SIZE 57 +typedef struct { + uint32_t tag; + uint16_t size; + uint32_t version; + uint32_t mergerVersion; + rk_time releaseTime; + uint32_t chipType; + uint8_t code471Num; + uint32_t code471Offset; + uint8_t code471Size; + uint8_t code472Num; + uint32_t code472Offset; + uint8_t code472Size; + uint8_t loaderNum; + uint32_t loaderOffset; + uint8_t loaderSize; + uint8_t signFlag; + uint8_t rc4Flag; + uint8_t reserved[BOOT_RESERVED_SIZE]; +} rk_boot_header; + +typedef struct { + uint8_t size; + rk_entry_type type; + uint16_t name[MAX_NAME_LEN]; + uint32_t dataOffset; + uint32_t dataSize; + uint32_t dataDelay; +} rk_boot_entry; +#pragma pack() + +#endif// BOOT_MERGER_H diff --git a/config.ini b/config.ini index e69de29..2f95d7d 100644 --- a/config.ini +++ b/config.ini @@ -0,0 +1,19 @@ +[CHIP_NAME] +NAME=RK30 +[VERSION] +MAJOR=0 +MINOR=3 +[CODE471_OPTION] +NUM=1 +Path1=rk3288_ddr_400MHZ_v1.01.bin +[CODE472_OPTION] +NUM=1 +Path1=rk3288_usbplug_v2.32.bin +[LOADER_OPTION] +NUM=2 +LOADER1=FlashData +LOADER2=FlashBoot +FlashData=rk3288_ddr_400MHZ_v1.01.bin +FlashBoot=u-boot.bin +[OUTPUT] +PATH=rk3288_bootloader_test.bin diff --git a/main.cpp b/main.cpp index 3fd0648..8e8eb59 100644 --- a/main.cpp +++ b/main.cpp @@ -55,6 +55,8 @@ void usage() printf("ReadFlashID:\t\trid\r\n"); printf("ReadFlashInfo:\t\trfi\r\n"); printf("ReadChipInfo:\t\trci\r\n"); + printf("PackBootLoader:\t\tpack\r\n"); + printf("UnpackBootLoader:\tunpack \r\n"); printf("-------------------------------------------------------\r\n\r\n"); } void ProgressInfoProc(DWORD deviceLayer, ENUM_PROGRESS_PROMPT promptID, long long totalValue, long long currentValue, ENUM_CALL_STEP emCall) @@ -679,6 +681,769 @@ bool write_gpt(STRUCT_RKDEVICE_DESC &dev, char *szParameter) return bSuccess; } +#include "boot_merger.h" +#define ENTRY_ALIGN (2048) +options gOpts; + + +char gSubfix[MAX_LINE_LEN] = OUT_SUBFIX; +char* gConfigPath; +uint8_t gBuf[MAX_MERGE_SIZE]; + +static inline void fixPath(char* path) { + int i, len = strlen(path); + for(i=0; i= gOpts.loaderNum) { + return false; + } + } + return true; +} + +static bool parseOut(FILE* file) { + if (SCANF_EAT(file) != 0) { + return false; + } + if (fscanf(file, OPT_OUT_PATH "=%[^\r^\n]", gOpts.outPath) != 1) + return false; + fixPath(gOpts.outPath); + printf("out:%s\n", gOpts.outPath); + return true; +} + + +void printOpts(FILE* out) { + int i; + fprintf(out, SEC_CHIP "\n" OPT_NAME "=%s\n", gOpts.chip); + fprintf(out, SEC_VERSION "\n" OPT_MAJOR "=%d\n" OPT_MINOR + "=%d\n", gOpts.major, gOpts.minor); + + fprintf(out, SEC_471 "\n" OPT_NUM "=%d\n", gOpts.code471Num); + for (i=0 ;i 0) + fprintf(out, OPT_SLEEP "=%d\n", gOpts.code471Sleep); + + fprintf(out, SEC_472 "\n" OPT_NUM "=%d\n", gOpts.code472Num); + for (i=0 ;i 0) + fprintf(out, OPT_SLEEP "=%d\n", gOpts.code472Sleep); + + fprintf(out, SEC_LOADER "\n" OPT_NUM "=%d\n", gOpts.loaderNum); + for (i=0 ;i 0xFFFF) { + // return 0; + //} + for(i=0; i < 2; i++) { + tmp[i] = (((value/10)%10)<<4) | (value%10); + value /= 100; + } + ret = ((uint16_t)(tmp[1] << 8)) | tmp[0]; + + printf("ret:%x\n",ret); + return ret&0xFF; +} + +static inline void str2wide(const char* str, uint16_t* wide, int len) +{ + int i; + for (i = 0; i < len; i++) { + wide[i] = (uint16_t) str[i]; + } + wide[len] = 0; +} + +static inline void getName(char* path, uint16_t* dst) { + char* end; + char* start; + int len; + if (!path || !dst) + return; + start = strrchr(path, '/'); + if (!start) + start = path; + else + start++; + end = strrchr(path, '.'); + if (!end) + end = path + strlen(path); + len = end - start; + if (len >= MAX_NAME_LEN) + len = MAX_NAME_LEN -1; + str2wide(start, dst, len); + + + char name[MAX_NAME_LEN]; + memset(name, 0, sizeof(name)); + memcpy(name, start, len); + printf("path:%s, name:%s\n", path, name); + +} + +static inline bool getFileSize(const char *path, uint32_t* size) { + struct stat st; + if(stat(path, &st) < 0) + return false; + *size = st.st_size; + printf("path:%s, size:%d\n", path, *size); + return true; +} + +static inline rk_time getTime(void) { + rk_time rkTime; + + struct tm *tm; + time_t tt = time(NULL); + tm = localtime(&tt); + rkTime.year = tm->tm_year + 1900; + rkTime.month = tm->tm_mon + 1; + rkTime.day = tm->tm_mday; + rkTime.hour = tm->tm_hour; + rkTime.minute = tm->tm_min; + rkTime.second = tm->tm_sec; + printf("%d-%d-%d %02d:%02d:%02d\n", + rkTime.year, rkTime.month, rkTime.day, + rkTime.hour, rkTime.minute, rkTime.second); + return rkTime; +} + +static bool writeFile(FILE* outFile, const char* path, bool fix) { + bool ret = false; + uint32_t size = 0, fixSize = 0; + uint8_t* buf; + + FILE* inFile = fopen(path, "rb"); + if (!inFile) + goto end; + + if (!getFileSize(path, &size)) + goto end; + if (fix) { + fixSize = ((size - 1) / SMALL_PACKET + 1) * SMALL_PACKET; + uint32_t tmp = fixSize % ENTRY_ALIGN; + tmp = tmp ? (ENTRY_ALIGN - tmp): 0; + fixSize +=tmp; + memset(gBuf, 0, fixSize); + } else { + memset(gBuf, 0, size+ENTRY_ALIGN); + } + if (!fread(gBuf, size, 1, inFile)) + goto end; + + if (fix) { + + buf = gBuf; + size = fixSize; + while(1) { + P_RC4(buf, fixSize < SMALL_PACKET ? fixSize : SMALL_PACKET); + buf += SMALL_PACKET; + if (fixSize <= SMALL_PACKET) + break; + fixSize -= SMALL_PACKET; + } + } else { + uint32_t tmp = size % ENTRY_ALIGN; + tmp = tmp ? (ENTRY_ALIGN - tmp): 0; + size +=tmp; + P_RC4(gBuf, size); + } + + if (!fwrite(gBuf, size, 1, outFile)) + goto end; + ret = true; +end: + if (inFile) + fclose(inFile); + if (!ret) + printf("write entry(%s) failed\n", path); + return ret; +} + +static bool saveEntry(FILE* outFile, char* path, rk_entry_type type, + uint16_t delay, uint32_t* offset, char* fixName, bool fix) { + printf("write:%s\n", path); + uint32_t size; + rk_boot_entry entry; + memset(&entry, 0, sizeof(rk_boot_entry)); + + printf("write:%s\n", path); + + getName(fixName ? fixName: path, entry.name); + entry.size = sizeof(rk_boot_entry); + entry.type = type; + entry.dataOffset = *offset; + if (!getFileSize(path, &size)) { + printf("save entry(%s) failed:\n\tcannot get file size.\n", path); + return false; + } + if (fix) + size = ((size - 1) / SMALL_PACKET + 1) * SMALL_PACKET; + uint32_t tmp = size % ENTRY_ALIGN; + size += tmp ? (ENTRY_ALIGN - tmp): 0; + printf("align size:%d\n", size); + entry.dataSize = size; + entry.dataDelay = delay; + *offset += size; + fwrite(&entry, sizeof(rk_boot_entry), 1, outFile); + return true; +} + +static inline uint32_t convertChipType(const char* chip) { + char buffer[5]; + memset(buffer, 0, sizeof(buffer)); + snprintf(buffer, sizeof(buffer), "%s", chip); + return buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3]; +} + +static inline uint32_t getChipType(const char* chip) { + printf("chip:%s\n", chip); + int chipType = RKNONE_DEVICE; + if(!chip) { + goto end; + } + if (!strcmp(chip, CHIP_RK28)) { + chipType = RK28_DEVICE; + } else if (!strcmp(chip, CHIP_RK28)) { + chipType = RK28_DEVICE; + } else if (!strcmp(chip, CHIP_RK281X)) { + chipType = RK281X_DEVICE; + } else if (!strcmp(chip, CHIP_RKPANDA)) { + chipType = RKPANDA_DEVICE; + } else if (!strcmp(chip, CHIP_RK27)) { + chipType = RK27_DEVICE; + } else if (!strcmp(chip, CHIP_RKNANO)) { + chipType = RKNANO_DEVICE; + } else if (!strcmp(chip, CHIP_RKSMART)) { + chipType = RKSMART_DEVICE; + } else if (!strcmp(chip, CHIP_RKCROWN)) { + chipType = RKCROWN_DEVICE; + } else if (!strcmp(chip, CHIP_RKCAYMAN)) { + chipType = RKCAYMAN_DEVICE; + } else if (!strcmp(chip, CHIP_RK29)) { + chipType = RK29_DEVICE; + } else if (!strcmp(chip, CHIP_RK292X)) { + chipType = RK292X_DEVICE; + } else if (!strcmp(chip, CHIP_RK30)) { + chipType = RK30_DEVICE; + } else if (!strcmp(chip, CHIP_RK30B)) { + chipType = RK30B_DEVICE; + } else if (!strcmp(chip, CHIP_RK31)) { + chipType = RK31_DEVICE; + } else if (!strcmp(chip, CHIP_RK32)) { + chipType = RK32_DEVICE; + } else { + chipType = convertChipType(chip + 2); + } + +end: + printf("type:0x%x\n", chipType); + if (chipType == RKNONE_DEVICE) { + printf("chip type not support!\n"); + } + return chipType; +} + +static inline void getBoothdr(rk_boot_header* hdr) { + memset(hdr, 0, sizeof(rk_boot_header)); + hdr->tag = TAG; + hdr->size = sizeof(rk_boot_header); + hdr->version = (getBCD(gOpts.major) << 8) | getBCD(gOpts.minor); + hdr->mergerVersion = MERGER_VERSION; + hdr->releaseTime = getTime(); + hdr->chipType = getChipType(gOpts.chip); + + hdr->code471Num = gOpts.code471Num; + hdr->code471Offset = sizeof(rk_boot_header); + hdr->code471Size = sizeof(rk_boot_entry); + + hdr->code472Num = gOpts.code472Num; + hdr->code472Offset = hdr->code471Offset + gOpts.code471Num * hdr->code471Size; + hdr->code472Size = sizeof(rk_boot_entry); + + hdr->loaderNum = gOpts.loaderNum; + hdr->loaderOffset = hdr->code472Offset + gOpts.code472Num * hdr->code472Size; + hdr->loaderSize = sizeof(rk_boot_entry); +#ifndef USE_P_RC4 + hdr->rc4Flag = 1; +#endif +} + +static inline uint32_t getCrc(const char* path) { + uint32_t size = 0; + uint32_t crc = 0; + + FILE* file = fopen(path, "rb"); + getFileSize(path, &size); + if (!file) + goto end; + if (!fread(gBuf, size, 1, file)) + goto end; + crc = CRC_32(gBuf, size); + printf("crc:0x%08x\n", crc); +end: + if (file) + fclose(file); + return crc; +} + +bool mergeBoot(void) { + uint32_t dataOffset; + bool ret = false; + int i; + FILE* outFile; + uint32_t crc; + rk_boot_header hdr; + + if (!initOpts()) + return false; + { + char* subfix = strstr(gOpts.outPath, OUT_SUBFIX); + char version[MAX_LINE_LEN]; + snprintf(version, sizeof(version), "%s", gSubfix); + if (subfix && !strcmp(subfix, OUT_SUBFIX)) { + subfix[0] = '\0'; + } + strcat(gOpts.outPath, version); + printf("fix opt:%s\n", gOpts.outPath); + } + + printf("---------------\nUSING CONFIG:\n"); + printOpts(stdout); + printf("---------------\n\n"); + + + outFile = fopen(gOpts.outPath, "wb+"); + if (!outFile) { + printf("open out file(%s) failed\n", gOpts.outPath); + goto end; + } + + getBoothdr(&hdr); + printf("write hdr\n"); + fwrite(&hdr, 1, sizeof(rk_boot_header), outFile); + + dataOffset = sizeof(rk_boot_header) + + (gOpts.code471Num + gOpts.code472Num + gOpts.loaderNum) * + sizeof(rk_boot_entry); + + printf("write code 471 entry\n"); + for (i=0; idataOffset, SEEK_SET); + size = entry->dataSize; + if (!fread(gBuf, size, 1, inFile)) + goto end; + if (entry->type == ENTRY_LOADER) { + for(i=0; iSearch(RKUSB_MASKROM | RKUSB_LOADER); if (cnt < 1) {