summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--utils/rknanoutils/rkload/Makefile20
-rw-r--r--utils/rknanoutils/rkload/rkloader.c219
2 files changed, 239 insertions, 0 deletions
diff --git a/utils/rknanoutils/rkload/Makefile b/utils/rknanoutils/rkload/Makefile
new file mode 100644
index 0000000000..dbeba3387b
--- /dev/null
+++ b/utils/rknanoutils/rkload/Makefile
@@ -0,0 +1,20 @@
1DEFINES=
2CC=gcc
3LD=gcc
4CFLAGS=-O3 -g -std=c99 -W -Wall `pkg-config --cflags libusb-1.0` $(DEFINES)
5LDFLAGS=`pkg-config --libs libusb-1.0`
6BINS=rkloader
7
8all: $(BINS)
9
10%.o: %.c
11 $(CC) $(CFLAGS) -c -o $@ $<
12
13sbtoelf: rkloader.o
14 $(LD) -o $@ $^ $(LDFLAGS)
15
16clean:
17 rm -fr *.o
18
19veryclean:
20 rm -rf $(BINS)
diff --git a/utils/rknanoutils/rkload/rkloader.c b/utils/rknanoutils/rkload/rkloader.c
new file mode 100644
index 0000000000..4953c7a9a8
--- /dev/null
+++ b/utils/rknanoutils/rkload/rkloader.c
@@ -0,0 +1,219 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2013 Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <libusb.h>
25#include <stdint.h>
26#include <stdbool.h>
27#include <getopt.h>
28
29bool g_debug = false;
30
31#ifndef MIN
32#define MIN(a,b) ((a) < (b) ? (a) : (b))
33#endif
34
35/* shamelessly copied from rk27xx utils */
36static void encode_page(uint8_t *inpg, uint8_t *outpg, const int size)
37{
38 uint8_t key[] =
39 {
40 0x7C, 0x4E, 0x03, 0x04,
41 0x55, 0x05, 0x09, 0x07,
42 0x2D, 0x2C, 0x7B, 0x38,
43 0x17, 0x0D, 0x17, 0x11
44 };
45 int i, i3, x, val, idx;
46
47 uint8_t key1[0x100];
48 uint8_t key2[0x100];
49
50 for (i=0; i < 0x100; i++)
51 {
52 key1[i] = i;
53 key2[i] = key[i & 0xf];
54 }
55
56 i3 = 0;
57 for (i=0; i < 0x100; i++)
58 {
59 x = key1[i];
60 i3 = key1[i] + i3;
61 i3 += key2[i];
62 i3 &= 0xff;
63 key1[i] = key1[i3];
64 key1[i3] = x;
65 }
66
67 idx = 0;
68 for (i=0; i < size; i++)
69 {
70 x = key1[(i + 1) & 0xff];
71 val = x;
72 idx = (x + idx) & 0xff;
73 key1[(i + 1) & 0xff] = key1[idx];
74 key1[idx] = (x & 0xff);
75 val = (key1[(i + 1)&0xff] + x) & 0xff;
76 val = key1[val];
77 outpg[i] = val ^ inpg[i];
78 }
79}
80
81static uint16_t compute_crc(uint8_t *buf, int size)
82{
83 uint16_t result = 65535;
84 for(; size; buf++, size--)
85 {
86 for(int bit = 128; bit; bit >>= 1)
87 {
88 if(result & 0x8000)
89 result = (2 * result) ^ 0x1021;
90 else
91 result *= 2;
92 if(*buf & bit)
93 result ^= 0x1021;
94 }
95 }
96 return result;
97}
98
99int send_dfu(libusb_device_handle *dev, void *buffer, long size)
100{
101 /* FIXME I never tried but if the image size is a multiple of 4096 we
102 * probably need to send a last zero length packet for the DFU to boot */
103 while(size >= 0)
104 {
105 int xfer = MIN(size, 4096);
106 if(g_debug)
107 printf("[rkloader] send %d bytes\n", xfer);
108 int ret = libusb_control_transfer(dev,
109 LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, 12, 0, 1137,
110 buffer, xfer, 1000);
111 if(ret < 0)
112 {
113 fprintf(stderr, "transfer error: %d\n", ret);
114 return 1;
115 }
116 buffer += xfer;
117 size -= xfer;
118 if(xfer != 4096)
119 break;
120 }
121
122 return 0;
123}
124
125static void usage(void)
126{
127 printf("usage: rkload [options] <file>\n");
128 printf("options:\n");
129 printf(" --help/-? Display this help\n");
130 printf(" --debug/-d Enable debug output\n");
131 printf(" --encode/-e Encode file before sending it\n");
132}
133
134int main(int argc, char **argv)
135{
136 bool encode = false;
137
138 while(1)
139 {
140 static struct option long_options[] =
141 {
142 {"help", no_argument, 0, '?'},
143 {"debug", no_argument, 0, 'd'},
144 {"encode", no_argument, 0, 'e'},
145 {0, 0, 0, 0}
146 };
147
148 int c = getopt_long(argc, argv, "?de", long_options, NULL);
149 if(c == -1)
150 break;
151 switch(c)
152 {
153 case -1:
154 break;
155 case 'd':
156 g_debug = true;
157 break;
158 case '?':
159 usage();
160 break;
161 case 'e':
162 encode = true;
163 break;
164 default:
165 abort();
166 }
167 }
168
169 if(argc - optind != 1)
170 {
171 usage();
172 return 1;
173 }
174
175 libusb_init(NULL);
176 libusb_set_debug(NULL, 3);
177 if(g_debug)
178 printf("[rkloader] opening device...\n");
179 libusb_device_handle *dev = libusb_open_device_with_vid_pid(NULL, 0x071b, 0x3226);
180 if(dev == NULL)
181 return fprintf(stderr, "No device found\n");
182
183 if(g_debug)
184 printf("[rkloader] loading file...\n");
185 FILE *f = fopen(argv[optind], "rb");
186 if(f == NULL)
187 return fprintf(stderr, "Cannot open file for reading: %m\n");
188 fseek(f, 0, SEEK_END);
189 long size = ftell(f);
190 fseek(f, 0, SEEK_SET);
191 /* allocate two more bytes for the crc */
192 void *buffer = malloc(size + 2);
193 fread(buffer, size, 1, f);
194 fclose(f);
195 /* encode buffer if needed */
196 if(encode)
197 {
198 if(g_debug)
199 printf("[rkloader] encoding buffer...\n");
200 encode_page(buffer, buffer, size);
201 }
202 /* compute crc */
203 if(g_debug)
204 printf("[rkloader] computing crc...\n");
205 uint16_t crc = compute_crc(buffer, size);
206 *(uint8_t *)(buffer + size) = crc >> 8;
207 *(uint8_t *)(buffer + size + 1) = crc & 0xff;
208
209 /* send buffer */
210 if(g_debug)
211 printf("[rkloader] sending buffer...\n");
212 int ret = send_dfu(dev, buffer, size + 2);
213
214 free(buffer);
215 libusb_close(dev);
216
217 return ret;
218}
219