summaryrefslogtreecommitdiffstats
path: root/utils/rk27utils/rkboottool/rkboottool.c
diff options
context:
space:
mode:
authorMarcin Bukat <marcin.bukat@gmail.com>2011-05-30 21:10:43 +0000
committerMarcin Bukat <marcin.bukat@gmail.com>2011-05-30 21:10:43 +0000
commit8f4202db285b2139cfee6269b838733d6d2a2306 (patch)
treea362bd367c35a03928b68485df0188e637e09ea3 /utils/rk27utils/rkboottool/rkboottool.c
parent976a1699da373f01dabc9353b34aef261ebf740f (diff)
downloadrockbox-8f4202db285b2139cfee6269b838733d6d2a2306.tar.gz
rockbox-8f4202db285b2139cfee6269b838733d6d2a2306.zip
Rockchip rk27xx utils
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29936 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'utils/rk27utils/rkboottool/rkboottool.c')
-rw-r--r--utils/rk27utils/rkboottool/rkboottool.c360
1 files changed, 360 insertions, 0 deletions
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 <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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<size; i++) {
+ x = key1[(i+1) & 0xff];
+ val = x;
+ idx = (x + idx) & 0xff;
+ key1[(i+1) & 0xff] = key1[idx];
+ key1[idx] = (x & 0xff);
+ val = (key1[(i+1)&0xff] + x) & 0xff;
+ val = key1[val];
+ outpg[i] = val ^ inpg[i];
+ }
+}
+
+static void *binary_extract(FILE *fp, uint32_t offset, uint32_t len, int descramble, int encode_mode)
+{
+ void *buff, *buff_ptr;
+ uint32_t ret;
+
+ if ((fp == NULL) || len == 0)
+ return NULL;
+
+ /* allocate buff */
+ if ((buff = malloc(len)) == NULL)
+ return NULL;
+
+ /* seek to the begining of the data */
+ fseek(fp, offset, SEEK_SET);
+
+ /* read into the buffer */
+ ret = fread(buff, 1, len, fp);
+
+ if (ret != len)
+ {
+ free(buff);
+ return NULL;
+ }
+
+ /* descramble */
+ if ( descramble )
+ {
+ buff_ptr = buff;
+ if (encode_mode == PAGE_ENC)
+ {
+ while (len >= 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;
+}
+