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