Remove FSF address from GPL notices
[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 void *buf_cpy(const void *from, void *_to, unsigned size)
49 {
50 if (NULL == from || NULL == _to)
51 return NULL;
52
53 /* copy entire buffer */
54 memcpy(_to, from, DIV_ROUND_UP(size, 8));
55
56 /* mask out bits that don't belong to the buffer */
57 unsigned trailing_bits = size % 8;
58 if (trailing_bits) {
59 uint8_t *to = _to;
60 to[size / 8] &= (1 << trailing_bits) - 1;
61 }
62 return _to;
63 }
64
65 static bool buf_cmp_masked(uint8_t a, uint8_t b, uint8_t m)
66 {
67 return (a & m) != (b & m);
68 }
69 static bool buf_cmp_trailing(uint8_t a, uint8_t b, uint8_t m, unsigned trailing)
70 {
71 uint8_t mask = (1 << trailing) - 1;
72 return buf_cmp_masked(a, b, mask & m);
73 }
74
75 bool buf_cmp(const void *_buf1, const void *_buf2, unsigned size)
76 {
77 if (!_buf1 || !_buf2)
78 return _buf1 != _buf2;
79
80 unsigned last = size / 8;
81 if (memcmp(_buf1, _buf2, last) != 0)
82 return false;
83
84 unsigned trailing = size % 8;
85 if (!trailing)
86 return false;
87
88 const uint8_t *buf1 = _buf1, *buf2 = _buf2;
89 return buf_cmp_trailing(buf1[last], buf2[last], 0xff, trailing);
90 }
91
92 bool buf_cmp_mask(const void *_buf1, const void *_buf2,
93 const void *_mask, unsigned size)
94 {
95 if (!_buf1 || !_buf2)
96 return _buf1 != _buf2 || _buf1 != _mask;
97
98 const uint8_t *buf1 = _buf1, *buf2 = _buf2, *mask = _mask;
99 unsigned last = size / 8;
100 for (unsigned i = 0; i < last; i++) {
101 if (buf_cmp_masked(buf1[i], buf2[i], mask[i]))
102 return true;
103 }
104 unsigned trailing = size % 8;
105 if (!trailing)
106 return false;
107 return buf_cmp_trailing(buf1[last], buf2[last], mask[last], trailing);
108 }
109
110
111 void *buf_set_ones(void *_buf, unsigned size)
112 {
113 uint8_t *buf = _buf;
114 if (!buf)
115 return NULL;
116
117 memset(buf, 0xff, size / 8);
118
119 unsigned trailing_bits = size % 8;
120 if (trailing_bits)
121 buf[size / 8] = (1 << trailing_bits) - 1;
122
123 return buf;
124 }
125
126 void *buf_set_buf(const void *_src, unsigned src_start,
127 void *_dst, unsigned dst_start, unsigned len)
128 {
129 const uint8_t *src = _src;
130 uint8_t *dst = _dst;
131 unsigned i, sb, db, sq, dq, lb, lq;
132
133 sb = src_start / 8;
134 db = dst_start / 8;
135 sq = src_start % 8;
136 dq = dst_start % 8;
137 lb = len / 8;
138 lq = len % 8;
139
140 src += sb;
141 dst += db;
142
143 /* check if both buffers are on byte boundary and
144 * len is a multiple of 8bit so we can simple copy
145 * the buffer */
146 if ((sq == 0) && (dq == 0) && (lq == 0)) {
147 for (i = 0; i < lb; i++)
148 *dst++ = *src++;
149 return _dst;
150 }
151
152 /* fallback to slow bit copy */
153 for (i = 0; i < len; i++) {
154 if (((*src >> (sq&7)) & 1) == 1)
155 *dst |= 1 << (dq&7);
156 else
157 *dst &= ~(1 << (dq&7));
158 if (sq++ == 7) {
159 sq = 0;
160 src++;
161 }
162 if (dq++ == 7) {
163 dq = 0;
164 dst++;
165 }
166 }
167
168 return _dst;
169 }
170
171 uint32_t flip_u32(uint32_t value, unsigned int num)
172 {
173 uint32_t c = (bit_reverse_table256[value & 0xff] << 24) |
174 (bit_reverse_table256[(value >> 8) & 0xff] << 16) |
175 (bit_reverse_table256[(value >> 16) & 0xff] << 8) |
176 (bit_reverse_table256[(value >> 24) & 0xff]);
177
178 if (num < 32)
179 c = c >> (32 - num);
180
181 return c;
182 }
183
184 static int ceil_f_to_u32(float x)
185 {
186 if (x < 0) /* return zero for negative numbers */
187 return 0;
188
189 uint32_t y = x; /* cut off fraction */
190
191 if ((x - y) > 0.0) /* if there was a fractional part, increase by one */
192 y++;
193
194 return y;
195 }
196
197 char *buf_to_str(const void *_buf, unsigned buf_len, unsigned radix)
198 {
199 float factor;
200 switch (radix) {
201 case 16:
202 factor = 2.0; /* log(256) / log(16) = 2.0 */
203 break;
204 case 10:
205 factor = 2.40824; /* log(256) / log(10) = 2.40824 */
206 break;
207 case 8:
208 factor = 2.66667; /* log(256) / log(8) = 2.66667 */
209 break;
210 default:
211 return NULL;
212 }
213
214 unsigned str_len = ceil_f_to_u32(DIV_ROUND_UP(buf_len, 8) * factor);
215 char *str = calloc(str_len + 1, 1);
216
217 const uint8_t *buf = _buf;
218 int b256_len = DIV_ROUND_UP(buf_len, 8);
219 for (int i = b256_len - 1; i >= 0; i--) {
220 uint32_t tmp = buf[i];
221 if (((unsigned)i == (buf_len / 8)) && (buf_len % 8))
222 tmp &= (0xff >> (8 - (buf_len % 8)));
223
224 /* base-256 digits */
225 for (unsigned j = str_len; j > 0; j--) {
226 tmp += (uint32_t)str[j-1] * 256;
227 str[j-1] = (uint8_t)(tmp % radix);
228 tmp /= radix;
229 }
230 }
231
232 const char * const DIGITS = "0123456789ABCDEF";
233 for (unsigned j = 0; j < str_len; j++)
234 str[j] = DIGITS[(int)str[j]];
235
236 return str;
237 }
238
239 /** identify radix, and skip radix-prefix (0, 0x or 0X) */
240 static void str_radix_guess(const char **_str, unsigned *_str_len,
241 unsigned *_radix)
242 {
243 unsigned radix = *_radix;
244 if (0 != radix)
245 return;
246 const char *str = *_str;
247 unsigned str_len = *_str_len;
248 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
249 radix = 16;
250 str += 2;
251 str_len -= 2;
252 } else if ((str[0] == '0') && (str_len != 1)) {
253 radix = 8;
254 str += 1;
255 str_len -= 1;
256 } else
257 radix = 10;
258 *_str = str;
259 *_str_len = str_len;
260 *_radix = radix;
261 }
262
263 int str_to_buf(const char *str, unsigned str_len,
264 void *_buf, unsigned buf_len, unsigned radix)
265 {
266 str_radix_guess(&str, &str_len, &radix);
267
268 float factor;
269 if (radix == 16)
270 factor = 0.5; /* log(16) / log(256) = 0.5 */
271 else if (radix == 10)
272 factor = 0.41524; /* log(10) / log(256) = 0.41524 */
273 else if (radix == 8)
274 factor = 0.375; /* log(8) / log(256) = 0.375 */
275 else
276 return 0;
277
278 /* copy to zero-terminated buffer */
279 char *charbuf = strndup(str, str_len);
280
281 /* number of digits in base-256 notation */
282 unsigned b256_len = ceil_f_to_u32(str_len * factor);
283 uint8_t *b256_buf = calloc(b256_len, 1);
284
285 /* go through zero terminated buffer
286 * input digits (ASCII) */
287 unsigned i;
288 for (i = 0; charbuf[i]; i++) {
289 uint32_t tmp = charbuf[i];
290 if ((tmp >= '0') && (tmp <= '9'))
291 tmp = (tmp - '0');
292 else if ((tmp >= 'a') && (tmp <= 'f'))
293 tmp = (tmp - 'a' + 10);
294 else if ((tmp >= 'A') && (tmp <= 'F'))
295 tmp = (tmp - 'A' + 10);
296 else
297 continue; /* skip characters other than [0-9,a-f,A-F] */
298
299 if (tmp >= radix)
300 continue; /* skip digits invalid for the current radix */
301
302 /* base-256 digits */
303 for (unsigned j = 0; j < b256_len; j++) {
304 tmp += (uint32_t)b256_buf[j] * radix;
305 b256_buf[j] = (uint8_t)(tmp & 0xFF);
306 tmp >>= 8;
307 }
308
309 }
310
311 uint8_t *buf = _buf;
312 for (unsigned j = 0; j < DIV_ROUND_UP(buf_len, 8); j++) {
313 if (j < b256_len)
314 buf[j] = b256_buf[j];
315 else
316 buf[j] = 0;
317 }
318
319 /* mask out bits that don't belong to the buffer */
320 if (buf_len % 8)
321 buf[(buf_len / 8)] &= 0xff >> (8 - (buf_len % 8));
322
323 free(b256_buf);
324 free(charbuf);
325
326 return i;
327 }
328
329 void bit_copy_queue_init(struct bit_copy_queue *q)
330 {
331 INIT_LIST_HEAD(&q->list);
332 }
333
334 int bit_copy_queued(struct bit_copy_queue *q, uint8_t *dst, unsigned dst_offset, const uint8_t *src,
335 unsigned src_offset, unsigned bit_count)
336 {
337 struct bit_copy_queue_entry *qe = malloc(sizeof(*qe));
338 if (!qe)
339 return ERROR_FAIL;
340
341 qe->dst = dst;
342 qe->dst_offset = dst_offset;
343 qe->src = src;
344 qe->src_offset = src_offset;
345 qe->bit_count = bit_count;
346 list_add_tail(&qe->list, &q->list);
347
348 return ERROR_OK;
349 }
350
351 void bit_copy_execute(struct bit_copy_queue *q)
352 {
353 struct bit_copy_queue_entry *qe;
354 struct bit_copy_queue_entry *tmp;
355 list_for_each_entry_safe(qe, tmp, &q->list, list) {
356 bit_copy(qe->dst, qe->dst_offset, qe->src, qe->src_offset, qe->bit_count);
357 list_del(&qe->list);
358 free(qe);
359 }
360 }
361
362 void bit_copy_discard(struct bit_copy_queue *q)
363 {
364 struct bit_copy_queue_entry *qe;
365 struct bit_copy_queue_entry *tmp;
366 list_for_each_entry_safe(qe, tmp, &q->list, list) {
367 list_del(&qe->list);
368 free(qe);
369 }
370 }
371
372 int unhexify(char *bin, const char *hex, int count)
373 {
374 int i, tmp;
375
376 for (i = 0; i < count; i++) {
377 if (sscanf(hex + (2 * i), "%02x", &tmp) != 1)
378 return i;
379 bin[i] = tmp;
380 }
381
382 return i;
383 }
384
385 int hexify(char *hex, const char *bin, int count, int out_maxlen)
386 {
387 int i, cmd_len = 0;
388
389 /* May use a length, or a null-terminated string as input. */
390 if (count == 0)
391 count = strlen(bin);
392
393 for (i = 0; i < count; i++)
394 cmd_len += snprintf(hex + cmd_len, out_maxlen - cmd_len, "%02x", bin[i] & 0xff);
395
396 return cmd_len;
397 }
398
399 void buffer_shr(void *_buf, unsigned buf_len, unsigned count)
400 {
401 unsigned i;
402 unsigned char *buf = _buf;
403 unsigned bytes_to_remove;
404 unsigned shift;
405
406 bytes_to_remove = count / 8;
407 shift = count - (bytes_to_remove * 8);
408
409 for (i = 0; i < (buf_len - 1); i++)
410 buf[i] = (buf[i] >> shift) | ((buf[i+1] << (8 - shift)) & 0xff);
411
412 buf[(buf_len - 1)] = buf[(buf_len - 1)] >> shift;
413
414 if (bytes_to_remove) {
415 memmove(buf, &buf[bytes_to_remove], buf_len - bytes_to_remove);
416 memset(&buf[buf_len - bytes_to_remove], 0, bytes_to_remove);
417 }
418 }

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)