#include #include #include #include #include #define VERSION "v0.3" /* time field stucture */ struct rktime_t { uint16_t year; uint16_t month; uint16_t day; uint16_t hour; uint16_t minute; uint16_t second; }; /* Rock27Boot.bin header structure */ struct rkboot_info_t { char sign[32]; uint8_t check_values[16]; struct rktime_t time; uint32_t ui_master_version; uint32_t ui_slave_version; uint32_t s1_offset; int32_t s1_len; uint32_t s2_offset; int32_t s2_len; uint32_t s3_offset; int32_t s3_len; uint32_t s4_offset; int32_t s4_len; uint32_t version_flag; }; /* actions */ enum { NONE = 0, INFO = 1, EXTRACT = 2, SCRAMBLE = 4 }; /* scramble mode */ enum { CONTINOUS_ENC, /* scramble whole block at once */ PAGE_ENC /* nand bootloader is scrambled in 0x200 chunks */ }; /* scrambling/descrambling reverse engineered by AleMaxx */ static void encode_page(uint8_t *inpg, uint8_t *outpg, const int size) { uint8_t key[] = { 0x7C, 0x4E, 0x03, 0x04, 0x55, 0x05, 0x09, 0x07, 0x2D, 0x2C, 0x7B, 0x38, 0x17, 0x0D, 0x17, 0x11 }; int i, i3, x, val, idx; uint8_t key1[0x100]; uint8_t key2[0x100]; for (i=0; i<0x100; i++) { key1[i] = i; key2[i] = key[i&0xf]; } i3 = 0; for (i=0; i<0x100; i++) { x = key1[i]; i3 = key1[i] + i3; i3 += key2[i]; i3 &= 0xff; key1[i] = key1[i3]; key1[i3] = x; } idx = 0; for (i=0; i= 0x200) { encode_page((uint8_t *)buff_ptr, (uint8_t *)buff_ptr, 0x200); buff_ptr += 0x200; len -= 0x200; } } encode_page((uint8_t *)buff_ptr, (uint8_t *)buff_ptr, len); } return buff; } static void usage(void) { printf("Usage: rkboottool [options] Rock27Boot.bin\n"); printf("-h|--help This help message\n"); printf("-e|--extract Extract binary images from Rock27Boot.bin file\n"); printf("-d|--descramble Descramble extracted binary images\n"); printf("-i|--info Print info about Rock27Boot.bin file\n"); printf("\n"); printf("Usually you would like to use -d -e together to obtain raw binary\n"); printf("(out files rkboot_s1.bin, rkboot_s2.bin, rkboot_s3.bin, rkboot_s4.bin)\n"); } int main (int argc, char **argv) { struct rkboot_info_t rkboot_info; FILE *fp_in, *fp_out; int32_t i = 0, action = NONE; int32_t ret; void *buff; char *in_filename = NULL; if ( argc < 2 ) { usage(); return -1; } /* print banner */ fprintf(stderr,"rkboottool " VERSION "\n"); fprintf(stderr,"(C) Marcin Bukat 2011\n"); fprintf(stderr,"This is free software; see the source for copying conditions. There is NO\n"); fprintf(stderr,"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"); /* arguments handling */ while (i < argc) { if ((strcmp(argv[i],"-i")==0) || (strcmp(argv[i],"--info")==0)) { action |= INFO; } else if ((strcmp(argv[i],"-e")==0) || (strcmp(argv[i],"--extract")==0)) { action |= EXTRACT; } else if ((strcmp(argv[i],"-d")==0) || (strcmp(argv[i],"--descramble")==0)) { action |= SCRAMBLE; } else if ((strcmp(argv[i],"-h")==0) || (strcmp(argv[i],"--help")==0)) { usage(); return 0; } else if ( argv[i][0] != '-' ) { /* file argument */ in_filename = argv[i]; } i++; } if ( (fp_in = fopen(in_filename, "rb")) == NULL ) { fprintf(stderr, "error: can't open %s file for reading\n", in_filename); return -1; } ret = fread(&rkboot_info, 1, sizeof(rkboot_info), fp_in); if (ret != sizeof(rkboot_info)) { fclose(fp_in); fprintf(stderr, "error: can't read %s file header\n", in_filename); fprintf(stderr, "read %d, expected %d\n", ret, sizeof(rkboot_info)); return -2; } if (action & INFO) { printf("file: %s\n", in_filename); printf("signature: %s\n", rkboot_info.sign); printf("check bytes: "); for (i = 0; i < 16; i++) printf("0x%0x ", rkboot_info.check_values[i]); printf("\n"); printf("timestamp %d.%d.%d %d:%d:%d\n", rkboot_info.time.day, rkboot_info.time.month, rkboot_info.time.year, rkboot_info.time.hour, rkboot_info.time.minute, rkboot_info.time.second); printf("UI master version: 0x%0x\n", rkboot_info.ui_master_version); printf("UI slave version: 0x%0x\n", rkboot_info.ui_slave_version); printf("s1 data offset: 0x%0x\n", rkboot_info.s1_offset); printf("s1 data len: 0x%0x\n", rkboot_info.s1_len); printf("s2 offset: 0x%0x\n", rkboot_info.s2_offset); printf("s2 len: 0x%0x\n", rkboot_info.s2_len); printf("s3 offset: 0x%0x\n", rkboot_info.s3_offset); printf("s3 len: 0x%0x\n", rkboot_info.s3_len); printf("s4 offset: 0x%0x\n", rkboot_info.s4_offset); printf("s4 len: 0x%0x\n", rkboot_info.s4_len); printf("UI version flag: 0x%0x\n", rkboot_info.version_flag); } if (action & EXTRACT) { /* first stage */ buff = binary_extract(fp_in, rkboot_info.s1_offset, rkboot_info.s1_len, action & SCRAMBLE, CONTINOUS_ENC); if ( buff == NULL ) { fclose(fp_in); fprintf(stderr, "error: can't extract image\n"); return -2; } /* output */ if ((fp_out = fopen("rkboot_s1.bin", "wb")) == NULL) { free(buff); fclose(fp_in); fprintf(stderr, "[error]: can't open rkboot_s1.bin for writing\n"); return -3; } fwrite(buff, 1, rkboot_info.s1_len, fp_out); fprintf(stderr, "[info]: extracted rkboot_s1.bin file\n"); free(buff); fclose(fp_out); /* second stage */ buff = binary_extract(fp_in, rkboot_info.s2_offset, rkboot_info.s2_len, action & SCRAMBLE, CONTINOUS_ENC); if ( buff == NULL ) { fclose(fp_in); fprintf(stderr, "error: can't extract image\n"); return -2; } if ((fp_out = fopen("rkboot_s2.bin", "wb")) == NULL) { free(buff); fclose(fp_in); fprintf(stderr, "[error]: can't open rkboot_s2.bin for writing\n"); return -4; } fwrite(buff, 1, rkboot_info.s2_len, fp_out); fprintf(stderr, "[info]: extracted rkboot_s2.bin file\n"); free(buff); fclose(fp_out); /* third stage */ buff = binary_extract(fp_in, rkboot_info.s3_offset, rkboot_info.s3_len, action & SCRAMBLE, PAGE_ENC); if ( buff == NULL ) { fclose(fp_in); fprintf(stderr, "[error]: can't extract image.\n"); return -2; } if ((fp_out = fopen("rkboot_s3.bin", "wb")) == NULL) { free(buff); fclose(fp_in); fprintf(stderr, "[error]: can't open rkboot_s3.bin for writing\n"); return -4; } fwrite(buff, 1, rkboot_info.s3_len, fp_out); fprintf(stderr, "[info]: extracted rkboot_s3.bin file\n"); free(buff); fclose(fp_out); /* forth stage */ buff = binary_extract(fp_in, rkboot_info.s4_offset, rkboot_info.s4_len, action & SCRAMBLE, CONTINOUS_ENC); if ( buff == NULL ) { fclose(fp_in); fprintf(stderr, "[error]: can't extract image\n"); return -2; } if ((fp_out = fopen("rkboot_s4.bin", "wb")) == NULL) { free(buff); fclose(fp_in); fprintf(stderr, "[error]: can't open rkboot_s4.bin for writing\n"); return -4; } fwrite(buff, 1, rkboot_info.s4_len, fp_out); fprintf(stderr, "[info]: extracted rkboot_s4.bin file\n"); free(buff); fclose(fp_out); } fclose(fp_in); return 0; }