]> cvs.zerfleddert.de Git - proxmark3-svn/blame - armsrc/BigBuf.c
Fix for USB uart slowness since PR #720 (#787)
[proxmark3-svn] / armsrc / BigBuf.c
CommitLineData
117d9ec2 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"
b8e461ff 16#include "util.h"
117d9ec2 17
f71f4deb 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
f4329b17
I
21/* BigBuf memory layout:
22Pointer 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
f71f4deb 29// declare it as uint32_t to achieve alignment to 4 Byte boundary
30static uint32_t BigBuf[BIGBUF_SIZE/sizeof(uint32_t)];
117d9ec2 31
32// High memory mark
33static uint16_t BigBuf_hi = BIGBUF_SIZE;
34
f71f4deb 35// pointer to the emulator memory.
36static uint8_t *emulator_memory = NULL;
37
3000dc4e 38// trace related variables
d9de20fa 39static uint32_t traceLen = 0;
40static bool tracing = true;
117d9ec2 41
42// get the address of BigBuf
43uint8_t *BigBuf_get_addr(void)
44{
f71f4deb 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
50uint8_t *BigBuf_get_EM_addr(void)
51{
f4329b17
I
52 // not yet allocated
53 if (emulator_memory == NULL) {
f71f4deb 54 emulator_memory = BigBuf_malloc(CARD_MEMORY_SIZE);
55 }
56
57 return emulator_memory;
117d9ec2 58}
59
60
61// clear ALL of BigBuf
62void BigBuf_Clear(void)
7cfc777b 63{
64 BigBuf_Clear_ext(true);
65}
66// clear ALL of BigBuf
67void BigBuf_Clear_ext(bool verbose)
117d9ec2 68{
d9de20fa 69 memset(BigBuf, 0, BIGBUF_SIZE);
7cfc777b 70 if (verbose)
71 Dbprintf("Buffer cleared (%i bytes)",BIGBUF_SIZE);
117d9ec2 72}
f4329b17
I
73void BigBuf_Clear_EM(void){
74 memset(BigBuf_get_EM_addr(), 0, CARD_MEMORY_SIZE);
75}
117d9ec2 76
3cec7061 77void BigBuf_Clear_keep_EM(void)
78{
d9de20fa 79 memset(BigBuf, 0, BigBuf_hi);
3cec7061 80}
117d9ec2 81
f71f4deb 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
117d9ec2 84uint8_t *BigBuf_malloc(uint16_t chunksize)
85{
86 if (BigBuf_hi - chunksize < 0) {
f71f4deb 87 return NULL; // no memory left
117d9ec2 88 } else {
f71f4deb 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;
117d9ec2 92 }
93}
94
95
f71f4deb 96// free ALL allocated chunks. The whole BigBuf is available for traces or samples again.
117d9ec2 97void BigBuf_free(void)
98{
99 BigBuf_hi = BIGBUF_SIZE;
f71f4deb 100 emulator_memory = NULL;
101}
102
103
104// free allocated chunks EXCEPT the emulator memory
105void 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 }
117d9ec2 112}
113
e2012d1b
MHS
114void BigBuf_print_status(void)
115{
116 Dbprintf("Memory");
117 Dbprintf(" BIGBUF_SIZE.............%d", BIGBUF_SIZE);
f4329b17 118 Dbprintf(" Available memory........%d", BigBuf_hi);
e2012d1b
MHS
119 Dbprintf("Tracing");
120 Dbprintf(" tracing ................%d", tracing);
121 Dbprintf(" traceLen ...............%d", traceLen);
122}
123
117d9ec2 124
125// return the maximum trace length (i.e. the unallocated size of BigBuf)
f71f4deb 126uint16_t BigBuf_max_traceLen(void)
117d9ec2 127{
128 return BigBuf_hi;
f71f4deb 129}
3000dc4e
MHS
130
131void clear_trace() {
3000dc4e
MHS
132 traceLen = 0;
133}
134
135void set_tracing(bool enable) {
136 tracing = enable;
137}
138
6e49717b 139bool get_tracing(void) {
140 return tracing;
141}
142
3000dc4e
MHS
143/**
144 * Get the number of bytes traced
145 * @return
146 */
147uint16_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**/
159bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag)
160{
f4329b17 161 if (!tracing) return false;
3000dc4e
MHS
162
163 uint8_t *trace = BigBuf_get_addr();
164
d9de20fa 165 uint32_t num_paritybytes = (iLen-1)/8 + 1; // number of valid paritybytes in *parity
166 uint32_t duration = timestamp_end - timestamp_start;
3000dc4e
MHS
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) {
f4329b17
I
172 tracing = false; // don't trace any more
173 return false;
3000dc4e
MHS
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) {
d9de20fa 203 for (int i = 0; i < iLen; i++) {
204 trace[traceLen++] = *btBytes++;
205 }
3000dc4e 206 }
3000dc4e
MHS
207
208 // parity bytes
c4c3af7c 209 if (num_paritybytes != 0) {
48ece4a7 210 if (parity != NULL) {
d9de20fa 211 for (int i = 0; i < num_paritybytes; i++) {
212 trace[traceLen++] = *parity++;
213 }
48ece4a7 214 } else {
d9de20fa 215 for (int i = 0; i < num_paritybytes; i++) {
216 trace[traceLen++] = 0x00;
217 }
48ece4a7 218 }
3000dc4e 219 }
3000dc4e 220
f4329b17 221 return true;
3000dc4e 222}
09ffd16e 223
224
beefe5bc 225int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int readerToTag)
aabb719d 226{
beefe5bc
MHS
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 **/
aabb719d 231
f4329b17 232 if (!tracing) return false;
665775c8
MHS
233
234 uint8_t *trace = BigBuf_get_addr();
235 uint16_t iLen = nbytes(iBits);
7b6e3205 236
aabb719d 237 // Return when trace is full
7b6e3205 238 if (traceLen + sizeof(rsamples) + sizeof(dwParity) + sizeof(iBits) + iLen > BigBuf_max_traceLen()) {
239 return false;
240 }
665775c8
MHS
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
beefe5bc 245 // 8 bits size (number of bits in the trace entry, not number of bytes)
665775c8 246 // y Bytes data
aabb719d 247
7b6e3205 248
249
aabb719d
MHS
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);
665775c8 255
beefe5bc 256 if (!readerToTag) {
665775c8 257 trace[traceLen - 1] |= 0x80;
aabb719d 258 }
665775c8 259
aabb719d
MHS
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;
665775c8 265
d9de20fa 266 for (int i = 0; i < iLen; i++) {
267 trace[traceLen++] = *btBytes++;
268 }
665775c8 269
f4329b17 270 return true;
aabb719d 271}
48ece4a7 272
273
e80aeb96
MHS
274// Emulator memory
275uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length){
276 uint8_t* mem = BigBuf_get_EM_addr();
f4329b17 277 if (offset+length < CARD_MEMORY_SIZE) {
e80aeb96
MHS
278 memcpy(mem+offset, data, length);
279 return 0;
f4329b17 280 } else {
e80aeb96
MHS
281 Dbprintf("Error, trying to set memory outside of bounds! %d > %d", (offset+length), CARD_MEMORY_SIZE);
282 return 1;
283 }
284}
Impressum, Datenschutz