diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2016-04-03 22:14:11 +0100 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2016-04-08 18:54:46 +0100 |
commit | c90d42dcc6aee53a0743e913d56a33ff9e1e14f3 (patch) | |
tree | b80e4ceba22df9920434a6c5536ae9d9f500d5ca | |
parent | 4934bd6f24f97923f2dacd5afa022055a4b52a6e (diff) | |
download | rockbox-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/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= 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 |