]> cvs.zerfleddert.de Git - proxmark3-svn/blob - armsrc/BigBuf.c
Fix for USB uart slowness since PR #720 (#787)
[proxmark3-svn] / armsrc / BigBuf.c
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
12 #include <stdint.h>
13 #include "proxmark3.h"
14 #include "apps.h"
15 #include "string.h"
16 #include "util.h"
17
18 // BigBuf is the large multi-purpose buffer, typically used to hold A/D samples or traces.
19 // Also used to hold various smaller buffers and the Mifare Emulator Memory.
20
21 /* BigBuf memory layout:
22 Pointer to highest available memory: BigBuf_hi
23
24 high BIGBUF_SIZE
25 reserved = BigBuf_malloc() subtracts amount from BigBuf_hi,
26 low 0x00
27 */
28
29 // declare it as uint32_t to achieve alignment to 4 Byte boundary
30 static uint32_t BigBuf[BIGBUF_SIZE/sizeof(uint32_t)];
31
32 // High memory mark
33 static uint16_t BigBuf_hi = BIGBUF_SIZE;
34
35 // pointer to the emulator memory.
36 static uint8_t *emulator_memory = NULL;
37
38 // trace related variables
39 static uint32_t traceLen = 0;
40 static bool tracing = true;
41
42 // get the address of BigBuf
43 uint8_t *BigBuf_get_addr(void)
44 {
45 return (uint8_t *)BigBuf;
46 }
47
48
49 // get the address of the emulator memory. Allocate part of Bigbuf for it, if not yet done
50 uint8_t *BigBuf_get_EM_addr(void)
51 {
52 // not yet allocated
53 if (emulator_memory == NULL) {
54 emulator_memory = BigBuf_malloc(CARD_MEMORY_SIZE);
55 }
56
57 return emulator_memory;
58 }
59
60
61 // clear ALL of BigBuf
62 void BigBuf_Clear(void)
63 {
64 BigBuf_Clear_ext(true);
65 }
66 // clear ALL of BigBuf
67 void BigBuf_Clear_ext(bool verbose)
68 {
69 memset(BigBuf, 0, BIGBUF_SIZE);
70 if (verbose)
71 Dbprintf("Buffer cleared (%i bytes)",BIGBUF_SIZE);
72 }
73 void BigBuf_Clear_EM(void){
74 memset(BigBuf_get_EM_addr(), 0, CARD_MEMORY_SIZE);
75 }
76
77 void BigBuf_Clear_keep_EM(void)
78 {
79 memset(BigBuf, 0, BigBuf_hi);
80 }
81
82 // allocate a chunk of memory from BigBuf. We allocate high memory first. The unallocated memory
83 // at the beginning of BigBuf is always for traces/samples
84 uint8_t *BigBuf_malloc(uint16_t chunksize)
85 {
86 if (BigBuf_hi - chunksize < 0) {
87 return NULL; // no memory left
88 } else {
89 chunksize = (chunksize + 3) & 0xfffc; // round to next multiple of 4
90 BigBuf_hi -= chunksize; // aligned to 4 Byte boundary
91 return (uint8_t *)BigBuf + BigBuf_hi;
92 }
93 }
94
95
96 // free ALL allocated chunks. The whole BigBuf is available for traces or samples again.
97 void BigBuf_free(void)
98 {
99 BigBuf_hi = BIGBUF_SIZE;
100 emulator_memory = NULL;
101 }
102
103
104 // free allocated chunks EXCEPT the emulator memory
105 void BigBuf_free_keep_EM(void)
106 {
107 if (emulator_memory != NULL) {
108 BigBuf_hi = emulator_memory - (uint8_t *)BigBuf;
109 } else {
110 BigBuf_hi = BIGBUF_SIZE;
111 }
112 }
113
114 void BigBuf_print_status(void)
115 {
116 Dbprintf("Memory");
117 Dbprintf(" BIGBUF_SIZE.............%d", BIGBUF_SIZE);
118 Dbprintf(" Available memory........%d", BigBuf_hi);
119 Dbprintf("Tracing");
120 Dbprintf(" tracing ................%d", tracing);
121 Dbprintf(" traceLen ...............%d", traceLen);
122 }
123
124
125 // return the maximum trace length (i.e. the unallocated size of BigBuf)
126 uint16_t BigBuf_max_traceLen(void)
127 {
128 return BigBuf_hi;
129 }
130
131 void clear_trace() {
132 traceLen = 0;
133 }
134
135 void set_tracing(bool enable) {
136 tracing = enable;
137 }
138
139 bool get_tracing(void) {
140 return tracing;
141 }
142
143 /**
144 * Get the number of bytes traced
145 * @return
146 */
147 uint16_t BigBuf_get_traceLen(void)
148 {
149 return traceLen;
150 }
151
152 /**
153 This is a function to store traces. All protocols can use this generic tracer-function.
154 The traces produced by calling this function can be fetched on the client-side
155 by 'hf list raw', alternatively 'hf list <proto>' for protocol-specific
156 annotation of commands/responses.
157
158 **/
159 bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag)
160 {
161 if (!tracing) return false;
162
163 uint8_t *trace = BigBuf_get_addr();
164
165 uint32_t num_paritybytes = (iLen-1)/8 + 1; // number of valid paritybytes in *parity
166 uint32_t duration = timestamp_end - timestamp_start;
167
168 // Return when trace is full
169 uint16_t max_traceLen = BigBuf_max_traceLen();
170
171 if (traceLen + sizeof(iLen) + sizeof(timestamp_start) + sizeof(duration) + num_paritybytes + iLen >= max_traceLen) {
172 tracing = false; // don't trace any more
173 return false;
174 }
175 // Traceformat:
176 // 32 bits timestamp (little endian)
177 // 16 bits duration (little endian)
178 // 16 bits data length (little endian, Highest Bit used as readerToTag flag)
179 // y Bytes data
180 // x Bytes parity (one byte per 8 bytes data)
181
182 // timestamp (start)
183 trace[traceLen++] = ((timestamp_start >> 0) & 0xff);
184 trace[traceLen++] = ((timestamp_start >> 8) & 0xff);
185 trace[traceLen++] = ((timestamp_start >> 16) & 0xff);
186 trace[traceLen++] = ((timestamp_start >> 24) & 0xff);
187
188 // duration
189 trace[traceLen++] = ((duration >> 0) & 0xff);
190 trace[traceLen++] = ((duration >> 8) & 0xff);
191
192 // data length
193 trace[traceLen++] = ((iLen >> 0) & 0xff);
194 trace[traceLen++] = ((iLen >> 8) & 0xff);
195
196 // readerToTag flag
197 if (!readerToTag) {
198 trace[traceLen - 1] |= 0x80;
199 }
200
201 // data bytes
202 if (btBytes != NULL && iLen != 0) {
203 for (int i = 0; i < iLen; i++) {
204 trace[traceLen++] = *btBytes++;
205 }
206 }
207
208 // parity bytes
209 if (num_paritybytes != 0) {
210 if (parity != NULL) {
211 for (int i = 0; i < num_paritybytes; i++) {
212 trace[traceLen++] = *parity++;
213 }
214 } else {
215 for (int i = 0; i < num_paritybytes; i++) {
216 trace[traceLen++] = 0x00;
217 }
218 }
219 }
220
221 return true;
222 }
223
224
225 int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int readerToTag)
226 {
227 /**
228 Todo, rewrite the logger to use the generic functionality instead. It should be noted, however,
229 that this logger takes number of bits as argument, not number of bytes.
230 **/
231
232 if (!tracing) return false;
233
234 uint8_t *trace = BigBuf_get_addr();
235 uint16_t iLen = nbytes(iBits);
236
237 // Return when trace is full
238 if (traceLen + sizeof(rsamples) + sizeof(dwParity) + sizeof(iBits) + iLen > BigBuf_max_traceLen()) {
239 return false;
240 }
241
242 //Hitag traces appear to use this traceformat:
243 // 32 bits timestamp (little endian,Highest Bit used as readerToTag flag)
244 // 32 bits parity
245 // 8 bits size (number of bits in the trace entry, not number of bytes)
246 // y Bytes data
247
248
249
250 rsamples += iSamples;
251 trace[traceLen++] = ((rsamples >> 0) & 0xff);
252 trace[traceLen++] = ((rsamples >> 8) & 0xff);
253 trace[traceLen++] = ((rsamples >> 16) & 0xff);
254 trace[traceLen++] = ((rsamples >> 24) & 0xff);
255
256 if (!readerToTag) {
257 trace[traceLen - 1] |= 0x80;
258 }
259
260 trace[traceLen++] = ((dwParity >> 0) & 0xff);
261 trace[traceLen++] = ((dwParity >> 8) & 0xff);
262 trace[traceLen++] = ((dwParity >> 16) & 0xff);
263 trace[traceLen++] = ((dwParity >> 24) & 0xff);
264 trace[traceLen++] = iBits;
265
266 for (int i = 0; i < iLen; i++) {
267 trace[traceLen++] = *btBytes++;
268 }
269
270 return true;
271 }
272
273
274 // Emulator memory
275 uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length){
276 uint8_t* mem = BigBuf_get_EM_addr();
277 if (offset+length < CARD_MEMORY_SIZE) {
278 memcpy(mem+offset, data, length);
279 return 0;
280 } else {
281 Dbprintf("Error, trying to set memory outside of bounds! %d > %d", (offset+length), CARD_MEMORY_SIZE);
282 return 1;
283 }
284 }
Impressum, Datenschutz