summaryrefslogtreecommitdiff
path: root/utils/rk27utils/rk27load
diff options
context:
space:
mode:
Diffstat (limited to 'utils/rk27utils/rk27load')
-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
23 files changed, 1046 insertions, 0 deletions
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);