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