forked from len0rd/rockbox
More improvements to jz4740_usbtool
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17785 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
07b2031ba0
commit
349c14c26d
1 changed files with 303 additions and 56 deletions
|
|
@ -34,8 +34,10 @@
|
|||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include "jz4740.h"
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define VERSION "0.2"
|
||||
#define VERSION "0.3"
|
||||
|
||||
#define MAX_FIRMWARESIZE (64*1024*1024) /* Arbitrary limit (for safety) */
|
||||
|
||||
|
|
@ -51,10 +53,6 @@
|
|||
#define EP_BULK_TO 0x01
|
||||
#define TOUT 5000
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
enum USB_JZ4740_REQUEST
|
||||
{
|
||||
VR_GET_CPU_INFO = 0,
|
||||
|
|
@ -118,6 +116,15 @@ enum OPTION
|
|||
NO_OOB,
|
||||
};
|
||||
|
||||
int filesize(FILE* fd)
|
||||
{
|
||||
int tmp;
|
||||
fseek(fd, 0, SEEK_END);
|
||||
tmp = ftell(fd);
|
||||
fseek(fd, 0, SEEK_SET);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#define SEND_COMMAND(cmd, arg) err = usb_control_msg(dh, USB_ENDPOINT_OUT | USB_TYPE_VENDOR, cmd, arg>>16, arg&0xFFFF, NULL, 0, TOUT);\
|
||||
if (err < 0) \
|
||||
{ \
|
||||
|
|
@ -125,7 +132,7 @@ enum OPTION
|
|||
return -1; \
|
||||
}
|
||||
|
||||
#define GET_CPU_INFO(s) err = usb_control_msg(dh, USB_ENDPOINT_IN | USB_TYPE_VENDOR, VR_GET_CPU_INFO, 0, 0, buf, 8, TOUT); \
|
||||
#define GET_CPU_INFO(s) err = usb_control_msg(dh, USB_ENDPOINT_IN | USB_TYPE_VENDOR, VR_GET_CPU_INFO, 0, 0, s, 8, TOUT); \
|
||||
if (err < 0) \
|
||||
{ \
|
||||
fprintf(stderr,"\n[ERR] Error sending control message (%d, %s)\n", err, usb_strerror()); \
|
||||
|
|
@ -133,7 +140,7 @@ enum OPTION
|
|||
}
|
||||
|
||||
#define SEND_DATA(ptr, size) err = usb_bulk_write(dh, USB_ENDPOINT_OUT | EP_BULK_TO, ptr, size, TOUT); \
|
||||
if (err != len) \
|
||||
if (err != size) \
|
||||
{ \
|
||||
fprintf(stderr,"\n[ERR] Error writing data\n"); \
|
||||
fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err)); \
|
||||
|
|
@ -148,7 +155,7 @@ enum OPTION
|
|||
return -1; \
|
||||
}
|
||||
|
||||
int upload_app(usb_dev_handle* dh, int address, unsigned char* p, int len)
|
||||
int upload_app(usb_dev_handle* dh, int address, unsigned char* p, int len, bool stage2)
|
||||
{
|
||||
int err;
|
||||
char buf[8];
|
||||
|
|
@ -158,6 +165,11 @@ int upload_app(usb_dev_handle* dh, int address, unsigned char* p, int len)
|
|||
GET_CPU_INFO(buf);
|
||||
buf[8] = 0;
|
||||
fprintf(stderr, "%s\n", buf);
|
||||
#if 0
|
||||
fprintf(stderr, "[INFO] Flushing cache...");
|
||||
SEND_COMMAND(VR_FLUSH_CACHES, 0);
|
||||
fprintf(stderr, " Done!\n");
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "[INFO] SET_DATA_ADDRESS to 0x%x...", address);
|
||||
SEND_COMMAND(VR_SET_DATA_ADDRESS, address);
|
||||
|
|
@ -179,16 +191,13 @@ int upload_app(usb_dev_handle* dh, int address, unsigned char* p, int len)
|
|||
}
|
||||
GET_DATA(tmp_buf, len);
|
||||
if (memcmp(tmp_buf, p, len) != 0)
|
||||
{
|
||||
fprintf(stderr, "\n[ERR] Sent data isn't the same as received data...\n");
|
||||
free(tmp_buf);
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "\n[WARN] Sent data isn't the same as received data...\n");
|
||||
else
|
||||
fprintf(stderr, " Done!\n");
|
||||
free(tmp_buf);
|
||||
fprintf(stderr, " Done !\n");
|
||||
|
||||
fprintf(stderr, "[INFO] Booting device...");
|
||||
SEND_COMMAND(VR_PROGRAM_START1, address);
|
||||
fprintf(stderr, "[INFO] Booting device [STAGE%d]...", (stage2 ? 2 : 1));
|
||||
SEND_COMMAND((stage2 ? VR_PROGRAM_START2 : VR_PROGRAM_START1), (address+(stage2 ? 8 : 0)) );
|
||||
fprintf(stderr, " Done!\n");
|
||||
|
||||
return 0;
|
||||
|
|
@ -212,44 +221,275 @@ int read_data(usb_dev_handle* dh, int address, unsigned char *p, int len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
unsigned int read_reg(usb_dev_handle* dh, int address)
|
||||
unsigned int read_reg(usb_dev_handle* dh, int address, int size)
|
||||
{
|
||||
int err;
|
||||
unsigned char buf[4];
|
||||
|
||||
SEND_COMMAND(VR_SET_DATA_ADDRESS, address);
|
||||
SEND_COMMAND(VR_SET_DATA_LENGTH, 4);
|
||||
GET_DATA(buf, 4);
|
||||
SEND_COMMAND(VR_SET_DATA_LENGTH, size);
|
||||
GET_DATA(buf, size);
|
||||
|
||||
return (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
|
||||
if(size == 1)
|
||||
return buf[0];
|
||||
else if(size == 2)
|
||||
return (buf[1] << 8) | buf[0];
|
||||
else if(size == 4)
|
||||
return (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define TEST(m) fprintf(stderr, "%s -> %x\n", #m, read_reg(dh, m));
|
||||
int set_reg(usb_dev_handle* dh, int address, unsigned int val, int size)
|
||||
{
|
||||
int err, i;
|
||||
unsigned char buf[4];
|
||||
|
||||
buf[0] = val & 0xff;
|
||||
if(i > 1)
|
||||
{
|
||||
buf[1] = (val >> 8) & 0xff;
|
||||
if(i > 2)
|
||||
{
|
||||
buf[2] = (val >> 16) & 0xff;
|
||||
buf[3] = (val >> 24) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
SEND_COMMAND(VR_SET_DATA_ADDRESS, address);
|
||||
SEND_DATA(buf, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#define or_reg(dh, adr, val, size) set_reg(dh, adr, (read_reg(dh, adr, size) | (val)), size);
|
||||
#define and_reg(dh, adr, val, size) set_reg(dh, adr, (read_reg(dh, adr, size) & (val)), size);
|
||||
#define bc_reg(dh, adr, val, size) set_reg(dh, adr, (read_reg(dh, adr, size) & ~(val)), size);
|
||||
#define xor_reg(dh, adr, val, size) set_reg(dh, adr, (read_reg(dh, adr, size) ^ (val)), size);
|
||||
|
||||
#define TEST(m, size) fprintf(stderr, "%s -> %x\n", #m, read_reg(dh, m, size));
|
||||
int test_device(usb_dev_handle* dh)
|
||||
{
|
||||
TEST(INTC_ISR);
|
||||
TEST(INTC_IMR);
|
||||
TEST(INTC_IMSR);
|
||||
TEST(INTC_IMCR);
|
||||
TEST(INTC_IPR);
|
||||
TEST(INTC_ISR, 4);
|
||||
TEST(INTC_IMR, 4);
|
||||
TEST(INTC_IMSR, 4);
|
||||
TEST(INTC_IMCR, 4);
|
||||
TEST(INTC_IPR, 4);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
TEST(RTC_RCR);
|
||||
TEST(RTC_RSR);
|
||||
TEST(RTC_RSAR);
|
||||
TEST(RTC_RGR);
|
||||
TEST(RTC_HCR);
|
||||
TEST(RTC_RCR);
|
||||
TEST(RTC_HWFCR);
|
||||
TEST(RTC_HRCR);
|
||||
TEST(RTC_HWCR);
|
||||
TEST(RTC_HWSR);
|
||||
TEST(RTC_RCR, 4);
|
||||
TEST(RTC_RSR, 4);
|
||||
TEST(RTC_RSAR, 4);
|
||||
TEST(RTC_RGR, 4);
|
||||
TEST(RTC_HCR, 4);
|
||||
TEST(RTC_RCR, 4);
|
||||
TEST(RTC_HWFCR, 4);
|
||||
TEST(RTC_HRCR, 4);
|
||||
TEST(RTC_HWCR, 4);
|
||||
TEST(RTC_HWSR, 4);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
TEST(GPIO_PXPIN(0));
|
||||
TEST(GPIO_PXPIN(1));
|
||||
TEST(GPIO_PXPIN(2));
|
||||
TEST(GPIO_PXPIN(3));
|
||||
TEST(GPIO_PXPIN(0), 4);
|
||||
TEST(GPIO_PXPIN(1), 4);
|
||||
TEST(GPIO_PXPIN(2), 4);
|
||||
TEST(GPIO_PXPIN(3), 4);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
TEST(CPM_CLKGR, 4);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
//or_reg(dh, SADC_ENA, SADC_ENA_TSEN, 1);
|
||||
TEST(SADC_ENA, 1);
|
||||
TEST(SADC_CTRL, 1);
|
||||
TEST(SADC_TSDAT, 4);
|
||||
TEST(SADC_BATDAT, 2);
|
||||
TEST(SADC_STATE, 1);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
TEST(SLCD_CFG, 4);
|
||||
TEST(SLCD_CTRL, 1);
|
||||
TEST(SLCD_STATE, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define VOL_DOWN (1 << 27)
|
||||
#define VOL_UP (1 << 0)
|
||||
#define MENU (1 << 1)
|
||||
#define HOLD (1 << 16)
|
||||
#define OFF (1 << 29)
|
||||
#define MASK (VOL_DOWN|VOL_UP|MENU|HOLD|OFF)
|
||||
#define TS_MASK (SADC_STATE_PEND|SADC_STATE_PENU|SADC_STATE_TSRDY)
|
||||
int probe_device(usb_dev_handle* dh)
|
||||
{
|
||||
int tmp;
|
||||
|
||||
//or_reg(dh, SADC_ENA, SADC_ENA_TSEN, 1);
|
||||
while(1)
|
||||
{
|
||||
if(read_reg(dh, SADC_STATE, 1) & SADC_STATE_TSRDY)
|
||||
{
|
||||
printf("%x\n", read_reg(dh, SADC_TSDAT, 4));
|
||||
or_reg(dh, SADC_CTRL, read_reg(dh, SADC_STATE, 1) & TS_MASK, 1);
|
||||
}
|
||||
|
||||
tmp = read_reg(dh, GPIO_PXPIN(3), 4);
|
||||
if(tmp < 0)
|
||||
return tmp;
|
||||
if(tmp ^ MASK)
|
||||
{
|
||||
if(!(tmp & VOL_DOWN))
|
||||
printf("VOL_DOWN\t");
|
||||
if(!(tmp & VOL_UP))
|
||||
printf("VOL_UP\t");
|
||||
if(!(tmp & MENU))
|
||||
printf("MENU\t");
|
||||
if(!(tmp & OFF))
|
||||
printf("OFF\t");
|
||||
if(!(tmp & HOLD))
|
||||
printf("HOLD\t");
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int read_file(const char *name, unsigned char **buffer)
|
||||
{
|
||||
FILE *fd;
|
||||
int len, n;
|
||||
|
||||
fd = fopen(name, "rb");
|
||||
if (fd < 0)
|
||||
{
|
||||
fprintf(stderr, "[ERR] Could not open %s\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = filesize(fd);
|
||||
|
||||
*buffer = (unsigned char*)malloc(len);
|
||||
if (*buffer == NULL)
|
||||
{
|
||||
fprintf(stderr, "[ERR] Could not allocate memory.\n");
|
||||
fclose(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = fread(*buffer, 1, len, fd);
|
||||
if (n != len)
|
||||
{
|
||||
fprintf(stderr, "[ERR] Short read.\n");
|
||||
fclose(fd);
|
||||
return 0;
|
||||
}
|
||||
fclose(fd);
|
||||
|
||||
return len;
|
||||
}
|
||||
#define _GET_CPU fprintf(stderr, "[INFO] GET_CPU_INFO:"); \
|
||||
GET_CPU_INFO(cpu); \
|
||||
cpu[8] = 0; \
|
||||
fprintf(stderr, " %s\n", cpu);
|
||||
#define _SET_ADDR(a) fprintf(stderr, "[INFO] Set address to 0x%x...", a); \
|
||||
SEND_COMMAND(VR_SET_DATA_ADDRESS, a); \
|
||||
fprintf(stderr, " Done!\n");
|
||||
#define _SEND_FILE(a) fsize = read_file(a, &buffer); \
|
||||
fprintf(stderr, "[INFO] Sending file %s: %d bytes...", a, fsize); \
|
||||
SEND_DATA(buffer, fsize); \
|
||||
free(buffer); \
|
||||
fprintf(stderr, " Done!\n");
|
||||
#define _VERIFY_DATA(a,b,c) fprintf(stderr, "[INFO] Verifying data (%s)...", a); \
|
||||
fsize = read_file(a, &buffer); \
|
||||
buffer2 = (unsigned char*)malloc(fsize); \
|
||||
SEND_COMMAND(VR_SET_DATA_ADDRESS, c); \
|
||||
SEND_COMMAND(VR_SET_DATA_LENGTH, fsize); \
|
||||
GET_DATA(buffer2, fsize); \
|
||||
if(memcmp(buffer, buffer2, fsize) != 0) \
|
||||
fprintf(stderr, "\n[WARN] Sent data isn't the same as received data...\n"); \
|
||||
else \
|
||||
fprintf(stderr, " Done!\n"); \
|
||||
free(buffer); \
|
||||
free(buffer2);
|
||||
#define _STAGE1(a) fprintf(stderr, "[INFO] Stage 1 at 0x%x\n", a); \
|
||||
SEND_COMMAND(VR_PROGRAM_START1, a);
|
||||
#define _STAGE2(a) fprintf(stderr, "[INFO] Stage 2 at 0x%x\n", a); \
|
||||
SEND_COMMAND(VR_PROGRAM_START2, a);
|
||||
#define _FLUSH fprintf(stderr, "[INFO] Flushing caches...\n"); \
|
||||
SEND_COMMAND(VR_FLUSH_CACHES, 0);
|
||||
int mimic_of(usb_dev_handle *dh)
|
||||
{
|
||||
int err, fsize;
|
||||
unsigned char *buffer, *buffer2;
|
||||
char cpu[8];
|
||||
|
||||
fprintf(stderr, "[INFO] Start!\n");
|
||||
_GET_CPU;
|
||||
_SET_ADDR(0x8000 << 16);
|
||||
_SEND_FILE("1.bin");
|
||||
_GET_CPU;
|
||||
_VERIFY_DATA("1.bin", 0, 0x8000 << 16);
|
||||
_STAGE1(0x8000 << 16);
|
||||
Sleep(3000);
|
||||
_VERIFY_DATA("2.bin", 0, 0xB3020060);
|
||||
_GET_CPU;
|
||||
_GET_CPU;
|
||||
_FLUSH;
|
||||
_GET_CPU;
|
||||
_GET_CPU;
|
||||
_SET_ADDR(0x8000 << 16);
|
||||
_SEND_FILE("3.bin");
|
||||
_GET_CPU;
|
||||
_VERIFY_DATA("3.bin", 0, 0x8000 << 16);
|
||||
_GET_CPU;
|
||||
_FLUSH;
|
||||
_GET_CPU;
|
||||
_GET_CPU;
|
||||
_SET_ADDR(0x80D0 << 16);
|
||||
_SEND_FILE("4.bin");
|
||||
_GET_CPU;
|
||||
_VERIFY_DATA("4.bin", 0, 0x80D0 << 16);
|
||||
_GET_CPU;
|
||||
_FLUSH;
|
||||
_GET_CPU;
|
||||
_GET_CPU;
|
||||
_SET_ADDR(0x80E0 << 16);
|
||||
_SEND_FILE("5.bin");
|
||||
_GET_CPU;
|
||||
_VERIFY_DATA("5.bin", 3 << 16, 0x80E0 << 16);
|
||||
_GET_CPU;
|
||||
_FLUSH;
|
||||
_GET_CPU;
|
||||
_GET_CPU;
|
||||
_SET_ADDR(0x80004000);
|
||||
_SEND_FILE("6.bin");
|
||||
_GET_CPU;
|
||||
_VERIFY_DATA("6.bin", 0, 0x80004000);
|
||||
_GET_CPU;
|
||||
_FLUSH;
|
||||
_GET_CPU;
|
||||
_GET_CPU;
|
||||
_SET_ADDR(0x80FD << 16);
|
||||
_SEND_FILE("7.bin");
|
||||
_GET_CPU;
|
||||
_VERIFY_DATA("7.bin", 0, 0x80FD << 16);
|
||||
_GET_CPU;
|
||||
_FLUSH;
|
||||
_GET_CPU;
|
||||
_STAGE2(0x80FD0004);
|
||||
_VERIFY_DATA("8.bin", 0, 0x80004004);
|
||||
_VERIFY_DATA("9.bin", 0, 0x80004008);
|
||||
Sleep(2000);
|
||||
_GET_CPU;
|
||||
_SET_ADDR(0x80E0 << 16);
|
||||
_SEND_FILE("verminkt.bin");
|
||||
_GET_CPU;
|
||||
_VERIFY_DATA("verminkt.bin", 3 << 16, 0x80E0 << 16);
|
||||
_GET_CPU;
|
||||
_FLUSH;
|
||||
_GET_CPU;
|
||||
_STAGE2(0x80E0 << 16);
|
||||
fprintf(stderr, "[INFO] Done!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -330,7 +570,8 @@ found:
|
|||
switch(func)
|
||||
{
|
||||
case 1:
|
||||
err = upload_app(dh, address, buf, len);
|
||||
case 5:
|
||||
err = upload_app(dh, address, buf, len, (func == 5));
|
||||
break;
|
||||
case 2:
|
||||
err = read_data(dh, address, buf, len);
|
||||
|
|
@ -338,6 +579,12 @@ found:
|
|||
case 3:
|
||||
err = test_device(dh);
|
||||
break;
|
||||
case 4:
|
||||
err = probe_device(dh);
|
||||
break;
|
||||
case 6:
|
||||
err = mimic_of(dh);
|
||||
break;
|
||||
}
|
||||
|
||||
/* release claimed interface */
|
||||
|
|
@ -346,15 +593,6 @@ found:
|
|||
usb_close(dh);
|
||||
}
|
||||
|
||||
int filesize(FILE* fd)
|
||||
{
|
||||
int tmp;
|
||||
fseek(fd, 0, SEEK_END);
|
||||
tmp = ftell(fd);
|
||||
fseek(fd, 0, SEEK_SET);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void print_usage(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
|
@ -364,7 +602,8 @@ void print_usage(void)
|
|||
#endif
|
||||
fprintf(stderr, "\t[ADDRESS] has to be in 0xHEXADECIMAL format\n");
|
||||
fprintf(stderr, "\t[CMD]:\n\t\t1 -> upload file to specified address and boot from it\n\t\t2 -> read data from [ADDRESS] with length [LEN] to [FILE]\n");
|
||||
fprintf(stderr, "\t\t3 -> read device status\n");
|
||||
fprintf(stderr, "\t\t3 -> read device status\n\t\t4 -> probe keys (only Onda VX747)\n");
|
||||
fprintf(stderr, "\t\t5 -> same as 1 but do a stage 2 boot\n\t\t6 -> mimic OF fw recovery\n");
|
||||
#ifdef _WIN32
|
||||
fprintf(stderr, "\nExample:\n\t usbtool.exe 1 fw.bin 0x80000000");
|
||||
fprintf(stderr, "\n\t usbtool.exe 2 save.bin 0x81000000 1024");
|
||||
|
|
@ -388,11 +627,17 @@ int main(int argc, char* argv[])
|
|||
sscanf(argv[1], "%d", &cmd);
|
||||
switch(cmd)
|
||||
{
|
||||
case 5:
|
||||
case 1:
|
||||
if (sscanf(argv[3], "0x%x", &address) <= 0)
|
||||
if (strcmp(argv[3], "-1") == 0)
|
||||
address = 0x80000000;
|
||||
else
|
||||
{
|
||||
print_usage();
|
||||
return -1;
|
||||
if (sscanf(argv[3], "0x%x", &address) <= 0)
|
||||
{
|
||||
print_usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
fd = fopen(argv[2], "rb");
|
||||
|
|
@ -430,7 +675,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
fprintf(stderr, "[INFO] File size: %d bytes\n", n);
|
||||
|
||||
jzconnect(address, buf, len, 1);
|
||||
jzconnect(address, buf, len, cmd);
|
||||
break;
|
||||
case 2:
|
||||
if (sscanf(argv[3], "0x%x", &address) <= 0)
|
||||
|
|
@ -468,7 +713,9 @@ int main(int argc, char* argv[])
|
|||
fclose(fd);
|
||||
break;
|
||||
case 3:
|
||||
jzconnect(address, NULL, 0, 3);
|
||||
case 4:
|
||||
case 6:
|
||||
jzconnect(address, NULL, 0, cmd);
|
||||
break;
|
||||
default:
|
||||
print_usage();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue