Skip to content

Commit

Permalink
Version 2.4
Browse files Browse the repository at this point in the history
  • Loading branch information
ufrisk committed Oct 18, 2017
1 parent 3d3ae82 commit 4d43970
Show file tree
Hide file tree
Showing 28 changed files with 958 additions and 243 deletions.
2 changes: 1 addition & 1 deletion pcileech/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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 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_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_MODULE := pcileech
LOCAL_SHARED_LIBRARIES += libusb1.0
Expand Down
2 changes: 1 addition & 1 deletion pcileech/Makefile
Original file line number Diff line number Diff line change
@@ -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 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_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

%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
Expand Down
69 changes: 58 additions & 11 deletions pcileech/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@
#include "device3380.h"
#include "device605_uart.h"
#include "device605_601.h"
#include "device605_tcp.h"

typedef struct tdREAD_DMA_EX_MEMORY_MAP {
BOOL fProbeExecuted;
QWORD qwAddrBase;
DWORD cPages;
PBYTE pb;
} READ_DMA_EX_MEMORY_MAP, *PREAD_DMA_EX_MEMORY_MAP;

BOOL DeviceReadDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags)
{
Expand All @@ -18,12 +26,26 @@ BOOL DeviceReadDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE
return ctx->cfg->dev.pfnReadDMA ? ctx->cfg->dev.pfnReadDMA(ctx, qwAddr, pb, cb) : FALSE;
}

BOOL DeviceReadDMAEx_IsMemoryMapOK(_In_ PREAD_DMA_EX_MEMORY_MAP pMemoryMap, _In_ QWORD qwAddr, _In_ DWORD dwSize)
{
DWORD i;
DWORD cPages = (dwSize + 0xfff) / 0x1000;
DWORD cPageStart = (DWORD)(((qwAddr + 0xfff) - pMemoryMap->qwAddrBase) / 0x1000);
for(i = cPageStart; i < cPageStart + cPages; i++) {
if(0 == pMemoryMap->pb[i]) {
return FALSE;
}
}
return TRUE;
}

