First pass rewrite of flashmem driver for optimization. Lot of changes here. Provides PoC of saving and recalling a tag in Standalone mode. Added some printing passthrough to client to azccomodate for vt100 eye-candyness. FastREAD mode implemented for flashmem, testable from client. Beta but functionnal. Reading the whole flash with 1Kb to 32kb buffers was ~730ms, now 380ms Max (even at 24Mhz spi baudrate)

This commit is contained in:
Colin J. Brigato 2018-09-03 00:02:44 +02:00
parent 41ca388edc
commit 8d673fa1bf
8 changed files with 865 additions and 292 deletions

View file

@ -24,7 +24,7 @@ APP_CFLAGS = -DWITH_CRC \
-DWITH_FLASH \
-DWITH_SMARTCARD \
-DWITH_HFSNOOP \
-DWITH_LF_SAMYRUN \
-DWITH_HF_COLIN \
-fno-strict-aliasing -ffunction-sections -fdata-sections
### IMPORTANT - move the commented variable below this line
@ -106,12 +106,9 @@ ARMSRC = fpgaloader.c \
parity.c \
usb_cdc.c \
cmd.c \
lf_samyrun.c \
vtsend.c
# lf_samyrun.c \
# lf_hidbrute.c \
# lf_proxbrute.c \
# hf_mattyrun.c \
vtsend.c \
hf_colin.c \
lib_AT91SAM7.c
VERSIONSRC = version.c \
fpga_version_info.c
@ -120,7 +117,6 @@ VERSIONSRC = version.c \
include ../common/Makefile.common
COMMON_FLAGS = -Os
OBJS = $(OBJDIR)/fullimage.s19
FPGA_COMPRESSOR = ../client/fpga_compress

File diff suppressed because it is too large Load diff

View file

