diff --git a/.gitignore b/.gitignore index 50f6144..a3847b6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ dumpee libftfake.so ftd2xx.h +ftdidrv WinTypes.h +spiflash.bin +libsqfake.so diff --git a/Makefile b/Makefile index a6c4655..7ac56c7 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,13 @@ -all: libftfake.so dumpee libsqfake.so +all: libftfake.so dumpee libsqfake.so ftdidrv libsqfake.so: libsqfake.c - $(CC) -shared -fPIC -Wall -Wextra -std=gnu11 -pipe -o $@ $< + $(CC) -shared -fPIC -Wall -Wextra -Wno-unused-parameter -std=gnu11 -pipe -o $@ $< libftfake.so: libftfake.c - gcc -shared -fPIC -o "$@" "$<" -I. -ldl -Wall + $(CC) -shared -fPIC -o "$@" "$<" -I. -ldl -Wall -Wextra dumpee: dumpee.c - gcc -o "$@" "$<" -L../build/ -I. -lftd2xx -Wl,-rpath=../build + $(CC) -o "$@" "$<" -L../build/ -I. -lftd2xx -Wl,-rpath=../build -Wall -Wextra + +ftdidrv: ftdidrv.c + $(CC) -o "$@" "$<" $(shell pkg-config --cflags --libs libftdi1) -Wall -Wextra diff --git a/ftdidrv.c b/ftdidrv.c new file mode 100644 index 0000000..4ae7c2c --- /dev/null +++ b/ftdidrv.c @@ -0,0 +1,256 @@ + +#include +#include +#include +#include + +#include + +static struct ftdi_context* ft; + +static int do_spi_cmd(const uint8_t *wpart, uint32_t wlen, uint8_t* rpart, uint32_t rlen) { + int stat; + + static const uint8_t start[2]={0x90,0x00}; + //printf(" start\n"); + stat = ftdi_write_data(ft, start, sizeof start); + if (stat < 0) return stat; + + uint8_t wbuf[2]; + uint8_t rbuf[1]; + for (uint32_t i = 0; i < wlen; ++i) { + wbuf[0] = 0x92; wbuf[1] = wpart[i]; + //printf(" write %02x\n", wpart[i]); + + stat = ftdi_write_data(ft, wbuf, sizeof wbuf); + if (stat < 0) return stat; + stat = ftdi_read_data (ft, rbuf, sizeof rbuf); + if (stat < 0) return stat; + //printf(" wres %02x\n", rbuf[0]); + } + + for (uint32_t i = 0; i < rlen; ++i) { + wbuf[0] = 0x92; wbuf[1] = 0xff; + + stat = ftdi_write_data(ft, wbuf, sizeof wbuf); + if (stat < 0) return stat; + stat = ftdi_read_data (ft, rbuf, sizeof rbuf); + if (stat < 0) return stat; + + rpart[i] = rbuf[0]; + //printf(" read %02x\n", rpart[i]); + } + + static const uint8_t stop [2]={0x91,0x00}; + //printf(" stop\n"); + stat = ftdi_write_data(ft, stop, sizeof stop); + if (stat < 0) return stat; + + return stat; +} + +int main(int argc, char* argv[]) { + int stat, rv = 0; + + if (!(ft = ftdi_new())) { + printf("can't init ftdi\n"); + return 1; + } + + ftdi_set_interface(ft, INTERFACE_ANY); + + stat = ftdi_usb_open(ft, 0x0403, 0x7fd0); + if(stat<0){printf("ftdi_usb_open failed: %d %s\n",stat,ftdi_get_error_string(ft));rv=1;goto finish;} + + static const char* typtbl[] = {"am","bm","2232c","r","2232h","4232h","232h","230x"}; + printf("chiptype=%d (%s), itf=%d index=%d in ep=%d out ep=%d\n", + ft->type, typtbl[ft->type], ft->interface, ft->index, ft->in_ep, ft->out_ep); + + ftdi_set_latency_timer(ft, 2); // ??? + + printf("get status\n"); + const uint8_t wdata[5] = {0xfd,0x00,0x01,0x02,0xfe}; + stat = ftdi_write_data(ft, wdata, sizeof wdata); + if(stat<0){printf("ftdi_write_data failed: %d %s\n",stat,ftdi_get_error_string(ft));rv=1;goto finish;} + + uint8_t rdata[4]={0}; + stat = ftdi_read_data(ft, rdata, sizeof rdata); + if (stat<0){printf("ftdi_read_data failed: %d %s\n",stat,ftdi_get_error_string(ft));rv=1;goto finish;} + printf("got rdata: %02x %02x %02x %02x\n", rdata[0], rdata[1], rdata[2], rdata[3]); + + stat = ftdi_write_data(ft, wdata, sizeof wdata); + if(stat<0){printf("ftdi_write_data failed: %d %s\n",stat,ftdi_get_error_string(ft));rv=1;goto finish;} + + stat = ftdi_read_data(ft, rdata, sizeof rdata); + if (stat<0){printf("ftdi_read_data failed: %d %s\n",stat,ftdi_get_error_string(ft));rv=1;goto finish;} + printf("got rdata: %02x %02x %02x %02x\n", rdata[0], rdata[1], rdata[2], rdata[3]); + + //const uint8_t rstcapt[]={0xf0,0x00}; + + uint8_t gobloader = 0x94; + printf("go to bootloader (%02x)\n", gobloader); + stat = ftdi_write_data(ft, &gobloader, 1); + if(stat<0){printf("ftdi_write_data failed: %d %s\n",stat,ftdi_get_error_string(ft));rv=1;goto finish;} + + printf("get status\n"); + stat = ftdi_write_data(ft, wdata, sizeof wdata); + if(stat<0){printf("ftdi_write_data failed: %d %s\n",stat,ftdi_get_error_string(ft));rv=1;goto finish;} + + stat = ftdi_read_data(ft, rdata, sizeof rdata); + if (stat<0){printf("ftdi_read_data failed: %d %s\n",stat,ftdi_get_error_string(ft));rv=1;goto finish;} + printf("got rdata: %02x %02x %02x %02x\n", rdata[0], rdata[1], rdata[2], rdata[3]); + + stat = ftdi_write_data(ft, wdata, sizeof wdata); + if(stat<0){printf("ftdi_write_data failed: %d %s\n",stat,ftdi_get_error_string(ft));rv=1;goto finish;} + + stat = ftdi_read_data(ft, rdata, sizeof rdata); + if (stat<0){printf("ftdi_read_data failed: %d %s\n",stat,ftdi_get_error_string(ft));rv=1;goto finish;} + printf("got rdata: %02x %02x %02x %02x\n", rdata[0], rdata[1], rdata[2], rdata[3]); + + const uint8_t unlockseq[27]={0xf1,0x62, 0xa7, 0x7e,0}; + printf("send magic sequence\n"); + stat = ftdi_write_data(ft, unlockseq, sizeof unlockseq); + if(stat<0){printf("ftdi_write_data failed: %d %s\n",stat,ftdi_get_error_string(ft));rv=1;goto finish;} + + printf("get status\n"); + stat = ftdi_write_data(ft, wdata, sizeof wdata); + if(stat<0){printf("ftdi_write_data failed: %d %s\n",stat,ftdi_get_error_string(ft));rv=1;goto finish;} + + stat = ftdi_read_data(ft, rdata, sizeof rdata); + if (stat<0){printf("ftdi_read_data failed: %d %s\n",stat,ftdi_get_error_string(ft));rv=1;goto finish;} + printf("got rdata: %02x %02x %02x %02x\n", rdata[0], rdata[1], rdata[2], rdata[3]); + + stat = ftdi_write_data(ft, wdata, sizeof wdata); + if(stat<0){printf("ftdi_write_data failed: %d %s\n",stat,ftdi_get_error_string(ft));rv=1;goto finish;} + + stat = ftdi_read_data(ft, rdata, sizeof rdata); + if (stat<0){printf("ftdi_read_data failed: %d %s\n",stat,ftdi_get_error_string(ft));rv=1;goto finish;} + printf("got rdata: %02x %02x %02x %02x\n", rdata[0], rdata[1], rdata[2], rdata[3]); + + printf("do spiflash id\n"); + uint8_t spiidwr[] = {0x9f}; uint8_t spiidrd[2]; + do_spi_cmd(spiidwr, sizeof spiidwr, spiidrd, sizeof spiidrd); + printf("spiflash id=%02x %02x\n", spiidrd[0], spiidrd[1]); + + printf("do spiflash stat\n"); + uint8_t spistatwr[] = {0xd7}; uint8_t spistatrd[1]; + do_spi_cmd(spistatwr, sizeof spistatwr, spistatrd, sizeof spistatrd); + printf("spiflash stat=%02x\n", spistatrd[0]); + + /*gobloader = 0x93; + printf("go to application (%02x)\n", gobloader); + stat = ftdi_write_data(ft, &gobloader, 1); + if(stat<0){printf("ftdi_write_data failed: %d %s\n",stat,ftdi_get_error_string(ft));rv=1;goto finish;}*/ + + printf("get status\n"); + stat = ftdi_write_data(ft, wdata, sizeof wdata); + if(stat<0){printf("ftdi_write_data failed: %d %s\n",stat,ftdi_get_error_string(ft));rv=1;goto finish;} + + stat = ftdi_read_data(ft, rdata, sizeof rdata); + if (stat<0){printf("ftdi_read_data failed: %d %s\n",stat,ftdi_get_error_string(ft));rv=1;goto finish;} + printf("got rdata: %02x %02x %02x %02x\n", rdata[0], rdata[1], rdata[2], rdata[3]); + + // bitstream: 0x000000..0x019fff + // userdata1: 0x01a000..0x01ffff + // multiboot: 0x020000..0x039fff + // userdata2: 0x03a000..0x03ffff // 2Mbit in size + printf("spiflash dump!\n"); + const uint8_t spifastread0[]={0x0b,0x00,0x00,0x00}; +#define nbytes 0x040000 + static uint8_t spifastreadbuf[1+nbytes]; // data back has an extra "don't care" bit... + do_spi_cmd(spifastread0, sizeof spifastread0, spifastreadbuf, sizeof spifastreadbuf); + FILE* f = fopen("spiflash.bin", "wb+"); + fwrite(&spifastreadbuf[1], 1, nbytes, f); +#undef nbytes + fclose(f); + + /* + * W f1 01 04 00 00 00 90 d0 03 90 d0 03 e8 6e f3 00 00 f0 0f 0f 81 4b 32 01 00 + * set settings (spurious?) + * [ 0]: normal + * [1:2]: clock freq 0004: 25 MHz + * [3:4]: trigger PW scale: no scale (0) + * [5:7]: 90 d0 03: memsetting 1: 250000*mem usage + * [8:a]: 90 d0 03: memsetting 2 + * [b:d]: e8 6e f3: MS1*(1-pre_trigger_samples) + * [ e]: fixed 00? + * [ f]: 00: no trigger + * [ 10]: fixed f0? + * [ 11]: fixed 0f? + * [ 12]: 0f: capture mode + * [13:14]: voltage: 81 4b: 3v3 + * [ 15]: fixed 32? + * [ 16]: !abort (0x01) + * [ 17]: abort (0x00) + * ReadEE 0x20 -> 0x8888 + * ??? location + * W f0 00 + * capture state reset? + * W fd 00 01 02 fe + * status + * R 09 09 09 09 || 22 22 22 22 + * retval: uninited(?) || application + * W 94 + * reset to bootloader + * ~ + * ReadEE 0x12 -> 0xa762 + * ReadEE 0x13 -> 0x037e + * read magic 24bit code + * W f1 62 a7 7e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * bootloader: enable device(?) + * W fd 00 01 02 fe + * R 01 01 01 01 + * status -> bootloader + * W fd 00 01 02 fe + * R 01 01 01 01 + * status -> bootloader (spurious double?) + * 93 + * reset to application + * ~ + * W fd 00 01 02 fe + * R 22 22 22 22 + * status -> application + * ~ + * W f1 01 04 00 00 00 90 d0 03 90 d0 03 e8 6e f3 00 00 f0 0f 0f 81 4b 32 01 00 + * set settings (same as in begin) + * W f0 00 + * capture state reset? + * W fd 00 01 02 fe + * R 22 22 22 22 + * status -> application + * W f1 01 04 00 00 00 90 d0 03 90 d0 03 e8 6e f3 00 00 f0 0f 0f 81 4b 32 01 00 + * W f1 01 04 00 00 00 90 d0 03 90 d0 03 90 6e f3 00 00 f0 0f 0f 81 4b 32 01 00 + * ^^ + * set settings + * W fd 00 01 02 fe + * R 22 22 22 22 + * status -> application + * W f0 00 + * capture state reset? + * W f0 01 + * start capture/wait for trigger + * R 11 00 00 + * "trig instant" + * R dd + * status byte: complete + * W f0 00 + * capture state reset? + * W f0 06 + * read acquired data + * R + * W f0 00 + * capture state reset? + * W f1 01 04 00 00 00 90 d0 03 90 d0 03 e8 6e f3 00 00 f0 0f 0f 81 4b 32 01 00 + * set settings + * W fd 00 01 02 fe + * R 22 22 22 22 + * status -> application + */ + +finish: + ftdi_usb_close(ft); + + ftdi_free(ft); + return rv; +} + diff --git a/libftfake.c b/libftfake.c index 3a712f9..adb3cdf 100644 --- a/libftfake.c +++ b/libftfake.c @@ -74,13 +74,12 @@ FT_STATUS FT_GetBitMode(FT_HANDLE ftHandle, PUCHAR pucMode) { FT_STATUS FT_GetQueueStatus(FT_HANDLE ftHandle, DWORD* dwRxBytes) { bind(FT_STATUS, (FT_HANDLE, DWORD*), ftHandle, dwRxBytes); // responsible for lots of spam - //printf("FT_GetSqueueStatus(%p, &0x%x) = %d\n", ftHandle, *dwRxBytes, rv); + printf("FT_GetSqueueStatus(%p, &0x%x) = %d\n", ftHandle, *dwRxBytes, rv); return rv; } FT_STATUS FT_ListDevices(PVOID pArg1, PVOID pArg2, DWORD flags) { bind(FT_STATUS, (PVOID, PVOID, DWORD), pArg1, pArg2, flags); - return rv; // possible usages: // * fn(nulterm array to strings, &numdevs, FT_LIST_ALL | FT_OPEN_BY_SERIAL_NUMBER) // * fn(null??, charbuf, FT_LIST_BY_INDEX | FT_OPEN_BY_SERIAL_NUMBER); @@ -121,7 +120,6 @@ FT_STATUS FT_OpenEx(PVOID pArg1, DWORD flags, FT_HANDLE* pHandle) { FT_STATUS FT_Read(FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesReturned) { bind(FT_STATUS, (FT_HANDLE, LPVOID, DWORD, LPDWORD), ftHandle, lpBuffer, dwBytesToRead, lpBytesReturned); - return rv; printf("FT_Read(%p, %p, 0x%x, &0x%x) = %d\n", ftHandle, lpBuffer, dwBytesToRead, *lpBytesReturned, rv); size_t nb = *lpBytesReturned; if (nb < 0x100) { diff --git a/libsqfake.c b/libsqfake.c index 807bef9..b637d8f 100644 --- a/libsqfake.c +++ b/libsqfake.c @@ -3,6 +3,7 @@ #include #include #include +#include typedef unsigned int FT_STATUS; typedef void* FT_HANDLE;