#define CHUNK_FAIL_DIVISOR 16
DWORD DeviceReadDMAEx_DoWork(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _Inout_opt_ PPAGE_STATISTICS pPageStat, _In_ DWORD cbMaxSizeIo)
DWORD DeviceReadDMAEx_DoWork(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _Inout_opt_ PPAGE_STATISTICS pPageStat, _In_ DWORD cbMaxSizeIo, _Inout_ PREAD_DMA_EX_MEMORY_MAP pMemoryMap, _In_ QWORD flags)
{
DWORD cbRd, cbRdOff;
DWORD cbChunk, cChunkTotal, cChunkSuccess = 0;
DWORD i, cbSuccess = 0;
BOOL result;
// calculate current chunk sizes
cbChunk = ~0xfff & min(cb, cbMaxSizeIo);
cbChunk = (cbChunk > 0x3000) ? cbChunk : 0x1000;
Expand All @@ -33,29 +55,51 @@ DWORD DeviceReadDMAEx_DoWork(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _
for(i = 0; i < cChunkTotal; i++) {
cbRdOff = i * cbChunk;
cbRd = ((i == cChunkTotal - 1) && (cb % cbChunk)) ? (cb % cbChunk) : cbChunk; // (last chunk may be smaller)
if(DeviceReadDMA(ctx, qwAddr + cbRdOff, pb + cbRdOff, cbRd, 0)) {
result =
DeviceReadDMAEx_IsMemoryMapOK(pMemoryMap, qwAddr + cbRdOff, cbRd) &&
DeviceReadDMA(ctx, qwAddr + cbRdOff, pb + cbRdOff, cbRd, 0);
if(!result && !pMemoryMap->fProbeExecuted && ctx->cfg->dev.pfnProbeDMA) { // probe memory on 1st fail (if supported)
DeviceProbeDMA(ctx, pMemoryMap->qwAddrBase, pMemoryMap->cPages, pMemoryMap->pb);
pMemoryMap->fProbeExecuted = TRUE;
}
if(result) {
cbSuccess += cbRd;
PageStatUpdate(pPageStat, qwAddr + cbRdOff + cbRd, cbRd / 0x1000, 0);
} else if(flags & PCILEECH_FLAG_MEM_EX_FASTFAIL) {
PageStatUpdate(pPageStat, qwAddr + cb, 0, (cb - cbRdOff) / 0x1000);
return cbSuccess;
} else if(cbRd == 0x1000) {
ZeroMemory(pb + cbRdOff, cbRd);
PageStatUpdate(pPageStat, qwAddr + cbRdOff + cbRd, 0, 1);
} else {
cbSuccess += DeviceReadDMAEx_DoWork(ctx, qwAddr + cbRdOff, pb + cbRdOff, cbRd, pPageStat, cbRd / CHUNK_FAIL_DIVISOR);
cbSuccess += DeviceReadDMAEx_DoWork(ctx, qwAddr + cbRdOff, pb + cbRdOff, cbRd, pPageStat, cbRd / CHUNK_FAIL_DIVISOR, pMemoryMap, flags);
}
}
return cbSuccess;
}

DWORD DeviceReadDMAEx(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _Inout_opt_ PPAGE_STATISTICS pPageStat)
DWORD DeviceReadDMAEx(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _Inout_opt_ PPAGE_STATISTICS pPageStat, _In_ QWORD flags)
{
READ_DMA_EX_MEMORY_MAP oMemoryMap;
BYTE pbWorkaround[4096];
DWORD cbWorkaround;
DWORD cbDataRead;
// set probe memory map to all mem readable
oMemoryMap.fProbeExecuted = FALSE;
oMemoryMap.qwAddrBase = qwAddr & ~0xfff;
oMemoryMap.cPages = (cb + 0xfff) / 0x1000;
oMemoryMap.pb = LocalAlloc(0, oMemoryMap.cPages);
if(!oMemoryMap.pb) { return 0; }
memset(oMemoryMap.pb, 0x01, oMemoryMap.cPages);
// read memory (with strange workaround for 1-page reads...)
if(cb != 0x1000) {
return DeviceReadDMAEx_DoWork(ctx, qwAddr, pb, cb, pPageStat, (DWORD)ctx->cfg->qwMaxSizeDmaIo);
cbDataRead = DeviceReadDMAEx_DoWork(ctx, qwAddr, pb, cb, pPageStat, (DWORD)ctx->cfg->qwMaxSizeDmaIo, &oMemoryMap, flags);
} else {
// why is this working ??? if not here console is screwed up... (threading issue?)
cbDataRead = DeviceReadDMAEx_DoWork(ctx, qwAddr, pbWorkaround, 0x1000, pPageStat, (DWORD)ctx->cfg->qwMaxSizeDmaIo, &oMemoryMap, flags);
memcpy(pb, pbWorkaround, 0x1000);
}
// why is this working ??? if not here console is screwed up... (threading issue?)
cbWorkaround = DeviceReadDMAEx_DoWork(ctx, qwAddr, pbWorkaround, 0x1000, pPageStat, (DWORD)ctx->cfg->qwMaxSizeDmaIo);
memcpy(pb, pbWorkaround, 0x1000);
return cbWorkaround;
LocalFree(oMemoryMap.pb);
return cbDataRead;
}

BOOL DeviceWriteDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _In_ PBYTE pb, _In_ DWORD cb, _In_ QWORD flags)
Expand Down Expand Up @@ -116,6 +160,9 @@ BOOL DeviceOpen(_Inout_ PPCILEECH_CONTEXT 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);
}
return result;
}

Expand All @@ -135,6 +182,6 @@ BOOL DeviceReadMEM(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE
} else if(flags || cb == 0x1000) {
return DeviceReadDMA(ctx, qwAddr, pb, cb, flags);
} else {
return cb == DeviceReadDMAEx(ctx, qwAddr, pb, cb, NULL);
return cb == DeviceReadDMAEx(ctx, qwAddr, pb, cb, NULL, 0);
}
}
6 changes: 5 additions & 1 deletion pcileech/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#define PCILEECH_MEM_FLAG_RETRYONFAIL 0x01
#define PCILEECH_MEM_FLAG_VERIFYWRITE 0x02

// return all fail on first fail instead of trying to re-read in smaller chunks.
#define PCILEECH_FLAG_MEM_EX_FASTFAIL 0x01

/*
* Open a USB connection to the target device.
* -- ctx
Expand Down Expand Up @@ -44,10 +47,11 @@ BOOL DeviceReadDMA(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE
* -- pb
* -- cb
* -- pPageStat = optional page statistics
* -- flags = PCILEECH_FLAG_MEM_EX_* flags
* -- return = the number of bytes successfully read.
*
*/
DWORD DeviceReadDMAEx(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _Inout_opt_ PPAGE_STATISTICS pPageStat);
DWORD DeviceReadDMAEx(_Inout_ PPCILEECH_CONTEXT ctx, _In_ QWORD qwAddr, _Out_ PBYTE pb, _In_ DWORD cb, _Inout_opt_ PPAGE_STATISTICS pPageStat, _In_ QWORD flags);

