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

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)