diff options
-rw-r--r-- | utils/jz4760_tools/Makefile | 4 | ||||
-rw-r--r-- | utils/jz4760_tools/packtools.cpp | 9 | ||||
-rw-r--r-- | utils/jz4760_tools/usbboot.c | 349 |
3 files changed, 357 insertions, 5 deletions
diff --git a/utils/jz4760_tools/Makefile b/utils/jz4760_tools/Makefile index 847539e38c..f181fa5c70 100644 --- a/utils/jz4760_tools/Makefile +++ b/utils/jz4760_tools/Makefile | |||
@@ -2,9 +2,9 @@ DEFINES= | |||
2 | CC?=gcc | 2 | CC?=gcc |
3 | CXX?=g++ | 3 | CXX?=g++ |
4 | LD?=g++ | 4 | LD?=g++ |
5 | CFLAGS=-g -std=c99 -Wall $(DEFINES) -Ilib | 5 | CFLAGS=-g -std=c99 -Wall $(DEFINES) `pkg-config --cflags libusb-1.0` |
6 | CXXFLAGS=-g -Wall $(DEFINES) | 6 | CXXFLAGS=-g -Wall $(DEFINES) |
7 | LDFLAGS= | 7 | LDFLAGS=`pkg-config --libs libusb-1.0` |
8 | SRC=$(wildcard *.c) | 8 | SRC=$(wildcard *.c) |
9 | SRCXX=$(wildcard *.cpp) | 9 | SRCXX=$(wildcard *.cpp) |
10 | EXEC=$(SRC:.c=) $(SRCXX:.cpp=) | 10 | EXEC=$(SRC:.c=) $(SRCXX:.cpp=) |
diff --git a/utils/jz4760_tools/packtools.cpp b/utils/jz4760_tools/packtools.cpp index 6bd5ec0330..b594525978 100644 --- a/utils/jz4760_tools/packtools.cpp +++ b/utils/jz4760_tools/packtools.cpp | |||
@@ -96,6 +96,9 @@ const uint32_t jz4760_crc_key[256] = | |||
96 | 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0, | 96 | 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0, |
97 | }; | 97 | }; |
98 | 98 | ||
99 | /* This table is generated programmatically: it contains two copies of a 172-bytes | ||
100 | * table. This table contains the lower 8-bit of the first 172 prime numbers: | ||
101 | * 2, 3, 5, 7, ..., 251(=0xfb), 257(=0x101 -> 0x01), ... */ | ||
99 | const unsigned JZ4760_XOR_KEY_SIZE = 344; | 102 | const unsigned JZ4760_XOR_KEY_SIZE = 344; |
100 | uint8_t jz4760_xor_key[JZ4760_XOR_KEY_SIZE] = | 103 | uint8_t jz4760_xor_key[JZ4760_XOR_KEY_SIZE] = |
101 | { | 104 | { |
@@ -530,7 +533,7 @@ int descramble(int argc, char **argv) | |||
530 | 533 | ||
531 | void usage() | 534 | void usage() |
532 | { | 535 | { |
533 | printf("usage: [--pack|--unpack|--descramble] <options>\n"); | 536 | printf("usage: [--pack|--unpack|--descramble|--scramble] <options>\n"); |
534 | printf(" unpack options:\n"); | 537 | printf(" unpack options:\n"); |
535 | printf(" -i <file> Input file\n"); | 538 | printf(" -i <file> Input file\n"); |
536 | printf(" -o <dir> Output directory\n"); | 539 | printf(" -o <dir> Output directory\n"); |
@@ -541,7 +544,7 @@ void usage() | |||
541 | printf(" -m <mach> Machine flags\n"); | 544 | printf(" -m <mach> Machine flags\n"); |
542 | printf(" -v Verbose output\n"); | 545 | printf(" -v Verbose output\n"); |
543 | printf(" -t <time> Override date/time (dd/mm/yy hh:mm)\n"); | 546 | printf(" -t <time> Override date/time (dd/mm/yy hh:mm)\n"); |
544 | printf(" descramble options:\n"); | 547 | printf(" (de)scramble options:\n"); |
545 | printf(" -i <file> Input file\n"); | 548 | printf(" -i <file> Input file\n"); |
546 | printf(" -o <file> Output file\n"); | 549 | printf(" -o <file> Output file\n"); |
547 | exit(1); | 550 | exit(1); |
@@ -555,7 +558,7 @@ int main(int argc, char **argv) | |||
555 | return unpack(argc - 1, argv + 1); | 558 | return unpack(argc - 1, argv + 1); |
556 | if(strcmp(argv[1], "--pack") == 0) | 559 | if(strcmp(argv[1], "--pack") == 0) |
557 | return pack(argc - 1, argv + 1); | 560 | return pack(argc - 1, argv + 1); |
558 | if(strcmp(argv[1], "--descramble") == 0) | 561 | if(strcmp(argv[1], "--descramble") == 0 || strcmp(argv[1], "--scramble") == 0) |
559 | return descramble(argc - 1, argv + 1); | 562 | return descramble(argc - 1, argv + 1); |
560 | usage(); | 563 | usage(); |
561 | return 1; | 564 | return 1; |
diff --git a/utils/jz4760_tools/usbboot.c b/utils/jz4760_tools/usbboot.c new file mode 100644 index 0000000000..0d7c7242fd --- /dev/null +++ b/utils/jz4760_tools/usbboot.c | |||
@@ -0,0 +1,349 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2015 by 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 | |||
22 | #include <stdio.h> | ||
23 | #include <stdlib.h> | ||
24 | #include <stdint.h> | ||
25 | #include <libusb.h> | ||
26 | #include <getopt.h> | ||
27 | #include <stdbool.h> | ||
28 | |||
29 | #define VR_GET_CPU_INFO 0 | ||
30 | #define VR_SET_DATA_ADDRESS 1 | ||
31 | #define VR_SET_DATA_LENGTH 2 | ||
32 | #define VR_FLUSH_CACHES 3 | ||
33 | #define VR_PROGRAM_START1 4 | ||
34 | #define VR_PROGRAM_START2 5 | ||
35 | |||
36 | bool g_verbose = false; | ||
37 | |||
38 | int jz_cpuinfo(libusb_device_handle *dev) | ||
39 | { | ||
40 | if(g_verbose) | ||
41 | printf("Get CPU Info...\n"); | ||
42 | uint8_t cpuinfo[9]; | ||
43 | int ret = libusb_control_transfer(dev, | ||
44 | LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, | ||
45 | VR_GET_CPU_INFO, 0, 0, cpuinfo, 8, 1000); | ||
46 | if(ret != 8) | ||
47 | { | ||
48 | printf("Cannot get CPU info: %d\n", ret); | ||
49 | return ret; | ||
50 | } | ||
51 | cpuinfo[8] = 0; | ||
52 | printf("CPU Info: %s\n", cpuinfo); | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | int jz_set_addr(libusb_device_handle *dev, unsigned long addr) | ||
57 | { | ||
58 | if(g_verbose) | ||
59 | printf("Set address to 0x%lx...\n", addr); | ||
60 | int ret = libusb_control_transfer(dev, | ||
61 | LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, | ||
62 | VR_SET_DATA_ADDRESS, addr >> 16, addr & 0xffff, NULL, 0, 1000); | ||
63 | if(ret != 0) | ||
64 | printf("Cannot set address: %d\n", ret); | ||
65 | return ret; | ||
66 | } | ||
67 | |||
68 | int jz_set_length(libusb_device_handle *dev, unsigned long length) | ||
69 | { | ||
70 | if(g_verbose) | ||
71 | printf("Set length to 0x%lx...\n", length); | ||
72 | int ret = libusb_control_transfer(dev, | ||
73 | LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, | ||
74 | VR_SET_DATA_LENGTH, length >> 16, length & 0xffff, NULL, 0, 1000); | ||
75 | if(ret != 0) | ||
76 | printf("Cannot set length: %d\n", ret); | ||
77 | return ret; | ||
78 | } | ||
79 | |||
80 | int jz_start1(libusb_device_handle *dev, unsigned long addr) | ||
81 | { | ||
82 | if(g_verbose) | ||
83 | printf("Start 1 at 0x%lx...\n", addr); | ||
84 | int ret = libusb_control_transfer(dev, | ||
85 | LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, | ||
86 | VR_PROGRAM_START1, addr >> 16, addr & 0xffff, NULL, 0, 1000); | ||
87 | if(ret != 0) | ||
88 | printf("Cannot start1: %d\n", ret); | ||
89 | return ret; | ||
90 | } | ||
91 | |||
92 | int jz_start2(libusb_device_handle *dev, unsigned long addr) | ||
93 | { | ||
94 | if(g_verbose) | ||
95 | printf("Start 2 at 0x%lx...\n", addr); | ||
96 | int ret = libusb_control_transfer(dev, | ||
97 | LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, | ||
98 | VR_PROGRAM_START2, addr >> 16, addr & 0xffff, NULL, 0, 1000); | ||
99 | if(ret != 0) | ||
100 | printf("Cannot start2: %d\n", ret); | ||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | int jz_flush_caches(libusb_device_handle *dev) | ||
105 | { | ||
106 | if(g_verbose) | ||
107 | printf("Flush caches...\n"); | ||
108 | int ret = libusb_control_transfer(dev, | ||
109 | LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, | ||
110 | VR_FLUSH_CACHES, 0, 0, NULL, 0, 1000); | ||
111 | if(ret != 0) | ||
112 | printf("Cannot flush caches: %d\n", ret); | ||
113 | return ret; | ||
114 | } | ||
115 | |||
116 | int jz_upload(libusb_device_handle *dev, const char *file, unsigned long length) | ||
117 | { | ||
118 | if(g_verbose) | ||
119 | printf("Upload %lu bytes...\n", length); | ||
120 | void *data = malloc(length); | ||
121 | int xfered; | ||
122 | int ret = libusb_bulk_transfer(dev, LIBUSB_ENDPOINT_IN | 1, data, length, | ||
123 | &xfered, 10000); | ||
124 | if(ret != 0) | ||
125 | printf("Cannot upload data from device: %d\n", ret); | ||
126 | if(ret == 0 && xfered != length) | ||
127 | { | ||
128 | printf("Device did not send all the data\n"); | ||
129 | ret = -1; | ||
130 | } | ||
131 | if(ret == 0) | ||
132 | { | ||
133 | FILE *f = fopen(file, "wb"); | ||
134 | if(f != NULL) | ||
135 | { | ||
136 | if(fwrite(data, length, 1, f) != 1) | ||
137 | { | ||
138 | printf("Cannot write file\n"); | ||
139 | ret = -3; | ||
140 | } | ||
141 | fclose(f); | ||
142 | } | ||
143 | else | ||
144 | { | ||
145 | printf("Cannot open file for writing\n"); | ||
146 | ret = -2; | ||
147 | } | ||
148 | } | ||
149 | free(data); | ||
150 | return ret; | ||
151 | } | ||
152 | |||
153 | int jz_download(libusb_device_handle *dev, const char *file) | ||
154 | { | ||
155 | FILE *f = fopen(file, "rb"); | ||
156 | if(f == NULL) | ||
157 | { | ||
158 | printf("Cannot open file for reading\n"); | ||
159 | return -1; | ||
160 | } | ||
161 | fseek(f, 0, SEEK_END); | ||
162 | size_t length = ftell(f); | ||
163 | fseek(f, 0, SEEK_SET); | ||
164 | if(g_verbose) | ||
165 | printf("Download %lu bytes..\n", length); | ||
166 | void *data = malloc(length); | ||
167 | if(fread(data, length, 1, f) != 1) | ||
168 | { | ||
169 | printf("Cannot read file\n"); | ||
170 | free(data); | ||
171 | fclose(f); | ||
172 | return -1; | ||
173 | } | ||
174 | fclose(f); | ||
175 | int xfered; | ||
176 | int ret = libusb_bulk_transfer(dev, LIBUSB_ENDPOINT_OUT | 1, data, length, | ||
177 | &xfered, 1000); | ||
178 | if(ret != 0) | ||
179 | printf("Cannot download data from device: %d\n", ret); | ||
180 | if(ret == 0 && xfered != length) | ||
181 | { | ||
182 | printf("Device did not receive all the data\n"); | ||
183 | ret = -1; | ||
184 | } | ||
185 | free(data); | ||
186 | return ret; | ||
187 | } | ||
188 | |||
189 | int renumerate(libusb_device_handle **dev) | ||
190 | { | ||
191 | if(g_verbose) | ||
192 | printf("Look for device again...\n"); | ||
193 | libusb_close(*dev); | ||
194 | *dev = libusb_open_device_with_vid_pid(NULL, 0x601a, 0x4760); | ||
195 | if(dev == NULL) | ||
196 | { | ||
197 | printf("Cannot open device\n"); | ||
198 | return -1; | ||
199 | } | ||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | void usage() | ||
204 | { | ||
205 | printf("Usage: usbboot [options]\n"); | ||
206 | printf("\n"); | ||
207 | printf("Basic options:\n"); | ||
208 | printf(" --stage1 <file> Upload first stage program (<=16Kio)\n"); | ||
209 | printf(" --stage2 <file> Upload second stage program to SDRAM\n"); | ||
210 | printf(" --s2-addr <addr> Change second stage address (default is 0x80000000)\n"); | ||
211 | printf(" --ram <target> Setup SDRAM for <target>, see list below\n"); | ||
212 | printf("\n"); | ||
213 | printf("Advanced options:\n"); | ||
214 | printf(" --addr <addr> Set address for next operation\n"); | ||
215 | printf(" --length <len> Set length for next operation\n"); | ||
216 | printf(" --download <file> Download data in file to the device (use file length)\n"); | ||
217 | printf(" --upload <file> Upload data from the device to the file\n"); | ||
218 | printf(" --cpuinfo Print CPU info\n"); | ||
219 | printf(" --flush-caches Flush CPU caches\n"); | ||
220 | printf(" --start1 <addr> Execute first stage from I-cache\n"); | ||
221 | printf(" --start2 <addr> Execute second stage\n"); | ||
222 | printf(" --wait <time> Wait <time> seconds\n"); | ||
223 | printf(" --renumerate Try to look for device again\n"); | ||
224 | printf(" --ram <ramopt> Setup SDRAM with parameters, see descrition below\n"); | ||
225 | printf(" -v Be verbose\n"); | ||
226 | printf("\n"); | ||
227 | printf("Targets for RAM setup:\n"); | ||
228 | printf(" fiiox1 Use <>\n"); | ||
229 | printf("\n"); | ||
230 | printf("Format of <ramopt> for RAM setup:\n"); | ||
231 | exit(1); | ||
232 | } | ||
233 | |||
234 | int main(int argc, char **argv) | ||
235 | { | ||
236 | if(argc <= 1) | ||
237 | usage(); | ||
238 | int ret = 0; | ||
239 | libusb_init(NULL); | ||
240 | libusb_device_handle *dev = libusb_open_device_with_vid_pid(NULL, 0x601a, 0x4760); | ||
241 | if(dev == NULL) | ||
242 | { | ||
243 | printf("Cannot open device\n"); | ||
244 | return -1; | ||
245 | } | ||
246 | if(libusb_claim_interface(dev, 0) != 0) | ||
247 | { | ||
248 | printf("Cannot claim interface\n"); | ||
249 | libusb_close(dev); | ||
250 | return -2; | ||
251 | } | ||
252 | |||
253 | enum | ||
254 | { | ||
255 | OPT_ADDR = 0x100, OPT_LENGTH, OPT_UPLOAD, OPT_CPUINFO, OPT_DOWNLOAD, | ||
256 | OPT_START1, OPT_WAIT, OPT_RENUMERATE, OPT_START2, OPT_FLUSH_CACHES | ||
257 | }; | ||
258 | unsigned long last_length = 0; | ||
259 | while(1) | ||
260 | { | ||
261 | static struct option long_options[] = | ||
262 | { | ||
263 | {"help", no_argument, 0, 'h'}, | ||
264 | {"cpuinfo", no_argument, 0, OPT_CPUINFO}, | ||
265 | {"addr", required_argument, 0, OPT_ADDR}, | ||
266 | {"length", required_argument, 0, OPT_LENGTH}, | ||
267 | {"upload", required_argument, 0, OPT_UPLOAD}, | ||
268 | {"download", required_argument, 0, OPT_DOWNLOAD}, | ||
269 | {"start1", required_argument, 0, OPT_START1}, | ||
270 | {"wait", required_argument, 0, OPT_WAIT}, | ||
271 | {"renumerate", no_argument, 0, OPT_RENUMERATE}, | ||
272 | {"start2", required_argument, 0, OPT_START2}, | ||
273 | {"flush-caches", no_argument, 0, OPT_FLUSH_CACHES}, | ||
274 | {0, 0, 0, 0} | ||
275 | }; | ||
276 | |||
277 | int c = getopt_long(argc, argv, "hv", long_options, NULL); | ||
278 | char *end = 0; | ||
279 | unsigned long param; | ||
280 | if(c == OPT_ADDR || c == OPT_LENGTH || c == OPT_START1 || c== OPT_WAIT) | ||
281 | { | ||
282 | param = strtoul(optarg, &end, 0); | ||
283 | if(*end) | ||
284 | { | ||
285 | printf("Invalid argument '%s'\n", optarg); | ||
286 | ret = 1; | ||
287 | break; | ||
288 | } | ||
289 | } | ||
290 | if(c == -1) | ||
291 | break; | ||
292 | switch(c) | ||
293 | { | ||
294 | default: | ||
295 | case -1: | ||
296 | break; | ||
297 | case 'h': | ||
298 | usage(); | ||
299 | break; | ||
300 | case 'v': | ||
301 | g_verbose = true; | ||
302 | break; | ||
303 | case OPT_ADDR: | ||
304 | ret = jz_set_addr(dev, param); | ||
305 | break; | ||
306 | case OPT_LENGTH: | ||
307 | last_length = param; | ||
308 | ret = jz_set_length(dev, param); | ||
309 | break; | ||
310 | case OPT_UPLOAD: | ||
311 | ret = jz_upload(dev, optarg, last_length); | ||
312 | break; | ||
313 | case OPT_DOWNLOAD: | ||
314 | ret = jz_download(dev, optarg); | ||
315 | break; | ||
316 | case OPT_CPUINFO: | ||
317 | ret = jz_cpuinfo(dev); | ||
318 | break; | ||
319 | case OPT_START1: | ||
320 | ret = jz_start1(dev, param); | ||
321 | break; | ||
322 | case OPT_WAIT: | ||
323 | if(g_verbose) | ||
324 | printf("Wait for %lu seconds...\n", param); | ||
325 | sleep(param); | ||
326 | break; | ||
327 | case OPT_RENUMERATE: | ||
328 | ret = renumerate(&dev); | ||
329 | break; | ||
330 | case OPT_START2: | ||
331 | ret = jz_start2(dev, param); | ||
332 | break; | ||
333 | case OPT_FLUSH_CACHES: | ||
334 | ret = jz_flush_caches(dev); | ||
335 | break; | ||
336 | } | ||
337 | if(ret != 0) | ||
338 | break; | ||
339 | } | ||
340 | if(optind != argc) | ||
341 | { | ||
342 | printf("Error: extra arguments on command line\n"); | ||
343 | ret = 1; | ||
344 | } | ||
345 | |||
346 | libusb_close(dev); | ||
347 | libusb_exit(NULL); | ||
348 | return ret; | ||
349 | } \ No newline at end of file | ||