@ -16,18 +16,21 @@
#ifndef __HF_COLIN_H
#define __HF_COLIN_H
#include <stdbool.h> // for bool
#include <stdio.h>
#include <string.h>
#include "standalone.h" // standalone definitions
#include "proxmark3.h"
#include "mifareutil.h"
#include "iso14443a.h"
//#include "printf.h"
#include "protocols.h"
#include "util.h"
#include "standalone.h" // standalone definitions
#include <stdbool.h> // for bool
#include <stdio.h>
#include <string.h>
//#include <stdio.h>
#include "vtsend.h"
#include "apps.h"
#include "usb_cmd.h" // mifare1ksim flags
#include "printf.h"
#define _RED_ "\x1b[31m"
#define _GREEN_ "\x1b[32m"
@ -38,14 +41,19 @@
#define _WHITE_ "\x1b[0m"
#define _ORANGE_ _YELLOW_
#define NTIME(n) for (int _index = 0; _index < n; _index++)
int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key);
void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void saMifareMakeTag(void);
int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void cjPrintBigArray(const char *bigar, int len, uint8_t newlines, uint8_t debug);
void WriteTagToFlash(uint8_t index, size_t size);
const char clearTerm[8] = {0x1b, 0x5b, 0x48, 0x1b, 0x5b, 0x32, 0x4a, '\0'};
#define LOGO logo_kigiv
const char sub_banner[] = " From Vigik : \"20 years of (un)security without a single update\"";
@ -410,7 +418,7 @@ const char logo_kigiv[] = {
0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x0d, 0x0a};
unsigned int logo_kigiv_len = 9303;
const char logo_kigiv_nocolor[] = {
/*const char logo_kigiv_nocolor[] = {
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x30, 0x30, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
@ -494,6 +502,6 @@ const char logo_kigiv_nocolor[] = {
0x30, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x31,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x31, 0x31, 0x0d, 0x0a};
unsigned int logo_kigiv_nocolor_len = 2153;
unsigned int logo_kigiv_nocolor_len = 2153;*/
#endif /* __HF_COLIN_H */

View file

@ -33,10 +33,6 @@
#include "i2c.h"
#endif
#ifdef WITH_FPC
#include "usart.h"
#endif
//=============================================================================
// A buffer where we can queue things up to be sent through the FPGA, for
// any purpose (fake tag, as reader, whatever). We go MSB first, since that
@ -78,26 +74,24 @@ void PrintToSendBuffer(void) {
}
void print_result(char *name, uint8_t *buf, size_t len) {
uint8_t *p = buf;
uint16_t tmp = len & 0xFFF0;
for(; p-buf < tmp; p += 16) {
Dbprintf("[%s: %02d/%02d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
if ( len % 16 == 0 ) {
for(; p-buf < len; p += 16)
Dbprintf("[%s:%d/%d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
name,
p-buf,
len,
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]
);
}
if (len % 16 != 0) {
char s[46] = {0};
char *sp = s;
for (; p-buf < len; p++ ) {
sprintf(sp, "%02x ", p[0] );
sp += 3;
}
Dbprintf("[%s: %02d/%02d] %s", name, p-buf, len, s);
else {
for(; p-buf < len; p += 8)
Dbprintf("[%s:%d/%d] %02x %02x %02x %02x %02x %02x %02x %02x",
name,
p-buf,
len,
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
}
}
@ -107,7 +101,7 @@ void print_result(char *name, uint8_t *buf, size_t len) {
void DbpStringEx(char *str, uint32_t cmd) {
#if DEBUG
uint8_t len = strlen(str);
byte_t len = strlen(str);
cmd_send(CMD_DEBUG_PRINT_STRING, len, cmd, 0, (byte_t*)str, len);
#endif
}
@ -119,7 +113,7 @@ void DbpString(char *str) {
}
#if 0
void DbpIntegers(int x1, int x2, int x3) {
void DbpIntegers(inst x1, int x2, int x3) {
cmd_send(CMD_DEBUG_PRINT_INTEGERS,x1,x2,x3,0,0);
}
#endif
@ -440,7 +434,7 @@ void printStandAloneModes(void) {
DbpString(" LF HID corporate 1000 bruteforce - (Federico dotta & Maurizio Agazzini)");
#endif
#if defined(WITH_HF_MATTYRUN)
DbpString(" HF Mifare sniff/clone - aka MattyRun (Matías A. Ré Medina)");
DbpString(" HF Mifare sniff/clone - aka MattyRun (Mat<EFBFBD>as A. R<> Medina)");
#endif
#if defined(WITH_HF_COLIN)
DbpString(" HF Mifare ultra fast sniff/sim/clone - aka VIGIKPWN (Colin Brigato)");
@ -448,7 +442,6 @@ void printStandAloneModes(void) {
//DbpString("Running ");
//Dbprintf(" Is Device attached to USB| %s", USB_ATTACHED() ? "Yes" : "No");
//Dbprintf(" Is Device attached to FPC| %s", 0 ? "Yes" : "No");
//Dbprintf(" Is USB_reconnect value | %d", GetUSBreconnect() );
//Dbprintf(" Is USB_configured value | %d", GetUSBconfigured() );
@ -1077,7 +1070,6 @@ void UsbPacketReceived(uint8_t *packet, int len) {
#endif
case CMD_BUFF_CLEAR:
BigBuf_Clear();
BigBuf_free();
break;
case CMD_MEASURE_ANTENNA_TUNING:
@ -1114,7 +1106,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
len = MIN( (numofbytes - i), USB_CMD_DATA_SIZE);
isok = cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K, i, len, BigBuf_get_traceLen(), mem + startidx + i, len);
if (!isok)
Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len);
Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len);
}
// Trigger a finish downloading signal with an ACK frame
// iceman, when did sending samplingconfig array got attached here?!?
@ -1160,7 +1152,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
len = MIN((numofbytes - i), USB_CMD_DATA_SIZE);
isok = cmd_send(CMD_DOWNLOADED_EML_BIGBUF, i, len, 0, mem + startidx + i, len);
if (!isok)
Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len);
Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len);
}
// Trigger a finish downloading signal with an ACK frame
cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
@ -1177,6 +1169,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
uint16_t isok = 0;
uint32_t startidx = c->arg[0];
uint16_t len = c->arg[1];
uint8_t fast = c->arg[2];
Dbprintf("FlashMem read | %d - %d", startidx, len);
@ -1184,14 +1177,23 @@ void UsbPacketReceived(uint8_t *packet, int len) {
uint8_t *mem = BigBuf_malloc(size);
if (fast) {
FlashInit(1);
//FlashInit();
Flash_CheckBusy(BUSY_TIMEOUT);
}
for(size_t i = 0; i < len; i += size) {
len = MIN((len - i), size);
memset(mem, 0, len);
Dbprintf("FlashMem reading | %d | %d | %d", startidx + i, i, len);
if (!fast){
isok = Flash_ReadData(startidx + i, mem, len);
}
if (fast){
isok = Flash_FastReadDataCont(startidx + i, mem, len);
}
if ( isok == len ) {
print_result("Chunk: ", mem, len);
} else {
@ -1199,6 +1201,9 @@ void UsbPacketReceived(uint8_t *packet, int len) {
break;
}
}
if (fast){
FlashStop();
}
LED_B_OFF();
break;
}
@ -1271,21 +1276,36 @@ void UsbPacketReceived(uint8_t *packet, int len) {
size_t len = 0;
uint32_t startidx = c->arg[0];
uint32_t numofbytes = c->arg[1];
uint8_t fast = c->arg[2];
// arg0 = startindex
// arg1 = length bytes to transfer
// arg2 = RFU
if (fast) {
FlashInit(1);
//FlashInit();
Flash_CheckBusy(BUSY_TIMEOUT);
}
for (size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) {
len = MIN((numofbytes - i), USB_CMD_DATA_SIZE);
if (!fast){
isok = Flash_ReadData(startidx + i, mem, len);
}
if (fast){
isok = Flash_FastReadDataCont(startidx + i, mem, len);
}
if (!isok )
Dbprintf("reading flash memory failed :: | bytes between %d - %d", i, len);
isok = cmd_send(CMD_DOWNLOADED_FLASHMEM, i, len, 0, mem, len);
if (!isok)
Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len);
Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len);
}
if (fast){
FlashStop();
}
cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
LED_B_OFF();
break;
@ -1297,7 +1317,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
bool isok = Flash_ReadData(FLASH_MEM_SIGNATURE_OFFSET, info->signature, FLASH_MEM_SIGNATURE_LEN);
if (FlashInit()) {
if (FlashInit(0)) {
Flash_UniqueID( info->flashid);
FlashStop();
}
@ -1392,8 +1412,6 @@ void __attribute__((noreturn)) AppMain(void) {
LEDsoff();
usb_enable();
// The FPGA gets its clock from us from PCK0 output, so set that up.
AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0;
AT91C_BASE_PIOA->PIO_PDR = GPIO_PCK0;
@ -1419,16 +1437,22 @@ void __attribute__((noreturn)) AppMain(void) {
StartTickCount();
#ifdef WITH_LCD
LCDInit();
// LCDInit();
#endif
#ifdef WITH_SMARTCARD
I2C_init();
// I2C_init();
#endif
#ifdef WITH_FPC
usart_init();
// usart_init();
#endif
// This is made as late as possible to ensure enumeration without timeout
// against device such as http://www.hobbytronics.co.uk/usb-host-board-v2
usb_disable();
usb_enable();
uint8_t rx[sizeof(UsbCommand)];
for(;;) {
@ -1464,6 +1488,10 @@ void __attribute__((noreturn)) AppMain(void) {
RunMod();
#endif
// when here, we are no longer in standalone mode.
// reseting the variables which keeps track of usb re-attached/configured
//SetUSBreconnect(0);
//SetUSBconfigured(0);
}
}
}

View file

@ -1,39 +1,43 @@
#include "flashmem.h"
#define MCK 48000000
//#define FLASH_BAUD 24000000
//define FLASH_BAUD 33000000
#define FLASH_BAUD MCK/2
#define FLASH_FASTBAUD MCK
/* here: use NCPS2 @ PA10: */
#define SPI_CSR_NUM 2 // Chip Select register[] 0,1,2,3 (at91samv512 has 4)
/* PCS_0 for NPCS0, PCS_1 for NPCS1 ... */
#define PCS_0 ((0<<0)|(1<<1)|(1<<2)|(1<<3)) // 0xE - 1110
#define PCS_1 ((1<<0)|(0<<1)|(1<<2)|(1<<3)) // 0xD - 1101
#define PCS_2 ((1<<0)|(1<<1)|(0<<2)|(1<<3)) // 0xB - 1011
#define PCS_3 ((1<<0)|(1<<1)|(1<<2)|(0<<3)) // 0x7 - 0111
// TODO
#if (SPI_CSR_NUM == 0)
#define SPI_MR_PCS PCS_0
#elif (SPI_CSR_NUM == 1)
#define SPI_MR_PCS PCS_1
#elif (SPI_CSR_NUM == 2)
#define SPI_MR_PCS PCS_2
#elif (SPI_CSR_NUM == 3)
#define SPI_MR_PCS PCS_3
#else
#error "SPI_CSR_NUM invalid"
// not realy - when using an external address decoder...
// but this code takes over the complete SPI-interace anyway
#endif
#define SPI_CSR_NUM 2
#define SPI_PCS(npcs) ((~(1 << (npcs)) & 0xF) << 16)
/// Calculates the value of the CSR SCBR field given the baudrate and MCK.
#define SPI_SCBR(baudrate, masterClock) ((uint32_t) ((masterClock) / (baudrate)) << 8)
/// Calculates the value of the CSR DLYBS field given the desired delay (in ns)
#define SPI_DLYBS(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 1000) << 16)
/// Calculates the value of the CSR DLYBCT field given the desired delay (in ns)
#define SPI_DLYBCT(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 32000) << 24)
/*
1-256256
CS拉高
*/
void FlashSetup(void) {
// PA1 -> SPI_NCS3 chip select (MEM)
// PA10 -> SPI_NCS2 chip select (LCD)
// initialize
bool FlashInit(bool fast) {
FlashSetup(fast);
StartTicks();
if (Flash_CheckBusy(BUSY_TIMEOUT)) {
StopTicks();
return false;
}
return true;
}
void FlashSetup(bool fast){
//WDT_DISABLE
AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS;
// PA10 -> SPI_NCS2 chip select (FLASHMEM)
// PA11 -> SPI_NCS0 chip select (FPGA)
// PA12 -> SPI_MISO Master-In Slave-Out
// PA13 -> SPI_MOSI Master-Out Slave-In
@ -54,27 +58,71 @@ void FlashSetup(void) {
//enable the SPI Peripheral clock
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI);
//reset spi needs double SWRST, see atmel's errata on this case
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
// Enable SPI
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN;
// NPCS2 Mode 0
AT91C_BASE_SPI->SPI_MR =
( 0 << 24) | // Delay between chip selects (take default: 6 MCK periods)
(0xB << 16) | // Peripheral Chip Select (selects SPI_NCS2 or PA10)
( 0 << 7) | // Local Loopback Disabled
( 1 << 4) | // Mode Fault Detection disabled
( 0 << 2) | // Chip selects connected directly to peripheral
( 0 << 1) | // Fixed Peripheral Select
( 1 << 0); // Master Mode
(0 << 24) | // Delay between chip selects = DYLBCS/MCK BUT:
// If DLYBCS is less than or equal to six, six MCK periods
// will be inserted by default.
SPI_PCS(SPI_CSR_NUM) | // Peripheral Chip Select (selects SPI_NCS2 or PA10)
( 0 << 7) | // Disable LLB (1=MOSI2MISO test mode)
( 1 << 4) | // Disable ModeFault Protection
( 0 << 3) | // makes spi operate at MCK (1 is MCK/2)
( 0 << 2) | // Chip selects connected directly to peripheral
AT91C_SPI_PS_FIXED | // Fixed Peripheral Select
AT91C_SPI_MSTR; // Master Mode
int baudrate = FLASH_BAUD;
uint8_t csaat = 1;
int dlybct = 0;
if (fast) {
baudrate = FLASH_FASTBAUD;
//csaat = 0;
dlybct = MCK/32;
}
// 8 bit
AT91C_BASE_SPI->SPI_CSR[2] =
( 0 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
( 0 << 16) | // Delay Before SPCK (1 MCK period)
( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud
( 0 << 4) | // Bits per Transfer (8 bits)
( 1 << 3) | // Chip Select inactive after transfer
( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge
SPI_DLYBCT(dlybct,MCK) | // Delay between Consecutive Transfers (32 MCK periods)
SPI_DLYBS(0,MCK) | // Delay Beforce SPCK CLock
SPI_SCBR(baudrate,MCK) | // SPI Baudrate Selection
AT91C_SPI_BITS_8 | // Bits per Transfer (8 bits)
//AT91C_SPI_CSAAT | // Chip Select inactive after transfer
// 40.4.6.2 SPI: Bad tx_ready Behavior when CSAAT = 1 and SCBR = 1
// If the SPI is programmed with CSAAT = 1, SCBR(baudrate) = 1 and two transfers are performed consecutively on
// the same slave with an IDLE state between them, the tx_ready signal does not rise after the second data has been
// transferred in the shifter. This can imply for example, that the second data is sent twice.
// COLIN :: For now we STILL use CSAAT=1 to avoid having to (de)assert NPCS manually via PIO lines and we deal with delay
( csaat << 3) |
/* Spi modes:
Mode CPOL CPHA NCPHA
0 0 0 1 clock normally low read on rising edge
1 0 1 0 clock normally low read on falling edge
2 1 0 1 clock normally high read on falling edge
3 1 1 0 clock normally high read on rising edge
However, page 512 of the AT91SAM7Sx datasheet say "Note that in SPI
master mode the ATSAM7S512/256/128/64/321/32 does not sample the data
(MISO) on the opposite edge where data clocks out (MOSI) but the same
edge is used as shown in Figure 36-3 and Figure 36-4." Figure 36-3
shows that CPOL=NCPHA=0 or CPOL=NCPHA=1 samples on the rising edge and
that the data changes sometime after the rising edge (about 2 ns). To
be consistent with normal SPI operation, it is probably safe to say
that the data changes on the falling edge and should be sampled on the
rising edge. Therefore, it appears that NCPHA should be treated the
same as CPHA. Thus:
Mode CPOL CPHA NCPHA
0 0 0 0 clock normally low read on rising edge
1 0 1 1 clock normally low read on falling edge
2 1 0 0 clock normally high read on falling edge
3 1 1 1 clock normally high read on rising edge
*/
( 0 << 1) | // Clock Phase data captured on leading edge, changes on following edge
( 0 << 0); // Clock Polarity inactive state is logic 0
// read first, empty buffer
@ -82,6 +130,7 @@ void FlashSetup(void) {
}
void FlashStop(void) {
//Bof
//* Reset all the Chip Select register
AT91C_BASE_SPI->SPI_CSR[0] = 0;
AT91C_BASE_SPI->SPI_CSR[1] = 0;
@ -104,24 +153,21 @@ void FlashStop(void) {
// send one byte over SPI
uint16_t FlashSendByte(uint32_t data) {
uint16_t incoming = 0;
WDT_HIT();
// wait until SPI is ready for transfer
while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0) {};
//if you are checking for incoming data returned then the TXEMPTY flag is redundant
//while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0) {};
// send the data
AT91C_BASE_SPI->SPI_TDR = data;
while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TDRE) == 0){};
// wait recive transfer is complete
while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0)
WDT_HIT();
while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0);
// reading incoming data
incoming = ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF);
return incoming;
return ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF);
}
// send last byte over SPI
@ -132,41 +178,35 @@ uint16_t FlashSendLastByte(uint32_t data) {
// read state register 1
uint8_t Flash_ReadStat1(void) {
FlashSendByte(READSTAT1);
uint8_t stat1 = FlashSendLastByte(0xFF);
// if ( MF_DBGLEVEL > 3 ) Dbprintf("stat1 [%02x]", stat1);
return stat1;
return FlashSendLastByte(0xFF);
}
// read state register 2
uint8_t Flash_ReadStat2(void) {
FlashSendByte(READSTAT2);
uint8_t stat2 = FlashSendLastByte(0xFF);
// if ( MF_DBGLEVEL > 3 ) Dbprintf("stat2 [%02x]", stat2);
return stat2;
}
bool Flash_CheckBusy(uint32_t timeout)
{
WaitUS(WINBOND_WRITE_DELAY);
StartCountUS();
uint32_t _time = GetCountUS();
// determine whether FLASHMEM is busy
bool Flash_CheckBusy(uint16_t times) {
bool ret = (Flash_ReadStat1() & BUSY);
do
{
if (!(Flash_ReadStat1() & BUSY))
{
return false;
}
} while ((GetCountUS() - _time) < timeout);
if (!ret || !times || !(times--))
return ret;
while (times) {
WDT_HIT();
SpinDelay(1);
ret = (Flash_ReadStat1() & BUSY);
if (!ret)
break;
times--;
if (timeout <= (GetCountUS() - _time))
{
return true;
}
return ret;
return false;
}
// read ID out
uint8_t Flash_ReadID(void) {
if (Flash_CheckBusy(100)) return 0;
if (Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
// Manufacture ID / device ID
FlashSendByte(ID);
@ -188,7 +228,7 @@ uint8_t Flash_ReadID(void) {
// read unique id for chip.
void Flash_UniqueID(uint8_t *uid) {
if (Flash_CheckBusy(100)) return;
if (Flash_CheckBusy(BUSY_TIMEOUT)) return;
// reading unique serial number
FlashSendByte(UNIQUE_ID);
@ -209,12 +249,10 @@ void Flash_UniqueID(uint8_t *uid) {
uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) {
if (!FlashInit()) return 0;
Flash_ReadStat1();
if (!FlashInit(0)) return 0;
// length should never be zero
if (!len || Flash_CheckBusy(100)) return 0;
if (!len || Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
FlashSendByte(READDATA);
FlashSendByte((address >> 16) & 0xFF);
@ -231,6 +269,55 @@ uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) {
return len;
}
/* This ensure we can ReadData without having to cycle through initialization everytime */
uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) {
// length should never be zero
if (!len) return 0;
FlashSendByte(READDATA);
FlashSendByte((address >> 16) & 0xFF);
FlashSendByte((address >> 8) & 0xFF);
FlashSendByte((address >> 0) & 0xFF);
uint16_t i = 0;
for (; i < (len - 1); i++)
out[i] = FlashSendByte(0xFF);
out[i] = FlashSendLastByte(0xFF);
return len;
}
uint16_t Flash_FastReadDataCont(uint32_t address, uint8_t *out, uint16_t len) {
// length should never be zero
if (!len) return 0;
//if (Flash_CheckBusy(BUSY_TIMEOUT))
//{return 0;}
FlashSendByte(FASTREAD);
FlashSendByte((address >> 16) & 0xFF);
FlashSendByte((address >> 8) & 0xFF);
FlashSendByte((address >> 0) & 0xFF);
FlashSendByte(0xFF);
//Flash_CheckBusy(BUSY_TIMEOUT);
uint16_t i = 0;
for (; i < (len - 1); i++)
out[i] = FlashSendByte(0xFF);
out[i] = FlashSendLastByte(0xFF);
return len;
}
////////////////////////////////////////
// Write data can only program one page. A page has 256 bytes.
// if len > 256, it might wrap around and overwrite pos 0.
uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
@ -251,12 +338,13 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
return 0;
}
if (!FlashInit()) {
if (!FlashInit(0)) {
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail");
return 0;
}
Flash_ReadStat1();
Flash_CheckBusy(BUSY_TIMEOUT);
//Flash_ReadStat1();
Flash_WriteEnable();
@ -275,22 +363,61 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
return len;
}
uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) {
// length should never be zero
if (!len)
return 0;
// Max 256 bytes write
if (((address & 0xFF) + len) > 256) {
Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF)+len, len );
return 0;
}
// out-of-range
if ( (( address >> 16 ) & 0xFF ) > MAX_BLOCKS) {
Dbprintf("Flash_WriteData, block out-of-range");
return 0;
}
//Flash_CheckBusy(100);
//SpinDelay(1);
Flash_CheckBusy(BUSY_TIMEOUT);
//Flash_ReadStat1();
Flash_WriteEnable();
FlashSendByte(PAGEPROG);
FlashSendByte((address >> 16) & 0xFF);
FlashSendByte((address >> 8) & 0xFF);
FlashSendByte((address >> 0) & 0xFF);
uint16_t i = 0;
for (; i < (len - 1); i++)
FlashSendByte(in[i]);
FlashSendLastByte(in[i]);
return len;
}
bool Flash_WipeMemoryPage(uint8_t page) {
if (!FlashInit()) {
if (!FlashInit(0)) {
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail");
return false;
}
Flash_ReadStat1();
// Each block is 64Kb. One block erase takes 1s ( 1000ms )
Flash_WriteEnable(); Flash_Erase64k(page); Flash_CheckBusy(1000);
Flash_WriteEnable(); Flash_Erase64k(page); Flash_CheckBusy(BUSY_TIMEOUT);
FlashStop();
return true;
}
// Wipes flash memory completely, fills with 0xFF
bool Flash_WipeMemory() {
if (!FlashInit()) {
if (!FlashInit(0)) {
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail");
return false;
}
@ -298,10 +425,10 @@ bool Flash_WipeMemory() {
// Each block is 64Kb. Four blocks
// one block erase takes 1s ( 1000ms )
Flash_WriteEnable(); Flash_Erase64k(0); Flash_CheckBusy(1000);
Flash_WriteEnable(); Flash_Erase64k(1); Flash_CheckBusy(1000);
Flash_WriteEnable(); Flash_Erase64k(2); Flash_CheckBusy(1000);
Flash_WriteEnable(); Flash_Erase64k(3); Flash_CheckBusy(1000);
Flash_WriteEnable(); Flash_Erase64k(0); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable(); Flash_Erase64k(1); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable(); Flash_Erase64k(2); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable(); Flash_Erase64k(3); Flash_CheckBusy(BUSY_TIMEOUT);
FlashStop();
return true;
@ -366,25 +493,13 @@ void Flash_EraseChip(void) {
FlashSendLastByte(CHIPERASE);
}
// initialize
bool FlashInit(void) {
FlashSetup();
StartTicks();
if (Flash_CheckBusy(100)) {
StopTicks();
return false;
}
if ( MF_DBGLEVEL > 3 ) Dbprintf("FlashInit OK");
return true;
}
void Flashmem_print_status(void) {
DbpString("Flash memory");
if (!FlashInit()) {
if (!FlashInit(0)) {
DbpString(" init....................FAIL");
return;
}
@ -414,4 +529,4 @@ void Flashmem_print_status(void) {
);
FlashStop();
}
}

View file

@ -45,6 +45,7 @@
#define WRITEENABLE 0x06
#define READDATA 0x03
#define FASTREAD 0x0B
#define PAGEPROG 0x02
#define SECTORERASE 0x20
@ -57,27 +58,17 @@
// Not used or not support command
#define RELEASE 0xAB
#define POWERDOWN 0xB9
#define FASTREAD 0x0B
#define SUSPEND 0x75
#define RESUME 0x7A
#define BUSY_TIMEOUT 1000000000L
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Chip specific instructions //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~ Winbond ~~~~~~~~~~~~~~~~~~~~~~~~~//
#define WINBOND_MANID 0xEF
#define WINBOND_DEVID 0x11
#define PAGESIZE 0x100
#define WINBOND_WRITE_DELAY 0x02
//~~~~~~~~~~~~~~~~~~~~~~~~ Microchip ~~~~~~~~~~~~~~~~~~~~~~~~//
#define MICROCHIP_MANID 0xBF
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Definitions //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
#define SPI_CLK 75000000 //Hex equivalent of 75MHz
#define SPI_CLK 48000000
#define BUSY 0x01
#define WRTEN 0x02
@ -113,14 +104,17 @@
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
extern void Dbprintf(const char *fmt, ...);
void FlashSetup(void);
bool FlashInit(bool fast);
void FlashSetup(bool fast);
void FlashStop(void);
bool Flash_WaitIdle(void);
uint8_t Flash_ReadStat1(void);
uint8_t Flash_ReadStat2(void);
uint16_t FlashSendByte(uint32_t data);
bool Flash_CheckBusy(uint32_t timeout);
void Flash_WriteEnable();
bool Flash_WipeMemoryPage(uint8_t page);
bool Flash_WipeMemory();
@ -128,12 +122,16 @@ bool Flash_Erase4k(uint8_t block, uint8_t sector);
//bool Flash_Erase32k(uint32_t address);
bool Flash_Erase64k(uint8_t block);
bool FlashInit();
void Flash_UniqueID(uint8_t *uid);
uint8_t Flash_ReadID(void);
uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len);
uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len);
uint16_t Flash_FastReadDataCont(uint32_t address, uint8_t *out, uint16_t len);
uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len);
uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len);
void Flashmem_print_status(void);
#endif

View file

@ -15,9 +15,10 @@
static int CmdHelp(const char *Cmd);
int usage_flashmem_read(void){
PrintAndLogEx(NORMAL, "Read flash memory on device");
PrintAndLogEx(NORMAL, "Usage: mem read o <offset> l <len>");
PrintAndLogEx(NORMAL, "Usage: mem read o <offset> l <len> [f]");
PrintAndLogEx(NORMAL, " o <offset> : offset in memory");
PrintAndLogEx(NORMAL, " l <len> : length");
PrintAndLogEx(NORMAL, " f : fastRead mode");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " mem read o 0 l 32"); // read 32 bytes starting at offset 0
@ -41,6 +42,7 @@ int usage_flashmem_save(void){
PrintAndLogEx(NORMAL, " o <offset> : offset in memory");
PrintAndLogEx(NORMAL, " l <length> : length");
PrintAndLogEx(NORMAL, " f <filename> : file name");
PrintAndLogEx(NORMAL, " + : fast read mode");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " mem save f myfile"); // download whole flashmem to file myfile
@ -79,9 +81,14 @@ int CmdFlashMemRead(const char *Cmd) {
uint8_t cmdp = 0;
bool errors = false;
uint32_t start_index = 0, len = 0;
uint8_t fast = 0;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'f':
fast = 1;
cmdp += 1;
break;
case 'o':
start_index = param_get32ex(Cmd, cmdp+1, 0, 10);
cmdp += 2;
@ -107,7 +114,7 @@ int CmdFlashMemRead(const char *Cmd) {
return 1;
}
UsbCommand c = {CMD_READ_FLASH_MEM, {start_index, len, 0}};
UsbCommand c = {CMD_READ_FLASH_MEM, {start_index, len, fast}};
clearCommandBuffer();
SendCommand(&c);
return 0;
@ -221,6 +228,7 @@ int CmdFlashMemSave(const char *Cmd){
uint8_t cmdp = 0;
bool errors = false;
uint32_t start_index = 0, len = FLASH_MEM_MAX_SIZE;
uint8_t fast = 0;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
@ -233,6 +241,10 @@ int CmdFlashMemSave(const char *Cmd){
start_index = param_get32ex(Cmd, cmdp+1, 0, 10);
cmdp += 2;
break;
case '+':
fast = 1;
cmdp += 1;
break;
case 'f':
//File handling
if ( param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE ) {

View file

@ -199,7 +199,31 @@ void UsbCommandReceived(UsbCommand* _ch) {
memset(s, 0x00, sizeof(s));
size_t len = MIN(c->arg[0], USB_CMD_DATA_SIZE);
memcpy(s, c->d.asBytes, len);
//#define FLAG_RAWPRINT 0x0111
//#define FLAG_NOOPT 0x0000
//#define FLAG_NOLOG 0x0001
//#define FLAG_NONEWLINE 0x0010
//#define FLAG_NOPROMPT 0x0100
uint64_t flag = c->arg[1];
if (flag > 0) { // FLAG_RAWPRINT) {
switch (flag) {
case FLAG_RAWPRINT: {
printf("%s", s);
} return; break;
case FLAG_NONEWLINE: {
printf("%s\r", s);
} return; break;
case FLAG_NOLOG: {
printf("%s\r\n", s);
} return; break;
// printf("%s", s);
fflush(stdout);
return;
}
}
// print debug line on same row. escape seq \r
if ( c->arg[1] == CMD_MEASURE_ANTENNA_TUNING_HF) {
PrintAndLogEx(NORMAL, "\r#db# %s", s);