3cadabdb1ade990ddcad858a67c592b44fb76042
[openocd.git] / src / helper / binarybuffer.c
1 /***************************************************************************
2 * Copyright (C) 2004, 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2007,2008 Øyvind Harboe *
6 * oyvind.harboe@zylin.com *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
22 ***************************************************************************/
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include "log.h"
29 #include "binarybuffer.h"
30
31 static const unsigned char bit_reverse_table256[] = {
32 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
33 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
34 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
35 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
36 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
37 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
38 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
39 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
40 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
41 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
42 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
43 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
44 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
45 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
46 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
47 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
48 };
49
50 void *buf_cpy(const void *from, void *_to, unsigned size)
51 {
52 if (NULL == from || NULL == _to)
53 return NULL;
54
55 /* copy entire buffer */
56 memcpy(_to, from, DIV_ROUND_UP(size, 8));
57
58 /* mask out bits that don't belong to the buffer */
59 unsigned trailing_bits = size % 8;
60 if (trailing_bits) {
61 uint8_t *to = _to;
62 to[size / 8] &= (1 << trailing_bits) - 1;
63 }
64 return _to;
65 }
66
67 static bool buf_cmp_masked(uint8_t a, uint8_t b, uint8_t m)
68 {
69 return (a & m) != (b & m);
70 }
71 static bool buf_cmp_trailing(uint8_t a, uint8_t b, uint8_t m, unsigned trailing)
72 {
73 uint8_t mask = (1 << trailing) - 1;
74 return buf_cmp_masked(a, b, mask & m);
75 }
76
77 bool buf_cmp(const void *_buf1, const void *_buf2, unsigned size)
78 {
79 if (!_buf1 || !_buf2)
80 return _buf1 != _buf2;
81
82 unsigned last = size / 8;
83 if (memcmp(_buf1, _buf2, last) != 0)
84 return false;
85
86 unsigned trailing = size % 8;
87 if (!trailing)
88 return false;
89
90 const uint8_t *buf1 = _buf1, *buf2 = _buf2;
91 return buf_cmp_trailing(buf1[last], buf2[last], 0xff, trailing);
92 }
93
94 bool buf_cmp_mask(const void *_buf1, const void *_buf2,
95 const void *_mask, unsigned size)
96 {
97 if (!_buf1 || !_buf2)
98 return _buf1 != _buf2 || _buf1 != _mask;
99
100 const uint8_t *buf1 = _buf1, *buf2 = _buf2, *mask = _mask;
101 unsigned last = size / 8;
102 for (unsigned i = 0; i < last; i++) {
103 if (buf_cmp_masked(buf1[i], buf2[i], mask[i]))
104 return true;
105 }
106 unsigned trailing = size % 8;
107 if (!trailing)
108 return false;
109 return buf_cmp_trailing(buf1[last], buf2[last], mask[last], trailing);
110 }
111
112
113 void *buf_set_ones(void *_buf, unsigned size)
114 {
115 uint8_t *buf = _buf;
116 if (!buf)
117 return NULL;
118
119 memset(buf, 0xff, size / 8);
120
121 unsigned trailing_bits = size % 8;
122 if (trailing_bits)
123 buf[size / 8] = (1 << trailing_bits) - 1;
124
125 return buf;
126 }
127
128 void *buf_set_buf(const void *_src, unsigned src_start,
129 void *_dst, unsigned dst_start, unsigned len)
130 {
131 const uint8_t *src = _src;
132 uint8_t *dst = _dst;
133 unsigned i, sb, db, sq, dq, lb, lq;
134
135 sb = src_start / 8;
136 db = dst_start / 8;
137 sq = src_start % 8;
138 dq = dst_start % 8;
139 lb = len / 8;
140 lq = len % 8;
141
142 src += sb;
143 dst += db;
144
145 /* check if both buffers are on byte boundary and
146 * len is a multiple of 8bit so we can simple copy
147 * the buffer */
148 if ((sq == 0) && (dq == 0) && (lq == 0)) {
149 for (i = 0; i < lb; i++)
150 *dst++ = *src++;
151 return _dst;
152 }
153
154 /* fallback to slow bit copy */
155 for (i = 0; i < len; i++) {
156 if (((*src >> (sq&7)) & 1) == 1)
157 *dst |= 1 << (dq&7);
158 else
159 *dst &= ~(1 << (dq&7));
160 if (sq++ == 7) {
161 sq = 0;
162 src++;
163 }
164 if (dq++ == 7) {
165 dq = 0;
166 dst++;
167 }
168 }
169
170 return _dst;
171 }
172
173 uint32_t flip_u32(uint32_t value, unsigned int num)
174 {
175 uint32_t c = (bit_reverse_table256[value & 0xff] << 24) |
176 (bit_reverse_table256[(value >> 8) & 0xff] << 16) |
177 (bit_reverse_table256[(value >> 16) & 0xff] << 8) |
178 (bit_reverse_table256[(value >> 24) & 0xff]);
179
180 if (num < 32)
181 c = c >> (32 - num);
182
183 return c;
184 }
185
186 static int ceil_f_to_u32(float x)
187 {
188 if (x < 0) /* return zero for negative numbers */
189 return 0;
190
191 uint32_t y = x; /* cut off fraction */
192
193 if ((x - y) > 0.0) /* if there was a fractional part, increase by one */
194 y++;
195
196 return y;
197 }
198
199 char *buf_to_str(const void *_buf, unsigned buf_len, unsigned radix)
200 {
201 float factor;
202 switch (radix) {
203 case 16:
204 factor = 2.0; /* log(256) / log(16) = 2.0 */
205 break;
206 case 10:
207 factor = 2.40824; /* log(256) / log(10) = 2.40824 */
208 break;
209 case 8:
210 factor = 2.66667; /* log(256) / log(8) = 2.66667 */
211 break;
212 default:
213 return NULL;
214 }
215
216 unsigned str_len = ceil_f_to_u32(DIV_ROUND_UP(buf_len, 8) * factor);
217 char *str = calloc(str_len + 1, 1);
218
219 const uint8_t *buf = _buf;
220 int b256_len = DIV_ROUND_UP(buf_len, 8);
221 for (int i = b256_len - 1; i >= 0; i--) {
222 uint32_t tmp = buf[i];
223 if (((unsigned)i == (buf_len / 8)) && (buf_len % 8))
224 tmp &= (0xff >> (8 - (buf_len % 8)));
225
226 /* base-256 digits */
227 for (unsigned j = str_len; j > 0; j--) {
228 tmp += (uint32_t)str[j-1] * 256;
229 str[j-1] = (uint8_t)(tmp % radix);
230 tmp /= radix;
231 }
232 }
233
234 const char * const DIGITS = "0123456789ABCDEF";
235 for (unsigned j = 0; j < str_len; j++)
236 str[j] = DIGITS[(int)str[j]];
237
238 return str;
239 }
240
241 /** identify radix, and skip radix-prefix (0, 0x or 0X) */
242 static void str_radix_guess(const char **_str, unsigned *_str_len,
243 unsigned *_radix)
244 {
245 unsigned radix = *_radix;
246 if (0 != radix)
247 return;
248 const char *str = *_str;
249 unsigned str_len = *_str_len;
250 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
251 radix = 16;
252 str += 2;
253 str_len -= 2;
254 } else if ((str[0] == '0') && (str_len != 1)) {
255 radix = 8;
256 str += 1;
257 str_len -= 1;
258 } else
259 radix = 10;
260 *_str = str;
261 *_str_len = str_len;
262 *_radix = radix;
263 }
264
265 int str_to_buf(const char *str, unsigned str_len,
266 void *_buf, unsigned buf_len, unsigned radix)
267 {
268 str_radix_guess(&str, &str_len, &radix);
269
270 float factor;
271 if (radix == 16)
272 factor = 0.5; /* log(16) / log(256) = 0.5 */
273 else if (radix == 10)
274 factor = 0.41524; /* log(10) / log(256) = 0.41524 */
275 else if (radix == 8)
276 factor = 0.375; /* log(8) / log(256) = 0.375 */
277 else
278 return 0;
279
280 /* copy to zero-terminated buffer */
281 char *charbuf = strndup(str, str_len);
282
283 /* number of digits in base-256 notation */
284 unsigned b256_len = ceil_f_to_u32(str_len * factor);
285 uint8_t *b256_buf = calloc(b256_len, 1);
286
287 /* go through zero terminated buffer
288 * input digits (ASCII) */
289 unsigned i;
290 for (i = 0; charbuf[i]; i++) {
291 uint32_t tmp = charbuf[i];
292 if ((tmp >= '0') && (tmp <= '9'))
293 tmp = (tmp - '0');
294 else if ((tmp >= 'a') && (tmp <= 'f'))
295 tmp = (tmp - 'a' + 10);
296 else if ((tmp >= 'A') && (tmp <= 'F'))
297 tmp = (tmp - 'A' + 10);
298 else
299 continue; /* skip characters other than [0-9,a-f,A-F] */
300
301 if (tmp >= radix)
302 continue; /* skip digits invalid for the current radix */
303
304 /* base-256 digits */
305 for (unsigned j = 0; j < b256_len; j++) {
306 tmp += (uint32_t)b256_buf[j] * radix;
307 b256_buf[j] = (uint8_t)(tmp & 0xFF);
308 tmp >>= 8;
309 }
310
311 }
312
313 uint8_t *buf = _buf;
314 for (unsigned j = 0; j < DIV_ROUND_UP(buf_len, 8); j++) {
315 if (j < b256_len)
316 buf[j] = b256_buf[j];
317 else
318 buf[j] = 0;
319 }
320
321 /* mask out bits that don't belong to the buffer */
322 if (buf_len % 8)
323 buf[(buf_len / 8)] &= 0xff >> (8 - (buf_len % 8));
324
325 free(b256_buf);
326 free(charbuf);
327
328 return i;
329 }
330
331 void bit_copy_queue_init(struct bit_copy_queue *q)
332 {
333 INIT_LIST_HEAD(&q->list);
334 }
335
336 int bit_copy_queued(struct bit_copy_queue *q, uint8_t *dst, unsigned dst_offset, const uint8_t *src,
337 unsigned src_offset, unsigned bit_count)
338 {
339 struct bit_copy_queue_entry *qe = malloc(sizeof(*qe));
340 if (!qe)
341 return ERROR_FAIL;
342
343 qe->dst = dst;
344 qe->dst_offset = dst_offset;
345 qe->src = src;
346 qe->src_offset = src_offset;
347 qe->bit_count = bit_count;
348 list_add_tail(&qe->list, &q->list);
349
350 return ERROR_OK;
351 }
352
353 void bit_copy_execute(struct bit_copy_queue *q)
354 {
355 struct bit_copy_queue_entry *qe;
356 struct bit_copy_queue_entry *tmp;
357 list_for_each_entry_safe(qe, tmp, &q->list, list) {
358 bit_copy(qe->dst, qe->dst_offset, qe->src, qe->src_offset, qe->bit_count);
359 list_del(&qe->list);
360 free(qe);
361 }
362 }
363
364 void bit_copy_discard(struct bit_copy_queue *q)
365 {
366 struct bit_copy_queue_entry *qe;
367 struct bit_copy_queue_entry *tmp;
368 list_for_each_entry_safe(qe, tmp, &q->list, list) {
369 list_del(&qe->list);
370 free(qe);
371 }
372 }
373
374 int unhexify(char *bin, const char *hex, int count)
375 {
376 int i, tmp;
377
378 for (i = 0; i < count; i++) {
379 if (sscanf(hex + (2 * i), "%02x", &tmp) != 1)
380 return i;
381 bin[i] = tmp;
382 }
383
384 return i;
385 }
386
387 int hexify(char *hex, const char *bin, int count, int out_maxlen)
388 {
389 int i, cmd_len = 0;
390
391 /* May use a length, or a null-terminated string as input. */
392 if (count == 0)
393 count = strlen(bin);
394
395 for (i = 0; i < count; i++)
396 cmd_len += snprintf(hex + cmd_len, out_maxlen - cmd_len, "%02x", bin[i] & 0xff);
397
398 return cmd_len;
399 }
400
401 void buffer_shr(void *_buf, unsigned buf_len, unsigned count)
402 {
403 unsigned i;
404 unsigned char *buf = _buf;
405 unsigned bytes_to_remove;
406 unsigned shift;
407
408 bytes_to_remove = count / 8;
409 shift = count - (bytes_to_remove * 8);
410
411 for (i = 0; i < (buf_len - 1); i++)
412 buf[i] = (buf[i] >> shift) | ((buf[i+1] << (8 - shift)) & 0xff);
413
414 buf[(buf_len - 1)] = buf[(buf_len - 1)] >> shift;
415
416 if (bytes_to_remove) {
417 memmove(buf, &buf[bytes_to_remove], buf_len - bytes_to_remove);
418 memset(&buf[buf_len - bytes_to_remove], 0, bytes_to_remove);
419 }
420 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)