2015-01-16 11:00:17 +01:00
//-----------------------------------------------------------------------------
// Jonathan Westhues, Aug 2005
// Gerhard de Koning Gans, April 2008, May 2011
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// BigBuf and functions to allocate/free parts of it.
//-----------------------------------------------------------------------------
2016-07-07 10:01:50 +02:00
# include "BigBuf.h"
2015-01-16 11:00:17 +01:00
2019-08-08 16:57:33 +02:00
# include "string.h"
# include "dbprint.h"
2020-05-19 02:39:39 +02:00
# include "pm3_cmd.h"
2021-12-29 23:40:18 +01:00
# include "util.h" // nbytes
2019-08-08 16:57:33 +02:00
2021-05-25 16:47:13 +02:00
extern uint32_t _stack_start [ ] , __bss_end__ [ ] ;
2020-06-10 12:41:18 +02:00
2015-01-27 08:34:48 +01:00
// BigBuf is the large multi-purpose buffer, typically used to hold A/D samples or traces.
// Also used to hold various smaller buffers and the Mifare Emulator Memory.
2020-06-10 12:41:18 +02:00
// We know that bss is aligned to 4 bytes.
2021-05-13 22:15:06 +02:00
static uint8_t * BigBuf = ( uint8_t * ) __bss_end__ ;
2015-01-16 11:00:17 +01:00
2016-03-12 09:03:28 +01:00
/* BigBuf memory layout:
2020-07-10 16:37:56 +02:00
Pointer to highest available memory : s_bigbuf_hi
high s_bigbuf_size
reserved = BigBuf_malloc ( ) subtracts amount from s_bigbuf_hi ,
2019-03-09 20:34:41 +01:00
low 0x00
2016-03-12 09:03:28 +01:00
*/
2020-07-13 12:26:26 +02:00
static uint32_t s_bigbuf_size = 0 ;
2020-06-10 12:41:18 +02:00
2015-01-16 11:00:17 +01:00
// High memory mark
2020-07-10 16:37:56 +02:00
static uint32_t s_bigbuf_hi = 0 ;
2015-01-16 11:00:17 +01:00
2015-01-27 08:34:48 +01:00
// pointer to the emulator memory.
static uint8_t * emulator_memory = NULL ;
2020-07-15 15:16:35 +02:00
//=============================================================================
// The ToSend buffer.
// 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
// is the order in which they go out on the wire.
//=============================================================================
static tosend_t toSend = {
. max = - 1 ,
. bit = 8 ,
. buf = NULL
} ;
//=============================================================================
// The dmaBuf 16bit buffer.
2021-10-10 01:35:38 +02:00
// A buffer where we receive IQ samples sent from the FPGA, for demodulating
2020-07-15 15:16:35 +02:00
//=============================================================================
static dmabuf16_t dma_16 = {
. size = DMA_BUFFER_SIZE ,
. buf = NULL
} ;
// dmaBuf 8bit buffer
static dmabuf8_t dma_8 = {
. size = DMA_BUFFER_SIZE ,
. buf = NULL
} ;
2015-02-07 20:49:40 +01:00
// trace related variables
2020-07-10 16:37:56 +02:00
static uint32_t trace_len = 0 ;
2020-06-10 12:41:18 +02:00
static bool tracing = true ;
// compute the available size for BigBuf
void BigBuf_initialize ( void ) {
2021-05-13 22:15:06 +02:00
s_bigbuf_size = ( uint32_t ) _stack_start - ( uint32_t ) __bss_end__ ;
2020-07-10 16:37:56 +02:00
s_bigbuf_hi = s_bigbuf_size ;
trace_len = 0 ;
2020-06-10 12:41:18 +02:00
}
2015-01-16 11:00:17 +01:00
// get the address of BigBuf
2019-03-10 11:20:22 +01:00
uint8_t * BigBuf_get_addr ( void ) {
2019-03-09 20:34:41 +01:00
return ( uint8_t * ) BigBuf ;
2015-01-27 08:34:48 +01:00
}
2020-06-10 12:41:18 +02:00
uint32_t BigBuf_get_size ( void ) {
2020-07-10 16:37:56 +02:00
return s_bigbuf_size ;
2020-06-10 12:41:18 +02:00
}
2015-01-27 08:34:48 +01:00
// get the address of the emulator memory. Allocate part of Bigbuf for it, if not yet done
2019-03-10 11:20:22 +01:00
uint8_t * BigBuf_get_EM_addr ( void ) {
2019-03-09 20:34:41 +01:00
// not yet allocated
if ( emulator_memory = = NULL )
emulator_memory = BigBuf_malloc ( CARD_MEMORY_SIZE ) ;
2019-03-09 08:59:13 +01:00
2019-03-09 20:34:41 +01:00
return emulator_memory ;
2015-01-16 11:00:17 +01:00
}
2020-07-10 16:37:56 +02:00
/*
uint32_t BigBuf_get_EM_size ( void ) {
return CARD_MEMORY_SIZE ;
}
*/
2015-01-16 11:00:17 +01:00
// clear ALL of BigBuf
2019-03-10 11:20:22 +01:00
void BigBuf_Clear ( void ) {
2019-03-09 20:34:41 +01:00
BigBuf_Clear_ext ( true ) ;
2015-10-16 23:16:46 +02:00
}
2016-03-20 19:33:07 +01:00
2015-10-16 23:16:46 +02:00
// clear ALL of BigBuf
2019-03-10 11:20:22 +01:00
void BigBuf_Clear_ext ( bool verbose ) {
2020-07-10 16:37:56 +02:00
memset ( BigBuf , 0 , s_bigbuf_size ) ;
2020-08-17 09:12:28 +02:00
clear_trace ( ) ;
2019-03-09 20:34:41 +01:00
if ( verbose )
2020-07-10 16:37:56 +02:00
Dbprintf ( " Buffer cleared (%i bytes) " , s_bigbuf_size ) ;
2015-01-16 11:00:17 +01:00
}
2019-03-10 11:20:22 +01:00
void BigBuf_Clear_EM ( void ) {
2019-03-09 20:34:41 +01:00
memset ( BigBuf_get_EM_addr ( ) , 0 , CARD_MEMORY_SIZE ) ;
2017-07-07 12:52:51 +02:00
}
2019-03-10 11:20:22 +01:00
void BigBuf_Clear_keep_EM ( void ) {
2020-07-10 16:37:56 +02:00
memset ( BigBuf , 0 , s_bigbuf_hi ) ;
2016-02-21 17:44:25 +01:00
}
2015-01-16 11:00:17 +01:00
2015-01-27 08:34:48 +01:00
// allocate a chunk of memory from BigBuf. We allocate high memory first. The unallocated memory
// at the beginning of BigBuf is always for traces/samples
2019-03-10 11:20:22 +01:00
uint8_t * BigBuf_malloc ( uint16_t chunksize ) {
2020-07-10 16:37:56 +02:00
if ( s_bigbuf_hi < chunksize )
2019-03-09 20:34:41 +01:00
return NULL ; // no memory left
2018-09-04 20:36:25 +02:00
2019-03-09 20:34:41 +01:00
chunksize = ( chunksize + 3 ) & 0xfffc ; // round to next multiple of 4
2020-07-10 16:37:56 +02:00
s_bigbuf_hi - = chunksize ; // aligned to 4 Byte boundary
return ( uint8_t * ) BigBuf + s_bigbuf_hi ;
2015-01-16 11:00:17 +01:00
}
2020-11-07 01:32:43 +01:00
// allocate a chunk of memory from BigBuf, and returns a pointer to it.
2020-11-02 19:07:03 +01:00
// sets the memory to zero
uint8_t * BigBuf_calloc ( uint16_t chunksize ) {
uint8_t * mem = BigBuf_malloc ( chunksize ) ;
if ( mem ! = NULL ) {
memset ( mem , 0x00 , chunksize ) ;
}
2020-11-07 01:32:43 +01:00
return mem ;
2020-11-02 19:07:03 +01:00
}
2015-01-27 08:34:48 +01:00
// free ALL allocated chunks. The whole BigBuf is available for traces or samples again.
2019-03-10 11:20:22 +01:00
void BigBuf_free ( void ) {
2020-07-10 16:37:56 +02:00
s_bigbuf_hi = s_bigbuf_size ;
2019-03-09 20:34:41 +01:00
emulator_memory = NULL ;
// shouldn't this empty BigBuf also?
2020-07-15 15:16:35 +02:00
toSend . buf = NULL ;
dma_16 . buf = NULL ;
dma_8 . buf = NULL ;
2015-01-27 08:34:48 +01:00
}
// free allocated chunks EXCEPT the emulator memory
2019-03-10 11:20:22 +01:00
void BigBuf_free_keep_EM ( void ) {
2019-03-09 20:34:41 +01:00
if ( emulator_memory ! = NULL )
2020-07-10 16:37:56 +02:00
s_bigbuf_hi = emulator_memory - ( uint8_t * ) BigBuf ;
2019-03-09 20:34:41 +01:00
else
2020-07-10 16:37:56 +02:00
s_bigbuf_hi = s_bigbuf_size ;
2020-07-15 15:16:35 +02:00
toSend . buf = NULL ;
dma_16 . buf = NULL ;
dma_8 . buf = NULL ;
2015-01-16 11:00:17 +01:00
}
2019-03-10 11:20:22 +01:00
void BigBuf_print_status ( void ) {
2020-06-11 19:20:59 +02:00
DbpString ( _CYAN_ ( " Memory " ) ) ;
2021-05-11 16:11:33 +02:00
Dbprintf ( " BigBuf_size............. %d " , s_bigbuf_size ) ;
Dbprintf ( " Available memory........ %d " , s_bigbuf_hi ) ;
2020-06-11 19:20:59 +02:00
DbpString ( _CYAN_ ( " Tracing " ) ) ;
2021-05-11 16:11:33 +02:00
Dbprintf ( " tracing ................ %d " , tracing ) ;
Dbprintf ( " traceLen ............... %d " , trace_len ) ;
2020-07-15 15:16:35 +02:00
2021-08-21 23:02:27 +02:00
if ( g_dbglevel > = DBG_DEBUG ) {
2021-05-11 16:11:33 +02:00
DbpString ( _CYAN_ ( " Sending buffers " ) ) ;
uint16_t d8 = 0 ;
if ( dma_8 . buf )
d8 = dma_8 . buf - BigBuf_get_addr ( ) ;
uint16_t d16 = 0 ;
if ( dma_16 . buf )
d16 = ( uint8_t * ) dma_16 . buf - BigBuf_get_addr ( ) ;
uint16_t ts = 0 ;
if ( toSend . buf )
ts = toSend . buf - BigBuf_get_addr ( ) ;
Dbprintf ( " dma8 memory............. %u " , d8 ) ;
Dbprintf ( " dma16 memory............ %u " , d16 ) ;
Dbprintf ( " toSend memory........... %u " , ts ) ;
}
2015-07-22 23:00:52 +02:00
}
2015-01-16 11:00:17 +01:00
// return the maximum trace length (i.e. the unallocated size of BigBuf)
2019-03-10 11:20:22 +01:00
uint16_t BigBuf_max_traceLen ( void ) {
2020-07-10 16:37:56 +02:00
return s_bigbuf_hi ;
2015-01-27 08:34:48 +01:00
}
2015-02-07 20:49:40 +01:00
2019-03-10 11:20:22 +01:00
void clear_trace ( void ) {
2020-07-10 16:37:56 +02:00
trace_len = 0 ;
2015-02-07 20:49:40 +01:00
}
2020-01-01 20:47:39 +01:00
2019-03-10 11:20:22 +01:00
void set_tracelen ( uint32_t value ) {
2020-07-10 16:37:56 +02:00
trace_len = value ;
2017-10-08 14:56:04 +02:00
}
2020-01-01 20:47:39 +01:00
2019-03-10 11:20:22 +01:00
void set_tracing ( bool enable ) {
2019-03-09 20:34:41 +01:00
tracing = enable ;
2015-02-07 20:49:40 +01:00
}
2019-03-10 11:20:22 +01:00
bool get_tracing ( void ) {
2019-03-09 20:34:41 +01:00
return tracing ;
2017-10-23 21:17:59 +02:00
}
2015-02-07 20:49:40 +01:00
/**
* Get the number of bytes traced
* @ return
*/
2019-03-10 11:20:22 +01:00
uint32_t BigBuf_get_traceLen ( void ) {
2020-07-10 16:37:56 +02:00
return trace_len ;
2015-02-07 20:49:40 +01:00
}
/**
This is a function to store traces . All protocols can use this generic tracer - function .
The traces produced by calling this function can be fetched on the client - side
2021-04-16 01:53:07 +02:00
by ' hf list - t raw ' , alternatively ' hf list - t < proto > ' for protocol - specific
2015-02-07 20:49:40 +01:00
annotation of commands / responses .
* */
2019-03-10 11:20:22 +01:00
bool RAMFUNC LogTrace ( const uint8_t * btBytes , uint16_t iLen , uint32_t timestamp_start , uint32_t timestamp_end , uint8_t * parity , bool readerToTag ) {
2020-07-09 19:40:54 +02:00
if ( tracing = = false ) {
return false ;
}
2019-03-09 20:34:41 +01:00
uint8_t * trace = BigBuf_get_addr ( ) ;
2020-07-10 16:37:56 +02:00
tracelog_hdr_t * hdr = ( tracelog_hdr_t * ) ( trace + trace_len ) ;
2019-03-09 20:34:41 +01:00
2019-03-10 00:00:59 +01:00
uint32_t num_paritybytes = ( iLen - 1 ) / 8 + 1 ; // number of valid paritybytes in *parity
2019-03-09 20:34:41 +01:00
// Return when trace is full
2020-07-10 16:37:56 +02:00
if ( TRACELOG_HDR_LEN + iLen + num_paritybytes > = BigBuf_max_traceLen ( ) - trace_len ) {
2020-07-13 12:20:12 +02:00
tracing = false ;
2019-03-09 20:34:41 +01:00
return false ;
}
2020-05-19 20:03:27 +02:00
uint32_t duration ;
if ( timestamp_end > timestamp_start ) {
duration = timestamp_end - timestamp_start ;
} else {
duration = ( UINT32_MAX - timestamp_start ) + timestamp_end ;
2019-03-09 20:34:41 +01:00
}
2020-05-19 20:03:27 +02:00
2020-07-21 10:49:29 +02:00
if ( duration > 0xFFFF ) {
2020-07-13 22:05:11 +02:00
/*
2021-08-21 23:02:27 +02:00
if ( g_dbglevel > = DBG_DEBUG ) {
2020-07-21 10:49:29 +02:00
Dbprintf ( " Error in LogTrace: duration too long for 16 bits encoding: 0x%08x start: 0x%08x end: 0x%08x " , duration , timestamp_start , timestamp_end ) ;
2020-05-19 20:03:27 +02:00
}
2020-07-13 22:05:11 +02:00
*/
2020-07-21 10:49:29 +02:00
duration = 0 ;
2020-05-19 20:03:27 +02:00
}
2020-08-13 12:25:04 +02:00
2020-05-19 02:39:39 +02:00
hdr - > timestamp = timestamp_start ;
2020-07-21 10:49:29 +02:00
hdr - > duration = duration & 0xFFFF ;
2020-05-19 02:39:39 +02:00
hdr - > data_len = iLen ;
hdr - > isResponse = ! readerToTag ;
2020-07-10 16:37:56 +02:00
trace_len + = TRACELOG_HDR_LEN ;
2019-03-09 20:34:41 +01:00
// data bytes
if ( btBytes ! = NULL & & iLen ! = 0 ) {
2020-07-13 12:20:12 +02:00
memcpy ( hdr - > frame , btBytes , iLen ) ;
trace_len + = iLen ;
2019-03-09 20:34:41 +01:00
}
// parity bytes
if ( num_paritybytes ! = 0 ) {
if ( parity ! = NULL ) {
2020-07-10 16:37:56 +02:00
memcpy ( trace + trace_len , parity , num_paritybytes ) ;
2019-03-09 20:34:41 +01:00
} else {
2020-07-10 16:37:56 +02:00
memset ( trace + trace_len , 0x00 , num_paritybytes ) ;
2019-03-09 20:34:41 +01:00
}
2020-07-13 12:20:12 +02:00
trace_len + = num_paritybytes ;
2019-03-09 20:34:41 +01:00
}
return true ;
2015-02-07 20:49:40 +01:00
}
2015-03-24 11:45:31 +01:00
2020-07-21 10:49:29 +02:00
// specific LogTrace function for ISO15693: the duration needs to be scaled because otherwise it won't fit into a uint16_t
bool LogTrace_ISO15693 ( const uint8_t * bytes , uint16_t len , uint32_t ts_start , uint32_t ts_end , uint8_t * parity , bool reader2tag ) {
uint32_t duration = ts_end - ts_start ;
duration / = 32 ;
ts_end = ts_start + duration ;
return LogTrace ( bytes , len , ts_start , ts_end , parity , reader2tag ) ;
}
2021-12-29 23:40:18 +01:00
// specific LogTrace function for bitstreams: the partial byte size is stored in first parity byte. E.g. bitstream "1100 00100010" -> partial byte: 4 bits
bool RAMFUNC LogTraceBits ( const uint8_t * btBytes , uint16_t bitLen , uint32_t timestamp_start , uint32_t timestamp_end , bool readerToTag ) {
uint8_t parity [ ( nbytes ( bitLen ) - 1 ) / 8 + 1 ] ;
memset ( parity , 0x00 , sizeof ( parity ) ) ;
2021-12-30 01:03:45 +01:00
parity [ 0 ] = bitLen % 8 ;
2021-12-29 23:40:18 +01:00
return LogTrace ( btBytes , nbytes ( bitLen ) , timestamp_start , timestamp_end , parity , readerToTag ) ;
}
2020-07-21 10:49:29 +02:00
2015-02-14 21:30:26 +01:00
// Emulator memory
2019-03-10 11:20:22 +01:00
uint8_t emlSet ( uint8_t * data , uint32_t offset , uint32_t length ) {
2019-03-10 00:00:59 +01:00
uint8_t * mem = BigBuf_get_EM_addr ( ) ;
2019-03-09 20:34:41 +01:00
if ( offset + length < CARD_MEMORY_SIZE ) {
2019-03-10 00:00:59 +01:00
memcpy ( mem + offset , data , length ) ;
2019-03-09 20:34:41 +01:00
return 0 ;
}
Dbprintf ( " Error, trying to set memory outside of bounds! %d > %d " , ( offset + length ) , CARD_MEMORY_SIZE ) ;
return 1 ;
2015-02-14 21:30:26 +01:00
}
2020-07-13 17:56:19 +02:00
// get the address of the ToSend buffer. Allocate part of Bigbuf for it, if not yet done
tosend_t * get_tosend ( void ) {
if ( toSend . buf = = NULL )
toSend . buf = BigBuf_malloc ( TOSEND_BUFFER_SIZE ) ;
return & toSend ;
}
void tosend_reset ( void ) {
toSend . max = - 1 ;
toSend . bit = 8 ;
}
void tosend_stuffbit ( int b ) {
2020-09-28 17:46:12 +02:00
if ( toSend . max > = TOSEND_BUFFER_SIZE - 1 ) {
Dbprintf ( _RED_ ( " toSend overflow " ) ) ;
return ;
}
2020-09-30 14:27:19 +02:00
2020-07-13 17:56:19 +02:00
if ( toSend . bit > = 8 ) {
toSend . max + + ;
toSend . buf [ toSend . max ] = 0 ;
toSend . bit = 0 ;
}
if ( b )
2020-09-28 17:46:12 +02:00
toSend . buf [ toSend . max ] | = ( 1 < < ( 7 - toSend . bit ) ) ;
2020-07-13 17:56:19 +02:00
toSend . bit + + ;
if ( toSend . max > = TOSEND_BUFFER_SIZE ) {
toSend . bit = 0 ;
}
}
2020-07-15 15:16:35 +02:00
dmabuf16_t * get_dma16 ( void ) {
if ( dma_16 . buf = = NULL )
2020-08-13 12:25:04 +02:00
dma_16 . buf = ( uint16_t * ) BigBuf_malloc ( DMA_BUFFER_SIZE * sizeof ( uint16_t ) ) ;
2020-07-15 15:16:35 +02:00
return & dma_16 ;
}
dmabuf8_t * get_dma8 ( void ) {
if ( dma_8 . buf = = NULL )
dma_8 . buf = BigBuf_malloc ( DMA_BUFFER_SIZE ) ;
return & dma_8 ;
}