/*
* Write data to the target system using DMA.
Expand Down
19 changes: 9 additions & 10 deletions pcileech/device605_601.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
#define FPGA_LOOP_TX_VALID 0x77010000

#define SP605_601_PROBE_MAXPAGES 0x400
#define SP601_601_MAX_SIZE_RX 0x001e000 // in data bytes (excl. overhead/TLP headers)
#define SP601_601_MAX_SIZE_TX 0x0002000 // in total data (incl. overhead/TLP headers)
#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 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))
Expand Down Expand Up @@ -186,7 +186,7 @@ BOOL Device605_601_TxTlp(_In_ PDEVICE_CONTEXT_SP605_601 ctx, _In_ PBYTE pbTlp, _
}
ctx->txbuf.cb += cbTx;
// transmit
if((ctx->txbuf.cb > SP601_601_MAX_SIZE_TX) || (fFlush && ctx->txbuf.cb)) {
if((ctx->txbuf.cb > SP605_601_MAX_SIZE_TX) || (fFlush && ctx->txbuf.cb)) {
status = ctx->dev.pfnFT_WritePipe(ctx->dev.hFTDI, 0x02, ctx->txbuf.pb, ctx->txbuf.cb, &cbTxed, NULL);
ctx->txbuf.cb = 0;
return (0 == status);
Expand All @@ -209,7 +209,7 @@ VOID Device605_601_RxTlpSynchronous(_In_ PDEVICE_CONTEXT_SP605_601 ctx)
ctx->dev.pfnFT_AbortPipe(ctx->dev.hFTDI, 0x82);
return;
}
if(ctx->rxbuf.cb % 8) {
if((ctx->rxbuf.cb % 8) && (ctx->rxbuf.cb > 4)) {
printf("Device Info: SP605 / FT601: Bad read from device. Should not happen!\n");
return;
}
Expand Down Expand Up @@ -245,7 +245,7 @@ BOOL Device605_601_ReadDMA(_Inout_ PPCILEECH_CONTEXT ctxPcileech, _In_ QWORD qwA
BOOL is32;
PTLP_HDR_MRdWr64 hdrRd64 = (PTLP_HDR_MRdWr64)tx;
PTLP_HDR_MRdWr32 hdrRd32 = (PTLP_HDR_MRdWr32)tx;
if(cb > SP601_601_MAX_SIZE_RX) { return FALSE; }
if(cb > SP605_601_MAX_SIZE_RX) { return FALSE; }
if(qwAddr % 0x1000) { return FALSE; }
if((cb >= 0x1000) && (cb % 0x1000)) { return FALSE; }
if((cb < 0x1000) && (cb % 0x8)) { return FALSE; }
Expand All @@ -267,8 +267,7 @@ BOOL Device605_601_ReadDMA(_Inout_ PPCILEECH_CONTEXT ctxPcileech, _In_ QWORD qwA
hdrRd32->FirstBE = 0xf;
hdrRd32->LastBE = 0xf;
hdrRd32->Address = (DWORD)(qwAddr + o);
}
else {
} else {
hdrRd64->h.TypeFmt = TLP_MRd64;
hdrRd64->h.Length = (WORD)((cb < 0x1000) ? cb >> 2 : 0);
hdrRd64->RequesterID = ctx->wDeviceId;
Expand Down Expand Up @@ -446,16 +445,16 @@ 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 * SP601_601_MAX_SIZE_RX); // buffer size tuned to lowest possible (+margin) for performance.
ctx->rxbuf.cbMax = (DWORD)(2.3 * SP605_601_MAX_SIZE_RX); // 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 = SP601_601_MAX_SIZE_TX + 0x10000;
ctx->txbuf.cbMax = SP605_601_MAX_SIZE_TX + 0x10000;
ctx->txbuf.pb = LocalAlloc(0, ctx->txbuf.cbMax);
if(!ctx->txbuf.pb) { goto fail; }
ctx->isPrintTlp = ctxPcileech->cfg->fVerboseExtra;
// set callback functions and fix up config
ctxPcileech->cfg->dev.tp = PCILEECH_DEVICE_SP605_FT601;
ctxPcileech->cfg->dev.qwMaxSizeDmaIo = SP601_601_MAX_SIZE_RX;
ctxPcileech->cfg->dev.qwMaxSizeDmaIo = SP605_601_MAX_SIZE_RX;
ctxPcileech->cfg->dev.qwAddrMaxNative = 0x0000ffffffffffff;
ctxPcileech->cfg->dev.fPartialPageReadSupported = TRUE;
ctxPcileech->cfg->dev.pfnClose = Device605_601_Close;
Expand Down
Loading

0 comments on commit 4d43970

Please sign in to comment.