]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/BigBuf.c
FIX: 'data print' - now don't crash the client when demodbuffer is empty
[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//-----------------------------------------------------------------------------
b9b480d0 11#include "BigBuf.h"
117d9ec2 12
f71f4deb 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.
f71f4deb 15// declare it as uint32_t to achieve alignment to 4 Byte boundary
16static uint32_t BigBuf[BIGBUF_SIZE/sizeof(uint32_t)];
117d9ec2 17
aaa1a9a2 18/* BigBuf memory layout:
19Pointer 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
117d9ec2 26// High memory mark
27static uint16_t BigBuf_hi = BIGBUF_SIZE;
28
f71f4deb 29// pointer to the emulator memory.
30static uint8_t *emulator_memory = NULL;
31
3000dc4e 32// trace related variables
c0f15a05 33static uint16_t traceLen = 0;
3000dc4e 34int tracing = 1; //Last global one.. todo static?
117d9ec2 35
36// get the address of BigBuf
37uint8_t *BigBuf_get_addr(void)
38{
f71f4deb 39 return (uint8_t *)BigBuf;
40}
41
f71f4deb 42// get the address of the emulator memory. Allocate part of Bigbuf for it, if not yet done
43uint8_t *BigBuf_get_EM_addr(void)
44{
aaa1a9a2 45 // not yet allocated
46 if (emulator_memory == NULL)
f71f4deb 47 emulator_memory = BigBuf_malloc(CARD_MEMORY_SIZE);
f71f4deb 48
49 return emulator_memory;
117d9ec2 50}
51
117d9ec2 52// clear ALL of BigBuf
53void BigBuf_Clear(void)
a739812e 54{
55 BigBuf_Clear_ext(true);
56}
6fc68747 57
a739812e 58// clear ALL of BigBuf
59void BigBuf_Clear_ext(bool verbose)
117d9ec2 60{
aaa1a9a2 61 memset(BigBuf, 0, BIGBUF_SIZE);
a739812e 62 if (verbose)
5bb62283 63 Dbprintf("Buffer cleared (%i bytes)", BIGBUF_SIZE);
117d9ec2 64}
65
c0f15a05 66void BigBuf_Clear_keep_EM(void)
67{
aaa1a9a2 68 memset(BigBuf, 0, BigBuf_hi);
c0f15a05 69}
117d9ec2 70
f71f4deb 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
117d9ec2 73uint8_t *BigBuf_malloc(uint16_t chunksize)
74{
75 if (BigBuf_hi - chunksize < 0) {
f71f4deb 76 return NULL; // no memory left
117d9ec2 77 } else {
f71f4deb 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;
117d9ec2 81 }
82}
83
f71f4deb 84// free ALL allocated chunks. The whole BigBuf is available for traces or samples again.
117d9ec2 85void BigBuf_free(void)
86{
87 BigBuf_hi = BIGBUF_SIZE;
f71f4deb 88 emulator_memory = NULL;
aaa1a9a2 89
90 // shouldn't this empty BigBuf also?
f71f4deb 91}
92
f71f4deb 93// free allocated chunks EXCEPT the emulator memory
94void BigBuf_free_keep_EM(void)
95{
aaa1a9a2 96 if (emulator_memory != NULL)
f71f4deb 97 BigBuf_hi = emulator_memory - (uint8_t *)BigBuf;
aaa1a9a2 98 else
f71f4deb 99 BigBuf_hi = BIGBUF_SIZE;
aaa1a9a2 100
101 // shouldn't this empty BigBuf also?
117d9ec2 102}
103
7838f4be 104void BigBuf_print_status(void)
105{
106 Dbprintf("Memory");
107 Dbprintf(" BIGBUF_SIZE.............%d", BIGBUF_SIZE);
aaa1a9a2 108 Dbprintf(" Available memory........%d", BigBuf_hi);
7838f4be 109 Dbprintf("Tracing");
110 Dbprintf(" tracing ................%d", tracing);
111 Dbprintf(" traceLen ...............%d", traceLen);
112}
113
117d9ec2 114// return the maximum trace length (i.e. the unallocated size of BigBuf)
f71f4deb 115uint16_t BigBuf_max_traceLen(void)
117d9ec2 116{
117 return BigBuf_hi;
f71f4deb 118}
3000dc4e
MHS
119
120void clear_trace() {
3000dc4e
MHS
121 traceLen = 0;
122}
123
124void set_tracing(bool enable) {
125 tracing = enable;
126}
127
128/**
129 * Get the number of bytes traced
130 * @return
131 */
132uint16_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.
3000dc4e
MHS
142**/
143bool 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
aaa1a9a2 153 if (traceLen + sizeof(iLen) + sizeof(timestamp_start) + sizeof(duration) + num_paritybytes + iLen >= BigBuf_max_traceLen()) {
3000dc4e
MHS
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
7f6ccd39 190 if (num_paritybytes != 0) {
7838f4be 191 if (parity != NULL) {
664bb5ae 192 memcpy(trace + traceLen, parity, num_paritybytes);
7838f4be 193 } else {
194 memset(trace + traceLen, 0x00, num_paritybytes);
195 }
3000dc4e
MHS
196 }
197 traceLen += num_paritybytes;
198
3000dc4e
MHS
199 return TRUE;
200}
0ec548dc 201
202
beefe5bc 203int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int readerToTag)
aabb719d 204{
beefe5bc
MHS
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 **/
aabb719d 209
665775c8
MHS
210 if (!tracing) return FALSE;
211
212 uint8_t *trace = BigBuf_get_addr();
213 uint16_t iLen = nbytes(iBits);
aabb719d 214 // Return when trace is full
665775c8
MHS
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
beefe5bc 220 // 8 bits size (number of bits in the trace entry, not number of bytes)
665775c8 221 // y Bytes data
aabb719d 222
aabb719d
MHS
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);
665775c8 228
beefe5bc 229 if (!readerToTag) {
665775c8 230 trace[traceLen - 1] |= 0x80;
aabb719d 231 }
665775c8 232
aabb719d
MHS
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;
665775c8
MHS
238
239 memcpy(trace + traceLen, btBytes, iLen);
240 traceLen += iLen;
241
aabb719d
MHS
242 return TRUE;
243}
7838f4be 244
c0f15a05 245
e80aeb96
MHS
246// Emulator memory
247uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length){
248 uint8_t* mem = BigBuf_get_EM_addr();
6fc68747 249 if(offset+length < CARD_MEMORY_SIZE) {
e80aeb96
MHS
250 memcpy(mem+offset, data, length);
251 return 0;
6fc68747 252 } else {
e80aeb96
MHS
253 Dbprintf("Error, trying to set memory outside of bounds! %d > %d", (offset+length), CARD_MEMORY_SIZE);
254 return 1;
255 }
256}
Impressum, Datenschutz