spi flash dumper!
This commit is contained in:
parent
ce699d3f32
commit
368c03400f
|
@ -1,4 +1,7 @@
|
||||||
dumpee
|
dumpee
|
||||||
libftfake.so
|
libftfake.so
|
||||||
ftd2xx.h
|
ftd2xx.h
|
||||||
|
ftdidrv
|
||||||
WinTypes.h
|
WinTypes.h
|
||||||
|
spiflash.bin
|
||||||
|
libsqfake.so
|
||||||
|
|
11
Makefile
11
Makefile
|
@ -1,10 +1,13 @@
|
||||||
all: libftfake.so dumpee libsqfake.so
|
all: libftfake.so dumpee libsqfake.so ftdidrv
|
||||||
|
|
||||||
libsqfake.so: libsqfake.c
|
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
|
libftfake.so: libftfake.c
|
||||||
gcc -shared -fPIC -o "$@" "$<" -I. -ldl -Wall
|
$(CC) -shared -fPIC -o "$@" "$<" -I. -ldl -Wall -Wextra
|
||||||
|
|
||||||
dumpee: dumpee.c
|
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
|
||||||
|
|
|
@ -0,0 +1,256 @@
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <ftdi.h>
|
||||||
|
|
||||||
|
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 <lots and lots of data, 500000 bytes>
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
|
@ -74,13 +74,12 @@ FT_STATUS FT_GetBitMode(FT_HANDLE ftHandle, PUCHAR pucMode) {
|
||||||
FT_STATUS FT_GetQueueStatus(FT_HANDLE ftHandle, DWORD* dwRxBytes) {
|
FT_STATUS FT_GetQueueStatus(FT_HANDLE ftHandle, DWORD* dwRxBytes) {
|
||||||
bind(FT_STATUS, (FT_HANDLE, DWORD*), ftHandle, dwRxBytes);
|
bind(FT_STATUS, (FT_HANDLE, DWORD*), ftHandle, dwRxBytes);
|
||||||
// responsible for lots of spam
|
// 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;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
FT_STATUS FT_ListDevices(PVOID pArg1, PVOID pArg2, DWORD flags) {
|
FT_STATUS FT_ListDevices(PVOID pArg1, PVOID pArg2, DWORD flags) {
|
||||||
bind(FT_STATUS, (PVOID, PVOID, DWORD), pArg1, pArg2, flags);
|
bind(FT_STATUS, (PVOID, PVOID, DWORD), pArg1, pArg2, flags);
|
||||||
return rv;
|
|
||||||
// possible usages:
|
// possible usages:
|
||||||
// * fn(nulterm array to strings, &numdevs, FT_LIST_ALL | FT_OPEN_BY_SERIAL_NUMBER)
|
// * 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);
|
// * 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) {
|
FT_STATUS FT_Read(FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesReturned) {
|
||||||
bind(FT_STATUS, (FT_HANDLE, LPVOID, DWORD, LPDWORD),
|
bind(FT_STATUS, (FT_HANDLE, LPVOID, DWORD, LPDWORD),
|
||||||
ftHandle, lpBuffer, dwBytesToRead, lpBytesReturned);
|
ftHandle, lpBuffer, dwBytesToRead, lpBytesReturned);
|
||||||
return rv;
|
|
||||||
printf("FT_Read(%p, %p, 0x%x, &0x%x) = %d\n", ftHandle, lpBuffer, dwBytesToRead, *lpBytesReturned, rv);
|
printf("FT_Read(%p, %p, 0x%x, &0x%x) = %d\n", ftHandle, lpBuffer, dwBytesToRead, *lpBytesReturned, rv);
|
||||||
size_t nb = *lpBytesReturned;
|
size_t nb = *lpBytesReturned;
|
||||||
if (nb < 0x100) {
|
if (nb < 0x100) {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
typedef unsigned int FT_STATUS;
|
typedef unsigned int FT_STATUS;
|
||||||
typedef void* FT_HANDLE;
|
typedef void* FT_HANDLE;
|
||||||
|
|
Loading…
Reference in New Issue