1
0
Fork 0
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:
Maurus Cuelenaere 2008-06-24 20:14:00 +00:00
parent 07b2031ba0
commit 349c14c26d

View file

@ -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();