summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2016-04-03 22:14:11 +0100
committerAmaury Pouly <amaury.pouly@gmail.com>2016-04-08 18:54:46 +0100
commitc90d42dcc6aee53a0743e913d56a33ff9e1e14f3 (patch)
treeb80e4ceba22df9920434a6c5536ae9d9f500d5ca
parent4934bd6f24f97923f2dacd5afa022055a4b52a6e (diff)
downloadrockbox-c90d42d.tar.gz
rockbox-c90d42d.zip
jz4670_tools: add usbboot tool, tweak Makefile and packtool
Although the jz4740 contains a similar tool to usbboot, its command-line interface is not very useful, also it does not compile by default because it relies on some external code, and it contains code specific to some JZ4740 devices. Change-Id: I22688238d147e21fb0fd524466b333b6003d4ff1
-rw-r--r--utils/jz4760_tools/Makefile4
-rw-r--r--utils/jz4760_tools/packtools.cpp9
-rw-r--r--utils/jz4760_tools/usbboot.c349
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=
CC?=gcc
CXX?=g++
LD?=g++
-CFLAGS=-g -std=c99 -Wall $(DEFINES) -Ilib
+CFLAGS=-g -std=c99 -Wall $(DEFINES) `pkg-config --cflags libusb-1.0`
CXXFLAGS=-g -Wall $(DEFINES)
-LDFLAGS=
+LDFLAGS=`pkg-config --libs libusb-1.0`
SRC=$(wildcard *.c)
SRCXX=$(wildcard *.cpp)
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] =
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
};
+/* This table is generated programmatically: it contains two copies of a 172-bytes
+ * table. This table contains the lower 8-bit of the first 172 prime numbers:
+ * 2, 3, 5, 7, ..., 251(=0xfb), 257(=0x101 -> 0x01), ... */
const unsigned JZ4760_XOR_KEY_SIZE = 344;
uint8_t jz4760_xor_key[JZ4760_XOR_KEY_SIZE] =
{
@@ -530,7 +533,7 @@ int descramble(int argc, char **argv)
void usage()
{
- printf("usage: [--pack|--unpack|--descramble] <options>\n");
+ printf("usage: [--pack|--unpack|--descramble|--scramble] <options>\n");
printf(" unpack options:\n");
printf(" -i <file> Input file\n");
printf(" -o <dir> Output directory\n");
@@ -541,7 +544,7 @@ void usage()
printf(" -m <mach> Machine flags\n");
printf(" -v Verbose output\n");
printf(" -t <time> Override date/time (dd/mm/yy hh:mm)\n");
- printf(" descramble options:\n");
+ printf(" (de)scramble options:\n");
printf(" -i <file> Input file\n");
printf(" -o <file> Output file\n");
exit(1);
@@ -555,7 +558,7 @@ int main(int argc, char **argv)
return unpack(argc - 1, argv + 1);
if(strcmp(argv[1], "--pack") == 0)
return pack(argc - 1, argv + 1);
- if(strcmp(argv[1], "--descramble") == 0)
+ if(strcmp(argv[1], "--descramble") == 0 || strcmp(argv[1], "--scramble") == 0)
return descramble(argc - 1, argv + 1);
usage();
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 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2015 by Amaury Pouly
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <libusb.h>
+#include <getopt.h>
+#include <stdbool.h>
+
+#define VR_GET_CPU_INFO 0
+#define VR_SET_DATA_ADDRESS 1
+#define VR_SET_DATA_LENGTH 2
+#define VR_FLUSH_CACHES 3
+#define VR_PROGRAM_START1 4
+#define VR_PROGRAM_START2 5
+
+bool g_verbose = false;
+
+int jz_cpuinfo(libusb_device_handle *dev)
+{
+ if(g_verbose)
+ printf("Get CPU Info...\n");
+ uint8_t cpuinfo[9];
+ int ret = libusb_control_transfer(dev,
+ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
+ VR_GET_CPU_INFO, 0, 0, cpuinfo, 8, 1000);
+ if(ret != 8)
+ {
+ printf("Cannot get CPU info: %d\n", ret);
+ return ret;
+ }
+ cpuinfo[8] = 0;
+ printf("CPU Info: %s\n", cpuinfo);
+ return 0;
+}
+
+int jz_set_addr(libusb_device_handle *dev, unsigned long addr)
+{
+ if(g_verbose)
+ printf("Set address to 0x%lx...\n", addr);
+ int ret = libusb_control_transfer(dev,
+ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
+ VR_SET_DATA_ADDRESS, addr >> 16, addr & 0xffff, NULL, 0, 1000);
+ if(ret != 0)
+ printf("Cannot set address: %d\n", ret);
+ return ret;
+}
+
+int jz_set_length(libusb_device_handle *dev, unsigned long length)
+{
+ if(g_verbose)
+ printf("Set length to 0x%lx...\n", length);
+ int ret = libusb_control_transfer(dev,
+ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
+ VR_SET_DATA_LENGTH, length >> 16, length & 0xffff, NULL, 0, 1000);
+ if(ret != 0)
+ printf("Cannot set length: %d\n", ret);
+ return ret;
+}
+
+int jz_start1(libusb_device_handle *dev, unsigned long addr)
+{
+ if(g_verbose)
+ printf("Start 1 at 0x%lx...\n", addr);
+ int ret = libusb_control_transfer(dev,
+ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
+ VR_PROGRAM_START1, addr >> 16, addr & 0xffff, NULL, 0, 1000);
+ if(ret != 0)
+ printf("Cannot start1: %d\n", ret);
+ return ret;
+}
+
+int jz_start2(libusb_device_handle *dev, unsigned long addr)
+{
+ if(g_verbose)
+ printf("Start 2 at 0x%lx...\n", addr);
+ int ret = libusb_control_transfer(dev,
+ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
+ VR_PROGRAM_START2, addr >> 16, addr & 0xffff, NULL, 0, 1000);
+ if(ret != 0)
+ printf("Cannot start2: %d\n", ret);
+ return ret;
+}
+
+int jz_flush_caches(libusb_device_handle *dev)
+{
+ if(g_verbose)
+ printf("Flush caches...\n");
+ int ret = libusb_control_transfer(dev,
+ LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE,
+ VR_FLUSH_CACHES, 0, 0, NULL, 0, 1000);
+ if(ret != 0)
+ printf("Cannot flush caches: %d\n", ret);
+ return ret;
+}
+
+int jz_upload(libusb_device_handle *dev, const char *file, unsigned long length)
+{
+ if(g_verbose)
+ printf("Upload %lu bytes...\n", length);
+ void *data = malloc(length);
+ int xfered;
+ int ret = libusb_bulk_transfer(dev, LIBUSB_ENDPOINT_IN | 1, data, length,
+ &xfered, 10000);
+ if(ret != 0)
+ printf("Cannot upload data from device: %d\n", ret);
+ if(ret == 0 && xfered != length)
+ {
+ printf("Device did not send all the data\n");
+ ret = -1;
+ }
+ if(ret == 0)
+ {
+ FILE *f = fopen(file, "wb");
+ if(f != NULL)
+ {
+ if(fwrite(data, length, 1, f) != 1)
+ {
+ printf("Cannot write file\n");
+ ret = -3;
+ }
+ fclose(f);
+ }
+ else
+ {
+ printf("Cannot open file for writing\n");
+ ret = -2;
+ }
+ }
+ free(data);
+ return ret;
+}
+
+int jz_download(libusb_device_handle *dev, const char *file)
+{
+ FILE *f = fopen(file, "rb");
+ if(f == NULL)
+ {
+ printf("Cannot open file for reading\n");
+ return -1;
+ }
+ fseek(f, 0, SEEK_END);
+ size_t length = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ if(g_verbose)
+ printf("Download %lu bytes..\n", length);
+ void *data = malloc(length);
+ if(fread(data, length, 1, f) != 1)
+ {
+ printf("Cannot read file\n");
+ free(data);
+ fclose(f);
+ return -1;
+ }
+ fclose(f);
+ int xfered;
+ int ret = libusb_bulk_transfer(dev, LIBUSB_ENDPOINT_OUT | 1, data, length,
+ &xfered, 1000);
+ if(ret != 0)
+ printf("Cannot download data from device: %d\n", ret);
+ if(ret == 0 && xfered != length)
+ {
+ printf("Device did not receive all the data\n");
+ ret = -1;
+ }
+ free(data);
+ return ret;
+}
+
+int renumerate(libusb_device_handle **dev)
+{
+ if(g_verbose)
+ printf("Look for device again...\n");
+ libusb_close(*dev);
+ *dev = libusb_open_device_with_vid_pid(NULL, 0x601a, 0x4760);
+ if(dev == NULL)
+ {
+ printf("Cannot open device\n");
+ return -1;
+ }
+ return 0;
+}
+
+void usage()
+{
+ printf("Usage: usbboot [options]\n");
+ printf("\n");
+ printf("Basic options:\n");
+ printf(" --stage1 <file> Upload first stage program (<=16Kio)\n");
+ printf(" --stage2 <file> Upload second stage program to SDRAM\n");
+ printf(" --s2-addr <addr> Change second stage address (default is 0x80000000)\n");
+ printf(" --ram <target> Setup SDRAM for <target>, see list below\n");
+ printf("\n");
+ printf("Advanced options:\n");
+ printf(" --addr <addr> Set address for next operation\n");
+ printf(" --length <len> Set length for next operation\n");
+ printf(" --download <file> Download data in file to the device (use file length)\n");
+ printf(" --upload <file> Upload data from the device to the file\n");
+ printf(" --cpuinfo Print CPU info\n");
+ printf(" --flush-caches Flush CPU caches\n");
+ printf(" --start1 <addr> Execute first stage from I-cache\n");
+ printf(" --start2 <addr> Execute second stage\n");
+ printf(" --wait <time> Wait <time> seconds\n");
+ printf(" --renumerate Try to look for device again\n");
+ printf(" --ram <ramopt> Setup SDRAM with parameters, see descrition below\n");
+ printf(" -v Be verbose\n");
+ printf("\n");
+ printf("Targets for RAM setup:\n");
+ printf(" fiiox1 Use <>\n");
+ printf("\n");
+ printf("Format of <ramopt> for RAM setup:\n");
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ if(argc <= 1)
+ usage();
+ int ret = 0;
+ libusb_init(NULL);
+ libusb_device_handle *dev = libusb_open_device_with_vid_pid(NULL, 0x601a, 0x4760);
+ if(dev == NULL)
+ {
+ printf("Cannot open device\n");
+ return -1;
+ }
+ if(libusb_claim_interface(dev, 0) != 0)
+ {
+ printf("Cannot claim interface\n");
+ libusb_close(dev);
+ return -2;
+ }
+
+ enum
+ {
+ OPT_ADDR = 0x100, OPT_LENGTH, OPT_UPLOAD, OPT_CPUINFO, OPT_DOWNLOAD,
+ OPT_START1, OPT_WAIT, OPT_RENUMERATE, OPT_START2, OPT_FLUSH_CACHES
+ };
+ unsigned long last_length = 0;
+ while(1)
+ {
+ static struct option long_options[] =
+ {
+ {"help", no_argument, 0, 'h'},
+ {"cpuinfo", no_argument, 0, OPT_CPUINFO},
+ {"addr", required_argument, 0, OPT_ADDR},
+ {"length", required_argument, 0, OPT_LENGTH},
+ {"upload", required_argument, 0, OPT_UPLOAD},
+ {"download", required_argument, 0, OPT_DOWNLOAD},
+ {"start1", required_argument, 0, OPT_START1},
+ {"wait", required_argument, 0, OPT_WAIT},
+ {"renumerate", no_argument, 0, OPT_RENUMERATE},
+ {"start2", required_argument, 0, OPT_START2},
+ {"flush-caches", no_argument, 0, OPT_FLUSH_CACHES},
+ {0, 0, 0, 0}
+ };
+
+ int c = getopt_long(argc, argv, "hv", long_options, NULL);
+ char *end = 0;
+ unsigned long param;
+ if(c == OPT_ADDR || c == OPT_LENGTH || c == OPT_START1 || c== OPT_WAIT)
+ {
+ param = strtoul(optarg, &end, 0);
+ if(*end)
+ {
+ printf("Invalid argument '%s'\n", optarg);
+ ret = 1;
+ break;
+ }
+ }
+ if(c == -1)
+ break;
+ switch(c)
+ {
+ default:
+ case -1:
+ break;
+ case 'h':
+ usage();
+ break;
+ case 'v':
+ g_verbose = true;
+ break;
+ case OPT_ADDR:
+ ret = jz_set_addr(dev, param);
+ break;
+ case OPT_LENGTH:
+ last_length = param;
+ ret = jz_set_length(dev, param);
+ break;
+ case OPT_UPLOAD:
+ ret = jz_upload(dev, optarg, last_length);
+ break;
+ case OPT_DOWNLOAD:
+ ret = jz_download(dev, optarg);
+ break;
+ case OPT_CPUINFO:
+ ret = jz_cpuinfo(dev);
+ break;
+ case OPT_START1:
+ ret = jz_start1(dev, param);
+ break;
+ case OPT_WAIT:
+ if(g_verbose)
+ printf("Wait for %lu seconds...\n", param);
+ sleep(param);
+ break;
+ case OPT_RENUMERATE:
+ ret = renumerate(&dev);
+ break;
+ case OPT_START2:
+ ret = jz_start2(dev, param);
+ break;
+ case OPT_FLUSH_CACHES:
+ ret = jz_flush_caches(dev);
+ break;
+ }
+ if(ret != 0)
+ break;
+ }
+ if(optind != argc)
+ {
+ printf("Error: extra arguments on command line\n");
+ ret = 1;
+ }
+
+ libusb_close(dev);
+ libusb_exit(NULL);
+ return ret;
+} \ No newline at end of file