1 //-----------------------------------------------------------------------------
2 // Jonathan Westhues, Aug 2005
3 // Gerhard de Koning Gans, April 2008, May 2011
5 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
6 // at your option, any later version. See the LICENSE.txt file for the text of
8 //-----------------------------------------------------------------------------
9 // BigBuf and functions to allocate/free parts of it.
10 //-----------------------------------------------------------------------------
17 extern uint32_t _stack_start
[], __bss_end__
[];
19 // BigBuf is the large multi-purpose buffer, typically used to hold A/D samples or traces.
20 // Also used to hold various smaller buffers and the Mifare Emulator Memory.
21 // We know that bss is aligned to 4 bytes.
22 static uint8_t *BigBuf
= (uint8_t *)__bss_end__
;
24 /* BigBuf memory layout:
25 Pointer to highest available memory: s_bigbuf_hi
27 reserved = BigBuf_malloc() subtracts amount from s_bigbuf_hi,
31 static uint32_t s_bigbuf_size
= 0;
34 static uint32_t s_bigbuf_hi
= 0;
36 // pointer to the emulator memory.
37 static uint8_t *emulator_memory
= NULL
;
39 //=============================================================================
41 // A buffer where we can queue things up to be sent through the FPGA, for
42 // any purpose (fake tag, as reader, whatever). We go MSB first, since that
43 // is the order in which they go out on the wire.
44 //=============================================================================
45 static tosend_t toSend
= {
50 //=============================================================================
51 // The dmaBuf 16bit buffer.
52 // A buffer where we recive IQ samples sent from the FPGA, for demodulating
53 //=============================================================================
54 static dmabuf16_t dma_16
= {
55 .size
= DMA_BUFFER_SIZE
,
59 static dmabuf8_t dma_8
= {
60 .size
= DMA_BUFFER_SIZE
,
66 // trace related variables
67 static uint32_t trace_len
= 0;
68 static bool tracing
= true;
70 // compute the available size for BigBuf
71 void BigBuf_initialize(void) {
72 s_bigbuf_size
= (uint32_t)_stack_start
- (uint32_t)__bss_end__
;
73 s_bigbuf_hi
= s_bigbuf_size
;
77 // get the address of BigBuf
78 uint8_t *BigBuf_get_addr(void) {
79 return (uint8_t *)BigBuf
;
82 uint32_t BigBuf_get_size(void) {
86 // get the address of the emulator memory. Allocate part of Bigbuf for it, if not yet done
87 uint8_t *BigBuf_get_EM_addr(void) {
89 if (emulator_memory
== NULL
)
90 emulator_memory
= BigBuf_malloc(CARD_MEMORY_SIZE
);
92 return emulator_memory
;
95 uint32_t BigBuf_get_EM_size(void) {
96 return CARD_MEMORY_SIZE;
100 // clear ALL of BigBuf
101 void BigBuf_Clear(void) {
102 BigBuf_Clear_ext(true);
105 // clear ALL of BigBuf
106 void BigBuf_Clear_ext(bool verbose
) {
107 memset(BigBuf
, 0, s_bigbuf_size
);
110 Dbprintf("Buffer cleared (%i bytes)", s_bigbuf_size
);
113 void BigBuf_Clear_EM(void) {
114 memset(BigBuf_get_EM_addr(), 0, CARD_MEMORY_SIZE
);
117 void BigBuf_Clear_keep_EM(void) {
118 memset(BigBuf
, 0, s_bigbuf_hi
);
121 // allocate a chunk of memory from BigBuf. We allocate high memory first. The unallocated memory
122 // at the beginning of BigBuf is always for traces/samples
123 uint8_t *BigBuf_malloc(uint16_t chunksize
) {
124 if (s_bigbuf_hi
< chunksize
)
125 return NULL
; // no memory left
127 chunksize
= (chunksize
+ 3) & 0xfffc; // round to next multiple of 4
128 s_bigbuf_hi
-= chunksize
; // aligned to 4 Byte boundary
129 return (uint8_t *)BigBuf
+ s_bigbuf_hi
;
132 // allocate a chunk of memory from BigBuf, and returns a pointer to it.
133 // sets the memory to zero
134 uint8_t *BigBuf_calloc(uint16_t chunksize
) {
135 uint8_t *mem
= BigBuf_malloc(chunksize
);
137 memset(mem
, 0x00, chunksize
);
142 // free ALL allocated chunks. The whole BigBuf is available for traces or samples again.
143 void BigBuf_free(void) {
144 s_bigbuf_hi
= s_bigbuf_size
;
145 emulator_memory
= NULL
;
146 // shouldn't this empty BigBuf also?
152 // free allocated chunks EXCEPT the emulator memory
153 void BigBuf_free_keep_EM(void) {
154 if (emulator_memory
!= NULL
)
155 s_bigbuf_hi
= emulator_memory
- (uint8_t *)BigBuf
;
157 s_bigbuf_hi
= s_bigbuf_size
;
164 void BigBuf_print_status(void) {
165 DbpString(_CYAN_("Memory"));
166 Dbprintf(" BigBuf_size............. %d", s_bigbuf_size
);
167 Dbprintf(" Available memory........ %d", s_bigbuf_hi
);
168 DbpString(_CYAN_("Tracing"));
169 Dbprintf(" tracing ................ %d", tracing
);
170 Dbprintf(" traceLen ............... %d", trace_len
);
172 if (DBGLEVEL
>= DBG_DEBUG
) {
173 DbpString(_CYAN_("Sending buffers"));
177 d8
= dma_8
.buf
- BigBuf_get_addr();
181 d16
= (uint8_t *)dma_16
.buf
- BigBuf_get_addr();
185 ts
= toSend
.buf
- BigBuf_get_addr();
187 Dbprintf(" dma8 memory............. %u", d8
);
188 Dbprintf(" dma16 memory............ %u", d16
);
189 Dbprintf(" toSend memory........... %u", ts
);
193 // return the maximum trace length (i.e. the unallocated size of BigBuf)
194 uint16_t BigBuf_max_traceLen(void) {
198 void clear_trace(void) {
202 void set_tracelen(uint32_t value
) {
206 void set_tracing(bool enable
) {
210 bool get_tracing(void) {
215 * Get the number of bytes traced
218 uint32_t BigBuf_get_traceLen(void) {
223 This is a function to store traces. All protocols can use this generic tracer-function.
224 The traces produced by calling this function can be fetched on the client-side
225 by 'hf list -t raw', alternatively 'hf list -t <proto>' for protocol-specific
226 annotation of commands/responses.
228 bool RAMFUNC
LogTrace(const uint8_t *btBytes
, uint16_t iLen
, uint32_t timestamp_start
, uint32_t timestamp_end
, uint8_t *parity
, bool readerToTag
) {
229 if (tracing
== false) {
233 uint8_t *trace
= BigBuf_get_addr();
234 tracelog_hdr_t
*hdr
= (tracelog_hdr_t
*)(trace
+ trace_len
);
236 uint32_t num_paritybytes
= (iLen
- 1) / 8 + 1; // number of valid paritybytes in *parity
238 // Return when trace is full
239 if (TRACELOG_HDR_LEN
+ iLen
+ num_paritybytes
>= BigBuf_max_traceLen() - trace_len
) {
245 if (timestamp_end
> timestamp_start
) {
246 duration
= timestamp_end
- timestamp_start
;
248 duration
= (UINT32_MAX
- timestamp_start
) + timestamp_end
;
251 if (duration
> 0xFFFF) {
253 if (DBGLEVEL >= DBG_DEBUG) {
254 Dbprintf("Error in LogTrace: duration too long for 16 bits encoding: 0x%08x start: 0x%08x end: 0x%08x", duration, timestamp_start, timestamp_end);
260 hdr
->timestamp
= timestamp_start
;
261 hdr
->duration
= duration
& 0xFFFF;
262 hdr
->data_len
= iLen
;
263 hdr
->isResponse
= !readerToTag
;
264 trace_len
+= TRACELOG_HDR_LEN
;
267 if (btBytes
!= NULL
&& iLen
!= 0) {
268 memcpy(hdr
->frame
, btBytes
, iLen
);
273 if (num_paritybytes
!= 0) {
274 if (parity
!= NULL
) {
275 memcpy(trace
+ trace_len
, parity
, num_paritybytes
);
277 memset(trace
+ trace_len
, 0x00, num_paritybytes
);
279 trace_len
+= num_paritybytes
;
284 // specific LogTrace function for ISO15693: the duration needs to be scaled because otherwise it won't fit into a uint16_t
285 bool LogTrace_ISO15693(const uint8_t *bytes
, uint16_t len
, uint32_t ts_start
, uint32_t ts_end
, uint8_t *parity
, bool reader2tag
) {
286 uint32_t duration
= ts_end
- ts_start
;
288 ts_end
= ts_start
+ duration
;
289 return LogTrace(bytes
, len
, ts_start
, ts_end
, parity
, reader2tag
);
294 uint8_t emlSet(uint8_t *data
, uint32_t offset
, uint32_t length
) {
295 uint8_t *mem
= BigBuf_get_EM_addr();
296 if (offset
+ length
< CARD_MEMORY_SIZE
) {
297 memcpy(mem
+ offset
, data
, length
);
300 Dbprintf("Error, trying to set memory outside of bounds! %d > %d", (offset
+ length
), CARD_MEMORY_SIZE
);
306 // get the address of the ToSend buffer. Allocate part of Bigbuf for it, if not yet done
307 tosend_t
*get_tosend(void) {
309 if (toSend
.buf
== NULL
)
310 toSend
.buf
= BigBuf_malloc(TOSEND_BUFFER_SIZE
);
315 void tosend_reset(void) {
320 void tosend_stuffbit(int b
) {
322 if (toSend
.max
>= TOSEND_BUFFER_SIZE
- 1) {
323 Dbprintf(_RED_("toSend overflow"));
327 if (toSend
.bit
>= 8) {
329 toSend
.buf
[toSend
.max
] = 0;
334 toSend
.buf
[toSend
.max
] |= (1 << (7 - toSend
.bit
));
338 if (toSend
.max
>= TOSEND_BUFFER_SIZE
) {
343 dmabuf16_t
*get_dma16(void) {
344 if (dma_16
.buf
== NULL
)
345 dma_16
.buf
= (uint16_t *)BigBuf_malloc(DMA_BUFFER_SIZE
* sizeof(uint16_t));
350 dmabuf8_t
*get_dma8(void) {
351 if (dma_8
.buf
== NULL
)
352 dma_8
.buf
= BigBuf_malloc(DMA_BUFFER_SIZE
);