diff --git a/pcileech/Android.mk b/pcileech/Android.mk index ad5bd1e..626397b 100644 --- a/pcileech/Android.mk +++ b/pcileech/Android.mk @@ -14,7 +14,7 @@ LOCAL_CFLAGS := -D ANDROID LOCAL_LDLIBS := -L$(LOCAL_PATH)/lib -llog -g LOCAL_C_INCLUDES := bionic -LOCAL_SRC_FILES:= pcileech.c oscompatibility.c device.c device3380.c device605_uart.c device605_601.c device605_tcp.c executor.c extra.c help.c kmd.c memdump.c mempatch.c statistics.c tlp.c util.c vfs.c +LOCAL_SRC_FILES:= pcileech.c oscompatibility.c device.c device3380.c device605_601.c device605_tcp.c executor.c extra.c help.c kmd.c memdump.c mempatch.c statistics.c tlp.c util.c vfs.c LOCAL_MODULE := pcileech LOCAL_SHARED_LIBRARIES += libusb1.0 diff --git a/pcileech/Makefile b/pcileech/Makefile index c083d97..b6eb9c8 100644 --- a/pcileech/Makefile +++ b/pcileech/Makefile @@ -1,7 +1,7 @@ CC=gcc CFLAGS=-I. -D LINUX -pthread `pkg-config libusb-1.0 --libs --cflags` DEPS = pcileech.h -OBJ = pcileech oscompatibility.o pcileech.o device.o device3380.o device605_uart.o device605_601.o device605_tcp.o executor.o extra.o help.o kmd.o memdump.o mempatch.o statistics.o tlp.o util.o vfs.o +OBJ = pcileech oscompatibility.o pcileech.o device.o device3380.o device605_601.o device605_tcp.o executor.o extra.o help.o kmd.o memdump.o mempatch.o statistics.o tlp.o util.o vfs.o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) diff --git a/pcileech/device.c b/pcileech/device.c index e86ed90..0eacdd6 100644 --- a/pcileech/device.c +++ b/pcileech/device.c @@ -7,7 +7,6 @@ #include "kmd.h" #include "statistics.h" #include "device3380.h" -#include "device605_uart.h" #include "device605_601.h" #include "device605_tcp.h" @@ -157,9 +156,6 @@ BOOL DeviceOpen(_Inout_ PPCILEECH_CONTEXT ctx) if(PCILEECH_DEVICE_SP605_FT601 == ctx->cfg->dev.tp || PCILEECH_DEVICE_NA == ctx->cfg->dev.tp) { result = Device605_601_Open(ctx); } - if(PCILEECH_DEVICE_SP605_UART == ctx->cfg->dev.tp) { - result = Device605_UART_Open(ctx); - } if(PCILEECH_DEVICE_SP605_TCP == ctx->cfg->dev.tp) { result = Device605_TCP_Open(ctx); } diff --git a/pcileech/device605_601.c b/pcileech/device605_601.c index 448bed1..1732ec6 100644 --- a/pcileech/device605_601.c +++ b/pcileech/device605_601.c @@ -14,30 +14,30 @@ // FPGA/SP605/FT601 defines below. //------------------------------------------------------------------------------- -#define FPGA_CFG_RX_VALID 0x77000000 -#define FPGA_CFG_RX_VALID_MASK 0xff070000 -#define FPGA_CMD_RX_VALID 0x77020000 -#define FPGA_CMD_RX_VALID_MASK 0xff070000 - -#define FPGA_TLP_RX_VALID 0x77030000 -#define FPGA_TLP_RX_VALID_MASK 0xff030000 -#define FPGA_TLP_RX_VALID_LAST 0x77070000 -#define FPGA_TLP_RX_VALID_LAST_MASK 0xff070000 - -#define FPGA_TLP_TX_VALID 0x77030000 -#define FPGA_TLP_TX_VALID_LAST 0x77070000 -#define FPGA_LOOP_TX_VALID 0x77010000 +#define FPGA_TLP_TX_VALID 0x77000000 +#define FPGA_TLP_TX_VALID_LAST 0x77040000 +#define FPGA_LOOP_TX_VALID 0x77020000 #define SP605_601_PROBE_MAXPAGES 0x400 -#define SP605_601_MAX_SIZE_RX 0x0001e000 // in data bytes (excl. overhead/TLP headers) -#define SP605_601_MAX_SIZE_TX 0x00002000 // in total data (incl. overhead/TLP headers) +#define SP605_601_MAX_SIZE_RX 0x0001f000 // in data bytes (excl. overhead/TLP headers) +#define SP605_601_MAX_SIZE_TX 0x00002000 // in total data (incl. overhead/TLP headers) + +#define FPGA_CMD_VERSION 0x01 +#define FPGA_CMD_PCIE_STATUS 0x02 #define ENDIAN_SWAP_WORD(x) (x = (x << 8) | (x >> 8)) #define ENDIAN_SWAP_DWORD(x) (x = (x << 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | (x >> 24)) +// Delay in uS. DELAY_READ=300, DELAY_WRITE=150 -> 85MB/s. +// Values below are a bit more conservative for hw tolerance reasons. +#define DELAY_READ 400 +#define DELAY_WRITE 175 +#define DELAY_PROBE 500 + typedef struct tdDEVICE_CONTEXT_SP605_601 { WORD wDeviceId; WORD wFpgaVersion; + WORD wFpgaStatus; BOOL isPrintTlp; PTLP_CALLBACK_BUF_MRd pMRdBuffer; struct { @@ -130,29 +130,43 @@ VOID Device605_601_Close(_Inout_ PPCILEECH_CONTEXT ctxPcileech) VOID Device605_601_GetDeviceID_FpgaVersion(_In_ PDEVICE_CONTEXT_SP605_601 ctx) { DWORD status; - DWORD cbTX, cbRX, i, dwStatus, dwData; + DWORD cbTX, cbRX, i, j; PBYTE pbRX = LocalAlloc(0, 0x01000000); + DWORD dwStatus, dwData, cdwCfg = 0; + PDWORD pdwData; BYTE pbTX[24] = { // cfg read addr 0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x77, // cmd msg: version - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x77, - // mirror msg -> at least something to read back -> no ft601 freeze. - 0xff, 0xee, 0xdd, 0xcc, 0x00, 0x00, 0x01, 0x77 + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x77, + // cmd msg: PCIe status + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x77 }; status = ctx->dev.pfnFT_WritePipe(ctx->dev.hFTDI, 0x02, pbTX, 24, &cbTX, NULL); if(status) { goto fail; } status = ctx->dev.pfnFT_ReadPipe(ctx->dev.hFTDI, 0x82, pbRX, 0x01000000, &cbRX, NULL); - if(status || cbRX < 16) { goto fail; } - for(i = 0; i < cbRX - 7; i += 8) { - dwData = *(PDWORD)(pbRX + i); - dwStatus = *(PDWORD)(pbRX + i + 4); - if(!ctx->wDeviceId && (FPGA_CFG_RX_VALID == (FPGA_CFG_RX_VALID_MASK & dwStatus))) { - ctx->wDeviceId = dwStatus & 0xffff; - } - if(!ctx->wFpgaVersion && (FPGA_CMD_RX_VALID == (FPGA_CMD_RX_VALID_MASK & dwStatus))) { - ctx->wFpgaVersion = dwData & 0xffff; - ENDIAN_SWAP_WORD(ctx->wFpgaVersion); + if(status) { goto fail; } + for(i = 0; i < cbRX; i += 32) { + dwStatus = *(PDWORD)(pbRX + i); + pdwData = (PDWORD)(pbRX + i + 4); + if((dwStatus & 0xf0000000) != 0xe0000000) { continue; } + for(j = 0; j < 7; j++) { + dwData = *pdwData; + if((dwStatus & 0x03) == 0x03) { // CMD REPLY (or filler) + if((dwData >> 24) == FPGA_CMD_VERSION) { // FPGA bitstream version + ctx->wFpgaVersion = (WORD)dwData; + } + if((dwData >> 24) == FPGA_CMD_PCIE_STATUS) { // PCIe status + ctx->wFpgaStatus = (WORD)dwData; + } + } + if((dwStatus & 0x03) == 0x01) { // PCIe CFG REPLY + if(((++cdwCfg % 2) == 0) && (WORD)dwData) { // DeviceID + ctx->wDeviceId = (WORD)dwData; + } + } + pdwData++; + dwStatus >>= 4; } } fail: @@ -198,41 +212,41 @@ BOOL Device605_601_TxTlp(_In_ PDEVICE_CONTEXT_SP605_601 ctx, _In_ PBYTE pbTlp, _ VOID Device605_601_RxTlpSynchronous(_In_ PDEVICE_CONTEXT_SP605_601 ctx) { DWORD status; - DWORD dwTlp, dwStatus; - DWORD i, cdwTlp = 0; + DWORD i, j, cdwTlp = 0; BYTE pbTlp[TLP_RX_MAX_SIZE]; PDWORD pdwTlp = (PDWORD)pbTlp; PDWORD pdwRx = (PDWORD)ctx->rxbuf.pb; - + DWORD dwStatus, *pdwData; status = ctx->dev.pfnFT_ReadPipe(ctx->dev.hFTDI, 0x82, ctx->rxbuf.pb, ctx->rxbuf.cbMax, &ctx->rxbuf.cb, NULL); if(status) { ctx->dev.pfnFT_AbortPipe(ctx->dev.hFTDI, 0x82); return; } - if((ctx->rxbuf.cb % 8) && (ctx->rxbuf.cb > 4)) { - printf("Device Info: SP605 / FT601: Bad read from device. Should not happen!\n"); - return; - } - for(i = 0; i < ctx->rxbuf.cb / sizeof(QWORD); i++) { // index in 64-bit (QWORD) - dwTlp = pdwRx[i << 1]; - dwStatus = pdwRx[1 + (i << 1)]; - if(FPGA_TLP_RX_VALID == (FPGA_TLP_RX_VALID_MASK & dwStatus)) { - pdwTlp[cdwTlp] = dwTlp; - cdwTlp++; - if(cdwTlp >= TLP_RX_MAX_SIZE / sizeof(DWORD)) { return; } - } - if(FPGA_TLP_RX_VALID_LAST == (FPGA_TLP_RX_VALID_LAST_MASK & dwStatus)) { - if(cdwTlp >= 3) { - if(ctx->isPrintTlp) { - TLP_Print(pbTlp, cdwTlp << 2, FALSE); - } - if(ctx->hRxTlpCallbackFn) { - ctx->hRxTlpCallbackFn(ctx->pMRdBuffer, pbTlp, cdwTlp << 2, NULL); + for(i = 0; i < ctx->rxbuf.cb; i += 32) { // index in 64-bit (QWORD) + dwStatus = *(PDWORD)(ctx->rxbuf.pb + i); + pdwData = (PDWORD)(ctx->rxbuf.pb + i + 4); + if((dwStatus & 0xf0000000) != 0xe0000000) { continue; } + for(j = 0; j < 7; j++) { + if((dwStatus & 0x03) == 0x00) { // PCIe TLP + pdwTlp[cdwTlp] = *pdwData; + cdwTlp++; + if(cdwTlp >= TLP_RX_MAX_SIZE / sizeof(DWORD)) { return; } + } + if((dwStatus & 0x07) == 0x04) { // PCIe TLP and LAST + if(cdwTlp >= 3) { + if(ctx->isPrintTlp) { + TLP_Print(pbTlp, cdwTlp << 2, FALSE); + } + if(ctx->hRxTlpCallbackFn) { + ctx->hRxTlpCallbackFn(ctx->pMRdBuffer, pbTlp, cdwTlp << 2, NULL); + } + } else { + printf("Device Info: SP605 / FT601: Bad PCIe TLP received! Should not happen!\n"); } - } else { - printf("Device Info: SP605 / FT601: Bad PCIe TLP received! Should not happen!\n"); + cdwTlp = 0; } - cdwTlp = 0; + pdwData++; + dwStatus >>= 4; } } } @@ -242,7 +256,7 @@ BOOL Device605_601_ReadDMA(_Inout_ PPCILEECH_CONTEXT ctxPcileech, _In_ QWORD qwA PDEVICE_CONTEXT_SP605_601 ctx = (PDEVICE_CONTEXT_SP605_601)ctxPcileech->hDevice; TLP_CALLBACK_BUF_MRd rxbuf; DWORD tx[4], o, i; - BOOL is32; + BOOL is32, isFlush; PTLP_HDR_MRdWr64 hdrRd64 = (PTLP_HDR_MRdWr64)tx; PTLP_HDR_MRdWr32 hdrRd32 = (PTLP_HDR_MRdWr32)tx; if(cb > SP605_601_MAX_SIZE_RX) { return FALSE; } @@ -280,10 +294,16 @@ BOOL Device605_601_ReadDMA(_Inout_ PPCILEECH_CONTEXT ctxPcileech, _In_ QWORD qwA for(i = 0; i < 4; i++) { ENDIAN_SWAP_DWORD(tx[i]); } - Device605_601_TxTlp(ctx, (PBYTE)tx, is32 ? 12 : 16, TRUE, (o % 0x8000 == 0x7000)); + isFlush = ((o % 0x8000) == 0x7000); + if(isFlush) { + Device605_601_TxTlp(ctx, (PBYTE)tx, is32 ? 12 : 16, FALSE, TRUE); + usleep(DELAY_WRITE); + } else { + Device605_601_TxTlp(ctx, (PBYTE)tx, is32 ? 12 : 16, FALSE, FALSE); + } } Device605_601_TxTlp(ctx, NULL, 0, TRUE, TRUE); - usleep(300); + usleep(DELAY_READ); Device605_601_RxTlpSynchronous(ctx); ctx->pMRdBuffer = NULL; return rxbuf.cb >= rxbuf.cbMax; @@ -340,7 +360,7 @@ VOID Device605_601_ProbeDMA(_Inout_ PPCILEECH_CONTEXT ctxPcileech, _In_ QWORD qw Device605_601_TxTlp(ctx, (PBYTE)tx, is32 ? 12 : 16, FALSE, (i % 24 == 0)); } Device605_601_TxTlp(ctx, NULL, 0, TRUE, TRUE); - usleep(300); + usleep(DELAY_PROBE); Device605_601_RxTlpSynchronous(ctx); ctx->hRxTlpCallbackFn = NULL; ctx->pMRdBuffer = NULL; @@ -445,7 +465,7 @@ BOOL Device605_601_Open(_Inout_ PPCILEECH_CONTEXT ctxPcileech) if(!ctx->dev.hFTDI) { goto fail; } Device605_601_GetDeviceID_FpgaVersion(ctx); if(!ctx->wDeviceId) { goto fail; } - ctx->rxbuf.cbMax = (DWORD)(2.3 * SP605_601_MAX_SIZE_RX); // buffer size tuned to lowest possible (+margin) for performance. + ctx->rxbuf.cbMax = (DWORD)(1.25 * SP605_601_MAX_SIZE_RX + 0x1000); // buffer size tuned to lowest possible (+margin) for performance. ctx->rxbuf.pb = LocalAlloc(0, ctx->rxbuf.cbMax); if(!ctx->rxbuf.pb) { goto fail; } ctx->txbuf.cbMax = SP605_601_MAX_SIZE_TX + 0x10000; @@ -478,7 +498,7 @@ BOOL Device605_601_Open(_Inout_ PPCILEECH_CONTEXT ctxPcileech) BOOL Device605_601_Open(_Inout_ PPCILEECH_CONTEXT ctx) { - if(ctx->cfg->dev.tp == PCILEECH_DEVICE_SP605_UART) { + if(ctx->cfg->dev.tp == PCILEECH_DEVICE_SP605_FT601) { printf("SP605 / FT601: Failed. Device currently only supported in PCILeech for Windows."); } return FALSE; diff --git a/pcileech/device605_tcp.c b/pcileech/device605_tcp.c index f627647..fff9dc9 100644 --- a/pcileech/device605_tcp.c +++ b/pcileech/device605_tcp.c @@ -5,6 +5,7 @@ #ifdef WIN32 #include +#include #pragma comment(lib, "ws2_32.lib") @@ -59,7 +60,7 @@ PCIE_CTL; #define TLP_RX_SIZE 128 #define TLP_RX_MAX_SIZE 1024 -#define SP605_PROBE_MAXPAGES 1024 +#define SP605_PROBE_MAXPAGES 1 #define SP605_TCP_MAX_SIZE_RX 0x00001000 #define SP605_TCP_MAX_SIZE_TX 0x00001000 @@ -157,7 +158,7 @@ BOOL Device605_TCP_TxTlp(_In_ PDEVICE_CONTEXT_SP605_TCP ctx, _In_ PBYTE pbTlp, _ } // prepare transmit buffer pbTx = ctx->txbuf.pb + ctx->txbuf.cb; - cbTx = sizeof(PCIE_CTL) * cbTlp; + cbTx = sizeof(PCIE_CTL) * (cbTlp / sizeof(DWORD)); for (Tx = (PCIE_CTL *)pbTx, i = 0; i < cbTlp; Tx++, i += 4) { Tx->data = ENDIAN_SWAP_DWORD(*(PDWORD)(pbTlp + i)); Tx->flags = PCIE_F_HAS_DATA; @@ -170,7 +171,7 @@ BOOL Device605_TCP_TxTlp(_In_ PDEVICE_CONTEXT_SP605_TCP ctx, _In_ PBYTE pbTlp, _ // transmit if (ctx->txbuf.cb && (fFlush || (ctx->txbuf.cb > ctx->txbuf.cbMax - 0x1000))) { while (Total < ctx->txbuf.cb) { - len = send(ctx->Sock, (const char *)ctx->txbuf.pb + Total, ctx->txbuf.cb - Total, 0); + len = send(ctx->Sock, (const char *)(ctx->txbuf.pb + Total), ctx->txbuf.cb - Total, 0); if (len == 0 || len == SOCKET_ERROR) { fprintf(stderr, "ERROR: send() fails\n"); return FALSE; @@ -182,41 +183,33 @@ BOOL Device605_TCP_TxTlp(_In_ PDEVICE_CONTEXT_SP605_TCP ctx, _In_ PBYTE pbTlp, _ return TRUE; } -BOOL Device605_TCP_RxTlpSynchronous(_In_ PDEVICE_CONTEXT_SP605_TCP ctx) +VOID Device605_TCP_RxTlpSynchronous(_In_ PDEVICE_CONTEXT_SP605_TCP ctx) { DWORD i = 0, cdwTlp = 0, Total = 0, len; - PCIE_CTL Rx, Tx; + PCIE_CTL *pRx, Tx; BYTE pbTlp[TLP_RX_MAX_SIZE]; PDWORD pdwTlp = (PDWORD)pbTlp; - PDWORD pdwRx = (PDWORD)ctx->rxbuf.pb; + //PDWORD pdwRx = (PDWORD)ctx->rxbuf.pb; + // Request Replies Tx.flags = PCIE_F_RECV_REPLY | PCIE_F_TIMEOUT; Tx.data = 0; - while (Total < sizeof(Tx)) { - len = send(ctx->Sock, (const char *)&Tx + Total, sizeof(Tx) - Total, 0); - if (len == 0 || len == SOCKET_ERROR) { - fprintf(stderr, "ERROR: send() fails\n"); - return FALSE; - } - Total += len; + len = send(ctx->Sock, (const char *)&Tx, sizeof(Tx), 0); + if(len == 0 || len == SOCKET_ERROR) { + fprintf(stderr, "ERROR: send() fails\n"); + return; } - while (cdwTlp < TLP_RX_MAX_SIZE / sizeof(DWORD)) { - Total = 0; - while (Total < sizeof(Rx)) { - len = recv(ctx->Sock, (char *)&Rx + Total, sizeof(Rx) - Total, 0); - if (len == 0 || len == SOCKET_ERROR) { - fprintf(stderr, "ERROR: recv() fails\n"); - return FALSE; - } - Total += len; - } - if (Rx.flags & PCIE_F_ERROR) { + // Receive Data + ctx->rxbuf.cb = recv(ctx->Sock, ctx->rxbuf.pb, ctx->rxbuf.cbMax, 0); + pRx = (PCIE_CTL*)ctx->rxbuf.pb; + for(i = 0; i < ctx->rxbuf.cb; i += sizeof(PCIE_CTL)) { + if(pRx->flags & PCIE_F_ERROR) { fprintf(stderr, "ERROR: failed to receive TLP\n"); - return FALSE; + return; } - if (!(Rx.flags & PCIE_F_HAS_DATA)) { return FALSE; } - pdwTlp[cdwTlp] = ENDIAN_SWAP_DWORD(Rx.data); + if(!(pRx->flags & PCIE_F_HAS_DATA)) { return; } + pdwTlp[cdwTlp] = ENDIAN_SWAP_DWORD(pRx->data); cdwTlp++; - if (Rx.flags & PCIE_F_TLAST) { + if(pRx->flags & PCIE_F_TLAST) { if (cdwTlp >= 3) { if (ctx->isPrintTlp) { TLP_Print(pbTlp, cdwTlp << 2, FALSE); @@ -224,15 +217,14 @@ BOOL Device605_TCP_RxTlpSynchronous(_In_ PDEVICE_CONTEXT_SP605_TCP ctx) if (ctx->hRxTlpCallbackFn) { ctx->hRxTlpCallbackFn(ctx->pMRdBuffer, pbTlp, cdwTlp << 2, NULL); } - } - else { + } else { fprintf(stderr, "WARNING: BAD PCIe TLP RECEIVED! THIS SHOULD NOT HAPPEN!\n"); - return FALSE; + return; } - break; + cdwTlp = 0; } + pRx++; } - return TRUE; } BOOL Device605_TCP_ReadDMA(_Inout_ PPCILEECH_CONTEXT ctxPcileech, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb) @@ -250,11 +242,10 @@ BOOL Device605_TCP_ReadDMA(_Inout_ PPCILEECH_CONTEXT ctxPcileech, _In_ QWORD qwA // prepare ctx->pMRdBuffer = &rxbuf; ctx->hRxTlpCallbackFn = TLP_CallbackMRd; + rxbuf.cb = 0; + rxbuf.pb = pb; // transmit TLPs while (o < cb) { - rxbuf.cb = 0; - rxbuf.pb = pb + o; - rxbuf.cbMax = TLP_RX_SIZE; memset(tx, 0, 16); is32 = qwAddr + o < 0x100000000; if (is32) { @@ -279,22 +270,16 @@ BOOL Device605_TCP_ReadDMA(_Inout_ PPCILEECH_CONTEXT ctxPcileech, _In_ QWORD qwA for (i = 0; i < 4; i++) { ENDIAN_SWAP_DWORD(tx[i]); } - if (!Device605_TCP_TxTlp(ctx, (PBYTE)tx, is32 ? 12 : 16, TRUE) || - !Device605_TCP_RxTlpSynchronous(ctx)) { - ctx->hRxTlpCallbackFn = NULL; - ctx->pMRdBuffer = NULL; - return FALSE; + if (!Device605_TCP_TxTlp(ctx, (PBYTE)tx, is32 ? 12 : 16, TRUE)) { + break; } - if (rxbuf.cb == 0) { - ctx->hRxTlpCallbackFn = NULL; - ctx->pMRdBuffer = NULL; - return FALSE; - } - o += rxbuf.cb; + o += TLP_RX_SIZE; + rxbuf.cbMax = o; + Device605_TCP_RxTlpSynchronous(ctx); } ctx->hRxTlpCallbackFn = NULL; - ctx->pMRdBuffer = NULL; - return TRUE; + ctx->pMRdBuffer = NULL; + return rxbuf.cb >= cb; } VOID Device605_TCP_ProbeDMA(_Inout_ PPCILEECH_CONTEXT ctxPcileech, _In_ QWORD qwAddr, _In_ DWORD cPages, _Out_ __bcount(cPages) PBYTE pbResultMap) @@ -346,11 +331,10 @@ VOID Device605_TCP_ProbeDMA(_Inout_ PPCILEECH_CONTEXT ctxPcileech, _In_ QWORD qw for (j = 0; j < 4; j++) { ENDIAN_SWAP_DWORD(tx[j]); } - if(!Device605_TCP_TxTlp(ctx, (PBYTE)tx, is32 ? 12 : 16, TRUE) || !Device605_TCP_RxTlpSynchronous(ctx)) { - goto err; - } - } -err: + Device605_TCP_TxTlp(ctx, (PBYTE)tx, is32 ? 12 : 16, FALSE); + } + Device605_TCP_TxTlp(ctx, NULL, 0, TRUE); + Device605_TCP_RxTlpSynchronous(ctx); ctx->hRxTlpCallbackFn = NULL; ctx->pMRdBuffer = NULL; } @@ -433,9 +417,7 @@ BOOL Device605_TCP_ListenTlp(_Inout_ PPCILEECH_CONTEXT ctxPcileech, _In_ DWORD d return FALSE; } Sleep(10); - if (!Device605_TCP_RxTlpSynchronous(ctx)) { - return FALSE; - } + Device605_TCP_RxTlpSynchronous(ctx); } return TRUE; } @@ -468,7 +450,7 @@ BOOL Device605_TCP_Open(_Inout_ PPCILEECH_CONTEXT ctxPcileech) if (!ctx->Sock) { goto fail; } ctx->wDeviceId = Device605_TCP_GetDeviceID(ctx); if (!ctx->wDeviceId) { goto fail; } - ctx->rxbuf.cbMax = (DWORD)(2.3 * SP605_TCP_MAX_SIZE_RX); + ctx->rxbuf.cbMax = (DWORD)(1.5 * SP605_TCP_MAX_SIZE_RX * 0x1000); ctx->rxbuf.pb = LocalAlloc(0, ctx->rxbuf.cbMax); if (!ctx->rxbuf.pb) { goto fail; } ctx->txbuf.cbMax = SP605_TCP_MAX_SIZE_TX + 0x10000; diff --git a/pcileech/device605_uart.c b/pcileech/device605_uart.c deleted file mode 100644 index 312d3e6..0000000 --- a/pcileech/device605_uart.c +++ /dev/null @@ -1,413 +0,0 @@ -// device605_uart.c : implementation related to the Xilinx SP605 dev board flashed with @d_olex early access bitstream. (UART communication). -// -// (c) Ulf Frisk, 2017 -// Author: Ulf Frisk, pcileech@frizk.net -// -#ifdef WIN32 - -#include "device605_uart.h" -#include "device.h" -#include "tlp.h" - -//------------------------------------------------------------------------------- -// SP605 defines below. -//------------------------------------------------------------------------------- - -#define COM_PORT_CFG "COM4" -#define COM_PORT_PCIE "COM3" -#define SP605_STATUS_TX_CONT 0x000000c0 -#define SP605_STATUS_TX_END 0x010000c0 -#define SP605_STATUS_MASK_VALID 0x00000080 -#define SP605_STATUS_MASK_END 0x01000000 -#define SP605_COM_TIMEOUT 100 // milliseconds -#define SP605_READ_TIMEOUT 500 // milliseconds -#define SP605_PROBE_TIMEOUT 350 // milliseconds -#define SP605_PROBE_MAXPAGES 1024 - -#define ENDIAN_SWAP_DWORD(x) (x = (x << 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | (x >> 24)) - -typedef struct tdDEVICE_CONTEXT_SP605 { - HANDLE hCommCfg; - HANDLE hCommPcie; - HANDLE hThreadRx; - WORD wDeviceId; - BOOL isTerminateThreadRx; - BOOL isPrintTlp; - OVERLAPPED oTx; - OVERLAPPED oRx; - OVERLAPPED oCfg; - HANDLE hRxBufferEvent; - PTLP_CALLBACK_BUF_MRd pMRdBuffer; - BOOL(*hRxTlpCallbackFn)(_Inout_ PTLP_CALLBACK_BUF_MRd pBufferMrd, _In_ PBYTE pb, _In_ DWORD cb, _In_opt_ HANDLE hEventCompleted); -} DEVICE_CONTEXT_SP605, *PDEVICE_CONTEXT_SP605; - -//------------------------------------------------------------------------------- -// SP605 implementation below. -//------------------------------------------------------------------------------- - -VOID Device605_UART_Close(_Inout_ PPCILEECH_CONTEXT ctx) -{ - PDEVICE_CONTEXT_SP605 ctx605 = (PDEVICE_CONTEXT_SP605)ctx->hDevice; - if(!ctx605) { return; } - if(ctx605->hThreadRx) { - ctx605->isTerminateThreadRx = TRUE; - WaitForSingleObject(ctx605->hThreadRx, INFINITE); - } - if(ctx605->hRxBufferEvent) { - WaitForSingleObject(ctx605->hRxBufferEvent, INFINITE); - while(ctx605->pMRdBuffer) { SwitchToThread(); } - CloseHandle(ctx605->hRxBufferEvent); - } - if(ctx605->hCommCfg) { CloseHandle(ctx605->hCommCfg); } - if(ctx605->hCommPcie) { CloseHandle(ctx605->hCommPcie); } - if(ctx605->oTx.hEvent) { CloseHandle(ctx605->oTx.hEvent); }; - if(ctx605->oRx.hEvent) { CloseHandle(ctx605->oRx.hEvent); }; - if(ctx605->oCfg.hEvent) { CloseHandle(ctx605->oCfg.hEvent); }; - LocalFree(ctx605); - ctx->hDevice = 0; -} - -HANDLE Device605_UART_Open_COM(_In_ LPSTR szCOM) -{ - DCB dcb = { 0 }; - HANDLE hComm; - dcb.DCBlength = sizeof(DCB); - if(!BuildCommDCBW(L"921600,n,8,1", &dcb)) { return 0; } - hComm = CreateFileA(szCOM, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); - if(hComm == INVALID_HANDLE_VALUE) { return 0; } - if(!SetCommState(hComm, &dcb)) { - CloseHandle(hComm); - return 0; - } - return hComm; -} - -WORD Device605_UART_GetDeviceID(_In_ PDEVICE_CONTEXT_SP605 ctx605) -{ - DWORD dw, txrx[] = { 0x00000000, 0x00000000 }; - if(!WriteFile(ctx605->hCommCfg, txrx, sizeof(txrx), &dw, &ctx605->oCfg)) { - if(ERROR_IO_PENDING != GetLastError()) { return 0; } - if(WAIT_TIMEOUT == WaitForSingleObject(ctx605->oCfg.hEvent, SP605_COM_TIMEOUT)) { return 0; } - } - if(!ReadFile(ctx605->hCommCfg, txrx, sizeof(txrx), &dw, &ctx605->oCfg)) { - if(ERROR_IO_PENDING != GetLastError()) { return 0; } - if(WAIT_TIMEOUT == WaitForSingleObject(ctx605->oCfg.hEvent, SP605_COM_TIMEOUT)) { return 0; } - if(!GetOverlappedResult(ctx605->hCommCfg, &ctx605->oCfg, &dw, FALSE)) { return 0; } - } - return (WORD)_byteswap_ulong(txrx[0]); -} - -BOOL Device605_UART_TxTlp(_In_ PDEVICE_CONTEXT_SP605 ctx605, _In_ PBYTE pbTlp, _In_ DWORD cbTlp) -{ - DWORD pdwTx[1024], cTx, i, dwTxed; - if(!cbTlp) { return TRUE; } - if((cbTlp & 0x3) || (cbTlp > 2048)) { return FALSE; } - if(ctx605->isPrintTlp) { - TLP_Print(pbTlp, cbTlp, TRUE); - } - // prepare transmit buffer - cTx = cbTlp >> 1; - for(i = 0; i < cTx; i += 2) { - pdwTx[i] = SP605_STATUS_TX_CONT; - pdwTx[i + 1] = *(PDWORD)(pbTlp + (i << 1)); - } - pdwTx[cTx - 2] = SP605_STATUS_TX_END; - // transmit - return - WriteFile(ctx605->hCommPcie, pdwTx, cTx << 2, &dwTxed, &ctx605->oTx) || - (GetLastError() == ERROR_IO_PENDING && GetOverlappedResult(ctx605->hCommPcie, &ctx605->oTx, &dwTxed, TRUE)); -} - -VOID Device605_UART_RxTlp_Thread(_In_ PDEVICE_CONTEXT_SP605 ctx605) -{ - DWORD rx[2], dwTlp[1024], cbRead, dwResult, cdwTlp = 0; - while(!ctx605->isTerminateThreadRx) { - if(!ReadFile(ctx605->hCommPcie, rx, 2 * sizeof(DWORD), &cbRead, &ctx605->oRx)) { - if(GetLastError() != ERROR_IO_PENDING) { goto fail; } - while(TRUE) { - dwResult = WaitForSingleObject(ctx605->oRx.hEvent, SP605_COM_TIMEOUT); - if(ctx605->isTerminateThreadRx) { goto fail; } - if(dwResult == WAIT_OBJECT_0) { break; } - if(dwResult == WAIT_TIMEOUT) { continue; } - ctx605->isTerminateThreadRx = TRUE; - return; - } - if(!GetOverlappedResult(ctx605->hCommPcie, &ctx605->oRx, &cbRead, FALSE)) { goto fail; } - } - if(!(rx[0] & SP605_STATUS_MASK_VALID)) { goto fail; } - dwTlp[cdwTlp] = rx[1]; - cdwTlp++; - if(rx[0] & SP605_STATUS_MASK_END) { - if(cdwTlp >= 3) { - if(ctx605->isPrintTlp) { - TLP_Print((PBYTE)dwTlp, cdwTlp << 2, FALSE); - } - if(ctx605->hRxTlpCallbackFn && ctx605->pMRdBuffer) { - ctx605->hRxTlpCallbackFn(ctx605->pMRdBuffer, (PBYTE)dwTlp, cdwTlp << 2, ctx605->hRxBufferEvent); - } - } - cdwTlp = 0; - } - if(cdwTlp >= 1024) { goto fail; } - } -fail: - ctx605->isTerminateThreadRx = TRUE; -} - -BOOL Device605_UART_ReadDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb) -{ - PDEVICE_CONTEXT_SP605 ctx605 = (PDEVICE_CONTEXT_SP605)ctx->hDevice; - TLP_CALLBACK_BUF_MRd rxbuf; - DWORD tx[4], o, i; - BOOL is32; - PTLP_HDR_MRdWr64 hdrRd64 = (PTLP_HDR_MRdWr64)tx; - PTLP_HDR_MRdWr32 hdrRd32 = (PTLP_HDR_MRdWr32)tx; - if(cb > 0x00004000) { return FALSE; } - if(qwAddr % 0x1000) { return FALSE; } - if((cb >= 0x1000) && (cb % 0x1000)) { return FALSE; } - if((cb < 0x1000) && (cb % 0x8)) { return FALSE; } - // prepare - rxbuf.cb = 0; - rxbuf.pb = pb; - rxbuf.cbMax = cb; - ctx605->pMRdBuffer = &rxbuf; - ResetEvent(ctx605->hRxBufferEvent); - ctx605->hRxTlpCallbackFn = TLP_CallbackMRd; - // transmit TLPs - for(o = 0; o < cb; o += 0x1000) { - memset(tx, 0, 16); - is32 = qwAddr + o < 0x100000000; - if(is32) { - hdrRd32->h.TypeFmt = TLP_MRd32; - hdrRd32->h.Length = (WORD)((cb < 0x1000) ? cb >> 2 : 0); - hdrRd32->RequesterID = ctx605->wDeviceId; - hdrRd32->Tag = (BYTE)(o >> 12); - hdrRd32->FirstBE = 0xf; - hdrRd32->LastBE = 0xf; - hdrRd32->Address = (DWORD)(qwAddr + o); - } else { - hdrRd64->h.TypeFmt = TLP_MRd64; - hdrRd64->h.Length = (WORD)((cb < 0x1000) ? cb >> 2 : 0); - hdrRd64->RequesterID = ctx605->wDeviceId; - hdrRd64->Tag = (BYTE)(o >> 12); - hdrRd64->FirstBE = 0xf; - hdrRd64->LastBE = 0xf; - hdrRd64->AddressHigh = (DWORD)((qwAddr + o) >> 32); - hdrRd64->AddressLow = (DWORD)(qwAddr + o); - } - for(i = 0; i < 4; i++) { - ENDIAN_SWAP_DWORD(tx[i]); - } - Device605_UART_TxTlp(ctx605, (PBYTE)tx, is32 ? 12 : 16); - } - // wait for result - WaitForSingleObject(ctx605->hRxBufferEvent, SP605_READ_TIMEOUT); - ctx605->hRxTlpCallbackFn = NULL; - ctx605->pMRdBuffer = NULL; - SetEvent(ctx605->hRxBufferEvent); - return rxbuf.cb >= rxbuf.cbMax; -} - -VOID Device605_UART_ProbeDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _In_ DWORD cPages, _Out_ __bcount(cPages) PBYTE pbResultMap) -{ - DWORD i, j; - PDEVICE_CONTEXT_SP605 ctx605 = (PDEVICE_CONTEXT_SP605)ctx->hDevice; - TLP_CALLBACK_BUF_MRd rxbuf; - DWORD tx[4]; - BOOL is32; - PTLP_HDR_MRdWr64 hdrRd64 = (PTLP_HDR_MRdWr64)tx; - PTLP_HDR_MRdWr32 hdrRd32 = (PTLP_HDR_MRdWr32)tx; - // split probe into processing chunks if too large... - while(cPages > SP605_PROBE_MAXPAGES) { - Device605_UART_ProbeDMA(ctx, qwAddr, SP605_PROBE_MAXPAGES, pbResultMap); - cPages -= SP605_PROBE_MAXPAGES; - pbResultMap += SP605_PROBE_MAXPAGES; - qwAddr += SP605_PROBE_MAXPAGES << 12; - } - memset(pbResultMap, 0, cPages); - // prepare - rxbuf.cb = 0; - rxbuf.pb = pbResultMap; - rxbuf.cbMax = cPages; - ctx605->pMRdBuffer = &rxbuf; - ResetEvent(ctx605->hRxBufferEvent); - ctx605->hRxTlpCallbackFn = TLP_CallbackMRdProbe; - // transmit TLPs - for(i = 0; i < cPages; i++) { - memset(tx, 0, 16); - is32 = qwAddr + (i << 12) < 0x100000000; - if(is32) { - hdrRd32->h.TypeFmt = TLP_MRd32; - hdrRd32->h.Length = 1; - hdrRd32->RequesterID = ctx605->wDeviceId; - hdrRd32->FirstBE = 0xf; - hdrRd32->LastBE = 0; - hdrRd32->Address = (DWORD)(qwAddr + (i << 12) + ((i & 0x1f) << 2)); // 5 low address bits coded into the dword read. - hdrRd32->Tag = (BYTE)((i >> 5) & 0x1f); // 5 high address bits coded into tag. - } else { - hdrRd64->h.TypeFmt = TLP_MRd64; - hdrRd64->h.Length = 1; - hdrRd64->RequesterID = ctx605->wDeviceId; - hdrRd64->FirstBE = 0xf; - hdrRd64->LastBE = 0; - hdrRd64->AddressHigh = (DWORD)((qwAddr + (i << 12)) >> 32); - hdrRd64->AddressLow = (DWORD)(qwAddr + (i << 12) + ((i & 0x1f) << 2)); // 5 low address bits coded into the dword read. - hdrRd64->Tag = (BYTE)((i >> 5) & 0x1f); // 5 high address bits coded into tag. - } - for(j = 0; j < 4; j++) { - ENDIAN_SWAP_DWORD(tx[j]); - } - Device605_UART_TxTlp(ctx605, (PBYTE)tx, is32 ? 12 : 16); - } - // wait for result - WaitForSingleObject(ctx605->hRxBufferEvent, SP605_PROBE_TIMEOUT); - ctx605->hRxTlpCallbackFn = NULL; - ctx605->pMRdBuffer = NULL; - SetEvent(ctx605->hRxBufferEvent); -} - -BOOL Device605_UART_WriteDMA_TXP(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwA, _In_ BYTE bFirstBE, _In_ BYTE bLastBE, _In_ PBYTE pb, _In_ DWORD cb) -{ - PDEVICE_CONTEXT_SP605 ctx605 = (PDEVICE_CONTEXT_SP605)ctx->hDevice; - DWORD txbuf[36], i, cbTlp; - PBYTE pbTlp = (PBYTE)txbuf; - PTLP_HDR_MRdWr32 hdrWr32 = (PTLP_HDR_MRdWr32)txbuf; - PTLP_HDR_MRdWr64 hdrWr64 = (PTLP_HDR_MRdWr64)txbuf; - memset(pbTlp, 0, 16); - if(qwA < 0x100000000) { - hdrWr32->h.TypeFmt = TLP_MWr32; - hdrWr32->h.Length = (WORD)(cb + 3) >> 2; - hdrWr32->FirstBE = bFirstBE; - hdrWr32->LastBE = bLastBE; - hdrWr32->RequesterID = ctx605->wDeviceId; - hdrWr32->Address = (DWORD)qwA; - for(i = 0; i < 3; i++) { - ENDIAN_SWAP_DWORD(txbuf[i]); - } - memcpy(pbTlp + 12, pb, cb); - cbTlp = (12 + cb + 3) & ~0x3; - } else { - hdrWr64->h.TypeFmt = TLP_MWr64; - hdrWr64->h.Length = (WORD)(cb + 3) >> 2; - hdrWr64->FirstBE = bFirstBE; - hdrWr64->LastBE = bLastBE; - hdrWr64->RequesterID = ctx605->wDeviceId; - hdrWr64->AddressHigh = (DWORD)(qwA >> 32); - hdrWr64->AddressLow = (DWORD)qwA; - for(i = 0; i < 4; i++) { - ENDIAN_SWAP_DWORD(txbuf[i]); - } - memcpy(pbTlp + 16, pb, cb); - cbTlp = (16 + cb + 3) & ~0x3; - } - return Device605_UART_TxTlp(ctx605, pbTlp, cbTlp); -} - -BOOL Device605_UART_WriteDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwA, _In_ PBYTE pb, _In_ DWORD cb) -{ - BOOL result = TRUE; - BYTE be, pbb[4]; - DWORD cbtx; - if(cb > 0x00004000) { return FALSE; } - // TX 1st dword if not aligned - if(cb && (qwA & 0x3)) { - be = (cb < 3) ? (0xf >> (4 - cb)) : 0xf; - be <<= qwA & 0x3; - cbtx = min(cb, 4 - (qwA & 0x3)); - memcpy(pbb + (qwA & 0x3), pb, cbtx); - result = Device605_UART_WriteDMA_TXP(ctx, qwA & ~0x3, be, 0, pbb, 4); - pb += cbtx; - cb -= cbtx; - qwA += cbtx; - } - // TX as 128-byte packets (aligned to 128-byte boundaries) - while(result && cb) { - cbtx = min(128 - (qwA & 0x7f), cb); - be = (cbtx & 0x3) ? (0xf >> (4 - (cbtx & 0x3))) : 0xf; - result = (cbtx <= 4) ? - Device605_UART_WriteDMA_TXP(ctx, qwA, be, 0, pb, 4) : - Device605_UART_WriteDMA_TXP(ctx, qwA, 0xf, be, pb, cbtx); - pb += cbtx; - cb -= cbtx; - qwA += cbtx; - } - return result; -} - -BOOL Device605_UART_ListenTlp(_Inout_ PPCILEECH_CONTEXT ctx, _In_ DWORD dwTime) -{ - Sleep(dwTime); - return TRUE; -} - -BOOL Device605_UART_WriteTlp(_Inout_ PPCILEECH_CONTEXT ctx, _In_ PBYTE pbTlp, _In_ DWORD cbTlp) -{ - return Device605_UART_TxTlp((PDEVICE_CONTEXT_SP605)ctx->hDevice, pbTlp, cbTlp); -} - -BOOL Device605_UART_Open(_Inout_ PPCILEECH_CONTEXT ctx) -{ - DWORD i; - CHAR szCOM[] = { 'C', 'O', 'M', 'x', 0 }; - PDEVICE_CONTEXT_SP605 ctx605; - ctx605 = LocalAlloc(LMEM_ZEROINIT, sizeof(DEVICE_CONTEXT_SP605)); - if(!ctx605) { return FALSE; } - ctx->hDevice = (HANDLE)ctx605; - // open COM ports - for(i = 1; i <= 9; i++) { - szCOM[3] = (CHAR)('0' + i); - if(!ctx605->hCommPcie) { - ctx605->hCommPcie = Device605_UART_Open_COM(szCOM); - } else { - ctx605->hCommCfg = Device605_UART_Open_COM(szCOM); - if(ctx605->hCommCfg) { break; } - } - } - if(!ctx605->hCommPcie || !ctx605->hCommCfg) { goto fail; } - SetupComm(ctx605->hCommPcie, 0x8000, 0x8000); - ctx605->oTx.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if(!ctx605->oTx.hEvent) { goto fail; } - ctx605->oRx.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if(!ctx605->oRx.hEvent) { goto fail; } - ctx605->oCfg.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if(!ctx605->oCfg.hEvent) { goto fail; } - ctx605->hRxBufferEvent = CreateEvent(NULL, TRUE, TRUE, NULL); - if(!ctx605->hRxBufferEvent) { goto fail; } - ctx605->wDeviceId = Device605_UART_GetDeviceID(ctx605); - if(!ctx605->wDeviceId) { goto fail; } - ctx605->isPrintTlp = ctx->cfg->fVerboseExtra; - ctx605->hThreadRx = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Device605_UART_RxTlp_Thread, ctx605, 0, NULL); // start rx thread, must be last in open - if(!ctx605->hThreadRx) { goto fail; } - // set callback functions and fix up config - ctx->cfg->dev.tp = PCILEECH_DEVICE_SP605_UART; - ctx->cfg->dev.qwMaxSizeDmaIo = 0x4000; - ctx->cfg->dev.qwAddrMaxNative = 0x0000ffffffffffff; - ctx->cfg->dev.fPartialPageReadSupported = TRUE; - ctx->cfg->dev.pfnClose = Device605_UART_Close; - ctx->cfg->dev.pfnProbeDMA = Device605_UART_ProbeDMA; - ctx->cfg->dev.pfnReadDMA = Device605_UART_ReadDMA; - ctx->cfg->dev.pfnWriteDMA = Device605_UART_WriteDMA; - ctx->cfg->dev.pfnWriteTlp = Device605_UART_WriteTlp; - ctx->cfg->dev.pfnListenTlp = Device605_UART_ListenTlp; - // return - if(ctx->cfg->fVerbose) { printf("Device Info: SP605 / UART.\n"); } - return TRUE; -fail: - Device605_UART_Close(ctx); - return FALSE; -} - -#endif /* WIN32 */ -#if defined(LINUX) || defined(ANDROID) - -#include "device605_uart.h" - -BOOL Device605_UART_Open(_Inout_ PPCILEECH_CONTEXT ctx) -{ - if(ctx->cfg->dev.tp == PCILEECH_DEVICE_SP605_UART) { - printf("SP605 / UART: Failed. Device currently only supported in PCILeech for Windows."); - } - return FALSE; -} - -#endif /* LINUX || ANDROID */ diff --git a/pcileech/device605_uart.h b/pcileech/device605_uart.h deleted file mode 100644 index 9496bc7..0000000 --- a/pcileech/device605_uart.h +++ /dev/null @@ -1,17 +0,0 @@ -// device605_uart.h : definitions related to the Xilinx SP605 dev board flashed with @d_olex early access bitstream. (UART communication). -// -// (c) Ulf Frisk, 2017 -// Author: Ulf Frisk, pcileech@frizk.net -// -#ifndef __DEVICE605_UART_H__ -#define __DEVICE605_UART_H__ -#include "pcileech.h" - -/* -* Open a connection to the SP605/UART PCILeech flashed device. -* -- ctx -* -- result -*/ -BOOL Device605_UART_Open(_Inout_ PPCILEECH_CONTEXT ctx); - -#endif /* __DEVICE605_UART_H__ */ diff --git a/pcileech/help.c b/pcileech/help.c index 4752f27..0f3793f 100644 --- a/pcileech/help.c +++ b/pcileech/help.c @@ -91,7 +91,7 @@ VOID Help_ShowGeneral() " Wait occurs after any other actions have been completed. \n" \ " -device: force the use of a specific hardware device instead of auto-detect.\n" \ " Affects all modes and commands. \n" \ - " Valid options: USB3380, SP605_UART, SP605_FT601, SP605_TCP \n" \ + " Valid options: USB3380, SP605_FT601, SP605_TCP \n" \ " -device-addr: Remote address for -device SP605_TCP. \n" \ " -device-port: Remote TCP port for -device SP605_TCP. Default value: 28472. \n" \ " -help: show help about the selected command or implant and then exit \n" \ @@ -140,7 +140,7 @@ VOID Help_ShowInfo() printf( " PCILEECH INFORMATION \n" \ " PCILeech (c) 2016, 2017 Ulf Frisk \n" \ - " Version: 2.4 \n" \ + " Version: 2.5 \n" \ " License: GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 \n" \ " Contact information: pcileech@frizk.net \n" \ " System requirements: 64-bit Windows 7, 10 or Linux. \n" \ diff --git a/pcileech/kmd.c b/pcileech/kmd.c index 382e576..a97fe3a 100644 --- a/pcileech/kmd.c +++ b/pcileech/kmd.c @@ -392,13 +392,11 @@ QWORD KMD_Linux48KernelBaseSeek(_Inout_ PPCILEECH_CONTEXT ctx) // assumed to end with 0x100 0x00's. for(; qwA <= qwAddrMax; qwA += 0x00200000) { ps.qwAddr = qwA; - // only read partial page to speed up SP605 if connected via UART - // TODO: investigate if this is slower/faster than reading whole pages on FPGA solution. if(!DeviceReadDMA(ctx, qwA, pb, ctx->cfg->fPartialPageReadSupported ? 0x400 : 0x1000, 0)) { - ps.cPageFail += 512; + PageStatUpdate(&ps, qwA, 0, 512); continue; } - ps.cPageSuccess += 512; + PageStatUpdate(&ps, qwA, 512, 0); // Search for GenuineIntel and AuthenticAMD strings. isGenuineIntel = isAuthenticAMD = FALSE; for(i = 0; i < 0x400; i++) { diff --git a/pcileech/pcileech.c b/pcileech/pcileech.c index 635d248..06a0c44 100644 --- a/pcileech/pcileech.c +++ b/pcileech/pcileech.c @@ -118,8 +118,6 @@ BOOL PCILeechConfigIntialize(_In_ DWORD argc, _In_ char* argv[], _Inout_ PPCILEE ctx->cfg->dev.tp = PCILEECH_DEVICE_NA; if(0 == _stricmp(argv[i + 1], "usb3380")) { ctx->cfg->dev.tp = PCILEECH_DEVICE_USB3380; - } else if(0 == _stricmp(argv[i + 1], "sp605_uart")) { - ctx->cfg->dev.tp = PCILEECH_DEVICE_SP605_UART; } else if(0 == _stricmp(argv[i + 1], "sp605_ft601")) { ctx->cfg->dev.tp = PCILEECH_DEVICE_SP605_FT601; } else if(0 == _stricmp(argv[i + 1], "sp605_tcp")) { diff --git a/pcileech/pcileech.h b/pcileech/pcileech.h index f556eb8..9769433 100644 --- a/pcileech/pcileech.h +++ b/pcileech/pcileech.h @@ -47,7 +47,6 @@ typedef enum tdActionType { typedef enum tdPCILEECH_DEVICE_TYPE { PCILEECH_DEVICE_NA, PCILEECH_DEVICE_USB3380, - PCILEECH_DEVICE_SP605_UART, PCILEECH_DEVICE_SP605_FT601, PCILEECH_DEVICE_SP605_TCP } PCILEECH_DEVICE_TYPE; diff --git a/pcileech/pcileech.vcxproj b/pcileech/pcileech.vcxproj index b0335d9..a64e37f 100644 --- a/pcileech/pcileech.vcxproj +++ b/pcileech/pcileech.vcxproj @@ -87,7 +87,6 @@ - @@ -108,7 +107,6 @@ - diff --git a/pcileech/pcileech.vcxproj.filters b/pcileech/pcileech.vcxproj.filters index f413df9..17d6a0a 100644 --- a/pcileech/pcileech.vcxproj.filters +++ b/pcileech/pcileech.vcxproj.filters @@ -69,9 +69,6 @@ Header Files - - Header Files - Header Files @@ -122,9 +119,6 @@ Source Files - - Source Files - Source Files diff --git a/pcileech/tlp.c b/pcileech/tlp.c index ead02d8..8258597 100644 --- a/pcileech/tlp.c +++ b/pcileech/tlp.c @@ -9,54 +9,98 @@ VOID TLP_Print(_In_ PBYTE pbTlp, _In_ DWORD cbTlp, _In_ BOOL isTx) { DWORD i; + LPSTR tp = ""; BYTE pb[0x1000]; PDWORD buf = (PDWORD)pb; PTLP_HDR hdr = (PTLP_HDR)pb; PTLP_HDR_CplD hdrC; PTLP_HDR_MRdWr32 hdrM32; PTLP_HDR_MRdWr64 hdrM64; + PTLP_HDR_Cfg hdrCfg; if(cbTlp < 12 || cbTlp > 0x1000 || cbTlp & 0x3) { return; } for(i = 0; i < cbTlp; i += 4) { buf[i >> 2] = _byteswap_ulong(*(PDWORD)(pbTlp + i)); } - if(hdr->TypeFmt == TLP_CplD) { + if((hdr->TypeFmt == TLP_Cpl) || (hdr->TypeFmt == TLP_CplD) || (hdr->TypeFmt == TLP_CplLk) || (hdr->TypeFmt == TLP_CplDLk)) { + if(hdr->TypeFmt == TLP_Cpl) { tp = "Cpl: "; } + if(hdr->TypeFmt == TLP_CplD) { tp = "CplD: "; } + if(hdr->TypeFmt == TLP_CplLk) { tp = "CplLk: "; } + if(hdr->TypeFmt == TLP_CplDLk) { tp = "CplDLk:"; } hdrC = (PTLP_HDR_CplD)pb; printf( - "\n%s: CplD: ReqID: %04x CplID: %04x Status: %01x BC: %03x Tag: %02x LowAddr: %02x", - (isTx ? "TX" : "RX"), - hdrC->RequesterID, - hdrC->CompleterID, - hdrC->Status, - hdrC->ByteCount, - hdrC->Tag, + "\n%s: %s Len: %03x ReqID: %04x CplID: %04x Status: %01x BC: %03x Tag: %02x LowAddr: %02x", + (isTx ? "TX" : "RX"), + tp, + hdr->Length, + hdrC->RequesterID, + hdrC->CompleterID, + hdrC->Status, + hdrC->ByteCount, + hdrC->Tag, hdrC->LowerAddress ); - } else if(hdr->TypeFmt == TLP_MRd32 || hdr->TypeFmt == TLP_MWr32) { + } else if((hdr->TypeFmt == TLP_MRd32) || (hdr->TypeFmt == TLP_MWr32)) { hdrM32 = (PTLP_HDR_MRdWr32)pb; printf( - "\n%s: %s: ReqID: %04x BE_FL: %01x%01x Tag: %02x Addr: %08x", + "\n%s: %s Len: %03x ReqID: %04x BE_FL: %01x%01x Tag: %02x Addr: %08x", (isTx ? "TX" : "RX"), - (hdr->TypeFmt == TLP_MRd32) ? "MRd32" : "MWr32", + (hdr->TypeFmt == TLP_MRd32) ? "MRd32: " : "MWr32: ", + hdr->Length, hdrM32->RequesterID, hdrM32->FirstBE, hdrM32->LastBE, hdrM32->Tag, hdrM32->Address); - } else if(hdr->TypeFmt == TLP_MRd64 || hdr->TypeFmt == TLP_MWr64) { + } else if((hdr->TypeFmt == TLP_MRd64) || (hdr->TypeFmt == TLP_MWr64)) { hdrM64 = (PTLP_HDR_MRdWr64)pb; printf( - "\n%s: %s: ReqID: %04x BE_FL: %01x%01x Tag: %02x Addr: %016llx", + "\n%s: %s Len: %03x ReqID: %04x BE_FL: %01x%01x Tag: %02x Addr: %016llx", (isTx ? "TX" : "RX"), - (hdr->TypeFmt == TLP_MRd64) ? "MRd64" : "MWr64", + (hdr->TypeFmt == TLP_MRd64) ? "MRd64: " : "MWr64: ", + hdr->Length, hdrM64->RequesterID, hdrM64->FirstBE, hdrM64->LastBE, hdrM64->Tag, ((QWORD)hdrM64->AddressHigh << 32) + hdrM64->AddressLow ); + } else if((hdr->TypeFmt == TLP_IORd) || (hdr->TypeFmt == TLP_IOWr)) { + hdrM32 = (PTLP_HDR_MRdWr32)pb; // same format for IO Rd/Wr + printf( + "\n%s: %s Len: %03x ReqID: %04x BE_FL: %01x%01x Tag: %02x Addr: %08x", + (isTx ? "TX" : "RX"), + (hdr->TypeFmt == TLP_IORd) ? "IORd: " : "IOWr: ", + hdr->Length, + hdrM32->RequesterID, + hdrM32->FirstBE, + hdrM32->LastBE, + hdrM32->Tag, + hdrM32->Address + ); + } else if((hdr->TypeFmt == TLP_CfgRd0) || (hdr->TypeFmt == TLP_CfgRd1) || (hdr->TypeFmt == TLP_CfgWr0) || (hdr->TypeFmt == TLP_CfgWr1)) { + if(hdr->TypeFmt == TLP_CfgRd0) { tp = "CfgRd0:"; } + if(hdr->TypeFmt == TLP_CfgRd1) { tp = "CfgRd1:"; } + if(hdr->TypeFmt == TLP_CfgWr0) { tp = "CfgWr0:"; } + if(hdr->TypeFmt == TLP_CfgWr1) { tp = "CfgWr1:"; } + hdrCfg = (PTLP_HDR_Cfg)pb; + printf( + "\n%s: %s Len: %03x ReqID: %04x BE_FL: %01x%01x Tag: %02x Dev: %i:%i.%i ExtRegNum: %01x RegNum: %02x", + (isTx ? "TX" : "RX"), + tp, + hdr->Length, + hdrCfg->RequesterID, + hdrCfg->FirstBE, + hdrCfg->LastBE, + hdrCfg->Tag, + hdrCfg->BusNum, + hdrCfg->DeviceNum, + hdrCfg->FunctionNum, + hdrCfg->ExtRegNum, + hdrCfg->RegNum + ); } else { printf( - "\n%s: TLP??: TypeFmt: %02x dwLen: %03x", + "\n%s: TLP???: TypeFmt: %02x dwLen: %03x", (isTx ? "TX" : "RX"), hdr->TypeFmt, hdr->Length diff --git a/pcileech/tlp.h b/pcileech/tlp.h index 35add20..c2b35e7 100644 --- a/pcileech/tlp.h +++ b/pcileech/tlp.h @@ -22,7 +22,7 @@ #define TLP_Cpl 0x0A #define TLP_CplD 0x4A #define TLP_CplLk 0x0B -#define TLP_CplLkD 0x4B +#define TLP_CplDLk 0x4B typedef struct tdTLP_HDR { WORD Length : 10; @@ -67,6 +67,21 @@ typedef struct tdTLP_HDR_CplD { WORD RequesterID; } TLP_HDR_CplD, *PTLP_HDR_CplD; +typedef struct tdTLP_HDR_Cfg { + TLP_HDR h; + BYTE FirstBE : 4; + BYTE LastBE : 4; + BYTE Tag; + WORD RequesterID; + BYTE _R1 : 2; + BYTE RegNum : 6; + BYTE ExtRegNum : 4; + BYTE _R2 : 4; + BYTE FunctionNum : 3; + BYTE DeviceNum : 5; + BYTE BusNum; +} TLP_HDR_Cfg, *PTLP_HDR_Cfg; + /* * Print a PCIe TLP packet on the screen in a human readable format. * -- pbTlp = complete TLP packet (header+data) diff --git a/pcileech_files/pcileech b/pcileech_files/pcileech index 45a9c10..f616eef 100644 Binary files a/pcileech_files/pcileech and b/pcileech_files/pcileech differ diff --git a/pcileech_files/pcileech.exe b/pcileech_files/pcileech.exe index cba942e..55d67b3 100644 Binary files a/pcileech_files/pcileech.exe and b/pcileech_files/pcileech.exe differ diff --git a/readme.md b/readme.md index 6800729..ad2cb31 100644 --- a/readme.md +++ b/readme.md @@ -57,7 +57,7 @@ PCILeech supports multiple hardware devices. Please check out the [PCILeech FPGA | ----------- | ------- | --------- | ------- | -------------------- | --------------- | | USB3380-EVB | USB3380 | USB3 | 150MB/s | No (via KMD only) | No | | PP3380 | USB3380 | USB3 | 150MB/s | No (via KMD only) | No | -| SP605/FT601 | FPGA | USB3 | 85MB/s | Yes | Yes | +| SP605/FT601 | FPGA | USB3 | 75MB/s | Yes | Yes | | SP605/TCP | FPGA | TCP/IP | 100kB/s | Yes | Yes | Hardware (USB3380): @@ -216,3 +216,7 @@ v2.4 * Linux file system mount support for kernel version 4.11 later. * Improved memory reading algorithm for FPGA devices. * Various bug fixes. + +v2.5 +* SP605/FT601: re-designed and improved. NB! FPGA device have to be re-flashed with new bitstream! +* SP605/TCP: bug fixes.