2015-01-16 18:00:17 +08:00
//-----------------------------------------------------------------------------
2022-01-06 09:19:46 +08:00
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
2015-01-16 18:00:17 +08:00
//
2022-01-06 09:19:46 +08:00
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the text of the license.
2015-01-16 18:00:17 +08:00
//-----------------------------------------------------------------------------
// BigBuf and functions to allocate/free parts of it.
//-----------------------------------------------------------------------------
2016-07-07 16:01:50 +08:00
# include "BigBuf.h"
2015-01-16 18:00:17 +08:00
2019-08-08 22:57:33 +08:00
# include "string.h"
# include "dbprint.h"
2020-05-19 08:39:39 +08:00
# include "pm3_cmd.h"
2021-12-30 06:40:18 +08:00
# include "util.h" // nbytes
2019-08-08 22:57:33 +08:00
2021-05-25 22:47:13 +08:00
extern uint32_t _stack_start [ ] , __bss_end__ [ ] ;
2020-06-10 18:41:18 +08:00
2015-01-27 15:34:48 +08: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 18:41:18 +08:00
// We know that bss is aligned to 4 bytes.
2021-05-14 04:15:06 +08:00
static uint8_t * BigBuf = ( uint8_t * ) __bss_end__ ;
2015-01-16 18:00:17 +08:00
2016-03-12 16:03:28 +08:00
/* BigBuf memory layout:
2020-07-10 22:37:56 +08:00
Pointer to highest available memory : s_bigbuf_hi
high s_bigbuf_size
reserved = BigBuf_malloc ( ) subtracts amount from s_bigbuf_hi ,
2019-03-10 03:34:41 +08:00
low 0x00
2016-03-12 16:03:28 +08:00
*/
2020-07-13 18:26:26 +08:00
static uint32_t s_bigbuf_size = 0 ;
2020-06-10 18:41:18 +08:00
2015-01-16 18:00:17 +08:00
// High memory mark
2020-07-10 22:37:56 +08:00
static uint32_t s_bigbuf_hi = 0 ;
2015-01-16 18:00:17 +08:00
2015-01-27 15:34:48 +08:00
// pointer to the emulator memory.
static uint8_t * emulator_memory = NULL ;
2020-07-15 21:16:35 +08: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 07:35:38 +08:00
// A buffer where we receive IQ samples sent from the FPGA, for demodulating
2020-07-15 21:16:35 +08: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-08 03:49:40 +08:00
// trace related variables
2020-07-10 22:37:56 +08:00
static uint32_t trace_len = 0 ;
2020-06-10 18:41:18 +08:00
static bool tracing = true ;
// compute the available size for BigBuf
void BigBuf_initialize ( void ) {
2021-05-14 04:15:06 +08:00
s_bigbuf_size = ( uint32_t ) _stack_start - ( uint32_t ) __bss_end__ ;
2020-07-10 22:37:56 +08:00
s_bigbuf_hi = s_bigbuf_size ;
trace_len = 0 ;
2020-06-10 18:41:18 +08:00
}
2015-01-16 18:00:17 +08:00
// get the address of BigBuf
2019-03-10 18:20:22 +08:00
uint8_t * BigBuf_get_addr ( void ) {
2019-03-10 03:34:41 +08:00
return ( uint8_t * ) BigBuf ;
2015-01-27 15:34:48 +08:00
}
2020-06-10 18:41:18 +08:00
uint32_t BigBuf_get_size ( void ) {
2020-07-10 22:37:56 +08:00
return s_bigbuf_size ;
2020-06-10 18:41:18 +08:00
}
2015-01-27 15:34:48 +08:00
// get the address of the emulator memory. Allocate part of Bigbuf for it, if not yet done
2019-03-10 18:20:22 +08:00
uint8_t * BigBuf_get_EM_addr ( void ) {
2019-03-10 03:34:41 +08:00
// not yet allocated
if ( emulator_memory = = NULL )
emulator_memory = BigBuf_malloc ( CARD_MEMORY_SIZE ) ;
2019-03-09 15:59:13 +08:00
2019-03-10 03:34:41 +08:00
return emulator_memory ;
2015-01-16 18:00:17 +08:00
}
2020-07-10 22:37:56 +08:00
/*
uint32_t BigBuf_get_EM_size ( void ) {
return CARD_MEMORY_SIZE ;
}
*/
2015-01-16 18:00:17 +08:00
// clear ALL of BigBuf
2019-03-10 18:20:22 +08:00
void BigBuf_Clear ( void ) {
2019-03-10 03:34:41 +08:00
BigBuf_Clear_ext ( true ) ;
2015-10-17 05:16:46 +08:00
}
2016-03-21 02:33:07 +08:00
2015-10-17 05:16:46 +08:00
// clear ALL of BigBuf
2019-03-10 18:20:22 +08:00
void BigBuf_Clear_ext ( bool verbose ) {
2020-07-10 22:37:56 +08:00
memset ( BigBuf , 0 , s_bigbuf_size ) ;
2020-08-17 15:12:28 +08:00
clear_trace ( ) ;
2019-03-10 03:34:41 +08:00
if ( verbose )
2020-07-10 22:37:56 +08:00
Dbprintf ( " Buffer cleared (%i bytes) " , s_bigbuf_size ) ;
2015-01-16 18:00:17 +08:00
}
2019-03-10 18:20:22 +08:00
void BigBuf_Clear_EM ( void ) {
2019-03-10 03:34:41 +08:00
memset ( BigBuf_get_EM_addr ( ) , 0 , CARD_MEMORY_SIZE ) ;
2017-07-07 18:52:51 +08:00
}
2019-03-10 18:20:22 +08:00
void BigBuf_Clear_keep_EM ( void ) {
2020-07-10 22:37:56 +08:00
memset ( BigBuf , 0 , s_bigbuf_hi ) ;
2016-02-22 00:44:25 +08:00
}
2015-01-16 18:00:17 +08:00
2015-01-27 15:34:48 +08: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 18:20:22 +08:00
uint8_t * BigBuf_malloc ( uint16_t chunksize ) {
2020-07-10 22:37:56 +08:00
if ( s_bigbuf_hi < chunksize )
2019-03-10 03:34:41 +08:00
return NULL ; // no memory left
2018-09-05 02:36:25 +08:00
2019-03-10 03:34:41 +08:00
chunksize = ( chunksize + 3 ) & 0xfffc ; // round to next multiple of 4
2020-07-10 22:37:56 +08:00
s_bigbuf_hi - = chunksize ; // aligned to 4 Byte boundary
return ( uint8_t * ) BigBuf + s_bigbuf_hi ;
2015-01-16 18:00:17 +08:00
}
2020-11-07 08:32:43 +08:00
// allocate a chunk of memory from BigBuf, and returns a pointer to it.
2020-11-03 02:07:03 +08: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 08:32:43 +08:00
return mem ;
2020-11-03 02:07:03 +08:00
}
2015-01-27 15:34:48 +08:00
// free ALL allocated chunks. The whole BigBuf is available for traces or samples again.
2019-03-10 18:20:22 +08:00
void BigBuf_free ( void ) {
2020-07-10 22:37:56 +08:00
s_bigbuf_hi = s_bigbuf_size ;
2019-03-10 03:34:41 +08:00
emulator_memory = NULL ;
// shouldn't this empty BigBuf also?
2020-07-15 21:16:35 +08:00
toSend . buf = NULL ;
dma_16 . buf = NULL ;
dma_8 . buf = NULL ;
2015-01-27 15:34:48 +08:00
}
// free allocated chunks EXCEPT the emulator memory
2019-03-10 18:20:22 +08:00
void BigBuf_free_keep_EM ( void ) {
2019-03-10 03:34:41 +08:00
if ( emulator_memory ! = NULL )
2020-07-10 22:37:56 +08:00
s_bigbuf_hi = emulator_memory - ( uint8_t * ) BigBuf ;
2019-03-10 03:34:41 +08:00
else
2020-07-10 22:37:56 +08:00
s_bigbuf_hi = s_bigbuf_size ;
2020-07-15 21:16:35 +08:00
toSend . buf = NULL ;
dma_16 . buf = NULL ;
dma_8 . buf = NULL ;
2015-01-16 18:00:17 +08:00
}
2019-03-10 18:20:22 +08:00
void BigBuf_print_status ( void ) {
2020-06-12 01:20:59 +08:00
DbpString ( _CYAN_ ( " Memory " ) ) ;
2021-05-11 22:11:33 +08:00
Dbprintf ( " BigBuf_size............. %d " , s_bigbuf_size ) ;
Dbprintf ( " Available memory........ %d " , s_bigbuf_hi ) ;
2020-06-12 01:20:59 +08:00
DbpString ( _CYAN_ ( " Tracing " ) ) ;
2021-05-11 22:11:33 +08:00
Dbprintf ( " tracing ................ %d " , tracing ) ;
Dbprintf ( " traceLen ............... %d " , trace_len ) ;
2020-07-15 21:16:35 +08:00
2021-08-22 05:02:27 +08:00
if ( g_dbglevel > = DBG_DEBUG ) {
2021-05-11 22:11:33 +08: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-23 05:00:52 +08:00
}
2015-01-16 18:00:17 +08:00
// return the maximum trace length (i.e. the unallocated size of BigBuf)
2019-03-10 18:20:22 +08:00
uint16_t BigBuf_max_traceLen ( void ) {
2020-07-10 22:37:56 +08:00
return s_bigbuf_hi ;
2015-01-27 15:34:48 +08:00
}
2015-02-08 03:49:40 +08:00
2019-03-10 18:20:22 +08:00
void clear_trace ( void ) {
2020-07-10 22:37:56 +08:00
trace_len = 0 ;
2015-02-08 03:49:40 +08:00
}
2020-01-02 03:47:39 +08:00
2019-03-10 18:20:22 +08:00
void set_tracelen ( uint32_t value ) {
2020-07-10 22:37:56 +08:00
trace_len = value ;
2017-10-08 20:56:04 +08:00
}
2020-01-02 03:47:39 +08:00
2019-03-10 18:20:22 +08:00
void set_tracing ( bool enable ) {
2019-03-10 03:34:41 +08:00
tracing = enable ;
2015-02-08 03:49:40 +08:00
}
2019-03-10 18:20:22 +08:00
bool get_tracing ( void ) {
2019-03-10 03:34:41 +08:00
return tracing ;
2017-10-24 03:17:59 +08:00
}
2015-02-08 03:49:40 +08:00
/**
* Get the number of bytes traced
* @ return
*/
2019-03-10 18:20:22 +08:00
uint32_t BigBuf_get_traceLen ( void ) {
2020-07-10 22:37:56 +08:00
return trace_len ;
2015-02-08 03:49:40 +08: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 07:53:07 +08:00
by ' hf list - t raw ' , alternatively ' hf list - t < proto > ' for protocol - specific
2015-02-08 03:49:40 +08:00
annotation of commands / responses .
* */
2023-08-09 11:52:21 +08:00
bool RAMFUNC LogTrace ( const uint8_t * btBytes , uint16_t iLen , uint32_t timestamp_start , uint32_t timestamp_end , const uint8_t * parity , bool reader2tag ) {
2020-07-10 01:40:54 +08:00
if ( tracing = = false ) {
return false ;
}
2019-03-10 03:34:41 +08:00
uint8_t * trace = BigBuf_get_addr ( ) ;
2020-07-10 22:37:56 +08:00
tracelog_hdr_t * hdr = ( tracelog_hdr_t * ) ( trace + trace_len ) ;
2019-03-10 03:34:41 +08:00
2019-03-10 07:00:59 +08:00
uint32_t num_paritybytes = ( iLen - 1 ) / 8 + 1 ; // number of valid paritybytes in *parity
2019-03-10 03:34:41 +08:00
// Return when trace is full
2020-07-10 22:37:56 +08:00
if ( TRACELOG_HDR_LEN + iLen + num_paritybytes > = BigBuf_max_traceLen ( ) - trace_len ) {
2020-07-13 18:20:12 +08:00
tracing = false ;
2019-03-10 03:34:41 +08:00
return false ;
}
2020-05-20 02:03:27 +08:00
uint32_t duration ;
if ( timestamp_end > timestamp_start ) {
duration = timestamp_end - timestamp_start ;
} else {
duration = ( UINT32_MAX - timestamp_start ) + timestamp_end ;
2019-03-10 03:34:41 +08:00
}
2020-05-20 02:03:27 +08:00
2020-07-21 16:49:29 +08:00
if ( duration > 0xFFFF ) {
2020-07-14 04:05:11 +08:00
/*
2021-08-22 05:02:27 +08:00
if ( g_dbglevel > = DBG_DEBUG ) {
2020-07-21 16:49:29 +08: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-20 02:03:27 +08:00
}
2020-07-14 04:05:11 +08:00
*/
2020-07-21 16:49:29 +08:00
duration = 0 ;
2020-05-20 02:03:27 +08:00
}
2020-08-13 18:25:04 +08:00
2020-05-19 08:39:39 +08:00
hdr - > timestamp = timestamp_start ;
2020-07-21 16:49:29 +08:00
hdr - > duration = duration & 0xFFFF ;
2020-05-19 08:39:39 +08:00
hdr - > data_len = iLen ;
2022-03-24 00:49:09 +08:00
hdr - > isResponse = ! reader2tag ;
2020-07-10 22:37:56 +08:00
trace_len + = TRACELOG_HDR_LEN ;
2019-03-10 03:34:41 +08:00
// data bytes
if ( btBytes ! = NULL & & iLen ! = 0 ) {
2020-07-13 18:20:12 +08:00
memcpy ( hdr - > frame , btBytes , iLen ) ;
trace_len + = iLen ;
2019-03-10 03:34:41 +08:00
}
// parity bytes
if ( num_paritybytes ! = 0 ) {
if ( parity ! = NULL ) {
2020-07-10 22:37:56 +08:00
memcpy ( trace + trace_len , parity , num_paritybytes ) ;
2019-03-10 03:34:41 +08:00
} else {
2020-07-10 22:37:56 +08:00
memset ( trace + trace_len , 0x00 , num_paritybytes ) ;
2019-03-10 03:34:41 +08:00
}
2020-07-13 18:20:12 +08:00
trace_len + = num_paritybytes ;
2019-03-10 03:34:41 +08:00
}
return true ;
2015-02-08 03:49:40 +08:00
}
2015-03-24 18:45:31 +08:00
2020-07-21 16:49:29 +08:00
// specific LogTrace function for ISO15693: the duration needs to be scaled because otherwise it won't fit into a uint16_t
2023-08-09 11:52:21 +08:00
bool LogTrace_ISO15693 ( const uint8_t * bytes , uint16_t len , uint32_t ts_start , uint32_t ts_end , const uint8_t * parity , bool reader2tag ) {
2020-07-21 16:49:29 +08:00
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-30 06:40:18 +08: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
2022-03-24 00:49:09 +08:00
bool RAMFUNC LogTraceBits ( const uint8_t * btBytes , uint16_t bitLen , uint32_t timestamp_start , uint32_t timestamp_end , bool reader2tag ) {
2021-12-30 06:40:18 +08:00
uint8_t parity [ ( nbytes ( bitLen ) - 1 ) / 8 + 1 ] ;
memset ( parity , 0x00 , sizeof ( parity ) ) ;
2021-12-30 08:03:45 +08:00
parity [ 0 ] = bitLen % 8 ;
2022-03-24 00:49:09 +08:00
return LogTrace ( btBytes , nbytes ( bitLen ) , timestamp_start , timestamp_end , parity , reader2tag ) ;
2021-12-30 06:40:18 +08:00
}
2020-07-21 16:49:29 +08:00
2015-02-15 04:30:26 +08:00
// Emulator memory
2023-08-09 11:52:21 +08:00
uint8_t emlSet ( const uint8_t * data , uint32_t offset , uint32_t length ) {
2019-03-10 07:00:59 +08:00
uint8_t * mem = BigBuf_get_EM_addr ( ) ;
2023-07-28 00:55:41 +08:00
if ( offset + length < = CARD_MEMORY_SIZE ) {
2019-03-10 07:00:59 +08:00
memcpy ( mem + offset , data , length ) ;
2019-03-10 03:34:41 +08:00
return 0 ;
}
2023-07-27 05:33:05 +08:00
Dbprintf ( " Error, trying to set memory outside of bounds! " _RED_ ( " %d " ) " > %d " , ( offset + length ) , CARD_MEMORY_SIZE ) ;
2019-03-10 03:34:41 +08:00
return 1 ;
2015-02-15 04:30:26 +08:00
}
2023-07-28 00:55:41 +08:00
uint8_t emlGet ( uint8_t * out , uint32_t offset , uint32_t length ) {
uint8_t * mem = BigBuf_get_EM_addr ( ) ;
if ( offset + length < = CARD_MEMORY_SIZE ) {
memcpy ( out , mem + offset , length ) ;
return 0 ;
}
Dbprintf ( " Error, trying to read memory outside of bounds! " _RED_ ( " %d " ) " > %d " , ( offset + length ) , CARD_MEMORY_SIZE ) ;
return 1 ;
}
2020-07-13 23:56:19 +08: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 23:46:12 +08:00
if ( toSend . max > = TOSEND_BUFFER_SIZE - 1 ) {
Dbprintf ( _RED_ ( " toSend overflow " ) ) ;
return ;
}
2020-09-30 20:27:19 +08:00
2020-07-13 23:56:19 +08:00
if ( toSend . bit > = 8 ) {
toSend . max + + ;
toSend . buf [ toSend . max ] = 0 ;
toSend . bit = 0 ;
}
if ( b )
2020-09-28 23:46:12 +08:00
toSend . buf [ toSend . max ] | = ( 1 < < ( 7 - toSend . bit ) ) ;
2020-07-13 23:56:19 +08:00
toSend . bit + + ;
if ( toSend . max > = TOSEND_BUFFER_SIZE ) {
toSend . bit = 0 ;
}
}
2020-07-15 21:16:35 +08:00
dmabuf16_t * get_dma16 ( void ) {
if ( dma_16 . buf = = NULL )
2020-08-13 18:25:04 +08:00
dma_16 . buf = ( uint16_t * ) BigBuf_malloc ( DMA_BUFFER_SIZE * sizeof ( uint16_t ) ) ;
2020-07-15 21:16:35 +08: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 ;
}