From 8f4202db285b2139cfee6269b838733d6d2a2306 Mon Sep 17 00:00:00 2001 From: Marcin Bukat Date: Mon, 30 May 2011 21:10:43 +0000 Subject: Rockchip rk27xx utils git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29936 a1c6a512-1295-4272-9138-f99709370657 --- utils/rk27utils/rkboottool/Makefile | 7 + utils/rk27utils/rkboottool/rkboottool.c | 360 ++++++++++++++++++++++++++++++++ 2 files changed, 367 insertions(+) create mode 100644 utils/rk27utils/rkboottool/Makefile create mode 100644 utils/rk27utils/rkboottool/rkboottool.c (limited to 'utils/rk27utils/rkboottool') diff --git a/utils/rk27utils/rkboottool/Makefile b/utils/rk27utils/rkboottool/Makefile new file mode 100644 index 0000000000..895dfc87cc --- /dev/null +++ b/utils/rk27utils/rkboottool/Makefile @@ -0,0 +1,7 @@ +all: rkboottool + +rkboottool: rkboottool.c + gcc -g -std=c99 -o $@ -W -Wall $^ + +clean: + rm -fr rkboottool diff --git a/utils/rk27utils/rkboottool/rkboottool.c b/utils/rk27utils/rkboottool/rkboottool.c new file mode 100644 index 0000000000..ad08b0b5f6 --- /dev/null +++ b/utils/rk27utils/rkboottool/rkboottool.c @@ -0,0 +1,360 @@ +#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; +} + -- cgit