reworked "lf em 4x50 chk" to use dynamic memory for dictionary
[RRG-proxmark3.git] / armsrc / BigBuf.c
blobbf5d961eabb840278ed949e497c36a77c5a2e084
1 //-----------------------------------------------------------------------------
2 // Jonathan Westhues, Aug 2005
3 // Gerhard de Koning Gans, April 2008, May 2011
4 //
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
7 // the license.
8 //-----------------------------------------------------------------------------
9 // BigBuf and functions to allocate/free parts of it.
10 //-----------------------------------------------------------------------------
11 #include "BigBuf.h"
13 #include "string.h"
14 #include "dbprint.h"
15 #include "pm3_cmd.h"
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
26 high s_bigbuf_size
27 reserved = BigBuf_malloc() subtracts amount from s_bigbuf_hi,
28 low 0x00
31 static uint32_t s_bigbuf_size = 0;
33 // High memory mark
34 static uint32_t s_bigbuf_hi = 0;
36 // pointer to the emulator memory.
37 static uint8_t *emulator_memory = NULL;
39 //=============================================================================
40 // The ToSend buffer.
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 = {
46 .max = -1,
47 .bit = 8,
48 .buf = NULL
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,
56 .buf = NULL
58 // dmaBuf 8bit buffer
59 static dmabuf8_t dma_8 = {
60 .size = DMA_BUFFER_SIZE,
61 .buf = NULL
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;
74 trace_len = 0;
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) {
83 return s_bigbuf_size;
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) {
88 // not yet allocated
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);
108 clear_trace();
109 if (verbose)
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);
136 if (mem != NULL) {
137 memset(mem, 0x00, chunksize);
139 return mem;
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?
147 toSend.buf = NULL;
148 dma_16.buf = NULL;
149 dma_8.buf = NULL;
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;
156 else
157 s_bigbuf_hi = s_bigbuf_size;
159 toSend.buf = NULL;
160 dma_16.buf = NULL;
161 dma_8.buf = NULL;
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"));
175 uint16_t d8 = 0;
176 if (dma_8.buf)
177 d8 = dma_8.buf - BigBuf_get_addr();
179 uint16_t d16 = 0;
180 if (dma_16.buf)
181 d16 = (uint8_t *)dma_16.buf - BigBuf_get_addr();
183 uint16_t ts = 0;
184 if (toSend.buf)
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) {
195 return s_bigbuf_hi;
198 void clear_trace(void) {
199 trace_len = 0;
202 void set_tracelen(uint32_t value) {
203 trace_len = value;
206 void set_tracing(bool enable) {
207 tracing = enable;
210 bool get_tracing(void) {
211 return tracing;
215 * Get the number of bytes traced
216 * @return
218 uint32_t BigBuf_get_traceLen(void) {
219 return trace_len;
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) {
230 return 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) {
240 tracing = false;
241 return false;
244 uint32_t duration;
245 if (timestamp_end > timestamp_start) {
246 duration = timestamp_end - timestamp_start;
247 } else {
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);
257 duration = 0;
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;
266 // data bytes
267 if (btBytes != NULL && iLen != 0) {
268 memcpy(hdr->frame, btBytes, iLen);
269 trace_len += iLen;
272 // parity bytes
273 if (num_paritybytes != 0) {
274 if (parity != NULL) {
275 memcpy(trace + trace_len, parity, num_paritybytes);
276 } else {
277 memset(trace + trace_len, 0x00, num_paritybytes);
279 trace_len += num_paritybytes;
281 return true;
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;
287 duration /= 32;
288 ts_end = ts_start + duration;
289 return LogTrace(bytes, len, ts_start, ts_end, parity, reader2tag);
293 // Emulator memory
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);
298 return 0;
300 Dbprintf("Error, trying to set memory outside of bounds! %d > %d", (offset + length), CARD_MEMORY_SIZE);
301 return 1;
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);
312 return &toSend;
315 void tosend_reset(void) {
316 toSend.max = -1;
317 toSend.bit = 8;
320 void tosend_stuffbit(int b) {
322 if (toSend.max >= TOSEND_BUFFER_SIZE - 1) {
323 Dbprintf(_RED_("toSend overflow"));
324 return;
327 if (toSend.bit >= 8) {
328 toSend.max++;
329 toSend.buf[toSend.max] = 0;
330 toSend.bit = 0;
333 if (b)
334 toSend.buf[toSend.max] |= (1 << (7 - toSend.bit));
336 toSend.bit++;
338 if (toSend.max >= TOSEND_BUFFER_SIZE) {
339 toSend.bit = 0;
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));
347 return &dma_16;
350 dmabuf8_t *get_dma8(void) {
351 if (dma_8.buf == NULL)
352 dma_8.buf = BigBuf_malloc(DMA_BUFFER_SIZE);
354 return &dma_8;