]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/BigBuf.c
Merge branch 'master' into fix_iclass_sim
[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
a8561e35 24 high BIGBUF_SIZE
25 reserved = BigBuf_malloc() subtracts amount from BigBuf_hi,
f4329b17
I
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
a8561e35 42
117d9ec2 43// get the address of BigBuf
44uint8_t *BigBuf_get_addr(void)
45{
f71f4deb 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
51uint8_t *BigBuf_get_EM_addr(void)
52{
f4329b17
I
53 // not yet allocated
54 if (emulator_memory == NULL) {
f71f4deb 55 emulator_memory = BigBuf_malloc(CARD_MEMORY_SIZE);
56 }
a8561e35 57
f71f4deb 58 return emulator_memory;
117d9ec2 59}
60
61
62// clear ALL of BigBuf
63void BigBuf_Clear(void)
7cfc777b 64{
65 BigBuf_Clear_ext(true);
66}
a8561e35 67
68
7cfc777b 69// clear ALL of BigBuf
70void BigBuf_Clear_ext(bool verbose)
117d9ec2 71{
d9de20fa 72 memset(BigBuf, 0, BIGBUF_SIZE);
a8561e35 73 if (verbose)
74 Dbprintf("Buffer cleared (%i bytes)", BIGBUF_SIZE);
117d9ec2 75}
a8561e35 76
77
f4329b17
I
78void BigBuf_Clear_EM(void){
79 memset(BigBuf_get_EM_addr(), 0, CARD_MEMORY_SIZE);
80}
117d9ec2 81
a8561e35 82
3cec7061 83void BigBuf_Clear_keep_EM(void)
84{
d9de20fa 85 memset(BigBuf, 0, BigBuf_hi);
3cec7061 86}
117d9ec2 87
f71f4deb 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
117d9ec2 90uint8_t *BigBuf_malloc(uint16_t chunksize)
91{
a8561e35 92 if (BigBuf_hi - chunksize < 0) {
93 return NULL; // no memory left
117d9ec2 94 } else {
a8561e35 95 chunksize = (chunksize + 3) & 0xfffc; // round to next multiple of 4
96 BigBuf_hi -= chunksize; // aligned to 4 Byte boundary
f71f4deb 97 return (uint8_t *)BigBuf + BigBuf_hi;
117d9ec2 98 }
99}
100
101
f71f4deb 102// free ALL allocated chunks. The whole BigBuf is available for traces or samples again.
117d9ec2 103void BigBuf_free(void)
104{
105 BigBuf_hi = BIGBUF_SIZE;
f71f4deb 106 emulator_memory = NULL;
107}
108
109
110// free allocated chunks EXCEPT the emulator memory
111void 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 }
117d9ec2 118}
119
e2012d1b
MHS
120void BigBuf_print_status(void)
121{
122 Dbprintf("Memory");
123 Dbprintf(" BIGBUF_SIZE.............%d", BIGBUF_SIZE);
f4329b17 124 Dbprintf(" Available memory........%d", BigBuf_hi);
e2012d1b
MHS
125 Dbprintf("Tracing");
126 Dbprintf(" tracing ................%d", tracing);
127 Dbprintf(" traceLen ...............%d", traceLen);
128}
129
117d9ec2 130
131// return the maximum trace length (i.e. the unallocated size of BigBuf)
f71f4deb 132uint16_t BigBuf_max_traceLen(void)
117d9ec2 133{
134 return BigBuf_hi;
f71f4deb 135}
3000dc4e 136
a8561e35 137
3000dc4e 138void clear_trace() {
3000dc4e
MHS
139 traceLen = 0;
140}
141
a8561e35 142
3000dc4e
MHS
143void set_tracing(bool enable) {
144 tracing = enable;
145}
146
a8561e35 147
6e49717b 148bool get_tracing(void) {
149 return tracing;
150}
151
a8561e35 152
3000dc4e
MHS
153/**
154 * Get the number of bytes traced
155 * @return
156 */
157uint16_t BigBuf_get_traceLen(void)
158{
159 return traceLen;
160}
161
a8561e35 162
3000dc4e
MHS
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**/
170bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag)
171{
f4329b17 172 if (!tracing) return false;
3000dc4e
MHS
173
174 uint8_t *trace = BigBuf_get_addr();
175
a8561e35 176 uint32_t num_paritybytes = (iLen-1)/8 + 1; // number of valid paritybytes in *parity
d9de20fa 177 uint32_t duration = timestamp_end - timestamp_start;
3000dc4e
MHS
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) {
a8561e35 183 tracing = false; // don't trace any more
f4329b17 184 return false;
3000dc4e
MHS
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) {
d9de20fa 214 for (int i = 0; i < iLen; i++) {
215 trace[traceLen++] = *btBytes++;
216 }
3000dc4e 217 }
3000dc4e
MHS
218
219 // parity bytes
c4c3af7c 220 if (num_paritybytes != 0) {
48ece4a7 221 if (parity != NULL) {
d9de20fa 222 for (int i = 0; i < num_paritybytes; i++) {
223 trace[traceLen++] = *parity++;
224 }
48ece4a7 225 } else {
d9de20fa 226 for (int i = 0; i < num_paritybytes; i++) {
227 trace[traceLen++] = 0x00;
228 }
48ece4a7 229 }
3000dc4e 230 }
3000dc4e 231
f4329b17 232 return true;
3000dc4e 233}
09ffd16e 234
235
beefe5bc 236int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int readerToTag)
aabb719d 237{
beefe5bc
MHS
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 **/
aabb719d 242
f4329b17 243 if (!tracing) return false;
665775c8
MHS
244
245 uint8_t *trace = BigBuf_get_addr();
246 uint16_t iLen = nbytes(iBits);
7b6e3205 247
aabb719d 248 // Return when trace is full
7b6e3205 249 if (traceLen + sizeof(rsamples) + sizeof(dwParity) + sizeof(iBits) + iLen > BigBuf_max_traceLen()) {
250 return false;
a8561e35 251 }
665775c8
MHS
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
beefe5bc 256 // 8 bits size (number of bits in the trace entry, not number of bytes)
665775c8 257 // y Bytes data
aabb719d 258
7b6e3205 259
260
aabb719d
MHS
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);
665775c8 266
beefe5bc 267 if (!readerToTag) {
665775c8 268 trace[traceLen - 1] |= 0x80;
aabb719d 269 }
665775c8 270
aabb719d
MHS
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;
665775c8 276
d9de20fa 277 for (int i = 0; i < iLen; i++) {
278 trace[traceLen++] = *btBytes++;
279 }
665775c8 280
f4329b17 281 return true;
aabb719d 282}
48ece4a7 283
284
e80aeb96
MHS
285// Emulator memory
286uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length){
287 uint8_t* mem = BigBuf_get_EM_addr();
f4329b17 288 if (offset+length < CARD_MEMORY_SIZE) {
e80aeb96
MHS
289 memcpy(mem+offset, data, length);
290 return 0;
f4329b17 291 } else {
e80aeb96
MHS
292 Dbprintf("Error, trying to set memory outside of bounds! %d > %d", (offset+length), CARD_MEMORY_SIZE);
293 return 1;
294 }
295}
Impressum, Datenschutz