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