// egontool.cpp : Defines the entry point for the console application. // #include #include #include #if defined (__GNUC__) /* GNU Compiler */ #include #define ATTRPACKED __attribute__ ((packed)) #else #define ATTRPACKED typedef unsigned int uint32_t; typedef unsigned char uint8_t; #endif /* __GNUC__ */ static int targetRV = 0; static int targetAARCH64 = 0; static int targetOLD = 0; static unsigned long resetHandler = 0x00020100; static unsigned long baseAddress = 0x00020000; /* boot_file_head copied from mksunxiboot */ /* boot head definition from sun4i boot code */ typedef struct boot_file_head { uint32_t jump_instruction; // +0000 one intruction jumping to real code uint8_t magic[8]; // +0004 "eGON.BT0" or "eGON.BT1", not C-style string. uint32_t check_sum; // +000C generated by PC uint32_t length; // +0010 generated by PC // Size of Boot0, it's must be 8-KiB aligned in NAND and 512-Bytes aligned in MMC uint32_t pub_head_size; // +0014 the size of boot_file_head_t uint32_t pub_head_vsn; // +0018 the version of boot_file_head_t uint32_t file_head_vsn; // +001C the version of boot0_file_head_t or boot1_file_head_t uint32_t Boot_vsn; // +0020 Boot version uint32_t eGON_vsn; // +0024 eGON version uint8_t platform[8]; // +0028 platform information } ATTRPACKED boot_file_head_t; static uint32_t alignup(uint32_t size, uint32_t page) { return (size + page - 1) & ~ (page - 1); } static void fillpad(FILE * fp, long size) { while (size --) { fputc(0x00, fp); } } static void place_uint32_le(void * buff, uint32_t v) { uint8_t * const p = (uint8_t * const) buff; p [0] = (v >> 0); p [1] = (v >> 8); p [2] = (v >> 16); p [3] = (v >> 24); } static uint32_t get_uint32_le(const void * buff) { const uint8_t * const p = (const uint8_t * const) buff; uint32_t v = 0; v = v * 256 + p [3]; v = v * 256 + p [2]; v = v * 256 + p [1]; v = v * 256 + p [0]; return v; } static uint32_t cks(const void * buff, unsigned size, uint32_t sum) { const uint32_t * p = (const uint32_t *) buff; size /= 4; while (size --) sum += * p ++; return sum; } static int process( FILE * infile, FILE * outfile) { boot_file_head_t head; static const uint8_t magic_eGON_BT0 [8] = { 'e', 'G', 'O', 'N', '.', 'B', 'T', '0' }; /* eGON.BT0 */ static const uint8_t pub_head_vsn3 [8] = { '3', '0', '0', '0' }; /* 3000 */ static const uint8_t platform4 [8] = { '\0', '\0', '\0', '\0', '4', '.', '0', '\0' }; /* 4.0 */ const unsigned execoffset = resetHandler - baseAddress; long binsize; long silesizealigned; uint32_t check_sum; if (execoffset % 4) { fprintf(stderr, "ResetHandler offset not aligned to 4 (0x%08X)\n", execoffset); return 1; } if (resetHandler < baseAddress) { fprintf(stderr, "Wrong parameters: resetHandler=0x%08X, baseAddress=0x%08X\n", resetHandler, baseAddress); return 1; } // todo: add range check for execoffset fprintf(stderr, "resetHandler=0x%08X, baseAddress=0x%08X\n", resetHandler, baseAddress); fseek(infile, 0, SEEK_END); binsize = ftell(infile); silesizealigned = alignup(binsize + execoffset, 8 * 1024); fprintf(stderr, "Okay open file: original:%ld aligned:%ld\n", binsize, silesizealigned); { long i; /* checksum calculate */ check_sum = 0; rewind(infile); for (i = 0; i < binsize;) { enum { CHUNKSIZE = 256 }; uint8_t buff [CHUNKSIZE]; unsigned chunk = CHUNKSIZE > (binsize - i) ? (binsize - i) : CHUNKSIZE; memset(buff + chunk, 0x00, CHUNKSIZE - chunk); fread(buff, chunk, 1, infile); check_sum = cks(buff, CHUNKSIZE, check_sum); i += chunk; } } /* Fill head */ memset(& head, 0x00, sizeof head); if (targetRV) place_uint32_le(& head.jump_instruction, 0x6F | (execoffset << 20)); /// Jump to $ + 0x0100 else if (targetAARCH64) place_uint32_le(& head.jump_instruction, 0x14000000 | ((execoffset / 4))); /// Jump to $ + 0x0100 else place_uint32_le(& head.jump_instruction, 0xEA000000 | (execoffset - 8) / 4); /// Jump to $ + 0x0100 memcpy(& head.magic, magic_eGON_BT0, 8); place_uint32_le(& head.check_sum, 0x5F0A6C39);//check_sum; place_uint32_le(& head.length, silesizealigned);//binsize; place_uint32_le(& head.pub_head_size, sizeof head); if (targetOLD) { // A64 //place_uint32_le(& head.pub_head_size, 0x014C5053); //place_uint32_le(& head.file_head_vsn, 0x000F0000); //memcpy(& head.platform, platform, sizeof head.platform); } else { //memcpy(& head.pub_head_vsn, pub_head_vsn3, sizeof head.pub_head_vsn);// Not need for T507 memcpy(& head.platform, platform4, sizeof head.platform); // need for T507 } check_sum = cks((const uint8_t *) & head, sizeof head, check_sum); place_uint32_le(& head.check_sum, check_sum); fwrite(& head, sizeof head, 1, outfile); fillpad(outfile, execoffset - sizeof head); { long i; /* copy file */ rewind(infile); for (i = 0; i < binsize; ) { enum { CHUNKSIZE = 256 }; uint8_t buff [CHUNKSIZE]; unsigned chunk = CHUNKSIZE > (binsize - i) ? (binsize - i) : CHUNKSIZE; fread(buff, chunk, 1, infile); fwrite(buff, chunk, 1, outfile); i += chunk; } } fillpad(outfile, silesizealigned - binsize - execoffset); fprintf(stderr, "Okay processing... %08X %08X\n", binsize, silesizealigned); return 0; } static void printfield32(const void * buff, const char * name, unsigned offset) { printf("%04X: '%-12s'=0x%08X\n", offset, name, get_uint32_le((const uint8_t *) buff + offset)); } static void printfile(FILE * fp) { boot_file_head_t head = { 0 }; size_t n; n = fread(& head, sizeof head, 1, fp); if (n < 1) { fprintf(stderr, "Not enough data (sizeof head=%d, n=%d)\n", sizeof head, n); return; } printf("magic: '%8.8s'\n", head.magic); printf("length: %u (0x%x) bytes\n", (unsigned) head.length, (unsigned) head.length); printfield32(& head, "jump_instruction", offsetof(boot_file_head_t, jump_instruction)); printfield32(& head, "check_sum", offsetof(boot_file_head_t, check_sum)); printfield32(& head, "length", offsetof(boot_file_head_t, length)); printfield32(& head, "pub_head_size", offsetof(boot_file_head_t, pub_head_size)); printfield32(& head, "pub_head_vsn", offsetof(boot_file_head_t, pub_head_vsn)); printfield32(& head, "file_head_vsn", offsetof(boot_file_head_t, file_head_vsn)); printfield32(& head, "Boot_vsn", offsetof(boot_file_head_t, Boot_vsn)); printfield32(& head, "eGON_vsn", offsetof(boot_file_head_t, eGON_vsn)); } static int printFLAG; int main(int argc, char* argv[]) { for (;;) { if (0) ; else if (argc > 2 && strcmp(argv [1], "-reset") == 0) { ++ argv; -- argc; resetHandler = strtoul(argv [1], NULL, 0); ++ argv; -- argc; } else if (argc > 2 && strcmp(argv [1], "-base") == 0) { ++ argv; -- argc; baseAddress = strtoul(argv [1], NULL, 0); ++ argv; -- argc; } else if (argc > 1 && strcmp(argv [1], "-old") == 0) { ++ argv; -- argc; targetOLD = 1; //fprintf(stderr, "RISC-V header generate\n"); } else if (argc > 1 && strcmp(argv [1], "-rv") == 0) { ++ argv; -- argc; targetRV = 1; //fprintf(stderr, "RISC-V header generate\n"); } else if (argc > 1 && strcmp(argv [1], "-print") == 0) { ++ argv; -- argc; printFLAG = 1; //fprintf(stderr, "RISC-V header generate\n"); } else if (argc > 1 && strcmp(argv [1], "-aarch64") == 0) { ++ argv; -- argc; targetAARCH64 = 1; //fprintf(stderr, "RISC-V header generate\n"); } else { break; } } if (printFLAG && argc >= 1) { int i; const char * const infilename = argv [1]; FILE * infile = fopen(infilename,"rb"); if (infile == NULL) { fprintf(stderr, "Can not open file '%s'...\n", infilename); return 1; } printfile(infile); // fseek(infile, 0x38, SEEK_SET); // for (i = 0; i < 40; ++ i) // { // uint32_t v; // fread(& v, 1, 4, infile); // printf(".xxx%i = 0x%08X, /* %i */,\n", i, v, i); // // } fclose(infile); return 0; } if (argc < 3) return 1; else { const char * const infilename = argv [1]; //"../../build/allwinner_t113_s3/tc1_t113s3_boot.bin"; const char * const outfilename = argv [2]; //"../../build/allwinner_t113_s3/fsbl.bt0"; int code; FILE * infile = fopen(infilename,"rb"); FILE * outfile = fopen(outfilename,"wb"); if (infile == NULL || outfile == NULL) { fprintf(stderr, "Can not open files...\n"); return 1; } code = process(infile, outfile); fclose(outfile); fclose(infile); return code; } return 0; }