aboutsummaryrefslogtreecommitdiff
path: root/src/helper
diff options
context:
space:
mode:
Diffstat (limited to 'src/helper')
-rw-r--r--src/helper/binarybuffer.c194
-rw-r--r--src/helper/binarybuffer.h24
-rw-r--r--src/helper/command.c21
-rw-r--r--src/helper/command.h9
-rw-r--r--src/helper/jep106.inc37
-rw-r--r--src/helper/startup.tcl4
6 files changed, 174 insertions, 115 deletions
diff --git a/src/helper/binarybuffer.c b/src/helper/binarybuffer.c
index 5f38b43..a7ca5af 100644
--- a/src/helper/binarybuffer.c
+++ b/src/helper/binarybuffer.c
@@ -57,20 +57,20 @@ void *buf_cpy(const void *from, void *_to, unsigned size)
return _to;
}
-static bool buf_cmp_masked(uint8_t a, uint8_t b, uint8_t m)
+static bool buf_eq_masked(uint8_t a, uint8_t b, uint8_t m)
{
- return (a & m) != (b & m);
+ return (a & m) == (b & m);
}
-static bool buf_cmp_trailing(uint8_t a, uint8_t b, uint8_t m, unsigned trailing)
+static bool buf_eq_trailing(uint8_t a, uint8_t b, uint8_t m, unsigned trailing)
{
uint8_t mask = (1 << trailing) - 1;
- return buf_cmp_masked(a, b, mask & m);
+ return buf_eq_masked(a, b, mask & m);
}
-bool buf_cmp(const void *_buf1, const void *_buf2, unsigned size)
+bool buf_eq(const void *_buf1, const void *_buf2, unsigned size)
{
if (!_buf1 || !_buf2)
- return _buf1 != _buf2;
+ return _buf1 == _buf2;
unsigned last = size / 8;
if (memcmp(_buf1, _buf2, last) != 0)
@@ -78,31 +78,30 @@ bool buf_cmp(const void *_buf1, const void *_buf2, unsigned size)
unsigned trailing = size % 8;
if (!trailing)
- return false;
+ return true;
const uint8_t *buf1 = _buf1, *buf2 = _buf2;
- return buf_cmp_trailing(buf1[last], buf2[last], 0xff, trailing);
+ return buf_eq_trailing(buf1[last], buf2[last], 0xff, trailing);
}
-bool buf_cmp_mask(const void *_buf1, const void *_buf2,
+bool buf_eq_mask(const void *_buf1, const void *_buf2,
const void *_mask, unsigned size)
{
if (!_buf1 || !_buf2)
- return _buf1 != _buf2 || _buf1 != _mask;
+ return _buf1 == _buf2 && _buf1 == _mask;
const uint8_t *buf1 = _buf1, *buf2 = _buf2, *mask = _mask;
unsigned last = size / 8;
for (unsigned i = 0; i < last; i++) {
- if (buf_cmp_masked(buf1[i], buf2[i], mask[i]))
- return true;
+ if (!buf_eq_masked(buf1[i], buf2[i], mask[i]))
+ return false;
}
unsigned trailing = size % 8;
if (!trailing)
- return false;
- return buf_cmp_trailing(buf1[last], buf2[last], mask[last], trailing);
+ return true;
+ return buf_eq_trailing(buf1[last], buf2[last], mask[last], trailing);
}
-
void *buf_set_ones(void *_buf, unsigned size)
{
uint8_t *buf = _buf;
@@ -176,19 +175,6 @@ uint32_t flip_u32(uint32_t value, unsigned int num)
return c;
}
-static int ceil_f_to_u32(float x)
-{
- if (x < 0) /* return zero for negative numbers */
- return 0;
-
- uint32_t y = x; /* cut off fraction */
-
- if ((x - y) > 0.0) /* if there was a fractional part, increase by one */
- y++;
-
- return y;
-}
-
char *buf_to_hex_str(const void *_buf, unsigned buf_len)
{
unsigned len_bytes = DIV_ROUND_UP(buf_len, 8);
@@ -206,94 +192,96 @@ char *buf_to_hex_str(const void *_buf, unsigned buf_len)
return str;
}
-/** identify radix, and skip radix-prefix (0, 0x or 0X) */
-static void str_radix_guess(const char **_str, unsigned *_str_len,
- unsigned *_radix)
-{
- unsigned radix = *_radix;
- if (radix != 0)
- return;
- const char *str = *_str;
- unsigned str_len = *_str_len;
- if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
- radix = 16;
- str += 2;
- str_len -= 2;
- } else if ((str[0] == '0') && (str_len != 1)) {
- radix = 8;
- str += 1;
- str_len -= 1;
- } else
- radix = 10;
- *_str = str;
- *_str_len = str_len;
- *_radix = radix;
-}
-
-int str_to_buf(const char *str, unsigned str_len,
- void *_buf, unsigned buf_len, unsigned radix)
+/*
+ * TCL standard prefix is '0b', '0o', '0d' or '0x' respectively for binary,
+ * octal, decimal or hexadecimal.
+ * The prefix '0' is interpreted by TCL <= 8.6 as octal, but is ignored and
+ * interpreted as part of a decimal number by JimTCL and by TCL >= 9.
+ */
+int str_to_buf(const char *str, void *_buf, unsigned int buf_bitsize)
{
- str_radix_guess(&str, &str_len, &radix);
-
- float factor;
- if (radix == 16)
- factor = 0.5; /* log(16) / log(256) = 0.5 */
- else if (radix == 10)
- factor = 0.41524; /* log(10) / log(256) = 0.41524 */
- else if (radix == 8)
- factor = 0.375; /* log(8) / log(256) = 0.375 */
- else
- return 0;
+ assert(str);
+ assert(_buf);
+ assert(buf_bitsize > 0);
- /* copy to zero-terminated buffer */
- char *charbuf = strndup(str, str_len);
-
- /* number of digits in base-256 notation */
- unsigned b256_len = ceil_f_to_u32(str_len * factor);
- uint8_t *b256_buf = calloc(b256_len, 1);
+ uint8_t *buf = _buf;
+ unsigned int radix = 10; /* default when no prefix */
+
+ if (str[0] == '0') {
+ switch (str[1]) {
+ case 'b':
+ case 'B':
+ radix = 2;
+ str += 2;
+ break;
+ case 'o':
+ case 'O':
+ radix = 8;
+ str += 2;
+ break;
+ case 'd':
+ case 'D':
+ radix = 10;
+ str += 2;
+ break;
+ case 'x':
+ case 'X':
+ radix = 16;
+ str += 2;
+ break;
+ default:
+ break;
+ }
+ }
- /* go through zero terminated buffer
- * input digits (ASCII) */
- unsigned i;
- for (i = 0; charbuf[i]; i++) {
- uint32_t tmp = charbuf[i];
- if ((tmp >= '0') && (tmp <= '9'))
- tmp = (tmp - '0');
- else if ((tmp >= 'a') && (tmp <= 'f'))
- tmp = (tmp - 'a' + 10);
- else if ((tmp >= 'A') && (tmp <= 'F'))
- tmp = (tmp - 'A' + 10);
- else
- continue; /* skip characters other than [0-9,a-f,A-F] */
+ const size_t str_len = strlen(str);
+ if (str_len == 0)
+ return ERROR_INVALID_NUMBER;
+
+ const size_t buf_len = DIV_ROUND_UP(buf_bitsize, 8);
+ memset(buf, 0, buf_len);
+
+ /* Go through the zero-terminated buffer
+ * of input digits (ASCII) */
+ for (; *str; str++) {
+ unsigned int tmp;
+ const char c = *str;
+
+ if ((c >= '0') && (c <= '9')) {
+ tmp = c - '0';
+ } else if ((c >= 'a') && (c <= 'f')) {
+ tmp = c - 'a' + 10;
+ } else if ((c >= 'A') && (c <= 'F')) {
+ tmp = c - 'A' + 10;
+ } else {
+ /* Characters other than [0-9,a-f,A-F] are invalid */
+ return ERROR_INVALID_NUMBER;
+ }
+ /* Error on invalid digit for current radix */
if (tmp >= radix)
- continue; /* skip digits invalid for the current radix */
+ return ERROR_INVALID_NUMBER;
- /* base-256 digits */
- for (unsigned j = 0; j < b256_len; j++) {
- tmp += (uint32_t)b256_buf[j] * radix;
- b256_buf[j] = (uint8_t)(tmp & 0xFF);
+ /* Add the current digit (tmp) to the intermediate result in buf */
+ for (unsigned int j = 0; j < buf_len; j++) {
+ tmp += buf[j] * radix;
+ buf[j] = tmp & 0xFFu;
tmp >>= 8;
}
+ /* buf should be large enough to contain the whole result. */
+ if (tmp != 0)
+ return ERROR_NUMBER_EXCEEDS_BUFFER;
}
- uint8_t *buf = _buf;
- for (unsigned j = 0; j < DIV_ROUND_UP(buf_len, 8); j++) {
- if (j < b256_len)
- buf[j] = b256_buf[j];
- else
- buf[j] = 0;
+ /* Check the partial most significant byte */
+ if (buf_bitsize % 8) {
+ const uint8_t mask = 0xFFu << (buf_bitsize % 8);
+ if ((buf[buf_len - 1] & mask) != 0x0)
+ return ERROR_NUMBER_EXCEEDS_BUFFER;
}
- /* mask out bits that don't belong to the buffer */
- if (buf_len % 8)
- buf[(buf_len / 8)] &= 0xff >> (8 - (buf_len % 8));
-
- free(b256_buf);
- free(charbuf);
-
- return i;
+ return ERROR_OK;
}
void bit_copy_queue_init(struct bit_copy_queue *q)
diff --git a/src/helper/binarybuffer.h b/src/helper/binarybuffer.h
index 3446296..ed13b98 100644
--- a/src/helper/binarybuffer.h
+++ b/src/helper/binarybuffer.h
@@ -14,6 +14,9 @@
#include <helper/list.h>
#include <helper/types.h>
+#define ERROR_INVALID_NUMBER (-1700)
+#define ERROR_NUMBER_EXCEEDS_BUFFER (-1701)
+
/** @file
* Support functions to access arbitrary bits in a byte array
*/
@@ -31,6 +34,7 @@
static inline void buf_set_u32(uint8_t *_buffer,
unsigned first, unsigned num, uint32_t value)
{
+ assert(num >= 1 && num <= 32);
uint8_t *buffer = _buffer;
if ((num == 32) && (first == 0)) {
@@ -61,6 +65,7 @@ static inline void buf_set_u32(uint8_t *_buffer,
static inline void buf_set_u64(uint8_t *_buffer,
unsigned first, unsigned num, uint64_t value)
{
+ assert(num >= 1 && num <= 64);
uint8_t *buffer = _buffer;
if ((num == 32) && (first == 0)) {
@@ -99,6 +104,7 @@ static inline void buf_set_u64(uint8_t *_buffer,
static inline uint32_t buf_get_u32(const uint8_t *_buffer,
unsigned first, unsigned num)
{
+ assert(num >= 1 && num <= 32);
const uint8_t *buffer = _buffer;
if ((num == 32) && (first == 0)) {
@@ -128,6 +134,7 @@ static inline uint32_t buf_get_u32(const uint8_t *_buffer,
static inline uint64_t buf_get_u64(const uint8_t *_buffer,
unsigned first, unsigned num)
{
+ assert(num >= 1 && num <= 64);
const uint8_t *buffer = _buffer;
if ((num == 32) && (first == 0)) {
@@ -165,8 +172,8 @@ static inline uint64_t buf_get_u64(const uint8_t *_buffer,
*/
uint32_t flip_u32(uint32_t value, unsigned width);
-bool buf_cmp(const void *buf1, const void *buf2, unsigned size);
-bool buf_cmp_mask(const void *buf1, const void *buf2,
+bool buf_eq(const void *buf1, const void *buf2, unsigned size);
+bool buf_eq_mask(const void *buf1, const void *buf2,
const void *mask, unsigned size);
/**
@@ -189,8 +196,17 @@ void *buf_set_ones(void *buf, unsigned size);
void *buf_set_buf(const void *src, unsigned src_start,
void *dst, unsigned dst_start, unsigned len);
-int str_to_buf(const char *str, unsigned len,
- void *bin_buf, unsigned buf_size, unsigned radix);
+/**
+ * Parse an unsigned number (provided as a zero-terminated string)
+ * into a bit buffer whose size is buf_len bits. The base of the
+ * number is detected between decimal, hexadecimal and octal.
+ * @param str Input number, zero-terminated string
+ * @param _buf Output buffer, allocated by the caller
+ * @param buf_bitsize Output buffer size in bits
+ * @returns Error on invalid or overflowing number
+ */
+int str_to_buf(const char *str, void *_buf, unsigned int buf_bitsize);
+
char *buf_to_hex_str(const void *buf, unsigned size);
/* read a uint32_t from a buffer in target memory endianness */
diff --git a/src/helper/command.c b/src/helper/command.c
index a775c73..9078693 100644
--- a/src/helper/command.c
+++ b/src/helper/command.c
@@ -1360,6 +1360,27 @@ int command_parse_bool_arg(const char *in, bool *out)
return ERROR_COMMAND_SYNTAX_ERROR;
}
+COMMAND_HELPER(command_parse_str_to_buf, const char *str, void *buf, unsigned int buf_len)
+{
+ assert(str);
+ assert(buf);
+
+ int ret = str_to_buf(str, buf, buf_len);
+ if (ret == ERROR_OK)
+ return ret;
+
+ /* Provide a clear error message to the user */
+ if (ret == ERROR_INVALID_NUMBER) {
+ command_print(CMD, "'%s' is not a valid number", str);
+ } else if (ret == ERROR_NUMBER_EXCEEDS_BUFFER) {
+ command_print(CMD, "Number %s exceeds %u bits", str, buf_len);
+ } else {
+ command_print(CMD, "Could not parse number '%s'", str);
+ }
+
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+}
+
COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label)
{
switch (CMD_ARGC) {
diff --git a/src/helper/command.h b/src/helper/command.h
index fc26dda..b224bd0 100644
--- a/src/helper/command.h
+++ b/src/helper/command.h
@@ -517,6 +517,15 @@ DECLARE_PARSE_WRAPPER(_target_addr, target_addr_t);
int command_parse_bool_arg(const char *in, bool *out);
COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label);
+/**
+ * Parse a number (base 10, base 16 or base 8) and store the result
+ * into a bit buffer. Use the prefixes '0' and '0x' for base 8 and 16,
+ * otherwise defaults to base 10.
+ *
+ * In case of parsing error, a user-readable error message is produced.
+ */
+COMMAND_HELPER(command_parse_str_to_buf, const char *str, void *buf, unsigned int buf_len);
+
/** parses an on/off command argument */
#define COMMAND_PARSE_ON_OFF(in, out) \
COMMAND_PARSE_BOOL(in, out, "on", "off")
diff --git a/src/helper/jep106.inc b/src/helper/jep106.inc
index 958dc4e..b74cda8 100644
--- a/src/helper/jep106.inc
+++ b/src/helper/jep106.inc
@@ -8,9 +8,7 @@
* identification code list, please visit the JEDEC website at www.jedec.org .
*/
-/* This file is aligned to revision JEP106BI January 2024. */
-
-/* "NXP (Philips)" is reported below, while missing since JEP106BG */
+/* This file is aligned to revision JEP106BJ.01 July 2024. */
[0][0x01 - 1] = "AMD",
[0][0x02 - 1] = "AMI",
@@ -30,7 +28,7 @@
[0][0x10 - 1] = "NEC",
[0][0x11 - 1] = "RCA",
[0][0x12 - 1] = "Raytheon",
-[0][0x13 - 1] = "Conexant (Rockwell)",
+[0][0x13 - 1] = "Synaptics",
[0][0x14 - 1] = "Seeq",
[0][0x15 - 1] = "NXP (Philips)",
[0][0x16 - 1] = "Synertek",
@@ -1045,7 +1043,7 @@
[8][0x17 - 1] = "Axell Corporation",
[8][0x18 - 1] = "Essencore Limited",
[8][0x19 - 1] = "Phytium",
-[8][0x1a - 1] = "Xi'an UniIC Semiconductors Co Ltd",
+[8][0x1a - 1] = "UniIC Semiconductors Co Ltd",
[8][0x1b - 1] = "Ambiq Micro",
[8][0x1c - 1] = "eveRAM Technology Inc",
[8][0x1d - 1] = "Infomax",
@@ -1452,7 +1450,7 @@
[11][0x34 - 1] = "Acacia Communications",
[11][0x35 - 1] = "Beijinjinshengyihe Technology Co Ltd",
[11][0x36 - 1] = "Zyzyx",
-[11][0x37 - 1] = "T-HEAD Semiconductor Co Ltd",
+[11][0x37 - 1] = "C-SKY Microsystems Co Ltd",
[11][0x38 - 1] = "Shenzhen Hystou Technology Co Ltd",
[11][0x39 - 1] = "Syzexion",
[11][0x3a - 1] = "Kembona",
@@ -1938,4 +1936,31 @@
[15][0x22 - 1] = "SkyeChip",
[15][0x23 - 1] = "Guangzhou Kaishile Trading Co Ltd",
[15][0x24 - 1] = "Jing Pai Digital Technology (Shenzhen) Co",
+[15][0x25 - 1] = "Memoritek",
+[15][0x26 - 1] = "Zhejiang Hikstor Technology Co Ltd",
+[15][0x27 - 1] = "Memoritek PTE Ltd",
+[15][0x28 - 1] = "Longsailing Semiconductor Co Ltd",
+[15][0x29 - 1] = "LX Semicon",
+[15][0x2a - 1] = "Shenzhen Techwinsemi Technology Co Ltd",
+[15][0x2b - 1] = "AOC",
+[15][0x2c - 1] = "GOEPEL Electronic GmbH",
+[15][0x2d - 1] = "Shenzhen G-Bong Technology Co Ltd",
+[15][0x2e - 1] = "Openedges Technology Inc",
+[15][0x2f - 1] = "EA Semi Shangahi Limited",
+[15][0x30 - 1] = "EMBCORF",
+[15][0x31 - 1] = "Shenzhen MicroBT Electronics Technology",
+[15][0x32 - 1] = "Shanghai Simor Chip Semiconductor Co",
+[15][0x33 - 1] = "Xllbyte",
+[15][0x34 - 1] = "Guangzhou Maidite Electronics Co Ltd.",
+[15][0x35 - 1] = "Zhejiang Changchun Technology Co Ltd",
+[15][0x36 - 1] = "Beijing Cloud Security Technology Co Ltd",
+[15][0x37 - 1] = "SSTC Technology and Distribution Inc",
+[15][0x38 - 1] = "Shenzhen Panmin Technology Co Ltd",
+[15][0x39 - 1] = "ITE Tech Inc",
+[15][0x3a - 1] = "Beijing Zettastone Technology Co Ltd",
+[15][0x3b - 1] = "Powerchip Micro Device",
+[15][0x3c - 1] = "Shenzhen Ysemi Computing Co Ltd",
+[15][0x3d - 1] = "Shenzhen Titan Micro Electronics Co Ltd",
+[15][0x3e - 1] = "Shenzhen Macroflash Technology Co Ltd",
+[15][0x3f - 1] = "Advantech Group",
/* EOF */
diff --git a/src/helper/startup.tcl b/src/helper/startup.tcl
index 5a0d479..e6e76e6 100644
--- a/src/helper/startup.tcl
+++ b/src/helper/startup.tcl
@@ -11,10 +11,10 @@ proc find {filename} {
if {[catch {ocd_find $filename} t]==0} {
return $t
}
- if {[catch {ocd_find [string map {\ /} $filename} t]==0} {
+ if {[catch {ocd_find [string map {\\ /} $filename]} t]==0} {
return $t
}
- if {[catch {ocd_find [string map {/ \\} $filename} t]==0} {
+ if {[catch {ocd_find [string map {/ \\} $filename]} t]==0} {
return $t
}
# make sure error message matches original input string