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

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)