summaryrefslogtreecommitdiff
path: root/utils
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
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')
-rw-r--r--utils/rk27utils/README37
-rw-r--r--utils/rk27utils/rk27load/Makefile7
-rw-r--r--utils/rk27utils/rk27load/checksum.c35
-rw-r--r--utils/rk27utils/rk27load/checksum.h1
-rw-r--r--utils/rk27utils/rk27load/common.c16
-rw-r--r--utils/rk27utils/rk27load/common.h1
-rw-r--r--utils/rk27utils/rk27load/main.c165
-rw-r--r--utils/rk27utils/rk27load/rk27load.h11
-rw-r--r--utils/rk27utils/rk27load/scramble.c46
-rw-r--r--utils/rk27utils/rk27load/scramble.h1
-rw-r--r--utils/rk27utils/rk27load/stage1/Makefile48
-rw-r--r--utils/rk27utils/rk27load/stage1/main.S42
-rw-r--r--utils/rk27utils/rk27load/stage1/stage1.lds23
-rw-r--r--utils/rk27utils/rk27load/stage1_upload.c113
-rw-r--r--utils/rk27utils/rk27load/stage1_upload.h3
-rw-r--r--utils/rk27utils/rk27load/stage2/Makefile48
-rw-r--r--utils/rk27utils/rk27load/stage2/crt0.S55
-rw-r--r--utils/rk27utils/rk27load/stage2/irq.S103
-rw-r--r--utils/rk27utils/rk27load/stage2/main.S89
-rw-r--r--utils/rk27utils/rk27load/stage2/stage2.lds40
-rw-r--r--utils/rk27utils/rk27load/stage2_upload.c102
-rw-r--r--utils/rk27utils/rk27load/stage2_upload.h3
-rw-r--r--utils/rk27utils/rk27load/stage3_upload.c93
-rw-r--r--utils/rk27utils/rk27load/stage3_upload.h1
-rw-r--r--utils/rk27utils/rkboottool/Makefile7
-rw-r--r--utils/rk27utils/rkboottool/rkboottool.c360
-rw-r--r--utils/rk27utils/rkusbtool/Makefile7
-rw-r--r--utils/rk27utils/rkusbtool/rkusbtool.c388
28 files changed, 1845 insertions, 0 deletions
diff --git a/utils/rk27utils/README b/utils/rk27utils/README
new file mode 100644
index 0000000000..a43d69a88f
--- /dev/null
+++ b/utils/rk27utils/README
@@ -0,0 +1,37 @@
1This is the collection of small utilities needed to hack Rockchip rk27xx
2series based DAPs. This tools were tested on linux only.
3
4
5rk27load
6This directory contains tool which can send arbitrary image(s) to the device
7in rockchip recovery mode (VID:PID 0x071B:0x3201).
8
9The first image can not exceed 510 bytes (+2 bytes checksum) and entry
10point is 0x18020e00. Usually this code is used to configure SDRAM controller.
11One can use first stage image extracted from Rock27Boot.bin file (a bit
12more sofisticated) or the one provided in rk27load/stage1 directory.
13
14The second image is loaded at the begining of the dram (0x60000000)
15and executed. For some reason (which is still unclear) the size of
162nd stage image is limited to about 3-4 kB.
17
18You can find example of custom 2nd stage image in rk27load/stage2 directory.
19The purpose of this image is to configure bulk transfer and allow to
20load usercode without size restriction mentioned above (the max size
21is 8MB actually). The entry point of usercode is 0x60000000.
22
23You need libusb 1.0 + header files in order to compile this utility.
24You need working arm-eabi crosscompiler in order to compile stage1/stage2
25bootloader binaries (but You should have one already if You tinker whith this)
26
27
28rkboottool
29This directory contains tool which allows to extract (and decrypt) images
30stored in Rock27Boot.bin recovery file.
31
32
33rkusbtool
34This directory contains tool which sends custom scsi commands to the
35rockchip player.
36
37You need libusb-1.0 + header files in order to compile this utility.
diff --git a/utils/rk27utils/rk27load/Makefile b/utils/rk27utils/rk27load/Makefile
new file mode 100644
index 0000000000..f777e76c36
--- /dev/null
+++ b/utils/rk27utils/rk27load/Makefile
@@ -0,0 +1,7 @@
1all: rk27load
2
3rk27load: main.c scramble.c checksum.c common.c stage1_upload.c stage2_upload.c stage3_upload.c
4 gcc -g -std=c99 -o $@ -W -Wall -lusb-1.0 -I/usr/include/libusb-1.0/ $^
5
6clean:
7 rm -fr *.o rk27load
diff --git a/utils/rk27utils/rk27load/checksum.c b/utils/rk27utils/rk27load/checksum.c
new file mode 100644
index 0000000000..f0fe59350e
--- /dev/null
+++ b/utils/rk27utils/rk27load/checksum.c
@@ -0,0 +1,35 @@
1#include <stdint.h>
2#include "checksum.h"
3
4uint16_t checksum(void *buff, uint32_t size)
5{
6 uint32_t r2 = 0xffff;
7 uint32_t r3 = 0;
8 uint32_t i, j;
9
10 for (i=0; i<size; i++) {
11 r3 = 0x80;
12 for (j=0; j<8; j++) {
13 if ((r2 & 0x8000) != 0) {
14 r2 <<= 17;
15 r2 >>= 16;
16 r2 ^= 0x1000;
17 r2 ^= 0x21;
18 }
19 else {
20 r2 <<= 17;
21 r2 >>= 16;
22 }
23
24 if ((((uint8_t *)buff)[i] & r3) != 0) {
25 r2 ^= 0x1000;
26 r2 ^= 0x21;
27 }
28
29 r3 >>= 1;
30 }
31 }
32
33 return r2 & 0xffff;
34}
35
diff --git a/utils/rk27utils/rk27load/checksum.h b/utils/rk27utils/rk27load/checksum.h
new file mode 100644
index 0000000000..468ca6643e
--- /dev/null
+++ b/utils/rk27utils/rk27load/checksum.h
@@ -0,0 +1 @@
uint16_t checksum(void *buff, uint32_t size);
diff --git a/utils/rk27utils/rk27load/common.c b/utils/rk27utils/rk27load/common.c
new file mode 100644
index 0000000000..b97cfbcd79
--- /dev/null
+++ b/utils/rk27utils/rk27load/common.c
@@ -0,0 +1,16 @@
1#include <stdint.h>
2#include <stdio.h>
3
4#include "common.h"
5
6uint32_t filesize(FILE * f)
7{
8 uint32_t filesize;
9
10 fseek(f, 0, SEEK_END);
11 filesize = ftell(f);
12 fseek(f, 0, SEEK_SET);
13
14 return filesize;
15}
16
diff --git a/utils/rk27utils/rk27load/common.h b/utils/rk27utils/rk27load/common.h
new file mode 100644
index 0000000000..f22ec7de40
--- /dev/null
+++ b/utils/rk27utils/rk27load/common.h
@@ -0,0 +1 @@
uint32_t filesize(FILE * f);
diff --git a/utils/rk27utils/rk27load/main.c b/utils/rk27utils/rk27load/main.c
new file mode 100644
index 0000000000..d183ae2df1
--- /dev/null
+++ b/utils/rk27utils/rk27load/main.c
@@ -0,0 +1,165 @@
1#include <stdlib.h>
2#include <stdio.h>
3#include <string.h>
4#include <stdint.h>
5#include <stdbool.h>
6
7#include <libusb.h>
8
9#include "rk27load.h"
10#include "common.h"
11#include "stage1_upload.h"
12#include "stage2_upload.h"
13#include "stage3_upload.h"
14
15#define VERSION "v0.2"
16
17enum {
18 NONE = 0,
19 ENCODE_S1 = 1,
20 ENCODE_S2 = 2
21};
22
23static void usage(char *name)
24{
25 printf("usage: (sudo) %s [-e1 -e2] -s1 stage1.bin -s2 stage2.bin -s3 usercode.bin\n", name);
26 printf("stage1.bin - binary of the stage1 (sdram init)\n");
27 printf("stage2.bin - binary of the stage2 bootloader\n");
28 printf("usercode.bin - binary of the custom usercode\n");
29 printf("\n");
30 printf("options:\n");
31 printf("-e1 - encode stage1 bootloader\n");
32 printf("-e2 - encode stage2 bootloader\n");
33}
34
35int main(int argc, char **argv)
36{
37 libusb_device_handle *hdev;
38 char *filenames[3];
39 int i=1, action=0, ret=0;
40
41 while (i < argc)
42 {
43 if (strcmp(argv[i],"-e1") == 0)
44 {
45 action |= ENCODE_S1;
46 i++;
47 }
48 else if (strcmp(argv[i],"-e2") == 0)
49 {
50 action |= ENCODE_S2;
51 i++;
52 }
53 else if (strcmp(argv[i],"-s1") == 0)
54 {
55 i++;
56 if (i == argc)
57 {
58 usage(argv[0]);
59 return -1;
60 }
61 filenames[0] = argv[i];
62 printf("%s", argv[i]);
63 i++;
64 }
65 else if (strcmp(argv[i],"-s2") == 0)
66 {
67 i++;
68 if (i == argc)
69 {
70 usage(argv[0]);
71 return -2;
72 }
73 filenames[1] = argv[i];
74 i++;
75 }
76 else if (strcmp(argv[i],"-s3") == 0)
77 {
78 i++;
79 if (i == argc)
80 {
81 usage(argv[0]);
82 return -3;
83 }
84 filenames[2] = argv[i];
85 i++;
86 }
87 else
88 {
89 usage(argv[0]);
90 return -4;
91 }
92 }
93
94
95 fprintf(stderr,"rk27load " VERSION "\n");
96 fprintf(stderr,"(C) Marcin Bukat 2011\n");
97 fprintf(stderr,"Based on rk27load ver. 0.1 written by AleMaxx (alemaxx at hotmail.de)\n\n");
98 fprintf(stderr,"This is free software; see the source for copying conditions. There is NO\n");
99 fprintf(stderr,"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
100
101 /* initialize libusb */
102 libusb_init(NULL);
103
104 /* configure device */
105 fprintf(stderr, "[info]: Initializing device... ");
106 hdev = libusb_open_device_with_vid_pid(NULL, VENDORID, PRODUCTID);
107
108 if (hdev == NULL)
109 {
110 fprintf(stderr, "\n[error]: Could not find rockchip device\n");
111 ret = -2;
112 goto finish;
113 }
114
115 ret = libusb_set_configuration(hdev, 1);
116 if (ret < 0)
117 {
118 fprintf(stderr, "\n[error]: Could not select configuration (1)\n");
119 ret = -3;
120 goto finish;
121 }
122
123 ret = libusb_claim_interface(hdev, 0);
124 if (ret < 0)
125 {
126 fprintf(stderr, "\n[error]: Could not claim interface #0\n");
127 ret = -4;
128 goto finish;
129 }
130
131 ret = libusb_set_interface_alt_setting(hdev, 0, 0);
132 if (ret < 0)
133 {
134 fprintf(stderr, "\n[error]: Could not set alternate interface #0\n");
135 ret = -5;
136 goto finish;
137 }
138
139 fprintf(stderr, "done\n");
140
141
142 ret = upload_stage1_code(hdev, filenames[0], (action & ENCODE_S1));
143 if (ret < 0)
144 goto finish;
145
146 ret = upload_stage2_code(hdev, filenames[1], (action & ENCODE_S2));
147 if (ret < 0)
148 goto finish;
149
150 ret = upload_stage3_code(hdev, filenames[2]);
151 if (ret < 0)
152 goto finish;
153
154 /* done */
155 ret = 0;
156
157 finish:
158 if (hdev != NULL)
159 libusb_close(hdev);
160
161 if (ret < 0)
162 fprintf(stderr, "[error]: Error %d\n", ret);
163
164 return ret;
165}
diff --git a/utils/rk27utils/rk27load/rk27load.h b/utils/rk27utils/rk27load/rk27load.h
new file mode 100644
index 0000000000..8239176a0d
--- /dev/null
+++ b/utils/rk27utils/rk27load/rk27load.h
@@ -0,0 +1,11 @@
1#define USB_TIMEOUT 512
2
3#define VENDORID 0x71b
4#define PRODUCTID 0x3201
5
6#define USB_EP0 0x41
7
8#define VCMD_UPLOAD 0x0c
9#define VCMD_INDEX_STAGE1 0x471
10#define VCMD_INDEX_STAGE2 0x472
11
diff --git a/utils/rk27utils/rk27load/scramble.c b/utils/rk27utils/rk27load/scramble.c
new file mode 100644
index 0000000000..7e5b1518d7
--- /dev/null
+++ b/utils/rk27utils/rk27load/scramble.c
@@ -0,0 +1,46 @@
1#include <stdint.h>
2#include "scramble.h"
3
4void scramble(uint8_t *in, uint8_t *out, const int size)
5{
6 /* table extracted from bootrom */
7 static const uint8_t key[] = {
8 0x7C, 0x4E, 0x03, 0x04,
9 0x55, 0x05, 0x09, 0x07,
10 0x2D, 0x2C, 0x7B, 0x38,
11 0x17, 0x0D, 0x17, 0x11
12 };
13
14 int i, i3, x, val, idx;
15
16 uint8_t key1[0x100];
17 uint8_t key2[0x100];
18
19 for (i=0; i<0x100; i++) {
20 key1[i] = i;
21 key2[i] = key[i&0xf];
22 }
23
24 i3 = 0;
25 for (i=0; i<0x100; i++) {
26 x = key1[i];
27 i3 = key1[i] + i3;
28 i3 += key2[i];
29 i3 &= 0xff;
30 key1[i] = key1[i3];
31 key1[i3] = x;
32 }
33
34 idx = 0;
35 for (i=0; i<size; i++) {
36 x = key1[(i+1) & 0xff];
37 val = x;
38 idx = (x + idx) & 0xff;
39 key1[(i+1) & 0xff] = key1[idx];
40 key1[idx] = (x & 0xff);
41 val = (key1[(i+1)&0xff] + x) & 0xff;
42 val = key1[val];
43 out[i] = val ^ in[i];
44 }
45}
46
diff --git a/utils/rk27utils/rk27load/scramble.h b/utils/rk27utils/rk27load/scramble.h
new file mode 100644
index 0000000000..ed4b291316
--- /dev/null
+++ b/utils/rk27utils/rk27load/scramble.h
@@ -0,0 +1 @@
void scramble(uint8_t *in, uint8_t *out, const int size);
diff --git a/utils/rk27utils/rk27load/stage1/Makefile b/utils/rk27utils/rk27load/stage1/Makefile
new file mode 100644
index 0000000000..5291685032
--- /dev/null
+++ b/utils/rk27utils/rk27load/stage1/Makefile
@@ -0,0 +1,48 @@
1
2TARGET = stage1
3
4TOOLCHAIN = arm-elf-eabi-
5
6CC = $(TOOLCHAIN)gcc
7CPP = $(TOOLCHAIN)cpp
8LD = $(TOOLCHAIN)gcc
9AS = $(TOOLCHAIN)as
10OBJCOPY = $(TOOLCHAIN)objcopy
11OBJDUMP = $(TOOLCHAIN)objdump
12
13CFLAGS = -Wundef -marm -march=armv5te -nostdlib -mfpu=fpa -O0 -c
14#ASFLAGS = -mcpu=arm926ej-s
15
16OBJS = main.o
17LDSCRIPT= stage1.lds
18
19#LIBDIRS = -L../arm/lib/gcc/arm-elf/4.1.0/ -L../lib
20#LIBS = -lgcc
21LIBS =
22LDFLAGS = -Wundef -marm -march=armv5te -T$(LDSCRIPT) -nostartfiles \
23 -mfpu=fpa -nostdlib -Xlinker -Map=$(TARGET).map
24
25all : $(TARGET).bin
26 ls -ls $(TARGET).bin
27
28%.o : %.c
29 $(CC) $(CPPFLAGS) $(CFLAGS) $(INCDIRS) $< -o $@
30
31%.o : %.S
32 $(CC) $(CFLAGS) -c $< -o $@
33
34$(TARGET).elf : $(OBJS)
35 $(LD) $(LDFLAGS) $(OBJS) $(LIBDIRS) $(LIBS) -o $(TARGET).elf
36
37$(TARGET).bin : $(TARGET).elf
38 $(OBJCOPY) -O binary $(TARGET).elf $(TARGET).bin
39
40dasm : $(TARGET).bin
41 $(OBJDUMP) -m arm -D $(TARGET).elf | cat > $(TARGET).asm
42
43clean :
44 rm -f $(OBJS)
45 rm -f $(TARGET).elf
46 rm -f $(TARGET).bin
47 rm -f $(TARGET).asm
48 rm -f $(TARGET).map
diff --git a/utils/rk27utils/rk27load/stage1/main.S b/utils/rk27utils/rk27load/stage1/main.S
new file mode 100644
index 0000000000..44e7e2f914
--- /dev/null
+++ b/utils/rk27utils/rk27load/stage1/main.S
@@ -0,0 +1,42 @@
1.section .text,"ax",%progbits
2.global start
3
4start:
5 msr cpsr_c, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */
6
7pll_setup:
8 mov r0, #0x18000000
9 add r0, r0, #0x1c000
10
11 /* setup ARM core freq = 200MHz */
12 /* AHB bus freq (HCLK) = 100MHz */
13 /* APB bus freq (PCLK) = 50MHz */
14 ldr r1, [r0,#0x14] /* SCU_DIVCON1 */
15 orr r1, #9 /* ARM slow mode, HCLK:PCLK = 2:1 */
16 str r1, [r0,#0x14]
17
18 ldr r1,=0x01970c70 /* (1<<24) | (1<<23) | (23<<16) | (199<<4) */
19 str r1, [r0,#0x08]
20
21 ldr r2,=0x40000
221:
23 ldr r1, [r0,#0x2c] /* SCU_STATUS */
24 tst r1, #1 /* ARM pll lock */
25 bne 1f
26 subs r2, #1
27 bne 1b
281:
29 ldr r1, [r0,#0x14] /* SCU_DIVCON1 */
30 bic r1, #5 /* leave ARM slow mode, ARMclk:HCLK = 2:1 */
31 str r1, [r0,#0x14]
32
33sdram_config:
34 add r0, r0, #0x94000 /* SDRAM base */
35
36 mov r1, #1
37 str r1, [r0,#0x10c] /* MCSDR_BASIC Round-robin, SDRAM width 16bits */
38
39 add r1, #0x10
40 str r1, [r0,#0x108] /* MCSDR_ADDCFG 12 bits row/9 bits col addr */
41
42 mov pc, lr /* we are done, return to bootrom code */
diff --git a/utils/rk27utils/rk27load/stage1/stage1.lds b/utils/rk27utils/rk27load/stage1/stage1.lds
new file mode 100644
index 0000000000..4af8b93c55
--- /dev/null
+++ b/utils/rk27utils/rk27load/stage1/stage1.lds
@@ -0,0 +1,23 @@
1ENTRY(start)
2OUTPUT_FORMAT(elf32-littlearm)
3OUTPUT_ARCH(arm)
4/* STARTUP(crt0.o) */
5
6/* this is where bootrom loads sdram init code */
7MEMORY
8{
9 IRAM : ORIGIN = 0x18200E00, LENGTH = 0x00000200
10}
11
12SECTIONS
13{
14 .text : {
15 *(.text*)
16 *(.glue_7*)
17 } > IRAM
18
19 .data : {
20 *(.rodata*)
21 *(.data*)
22 } > IRAM
23}
diff --git a/utils/rk27utils/rk27load/stage1_upload.c b/utils/rk27utils/rk27load/stage1_upload.c
new file mode 100644
index 0000000000..8eb4ae9e37
--- /dev/null
+++ b/utils/rk27utils/rk27load/stage1_upload.c
@@ -0,0 +1,113 @@
1#include <unistd.h>
2#include <stdio.h>
3#include <stdint.h>
4#include <stdbool.h>
5#include <stdlib.h>
6#include <string.h>
7#include <libusb.h>
8
9#include "rk27load.h"
10#include "common.h"
11#include "scramble.h"
12#include "checksum.h"
13#include "stage1_upload.h"
14
15/* ### upload sdram init code ### */
16int upload_stage1_code(libusb_device_handle *hdev, char *fn_stage1,
17 bool do_scramble)
18{
19 FILE *f;
20 int ret;
21 uint8_t *code;
22 uint32_t codesize;
23 uint16_t cks;
24
25 if ((f = fopen(fn_stage1, "rb")) == NULL)
26 {
27 fprintf(stderr, "[error]: Could not open file \"%s\"\n", fn_stage1);
28 return -10;
29 }
30
31 codesize = filesize(f);
32
33 if (codesize > 0x1fe)
34 {
35 fprintf(stderr, "[error]: Code too big for stage1\n");
36 return -11;
37 }
38
39 fprintf(stderr, "[stage1]: Loading %d bytes (%s) of code... ", codesize, fn_stage1);
40
41 code = (uint8_t *)malloc(0x200);
42 if (code == NULL)
43 {
44 fprintf(stderr, "\n[error]: Out of memory\n");
45 fclose(f);
46 return -12;
47 }
48
49 memset(code, 0, 0x200);
50 if (fread(code, 1, codesize, f) != codesize)
51 {
52 fprintf(stderr, "\n[error]: I/O error\n");
53 fclose(f);
54 free(code);
55 return -13;
56 }
57
58 fprintf(stderr, "done\n");
59 fclose(f);
60
61 /* encode data if requested */
62 if (do_scramble)
63 {
64
65 fprintf(stderr, "[stage1]: Encoding %d bytes of data ... ", codesize);
66 scramble(code, code, codesize);
67 fprintf(stderr, "done\n");
68 }
69
70
71 fprintf(stderr, "[stage1]: codesize = %d (0x%x)\n", codesize, codesize);
72
73 fprintf(stderr, "[stage1]: Calculating checksum... ");
74 cks = checksum((void *)code, codesize);
75 fprintf(stderr, "0x%04x\n", cks);
76 code[0x1fe] = (cks >> 8) & 0xff;
77 code[0x1ff] = cks & 0xff;
78 codesize += 2;
79
80 fprintf(stderr, "[stage1]: Uploading code (%d bytes)... ", codesize);
81
82 ret = libusb_control_transfer(hdev, /* device handle */
83 USB_EP0, /* bmRequestType */
84 VCMD_UPLOAD, /* bRequest */
85 0, /* wValue */
86 VCMD_INDEX_STAGE1, /* wIndex */
87 code, /* data */
88 codesize, /* wLength */
89 USB_TIMEOUT /* timeout */
90 );
91 if (ret < 0)
92 {
93 fprintf(stderr, "\n[error]: Code upload request failed (ret=%d)\n", ret);
94 free(code);
95 return -14;
96 }
97
98 if (ret != (int)codesize)
99 {
100 fprintf(stderr, "\n[error]: Sent %d of %d total\n", ret, codesize);
101 free(code);
102 return -15;
103 }
104
105 sleep(1); /* wait for code to finish */
106 fprintf(stderr, "done\n");
107
108 /* free code */
109 free(code);
110
111 return 0;
112}
113
diff --git a/utils/rk27utils/rk27load/stage1_upload.h b/utils/rk27utils/rk27load/stage1_upload.h
new file mode 100644
index 0000000000..efb1c3407e
--- /dev/null
+++ b/utils/rk27utils/rk27load/stage1_upload.h
@@ -0,0 +1,3 @@
1int upload_stage1_code(libusb_device_handle * hdev, char *fn_stage1,
2 bool do_scramble);
3
diff --git a/utils/rk27utils/rk27load/stage2/Makefile b/utils/rk27utils/rk27load/stage2/Makefile
new file mode 100644
index 0000000000..4b216db2f3
--- /dev/null
+++ b/utils/rk27utils/rk27load/stage2/Makefile
@@ -0,0 +1,48 @@
1
2TARGET = stage2
3
4TOOLCHAIN = arm-elf-eabi-
5
6CC = $(TOOLCHAIN)gcc
7CPP = $(TOOLCHAIN)cpp
8LD = $(TOOLCHAIN)gcc
9AS = $(TOOLCHAIN)as
10OBJCOPY = $(TOOLCHAIN)objcopy
11OBJDUMP = $(TOOLCHAIN)objdump
12
13CFLAGS = -Wundef -marm -march=armv5te -nostdlib -mfpu=fpa -O0 -c
14#ASFLAGS = -mcpu=arm926ej-s
15
16OBJS = crt0.o main.o irq.o
17LDSCRIPT= stage2.lds
18
19#LIBDIRS = -L../arm/lib/gcc/arm-elf/4.1.0/ -L../lib
20#LIBS = -lgcc
21LIBS =
22LDFLAGS = -Wundef -marm -march=armv5te -T$(LDSCRIPT) -nostartfiles \
23 -mfpu=fpa -nostdlib -Xlinker -Map=$(TARGET).map
24
25all : $(TARGET).bin
26 ls -ls $(TARGET).bin
27
28%.o : %.c
29 $(CC) $(CPPFLAGS) $(CFLAGS) $(INCDIRS) $< -o $@
30
31%.o : %.S
32 $(CC) $(CFLAGS) -c $< -o $@
33
34$(TARGET).elf : $(OBJS)
35 $(LD) $(LDFLAGS) $(OBJS) $(LIBDIRS) $(LIBS) -o $(TARGET).elf
36
37$(TARGET).bin : $(TARGET).elf
38 $(OBJCOPY) -O binary $(TARGET).elf $(TARGET).bin
39
40dasm : $(TARGET).bin
41 $(OBJDUMP) -m arm -D $(TARGET).elf | cat > $(TARGET).asm
42
43clean :
44 rm -f $(OBJS)
45 rm -f $(TARGET).elf
46 rm -f $(TARGET).bin
47 rm -f $(TARGET).asm
48 rm -f $(TARGET).map
diff --git a/utils/rk27utils/rk27load/stage2/crt0.S b/utils/rk27utils/rk27load/stage2/crt0.S
new file mode 100644
index 0000000000..c85477546d
--- /dev/null
+++ b/utils/rk27utils/rk27load/stage2/crt0.S
@@ -0,0 +1,55 @@
1//
2// startup code
3//
4//
5
6#define PSR_MODE 0x0000001f
7#define PSR_USR_MODE 0x00000010
8#define PSR_IRQ_MODE 0x00000012
9#define PSR_SVC_MODE 0x00000013
10
11#define PSR_INT_MASK 0x000000c0
12#define PSR_FIQ_DIS 0x00000040
13#define PSR_IRQ_DIS 0x00000080
14
15.section .init.text,"ax",%progbits
16.global start
17.extern _interrupt_disable
18
19// -----------------------------------------------------
20// startup code (setup stacks, branch to main)
21// -----------------------------------------------------
22start:
23 // setup IRQ stack
24 mov r0, #(PSR_IRQ_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
25 msr cpsr, r0
26 ldr sp,=irqstackend
27
28 // setup SVC stack
29 mov r0, #(PSR_SVC_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
30 msr cpsr, r0
31 ldr sp,=stackend
32
33 // disbale interrupts
34 mrs r0, cpsr
35 orr r0, r0, #0xc0
36 msr cpsr_c, r0
37
38 // remap
39 mov r0, #0x18000000
40 add r0, r0, #0x1C000
41 ldr r1,=0xdeadbeef
42 str r1, [r0, #4]
43
44 // relocate itself
45 ldr r0,=_relocstart
46 ldr r1,=_relocend
47 ldr r2,=0x0
481:
49 cmp r1,r0
50 ldrhi r3,[r0],#4
51 strhi r3,[r2],#4
52 bhi 1b
53
54 // continue running in SVC (supervisor mode)
55 ldr pc,=0x0
diff --git a/utils/rk27utils/rk27load/stage2/irq.S b/utils/rk27utils/rk27load/stage2/irq.S
new file mode 100644
index 0000000000..043bf185a5
--- /dev/null
+++ b/utils/rk27utils/rk27load/stage2/irq.S
@@ -0,0 +1,103 @@
1 .section .text
2 .align 4
3
4 .global irq_handler
5 #define BUFF_ADDR 0x60800000
6
7irq_handler:
8 stmfd sp!, {r0-r7, ip, lr}
9
10 // get interrupt number
11 mov r4, #0x18000000
12 add r4, r4, #0x80000
13 ldr r5, [r4, #0x104]
14 and r5, r5, #0x1f
15 cmp r5, #0x10 // UDC interrupt
16
17 bleq udc_irq
18
19 // clear pending interrupt
20 mov r3, #1
21 mov r2, r3, LSL r5
22 str r2, [r4, #0x118]
23
24 ldmfd sp!, {r0-r7, ip, lr}
25 subs pc, lr, #4
26
27udc_irq:
28 stmfd sp!, {r4-r8, lr}
29
30 // handle usb interrupt
31 ldr r4,=0x180A0000
32 ldr r5, [r4, #0x18] // UDC_INTFLAG
33
34 // ep0 in intr
35 tst r5, #0x04
36 beq bulk_recv_intr
37
38 // write_reg32(UDC_TX0STAT, read_reg32(UDC_TX0STAT) & ~0x7FF);
39 ldr r5, [r4, #0x40]
40 mov r5, r5, lsr #10
41 mov r5, r5, lsl #10 // clear clower 10 bits
42 str r5, [r4, #0x40]
43
44 // write_reg32(UDC_DMA0LM_OADDR, (uint32_t)(state.ctrlep_data));
45 mov r5, #0x60000000
46 str r5, [r4, #0x3c]
47
48 // write_reg32(UDC_DMA0CTLO, read_reg32(UDC_DMA0CTLO) | ENP_DMA_START);
49 mov r5, #1
50 str r5, [r4, #0x38]
51
52 ldmfd sp!, {r4-r8, pc}
53
54// bulk out interrupt
55bulk_recv_intr:
56 tst r5, #0x100
57 ldmeqfd sp!, {r4-r8, pc}
58
59 // read UDC_RX1STAT
60 ldr r5, [r4, #0x54]
61 mov r5, r5, lsl #21
62 mov r5, r5, lsr #21 // r5 = length
63
64 ldr r6,=usb_sz
65 ldr r6, [r6]
66 ldr r7, [r6] // r7 = total_code_length expected
67
68 subs r7, r7, r5
69 bne usb_bulk_out1_recv
70
71 // copy from buff to the begining of the ram
72 ldr r0,=BUFF_ADDR
73 ldr r1,[r0,#-4] // size
74
75 ldr r1,=0x800000 // buffer size
76
77 add r1,r1,r0 // end address
78 ldr r2,=0x60000000 // destination
791:
80 cmp r1,r0
81 ldrhi r3,[r0],#4
82 strhi r3,[r2],#4
83 bhi 1b
84
85 // execute user code
86 ldr r0,=0x60000000
87 bx r0 // jump to 0x60000000
88
89usb_bulk_out1_recv:
90 str r7, [r6] // size = size - received
91
92 ldr r6,=usb_write_addr
93 ldr r7, [r6]
94
95 add r7, r7, r5
96 str r7, [r6] // usb_write_addr += length
97
98 str r7, [r4, #0x60] // DMA1LM_OADDR = usb_write_addr
99
100 mov r5, #1
101 str r5, [r4, #0x5c] // DMA1_CTL0 = ENP_DMA_START
102
103 ldmfd sp!, {r4-r8, pc}
diff --git a/utils/rk27utils/rk27load/stage2/main.S b/utils/rk27utils/rk27load/stage2/main.S
new file mode 100644
index 0000000000..c8474b0579
--- /dev/null
+++ b/utils/rk27utils/rk27load/stage2/main.S
@@ -0,0 +1,89 @@
1
2 .section .text
3 .align 4
4
5 .arm
6
7 .global main
8 .global _interrupt_disable
9 .global _interrupt_enable
10
11 .global usb_write_addr
12 .global usb_sz
13
14 #define BUFF_ADDR 0x60800000
15
16// -----------------------------------------------------
17// vector table
18// -----------------------------------------------------
19 ldr pc, =main
20 ldr pc, =main
21 ldr pc, =main
22 ldr pc, =main
23 ldr pc, =main
24 ldr pc, =main
25 ldr pc, =irq_handler
26 ldr pc, =main
27
28// -----------------------------------------------------
29// main
30// -----------------------------------------------------
31main:
32 // turn on usb interrupts
33 mov r0, #0x18000000
34 add r0, r0, #0x80000
35 ldr r1, [r0, #0x10c]
36 orr r1, r1, #0x10000
37 str r1, [r0, #0x10c]
38
39 // enable usb-bulk
40 add r0, r0, #0x20000 // R0 = 0x180A0000 (UDC_BASE)
41
42 // enable EP1, write_reg32(UDC_RX1CON, (0x1 << 8) | RxACKINTEN | RxEPEN);
43 mov r1, #0x190 // bits 8,7,4 -> 0x190
44 str r1, [r0, #0x58]
45
46 // setup receive buffer (must be aligned on dword boundary)
47 ldr r1,=usb_write_addr // write_reg32(UDC_DMA1LM_OADDR, (uint32_t)rx_buff);
48 ldr r1, [r1]
49 str r1, [r0, #0x60] // UDC_DMA1LM_OADDR = usb_write_addr
50
51 // write_reg32(UDC_DMA1CTRLO, read_reg32(UDC_DMA1CTRLO) | ENP_DMA_START);
52 ldr r1, [r0, #0x5c]
53 orr r1, r1, #2
54 str r1, [r0, #0x5c]
55
56 // enable bulk_out1 interrupt
57 ldr r1, [r0, #0x14] // UDC_ENINT
58 orr r1, r1, #0x100 // EN_BOUT1_INTR
59 str r1, [r0, #0x14]
60
61 bl _interrupt_enable
62idle:
63 b idle
64
65// -----------------------------------------------------
66// _interrupt_enable - enables interrupts
67// -----------------------------------------------------
68_interrupt_enable:
69 mrs r0, cpsr
70 bic r0, r0, #0x80
71 msr cpsr_c, r0
72 mov pc, lr
73
74// -----------------------------------------------------
75// _interrupt_disable - disables interrupts
76// -----------------------------------------------------
77_interrupt_disable:
78 mrs r0, cpsr
79 orr r0, r0, #0xc0
80 msr cpsr_c, r0
81 mov pc, lr
82
83
84 .section .data
85usb_write_addr:
86 .word (BUFF_ADDR-4)
87
88usb_sz:
89 .word (BUFF_ADDR-4)
diff --git a/utils/rk27utils/rk27load/stage2/stage2.lds b/utils/rk27utils/rk27load/stage2/stage2.lds
new file mode 100644
index 0000000000..2c07b201f7
--- /dev/null
+++ b/utils/rk27utils/rk27load/stage2/stage2.lds
@@ -0,0 +1,40 @@
1ENTRY(start)
2OUTPUT_FORMAT(elf32-littlearm)
3OUTPUT_ARCH(arm)
4/* STARTUP(crt0.o) */
5
6MEMORY
7{
8 DRAM : ORIGIN = 0x60000000, LENGTH = 0x01000000
9 IRAM : ORIGIN = 0x00000000, LENGTH = 0x00002000
10}
11
12SECTIONS
13{
14 .init.text : {
15 *(.init.text)
16 } > DRAM
17
18 .text : {
19 *(.text*)
20 *(.glue_7*)
21 } > IRAM AT > DRAM
22
23 .data : {
24 *(.data*)
25 } > IRAM AT > DRAM
26
27 _relocstart = LOADADDR(.text);
28 _relocend = LOADADDR(.data) + SIZEOF(.data);
29
30 .stack (NOLOAD) : {
31 . = ALIGN(0x100);
32 *(.stack)
33 stackbegin = .;
34 . += 0x200;
35 stackend = .;
36 irqstackbegin = .;
37 . += 0x200;
38 irqstackend = .;
39 } > IRAM
40}
diff --git a/utils/rk27utils/rk27load/stage2_upload.c b/utils/rk27utils/rk27load/stage2_upload.c
new file mode 100644
index 0000000000..820ad4463c
--- /dev/null
+++ b/utils/rk27utils/rk27load/stage2_upload.c
@@ -0,0 +1,102 @@
1#include <stdio.h>
2#include <stdint.h>
3#include <stdbool.h>
4#include <stdlib.h>
5#include <string.h>
6#include <libusb.h>
7
8#include "rk27load.h"
9#include "common.h"
10#include "scramble.h"
11#include "checksum.h"
12#include "stage2_upload.h"
13
14int upload_stage2_code(libusb_device_handle *hdev, char *fn_stage2,
15 bool do_scramble)
16{
17 FILE *f;
18 uint32_t codesize;
19 uint8_t *code;
20 uint16_t cks;
21 int ret;
22
23 if ((f = fopen(fn_stage2, "rb")) == NULL)
24 {
25 fprintf(stderr, "[error]: Could not open file \"%s\"\n", fn_stage2);
26 return -21;
27 }
28
29 codesize = filesize(f);
30
31 fprintf(stderr, "[stage1]: Loading %d bytes (%s) of code... ", codesize, fn_stage2);
32
33 code = (uint8_t *) malloc(codesize + 0x400);
34 if (code == NULL)
35 {
36 fprintf(stderr, "\n[error]: Out of memory\n");
37 fclose(f);
38 return -22;
39
40 }
41
42 memset(code, 0, codesize + 0x400);
43
44 if (fread(code, 1, codesize, f) != codesize)
45 {
46 fprintf(stderr, "\n[error]: I/O error\n");
47 fclose(f);
48 free(code);
49 return -23;
50 }
51 fprintf(stderr, "done\n");
52 fclose(f);
53
54 codesize = ((codesize + 0x201) & 0xfffffe00) - 2;
55
56 if (do_scramble)
57 {
58 /* encode data if its user code */
59 fprintf(stderr, "[stage2]: Encoding %d bytes data... ", codesize);
60 scramble(code, code, codesize);
61 fprintf(stderr, "done\n");
62 }
63
64 fprintf(stderr, "[stage2]: Calculating checksum... ");
65 cks = checksum(code, codesize);
66 code[codesize + 0] = (cks >> 8) & 0xff;
67 code[codesize + 1] = cks & 0xff;
68 codesize += 2;
69 fprintf(stderr, "0x%04x\n", cks);
70
71 fprintf(stderr, "[stage2]: Uploading code (%d bytes)... ", codesize);
72
73 ret = libusb_control_transfer(hdev, /* device handle */
74 USB_EP0, /* bmRequestType */
75 VCMD_UPLOAD, /* bRequest */
76 0, /* wValue */
77 VCMD_INDEX_STAGE2, /* wIndex */
78 code, /* data */
79 codesize, /* wLength */
80 USB_TIMEOUT /* timeout */
81 );
82
83 if (ret < 0)
84 {
85 fprintf(stderr, "\n[error]: Code upload request failed (ret=%d)\n", ret);
86 free(code);
87 return -24;
88 }
89
90 if (ret != (int)codesize)
91 {
92 fprintf(stderr, "[error]: Sent %d of %d total\n", ret, codesize);
93 free(code);
94 return -25;
95 }
96
97 fprintf(stderr, "done\n");
98
99 free(code);
100 return 0;
101}
102
diff --git a/utils/rk27utils/rk27load/stage2_upload.h b/utils/rk27utils/rk27load/stage2_upload.h
new file mode 100644
index 0000000000..852d17adb2
--- /dev/null
+++ b/utils/rk27utils/rk27load/stage2_upload.h
@@ -0,0 +1,3 @@
1int upload_stage2_code(libusb_device_handle * hdev, char *fn_stage2,
2 bool do_scramble);
3
diff --git a/utils/rk27utils/rk27load/stage3_upload.c b/utils/rk27utils/rk27load/stage3_upload.c
new file mode 100644
index 0000000000..6f10a7c995
--- /dev/null
+++ b/utils/rk27utils/rk27load/stage3_upload.c
@@ -0,0 +1,93 @@
1#include <stdio.h>
2#include <stdint.h>
3#include <stdlib.h>
4#include <string.h>
5#include <libusb.h>
6
7#include "rk27load.h"
8#include "common.h"
9#include "scramble.h"
10#include "checksum.h"
11#include "stage3_upload.h"
12
13int upload_stage3_code(libusb_device_handle *hdev, char *fn_stage3)
14{
15 FILE *f;
16 uint32_t codesize;
17 uint32_t remain;
18 uint8_t *code;
19 uint16_t send_size = 0x200;
20 uint32_t i = 0;
21 int ret, transfered;
22
23 if ((f = fopen(fn_stage3, "rb")) == NULL)
24 {
25 fprintf(stderr, "[error]: Could not open file \"%s\"\n", fn_stage3);
26 return -31;
27 }
28
29 codesize = filesize(f);
30
31 fprintf(stderr, "[stage3]: Loading user code (%d bytes)... ", codesize);
32
33 /* allocate buffer */
34 code = (uint8_t *) malloc(codesize + 0x204);
35 if (code == NULL)
36 {
37 fprintf(stderr, "\n[error]: Out of memory\n");
38 fclose(f);
39 return -32;
40 }
41
42 memset(code, 0, codesize + 0x204);
43 /* read usercode into buffer */
44 if (fread(&code[4], 1, codesize, f) != codesize)
45 {
46 fprintf(stderr, "\n[error]: I/O error\n");
47 fclose(f);
48 free(f);
49 return -33;
50 }
51 fprintf(stderr, "done\n");
52
53 fclose(f);
54
55 /* put code size at the first 4 bytes */
56 codesize += 4;
57 code[0] = codesize & 0xff;
58 code[1] = (codesize >> 8) & 0xff;
59 code[2] = (codesize >> 16) & 0xff;
60 code[3] = (codesize >> 24) & 0xff;
61
62 fprintf(stderr, "[stage3]: Uploading user code (%d bytes)... ", codesize);
63
64 remain = codesize;
65
66 while (remain > 0)
67 {
68 if (remain < 0x200)
69 send_size = remain;
70
71 ret = libusb_bulk_transfer(hdev, /* handle */
72 1, /* EP */
73 &code[i * 0x200], /* data */
74 send_size, /* length */
75 &transfered, /* xfered */
76 USB_TIMEOUT /* timeout */
77 );
78
79 if (ret != LIBUSB_SUCCESS)
80 {
81 fprintf(stderr, "\n[error]: Bulk transfer error (%d, %d)\n", ret, i);
82 free(code);
83 return -34;
84 }
85
86 remain -= send_size;
87 i++;
88 }
89
90 fprintf(stderr,"done (sent %d blocks)\n", i);
91 return 0;
92}
93
diff --git a/utils/rk27utils/rk27load/stage3_upload.h b/utils/rk27utils/rk27load/stage3_upload.h
new file mode 100644
index 0000000000..03f9f0e46a
--- /dev/null
+++ b/utils/rk27utils/rk27load/stage3_upload.h
@@ -0,0 +1 @@
int upload_stage3_code(libusb_device_handle *hdev, char *fn_stage3);
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 @@
1all: rkboottool
2
3rkboottool: rkboottool.c
4 gcc -g -std=c99 -o $@ -W -Wall $^
5
6clean:
7 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 @@
1#include <stdio.h>
2#include <stdint.h>
3#include <stdbool.h>
4#include <stdlib.h>
5#include <string.h>
6
7#define VERSION "v0.3"
8
9/* time field stucture */
10struct rktime_t
11{
12 uint16_t year;
13 uint16_t month;
14 uint16_t day;
15 uint16_t hour;
16 uint16_t minute;
17 uint16_t second;
18};
19
20/* Rock27Boot.bin header structure */
21struct rkboot_info_t
22{
23 char sign[32];
24 uint8_t check_values[16];
25 struct rktime_t time;
26 uint32_t ui_master_version;
27 uint32_t ui_slave_version;
28 uint32_t s1_offset;
29 int32_t s1_len;
30 uint32_t s2_offset;
31 int32_t s2_len;
32 uint32_t s3_offset;
33 int32_t s3_len;
34 uint32_t s4_offset;
35 int32_t s4_len;
36 uint32_t version_flag;
37};
38
39/* actions */
40enum {
41 NONE = 0,
42 INFO = 1,
43 EXTRACT = 2,
44 SCRAMBLE = 4
45};
46
47/* scramble mode */
48enum {
49 CONTINOUS_ENC, /* scramble whole block at once */
50 PAGE_ENC /* nand bootloader is scrambled in 0x200 chunks */
51};
52
53/* scrambling/descrambling reverse engineered by AleMaxx */
54static void encode_page(uint8_t *inpg, uint8_t *outpg, const int size)
55{
56
57uint8_t key[] = {
58 0x7C, 0x4E, 0x03, 0x04,
59 0x55, 0x05, 0x09, 0x07,
60 0x2D, 0x2C, 0x7B, 0x38,
61 0x17, 0x0D, 0x17, 0x11
62};
63 int i, i3, x, val, idx;
64
65 uint8_t key1[0x100];
66 uint8_t key2[0x100];
67
68 for (i=0; i<0x100; i++) {
69 key1[i] = i;
70 key2[i] = key[i&0xf];
71 }
72
73 i3 = 0;
74 for (i=0; i<0x100; i++) {
75 x = key1[i];
76 i3 = key1[i] + i3;
77 i3 += key2[i];
78 i3 &= 0xff;
79 key1[i] = key1[i3];
80 key1[i3] = x;
81 }
82
83 idx = 0;
84 for (i=0; i<size; i++) {
85 x = key1[(i+1) & 0xff];
86 val = x;
87 idx = (x + idx) & 0xff;
88 key1[(i+1) & 0xff] = key1[idx];
89 key1[idx] = (x & 0xff);
90 val = (key1[(i+1)&0xff] + x) & 0xff;
91 val = key1[val];
92 outpg[i] = val ^ inpg[i];
93 }
94}
95
96static void *binary_extract(FILE *fp, uint32_t offset, uint32_t len, int descramble, int encode_mode)
97{
98 void *buff, *buff_ptr;
99 uint32_t ret;
100
101 if ((fp == NULL) || len == 0)
102 return NULL;
103
104 /* allocate buff */
105 if ((buff = malloc(len)) == NULL)
106 return NULL;
107
108 /* seek to the begining of the data */
109 fseek(fp, offset, SEEK_SET);
110
111 /* read into the buffer */
112 ret = fread(buff, 1, len, fp);
113
114 if (ret != len)
115 {
116 free(buff);
117 return NULL;
118 }
119
120 /* descramble */
121 if ( descramble )
122 {
123 buff_ptr = buff;
124 if (encode_mode == PAGE_ENC)
125 {
126 while (len >= 0x200)
127 {
128 encode_page((uint8_t *)buff_ptr,
129 (uint8_t *)buff_ptr,
130 0x200);
131
132 buff_ptr += 0x200;
133 len -= 0x200;
134 }
135 }
136 encode_page((uint8_t *)buff_ptr, (uint8_t *)buff_ptr, len);
137 }
138
139 return buff;
140}
141
142static void usage(void)
143{
144 printf("Usage: rkboottool [options] Rock27Boot.bin\n");
145 printf("-h|--help This help message\n");
146 printf("-e|--extract Extract binary images from Rock27Boot.bin file\n");
147 printf("-d|--descramble Descramble extracted binary images\n");
148 printf("-i|--info Print info about Rock27Boot.bin file\n");
149 printf("\n");
150 printf("Usually you would like to use -d -e together to obtain raw binary\n");
151 printf("(out files rkboot_s1.bin, rkboot_s2.bin, rkboot_s3.bin, rkboot_s4.bin)\n");
152}
153
154int main (int argc, char **argv)
155{
156 struct rkboot_info_t rkboot_info;
157 FILE *fp_in, *fp_out;
158 int32_t i = 0, action = NONE;
159 int32_t ret;
160 void *buff;
161 char *in_filename = NULL;
162
163 if ( argc < 2 )
164 {
165 usage();
166 return -1;
167 }
168
169 /* print banner */
170 fprintf(stderr,"rkboottool " VERSION "\n");
171 fprintf(stderr,"(C) Marcin Bukat 2011\n");
172 fprintf(stderr,"This is free software; see the source for copying conditions. There is NO\n");
173 fprintf(stderr,"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
174
175 /* arguments handling */
176 while (i < argc)
177 {
178 if ((strcmp(argv[i],"-i")==0) || (strcmp(argv[i],"--info")==0))
179 {
180 action |= INFO;
181 }
182 else if ((strcmp(argv[i],"-e")==0) || (strcmp(argv[i],"--extract")==0))
183 {
184 action |= EXTRACT;
185 }
186 else if ((strcmp(argv[i],"-d")==0) || (strcmp(argv[i],"--descramble")==0))
187 {
188 action |= SCRAMBLE;
189 }
190 else if ((strcmp(argv[i],"-h")==0) || (strcmp(argv[i],"--help")==0))
191 {
192 usage();
193 return 0;
194 }
195 else if ( argv[i][0] != '-' )
196 {
197 /* file argument */
198 in_filename = argv[i];
199 }
200 i++;
201 }
202
203 if ( (fp_in = fopen(in_filename, "rb")) == NULL )
204 {
205 fprintf(stderr, "error: can't open %s file for reading\n", in_filename);
206 return -1;
207 }
208
209 ret = fread(&rkboot_info, 1, sizeof(rkboot_info), fp_in);
210
211 if (ret != sizeof(rkboot_info))
212 {
213 fclose(fp_in);
214 fprintf(stderr, "error: can't read %s file header\n", in_filename);
215 fprintf(stderr, "read %d, expected %d\n", ret, sizeof(rkboot_info));
216 return -2;
217 }
218
219 if (action & INFO)
220 {
221 printf("file: %s\n", in_filename);
222 printf("signature: %s\n", rkboot_info.sign);
223 printf("check bytes: ");
224 for (i = 0; i < 16; i++)
225 printf("0x%0x ", rkboot_info.check_values[i]);
226
227 printf("\n");
228 printf("timestamp %d.%d.%d %d:%d:%d\n", rkboot_info.time.day,
229 rkboot_info.time.month,
230 rkboot_info.time.year,
231 rkboot_info.time.hour,
232 rkboot_info.time.minute,
233 rkboot_info.time.second);
234 printf("UI master version: 0x%0x\n", rkboot_info.ui_master_version);
235 printf("UI slave version: 0x%0x\n", rkboot_info.ui_slave_version);
236 printf("s1 data offset: 0x%0x\n", rkboot_info.s1_offset);
237 printf("s1 data len: 0x%0x\n", rkboot_info.s1_len);
238 printf("s2 offset: 0x%0x\n", rkboot_info.s2_offset);
239 printf("s2 len: 0x%0x\n", rkboot_info.s2_len);
240 printf("s3 offset: 0x%0x\n", rkboot_info.s3_offset);
241 printf("s3 len: 0x%0x\n", rkboot_info.s3_len);
242 printf("s4 offset: 0x%0x\n", rkboot_info.s4_offset);
243 printf("s4 len: 0x%0x\n", rkboot_info.s4_len);
244 printf("UI version flag: 0x%0x\n", rkboot_info.version_flag);
245 }
246
247 if (action & EXTRACT)
248 {
249 /* first stage */
250 buff = binary_extract(fp_in, rkboot_info.s1_offset,
251 rkboot_info.s1_len,
252 action & SCRAMBLE,
253 CONTINOUS_ENC);
254
255 if ( buff == NULL )
256 {
257 fclose(fp_in);
258 fprintf(stderr, "error: can't extract image\n");
259 return -2;
260 }
261
262 /* output */
263 if ((fp_out = fopen("rkboot_s1.bin", "wb")) == NULL)
264 {
265 free(buff);
266 fclose(fp_in);
267 fprintf(stderr, "[error]: can't open rkboot_s1.bin for writing\n");
268 return -3;
269 }
270
271 fwrite(buff, 1, rkboot_info.s1_len, fp_out);
272
273 fprintf(stderr, "[info]: extracted rkboot_s1.bin file\n");
274 free(buff);
275 fclose(fp_out);
276
277 /* second stage */
278 buff = binary_extract(fp_in, rkboot_info.s2_offset,
279 rkboot_info.s2_len,
280 action & SCRAMBLE,
281 CONTINOUS_ENC);
282
283 if ( buff == NULL )
284 {
285 fclose(fp_in);
286 fprintf(stderr, "error: can't extract image\n");
287 return -2;
288 }
289
290 if ((fp_out = fopen("rkboot_s2.bin", "wb")) == NULL)
291 {
292 free(buff);
293 fclose(fp_in);
294 fprintf(stderr, "[error]: can't open rkboot_s2.bin for writing\n");
295 return -4;
296 }
297
298 fwrite(buff, 1, rkboot_info.s2_len, fp_out);
299
300 fprintf(stderr, "[info]: extracted rkboot_s2.bin file\n");
301 free(buff);
302 fclose(fp_out);
303
304 /* third stage */
305 buff = binary_extract(fp_in, rkboot_info.s3_offset,
306 rkboot_info.s3_len,
307 action & SCRAMBLE,
308 PAGE_ENC);
309 if ( buff == NULL )
310 {
311 fclose(fp_in);
312 fprintf(stderr, "[error]: can't extract image.\n");
313 return -2;
314 }
315
316 if ((fp_out = fopen("rkboot_s3.bin", "wb")) == NULL)
317 {
318 free(buff);
319 fclose(fp_in);
320 fprintf(stderr, "[error]: can't open rkboot_s3.bin for writing\n");
321 return -4;
322 }
323
324 fwrite(buff, 1, rkboot_info.s3_len, fp_out);
325
326 fprintf(stderr, "[info]: extracted rkboot_s3.bin file\n");
327 free(buff);
328 fclose(fp_out);
329
330 /* forth stage */
331 buff = binary_extract(fp_in, rkboot_info.s4_offset,
332 rkboot_info.s4_len,
333 action & SCRAMBLE,
334 CONTINOUS_ENC);
335 if ( buff == NULL )
336 {
337 fclose(fp_in);
338 fprintf(stderr, "[error]: can't extract image\n");
339 return -2;
340 }
341
342 if ((fp_out = fopen("rkboot_s4.bin", "wb")) == NULL)
343 {
344 free(buff);
345 fclose(fp_in);
346 fprintf(stderr, "[error]: can't open rkboot_s4.bin for writing\n");
347 return -4;
348 }
349
350 fwrite(buff, 1, rkboot_info.s4_len, fp_out);
351
352 fprintf(stderr, "[info]: extracted rkboot_s4.bin file\n");
353 free(buff);
354 fclose(fp_out);
355 }
356
357 fclose(fp_in);
358 return 0;
359}
360
diff --git a/utils/rk27utils/rkusbtool/Makefile b/utils/rk27utils/rkusbtool/Makefile
new file mode 100644
index 0000000000..785a09a1f1
--- /dev/null
+++ b/utils/rk27utils/rkusbtool/Makefile
@@ -0,0 +1,7 @@
1all: rkusbtool
2
3rkusbtool: rkusbtool.c
4 gcc -g -std=c99 -o $@ -W -Wall -lusb-1.0 -I/usr/include/libusb-1.0/ $^
5
6clean:
7 rm -fr rkusbtool
diff --git a/utils/rk27utils/rkusbtool/rkusbtool.c b/utils/rk27utils/rkusbtool/rkusbtool.c
new file mode 100644
index 0000000000..06fb7e860c
--- /dev/null
+++ b/utils/rk27utils/rkusbtool/rkusbtool.c
@@ -0,0 +1,388 @@
1/* on ubuntu compile with gcc -W rkusbtool.c -o rkusbtool -lusb-1.0 -I/usr/include/libusb-1.0/ */
2#include <libusb.h>
3#include <stdint.h>
4#include <stdio.h>
5#include <string.h>
6
7#define VERSION "v0.1"
8
9#define RETRY_MAX 5
10#define USB_TIMEOUT 512
11#define VENDORID 0x071b
12#define PRODUCTID 0x3203
13
14#define OUT_EP 0x01
15#define IN_EP 0x82
16
17#define CBW_SIGNATURE 0x43425355
18#define CSW_SIGNATURE 0x53425355
19#define SCSICMD_READ_12 0xa8
20
21/* rockchip specific commands */
22#define RK_CMD 0xe0
23#define RK_GET_VERSION 0xffffffff
24#define RK_SWITCH_ROCKUSB 0xfeffffff
25#define RK_CHECK_USB 0xfdffffff
26#define RK_OPEN_SYSDISK 0xfcffffff
27
28enum {
29 NONE = 0,
30 INFO = 1,
31 RKUSB = 2,
32 SYSDISK = 4,
33 CHECKUSB = 8
34};
35
36enum {
37 COMMAND_PASSED = 0,
38 COMMAND_FAILED = 1,
39 PHASE_ERROR = 2
40};
41
42struct CBWCB_t
43{
44 uint8_t cbCode;
45 uint8_t cbLun;
46 uint32_t LBA;
47 uint32_t cbLen;
48 uint8_t reseved;
49 uint8_t control;
50} __attribute__((__packed__));
51
52struct CBW_t
53{
54 uint32_t dCBWSignature;
55 uint32_t dCBWTag;
56 uint32_t dCBWDataTransferLength;
57 uint8_t bmCBWFlags;
58 uint8_t bCBWLUN;
59 uint8_t bCBWCBLength;
60 uint8_t CBWCB[16];
61} __attribute__((__packed__));
62
63struct CSW_t
64{
65 uint32_t dCSWSignature;
66 uint32_t dCSWTag;
67 uint32_t dCSWDataResidue;
68 uint8_t bCSWStatus;
69} __attribute__((__packed__));
70
71static int send_msc_cmd(libusb_device_handle *hdev, struct CBWCB_t *cbwcb, uint32_t data_len, uint32_t *reftag)
72{
73 struct CBW_t cbw;
74 int ret, repeat, transferred;
75 static uint32_t tag = 0xdaefbc01;
76
77 memset(&cbw, 0, sizeof(cbw));
78 cbw.dCBWSignature = CBW_SIGNATURE;
79 cbw.dCBWTag = tag++;
80 cbw.dCBWDataTransferLength = data_len;
81 cbw.bmCBWFlags = 0x80; /* device to host */
82 cbw.bCBWLUN = 0;
83 cbw.bCBWCBLength = sizeof(struct CBWCB_t);
84 memcpy(cbw.CBWCB, cbwcb, sizeof(struct CBWCB_t));
85
86 *reftag = cbw.dCBWTag;
87 do
88 {
89 /* transfer command to the device */
90 ret = libusb_bulk_transfer(hdev, OUT_EP, (unsigned char*)&cbw, 31, &transferred, USB_TIMEOUT);
91 if (ret == LIBUSB_ERROR_PIPE)
92 {
93 libusb_clear_halt(hdev, OUT_EP);
94 }
95 repeat++;
96 } while ((ret == LIBUSB_ERROR_PIPE) && (repeat < RETRY_MAX));
97
98 if (ret != LIBUSB_SUCCESS)
99 {
100 printf("error: command transfer error\n");
101 return -1;
102 }
103
104 return 0;
105}
106
107static int get_msc_csw(libusb_device_handle *hdev, uint32_t reftag)
108{
109 struct CSW_t csw;
110 int ret, repeat, transferred;
111
112 /* get CSW response from device */
113 repeat = 0;
114 do
115 {
116 ret = libusb_bulk_transfer(hdev, IN_EP, (unsigned char *)&csw, 13, &transferred, USB_TIMEOUT);
117 if (ret == LIBUSB_ERROR_PIPE)
118 {
119 libusb_clear_halt(hdev, IN_EP);
120 }
121 repeat++;
122 } while ((ret == LIBUSB_ERROR_PIPE) && (repeat < RETRY_MAX));
123
124 if (ret != LIBUSB_SUCCESS)
125 {
126 printf("error reading CSW\n");
127 return -3;
128 }
129
130 if (transferred != 13)
131 {
132 printf("error wrong size of CSW packet\n");
133 return -4;
134 }
135
136 if (csw.dCSWSignature != CSW_SIGNATURE)
137 {
138 printf("error: wrong CSW signature.\n");
139 return -5;
140 }
141
142 if (csw.dCSWTag != reftag)
143 {
144 printf("error: CSW dCSWTag mismatch\n");
145 return -6;
146 }
147
148 if (csw.bCSWStatus)
149 {
150 /* In case of CSW indicating error dump the content of the packet */
151 printf ("dCSWSignature: 0x%0x\n", csw.dCSWSignature);
152 printf ("dCSWTag: 0x%0x\n", csw.dCSWTag);
153 printf ("dCSWDataResidue: 0x%0x\n", csw.dCSWDataResidue);
154 printf ("bCSWStatus: 0x%0x\n", csw.bCSWStatus);
155 }
156
157 return csw.bCSWStatus;
158}
159
160static int rk_cmd(libusb_device_handle *hdev, uint32_t command, uint8_t *buf, uint8_t len)
161{
162 struct CBWCB_t cbwcb;
163 int ret, transferred;
164 uint32_t reftag;
165
166 /* enter command */
167 memset(&cbwcb, 0, sizeof(cbwcb));
168 cbwcb.cbCode = SCSICMD_READ_12;
169 cbwcb.cbLun = RK_CMD;
170 cbwcb.LBA = command; /* RK_GET_VERSION, RK_OPEN_SYSDISK, RK_SWITCH_ROCKUSB */
171 cbwcb.cbLen = len; /* size of transfer in response to this command */
172
173 ret = send_msc_cmd(hdev, &cbwcb, len, &reftag);
174
175 /* get the response */
176 if (len > 0)
177 {
178 ret = libusb_bulk_transfer(hdev, IN_EP, buf, len, &transferred, USB_TIMEOUT);
179 if (ret != LIBUSB_SUCCESS || transferred != len)
180 {
181 printf("error: reading response data failed\n");
182 return -2;
183 }
184 }
185
186 return get_msc_csw(hdev, reftag);
187}
188
189static int get_sense(libusb_device_handle *hdev)
190{
191 struct CBWCB_t cbwcb;
192 unsigned char sense[0x12];
193 int size, ret;
194 uint32_t reftag;
195
196 memset(&cbwcb, 0, sizeof(cbwcb));
197 cbwcb.cbCode = 0x03;
198 cbwcb.cbLun = 0;
199 cbwcb.LBA = 0;
200 cbwcb.cbLen = 0x12;
201
202 ret = send_msc_cmd(hdev, &cbwcb, 0x12, &reftag);
203 libusb_bulk_transfer(hdev, IN_EP, (unsigned char*)&sense, 0x12, &size, USB_TIMEOUT);
204
205 return get_msc_csw(hdev, reftag);
206}
207
208static void usage(void)
209{
210 printf("Usage: rkusbtool [options]\n");
211 printf("-h|--help This help message\n");
212 printf("-i|--info Get version string from the device\n");
213 printf("-d|--dfu Put device into DFU mode\n");
214 printf("-s|--sysdisk Open system disk\n");
215 printf("-c|--checkusb Check if dev is in System or Loader USB mode\n");
216}
217
218int main (int argc, char **argv)
219{
220 libusb_device_handle *hdev;
221 int ret;
222 int i = 0, action = NONE;
223 uint32_t ver[3];
224
225 if (argc < 2)
226 {
227 usage();
228 return 1;
229 }
230
231 /* print banner */
232 fprintf(stderr,"rkusbtool " VERSION "\n");
233 fprintf(stderr,"(C) Marcin Bukat 2011\n");
234 fprintf(stderr,"This is free software; see the source for copying conditions. There is NO\n");
235 fprintf(stderr,"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
236
237 /* arguments handling */
238 while (i < argc)
239 {
240 if ((strcmp(argv[i],"-i")==0) || (strcmp(argv[i],"--info")==0))
241 {
242 action |= INFO;
243 }
244 else if ((strcmp(argv[i],"-d")==0) || (strcmp(argv[i],"--dfu")==0))
245 {
246 action |= RKUSB;
247 }
248 else if ((strcmp(argv[i],"-s")==0) || (strcmp(argv[i],"--sysdisk")==0))
249 {
250 action |= SYSDISK;
251 }
252 else if ((strcmp(argv[i],"-c")==0) || (strcmp(argv[i],"--checkusb")==0))
253 {
254 action |= CHECKUSB;
255 }
256 else if ((strcmp(argv[i],"-h")==0) || (strcmp(argv[i],"--help")==0))
257 {
258 usage();
259 return 0;
260 }
261 i++;
262 }
263
264 /* initialize libusb */
265 libusb_init(NULL);
266 /* usb_set_debug(2); */
267
268 hdev = libusb_open_device_with_vid_pid(NULL, VENDORID, PRODUCTID);
269 if (hdev == NULL)
270 {
271 printf("error: can't open device\n");
272 return -10;
273 }
274
275 ret = libusb_kernel_driver_active(hdev, 0);
276
277 if (ret < 0)
278 {
279 printf ("error checking kernel driver active\n");
280 libusb_close(hdev);
281 return -3;
282 }
283 else
284 {
285 if (ret)
286 libusb_detach_kernel_driver(hdev, 0);
287 }
288
289 ret = libusb_set_configuration(hdev, 1);
290 if (ret < 0)
291 {
292 printf("error: could not select configuration (1)\n");
293 libusb_close(hdev);
294 return -3;
295 }
296
297 ret = libusb_claim_interface(hdev, 0);
298 if (ret < 0)
299 {
300 printf("error: could not claim interface #0\n");
301 libusb_close(hdev);
302 return -11;
303 }
304
305 ret = libusb_set_interface_alt_setting(hdev, 0, 0);
306 if ( ret != LIBUSB_SUCCESS)
307 {
308 printf("error: could not set alt setting for interface #0\n");
309 libusb_close(hdev);
310 return -11;
311 }
312
313 /* BulkOnly reset */
314 //ret = libusb_control_transfer(hdev, 0x21, 0xff, 0, 0, NULL, 0, USB_TIMEOUT);
315
316 /* BulkOnly get max lun */
317 //ret = libusb_control_transfer(hdev, 0xa1, 0xfe, 0, 0, &maxlun, 1, USB_TIMEOUT);
318
319 /* Devices that do not support multiple LUNs may STALL this command. */
320 //if (ret == 0)
321 // maxlun = -1;
322
323 //printf("MAXLUN: %d\n", maxlun);
324
325 get_sense(hdev);
326
327 if (action & INFO)
328 {
329 ret = rk_cmd(hdev, RK_GET_VERSION, (uint8_t *)ver, 12);
330
331 if (ret)
332 {
333 printf("error sending RK_GET_VERSION command. Err 0x%0x\n", ret);
334 libusb_close(hdev);
335 return ret;
336 }
337
338 printf("Rockchip device info:\n");
339 printf("loader ver: %x.%x\n", (ver[0]>>16)&0xff, ver[0]&0xff);
340 printf("kernel ver: %x.%x\n", (ver[1]>>16)&0xff, ver[1]&0xff);
341 printf("sdk ver: %x.%x\n", (ver[2]>>16)&0xff, ver[2]&0xff);
342 }
343
344 if (action & CHECKUSB)
345 {
346 printf("Checking USB mode...\n");
347 ret = rk_cmd(hdev, RK_CHECK_USB, (uint8_t *)ver, 1);
348
349 //if (ret)
350 //{
351 // libusb_close(hdev);
352 // return ret;
353 //}
354
355 if (*(char *)ver)
356 printf("The device is in Loader USB mode\n");
357 else
358 printf("The device is in System USB mode\n");
359 }
360
361 if (action & SYSDISK)
362 {
363 printf("Opening system disk...\n");
364 ret = rk_cmd(hdev, RK_OPEN_SYSDISK, NULL, 0);
365
366 if (ret)
367 {
368 libusb_close(hdev);
369 return ret;
370 }
371 }
372
373 if (action & RKUSB)
374 {
375 printf("Switching into rk DFU mode...\n");
376 ret = rk_cmd(hdev, RK_SWITCH_ROCKUSB, NULL, 0);
377
378 if (ret)
379 {
380 libusb_close(hdev);
381 return ret;
382 }
383 }
384
385 libusb_close(hdev);
386 libusb_exit(NULL);
387 return 0;
388}