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