Merge pull request #63 from marshmellow42/master
[legacy-proxmark3.git] / armsrc / BigBuf.c
blob0c666bce87992229fecaa2dafaeba508efb6035a
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 //-----------------------------------------------------------------------------
12 #include <stdint.h>
13 #include "proxmark3.h"
14 #include "apps.h"
15 #include "string.h"
17 // BigBuf is the large multi-purpose buffer, typically used to hold A/D samples or traces.
18 // Also used to hold various smaller buffers and the Mifare Emulator Memory.
20 // declare it as uint32_t to achieve alignment to 4 Byte boundary
21 static uint32_t BigBuf[BIGBUF_SIZE/sizeof(uint32_t)];
23 // High memory mark
24 static uint16_t BigBuf_hi = BIGBUF_SIZE;
26 // pointer to the emulator memory.
27 static uint8_t *emulator_memory = NULL;
29 // trace related variables
30 static uint16_t traceLen = 0;
31 int tracing = 1; //Last global one.. todo static?
33 // get the address of BigBuf
34 uint8_t *BigBuf_get_addr(void)
36 return (uint8_t *)BigBuf;
40 // get the address of the emulator memory. Allocate part of Bigbuf for it, if not yet done
41 uint8_t *BigBuf_get_EM_addr(void)
43 if (emulator_memory == NULL) { // not yet allocated
44 emulator_memory = BigBuf_malloc(CARD_MEMORY_SIZE);
47 return emulator_memory;
51 // clear ALL of BigBuf
52 void BigBuf_Clear(void)
54 memset(BigBuf,0,BIGBUF_SIZE);
55 Dbprintf("Buffer cleared (%i bytes)",BIGBUF_SIZE);
59 // allocate a chunk of memory from BigBuf. We allocate high memory first. The unallocated memory
60 // at the beginning of BigBuf is always for traces/samples
61 uint8_t *BigBuf_malloc(uint16_t chunksize)
63 if (BigBuf_hi - chunksize < 0) {
64 return NULL; // no memory left
65 } else {
66 chunksize = (chunksize + 3) & 0xfffc; // round to next multiple of 4
67 BigBuf_hi -= chunksize; // aligned to 4 Byte boundary
68 return (uint8_t *)BigBuf + BigBuf_hi;
73 // free ALL allocated chunks. The whole BigBuf is available for traces or samples again.
74 void BigBuf_free(void)
76 BigBuf_hi = BIGBUF_SIZE;
77 emulator_memory = NULL;
81 // free allocated chunks EXCEPT the emulator memory
82 void BigBuf_free_keep_EM(void)
84 if (emulator_memory != NULL) {
85 BigBuf_hi = emulator_memory - (uint8_t *)BigBuf;
86 } else {
87 BigBuf_hi = BIGBUF_SIZE;
92 // return the maximum trace length (i.e. the unallocated size of BigBuf)
93 uint16_t BigBuf_max_traceLen(void)
95 return BigBuf_hi;
98 void clear_trace() {
99 uint8_t *trace = BigBuf_get_addr();
100 uint16_t max_traceLen = BigBuf_max_traceLen();
101 memset(trace, 0x44, max_traceLen);
102 traceLen = 0;
105 void set_tracing(bool enable) {
106 tracing = enable;
110 * Get the number of bytes traced
111 * @return
113 uint16_t BigBuf_get_traceLen(void)
115 return traceLen;
119 This is a function to store traces. All protocols can use this generic tracer-function.
120 The traces produced by calling this function can be fetched on the client-side
121 by 'hf list raw', alternatively 'hf list <proto>' for protocol-specific
122 annotation of commands/responses.
125 bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag)
127 if (!tracing) return FALSE;
129 uint8_t *trace = BigBuf_get_addr();
131 uint16_t num_paritybytes = (iLen-1)/8 + 1; // number of valid paritybytes in *parity
132 uint16_t duration = timestamp_end - timestamp_start;
134 // Return when trace is full
135 uint16_t max_traceLen = BigBuf_max_traceLen();
137 if (traceLen + sizeof(iLen) + sizeof(timestamp_start) + sizeof(duration) + num_paritybytes + iLen >= max_traceLen) {
138 tracing = FALSE; // don't trace any more
139 return FALSE;
141 // Traceformat:
142 // 32 bits timestamp (little endian)
143 // 16 bits duration (little endian)
144 // 16 bits data length (little endian, Highest Bit used as readerToTag flag)
145 // y Bytes data
146 // x Bytes parity (one byte per 8 bytes data)
148 // timestamp (start)
149 trace[traceLen++] = ((timestamp_start >> 0) & 0xff);
150 trace[traceLen++] = ((timestamp_start >> 8) & 0xff);
151 trace[traceLen++] = ((timestamp_start >> 16) & 0xff);
152 trace[traceLen++] = ((timestamp_start >> 24) & 0xff);
154 // duration
155 trace[traceLen++] = ((duration >> 0) & 0xff);
156 trace[traceLen++] = ((duration >> 8) & 0xff);
158 // data length
159 trace[traceLen++] = ((iLen >> 0) & 0xff);
160 trace[traceLen++] = ((iLen >> 8) & 0xff);
162 // readerToTag flag
163 if (!readerToTag) {
164 trace[traceLen - 1] |= 0x80;
167 // data bytes
168 if (btBytes != NULL && iLen != 0) {
169 memcpy(trace + traceLen, btBytes, iLen);
171 traceLen += iLen;
173 // parity bytes
174 if (parity != NULL && iLen != 0) {
175 memcpy(trace + traceLen, parity, num_paritybytes);
177 traceLen += num_paritybytes;
179 if(traceLen +4 < max_traceLen)
180 { //If it hadn't been cleared, for whatever reason..
181 memset(trace+traceLen,0x44, 4);
184 return TRUE;
186 int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int readerToTag)
189 Todo, rewrite the logger to use the generic functionality instead. It should be noted, however,
190 that this logger takes number of bits as argument, not number of bytes.
193 if (!tracing) return FALSE;
195 uint8_t *trace = BigBuf_get_addr();
196 uint16_t iLen = nbytes(iBits);
197 // Return when trace is full
198 if (traceLen + sizeof(rsamples) + sizeof(dwParity) + sizeof(iBits) + iLen > BigBuf_max_traceLen()) return FALSE;
200 //Hitag traces appear to use this traceformat:
201 // 32 bits timestamp (little endian,Highest Bit used as readerToTag flag)
202 // 32 bits parity
203 // 8 bits size (number of bits in the trace entry, not number of bytes)
204 // y Bytes data
206 rsamples += iSamples;
207 trace[traceLen++] = ((rsamples >> 0) & 0xff);
208 trace[traceLen++] = ((rsamples >> 8) & 0xff);
209 trace[traceLen++] = ((rsamples >> 16) & 0xff);
210 trace[traceLen++] = ((rsamples >> 24) & 0xff);
212 if (!readerToTag) {
213 trace[traceLen - 1] |= 0x80;
216 trace[traceLen++] = ((dwParity >> 0) & 0xff);
217 trace[traceLen++] = ((dwParity >> 8) & 0xff);
218 trace[traceLen++] = ((dwParity >> 16) & 0xff);
219 trace[traceLen++] = ((dwParity >> 24) & 0xff);
220 trace[traceLen++] = iBits;
222 memcpy(trace + traceLen, btBytes, iLen);
223 traceLen += iLen;
225 return TRUE;