build: add common.mk
[openocd.git] / src / svf / svf.c
index fb5e1b0e5ae51ffe0d3417ecb308bb9fa9134c2f..62e2324883a9c2acb5f215f115879f688eb81046 100644 (file)
@@ -31,9 +31,9 @@
 #include "config.h"
 #endif
 
-#include "jtag.h"
+#include <jtag/jtag.h>
 #include "svf.h"
-#include "time_support.h"
+#include <helper/time_support.h>
 
 
 // SVF command
@@ -216,8 +216,6 @@ static char *svf_command_buffer = NULL;
 static int svf_command_buffer_size = 0;
 static int svf_line_number = 1;
 
-static struct jtag_tap *tap = NULL;
-
 #define SVF_MAX_BUFFER_SIZE_TO_COMMIT  (4 * 1024)
 static uint8_t *svf_tdi_buffer = NULL, *svf_tdo_buffer = NULL, *svf_mask_buffer = NULL;
 static int svf_buffer_index = 0, svf_buffer_size = 0;
@@ -274,7 +272,7 @@ static unsigned svf_get_mask_u32(int bitlen)
 int svf_add_statemove(tap_state_t state_to)
 {
        tap_state_t state_from = cmd_queue_cur_state;
-       uint8_t index;
+       unsigned index_var;
 
        /* when resetting, be paranoid and ignore current state */
        if (state_to == TAP_RESET) {
@@ -282,18 +280,18 @@ int svf_add_statemove(tap_state_t state_to)
                return ERROR_OK;
        }
 
-       for (index = 0; index < ARRAY_SIZE(svf_statemoves); index++)
+       for (index_var = 0; index_var < ARRAY_SIZE(svf_statemoves); index_var++)
        {
-               if ((svf_statemoves[index].from == state_from)
-                       && (svf_statemoves[index].to == state_to))
+               if ((svf_statemoves[index_var].from == state_from)
+                       && (svf_statemoves[index_var].to == state_to))
                {
                        /* recorded path includes current state ... avoid extra TCKs! */
-                       if (svf_statemoves[index].num_of_moves > 1)
-                               jtag_add_pathmove(svf_statemoves[index].num_of_moves - 1,
-                                               svf_statemoves[index].paths + 1);
+                       if (svf_statemoves[index_var].num_of_moves > 1)
+                               jtag_add_pathmove(svf_statemoves[index_var].num_of_moves - 1,
+                                               svf_statemoves[index_var].paths + 1);
                        else
-                               jtag_add_pathmove(svf_statemoves[index].num_of_moves,
-                                               svf_statemoves[index].paths);
+                               jtag_add_pathmove(svf_statemoves[index_var].num_of_moves,
+                                               svf_statemoves[index_var].paths);
                        return ERROR_OK;
                }
        }
@@ -308,38 +306,38 @@ COMMAND_HANDLER(handle_svf_command)
        int ret = ERROR_OK;
        long long time_ago;
 
-       if ((argc < 1) || (argc > (1 + SVF_NUM_OF_OPTIONS)))
+       if ((CMD_ARGC < 1) || (CMD_ARGC > (1 + SVF_NUM_OF_OPTIONS)))
        {
-               command_print(cmd_ctx, "usage: svf <file> [quiet]");
+               command_print(CMD_CTX, "usage: svf <file> [quiet]");
                return ERROR_FAIL;
        }
 
        // parse variant
        svf_quiet = 0;
-       for (unsigned i = 1; i < argc; i++)
+       for (unsigned i = 1; i < CMD_ARGC; i++)
        {
-               if (!strcmp(args[i], "quiet"))
+               if (!strcmp(CMD_ARGV[i], "quiet"))
                {
                        svf_quiet = 1;
                }
                else
                {
-                       LOG_ERROR("unknown variant for svf: %s", args[i]);
+                       LOG_ERROR("unknown variant for svf: %s", CMD_ARGV[i]);
 
                        // no need to free anything now
                        return ERROR_FAIL;
                }
        }
 
-       if ((svf_fd = open(args[0], O_RDONLY)) < 0)
+       if ((svf_fd = open(CMD_ARGV[0], O_RDONLY)) < 0)
        {
-               command_print(cmd_ctx, "file \"%s\" not found", args[0]);
+               command_print(CMD_CTX, "file \"%s\" not found", CMD_ARGV[0]);
 
                // no need to free anything now
                return ERROR_FAIL;
        }
 
-       LOG_USER("svf processing file: \"%s\"", args[0]);
+       LOG_USER("svf processing file: \"%s\"", CMD_ARGV[0]);
 
        // get time
        time_ago = timeval_ms();
@@ -392,7 +390,7 @@ COMMAND_HANDLER(handle_svf_command)
 
        while (ERROR_OK == svf_read_command_from_file(svf_fd))
        {
-               if (ERROR_OK != svf_run_command(cmd_ctx, svf_command_buffer))
+               if (ERROR_OK != svf_run_command(CMD_CTX, svf_command_buffer))
                {
                        LOG_ERROR("fail to run command at line %d", svf_line_number);
                        ret = ERROR_FAIL;
@@ -410,7 +408,7 @@ COMMAND_HANDLER(handle_svf_command)
        }
 
        // print time
-       command_print(cmd_ctx, "%lld ms used", timeval_ms() - time_ago);
+       command_print(CMD_CTX, "%lld ms used", timeval_ms() - time_ago);
 
 free_all:
 
@@ -457,11 +455,11 @@ free_all:
 
        if (ERROR_OK == ret)
        {
-               command_print(cmd_ctx, "svf file programmed successfully for %d commands", command_num);
+               command_print(CMD_CTX, "svf file programmed successfully for %d commands", command_num);
        }
        else
        {
-               command_print(cmd_ctx, "svf file programmed failed");
+               command_print(CMD_CTX, "svf file programmed failed");
        }
 
        return ret;
@@ -470,7 +468,8 @@ free_all:
 #define SVFP_CMD_INC_CNT                       1024
 static int svf_read_command_from_file(int fd)
 {
-       char ch, *tmp_buffer = NULL;
+       unsigned char ch;
+       char *tmp_buffer = NULL;
        int cmd_pos = 0, cmd_ok = 0, slash = 0, comment = 0;
 
        while (!cmd_ok && (read(fd, &ch, 1) > 0))
@@ -499,31 +498,55 @@ static int svf_read_command_from_file(int fd)
                case '\r':
                        slash = 0;
                        comment = 0;
-                       break;
+                       /* Don't save '\r' and '\n' if no data is parsed */
+                       if (!cmd_pos)
+                               break;
                default:
                        if (!comment)
                        {
-                               if (cmd_pos >= svf_command_buffer_size - 1)
+                               /* The parsing code currently expects a space
+                                * before parentheses -- "TDI (123)".  Also a
+                                * space afterwards -- "TDI (123) TDO(456)".
+                                * But such spaces are optional... instead of
+                                * parser updates, cope with that by adding the
+                                * spaces as needed.
+                                *
+                                * Ensure there are 3 bytes available, for:
+                                *  - current character
+                                *  - added space.
+                                *  - terminating NUL ('\0')
+                                */
+                               if ((cmd_pos + 2) >= svf_command_buffer_size)
                                {
-                                       tmp_buffer = (char*)malloc(svf_command_buffer_size + SVFP_CMD_INC_CNT);         // 1 more byte for '\0'
+                                       /* REVISIT use realloc(); simpler */
+                                       tmp_buffer = malloc(
+                                                       svf_command_buffer_size
+                                                       + SVFP_CMD_INC_CNT);
                                        if (NULL == tmp_buffer)
                                        {
                                                LOG_ERROR("not enough memory");
                                                return ERROR_FAIL;
                                        }
                                        if (svf_command_buffer_size > 0)
-                                       {
-                                               memcpy(tmp_buffer, svf_command_buffer, svf_command_buffer_size);
-                                       }
+                                               memcpy(tmp_buffer,
+                                                       svf_command_buffer,
+                                                       svf_command_buffer_size);
                                        if (svf_command_buffer != NULL)
-                                       {
                                                free(svf_command_buffer);
-                                       }
                                        svf_command_buffer = tmp_buffer;
                                        svf_command_buffer_size += SVFP_CMD_INC_CNT;
                                        tmp_buffer = NULL;
                                }
+
+                               /* insert a space before '(' */
+                               if ('(' == ch)
+                                       svf_command_buffer[cmd_pos++] = ' ';
+
                                svf_command_buffer[cmd_pos++] = (char)toupper(ch);
+
+                               /* insert a space after ')' */
+                               if (')' == ch)
+                                       svf_command_buffer[cmd_pos++] = ' ';
                        }
                        break;
                }
@@ -542,25 +565,30 @@ static int svf_read_command_from_file(int fd)
 
 static int svf_parse_cmd_string(char *str, int len, char **argus, int *num_of_argu)
 {
-       int pos = 0, num = 0, space_found = 1;
+       int pos = 0, num = 0, space_found = 1, in_bracket = 0;
 
        while (pos < len)
        {
                switch (str[pos])
                {
-               case '\n':
-               case '\r':
                case '!':
                case '/':
                        LOG_ERROR("fail to parse svf command");
                        return ERROR_FAIL;
-                       break;
-               case ' ':
-                       space_found = 1;
-                       str[pos] = '\0';
-                       break;
+               case '(':
+                       in_bracket = 1;
+                       goto parse_char;
+               case ')':
+                       in_bracket = 0;
+                       goto parse_char;
                default:
-                       if (space_found)
+parse_char:
+                       if (!in_bracket && isspace((int) str[pos]))
+                       {
+                               space_found = 1;
+                               str[pos] = '\0';
+                       }
+                       else if (space_found)
                        {
                                argus[num++] = &str[pos];
                                space_found = 0;
@@ -628,6 +656,7 @@ static int svf_copy_hexstring_to_binary(char *str, uint8_t **bin, int orig_bit_l
                return ERROR_FAIL;
        }
 
+       /* fill from LSB (end of str) to MSB (beginning of str) */
        for (i = 0; i < str_hbyte_len; i++)
        {
                ch = 0;
@@ -635,7 +664,13 @@ static int svf_copy_hexstring_to_binary(char *str, uint8_t **bin, int orig_bit_l
                {
                        ch = str[--str_len];
 
-                       if (!isblank(ch))
+                       /* Skip whitespace.  The SVF specification (rev E) is
+                        * deficient in terms of basic lexical issues like
+                        * where whitespace is allowed.  Long bitstrings may
+                        * require line ends for correctness, since there is
+                        * a hard limit on line length.
+                        */
+                       if (!isspace(ch))
                        {
                                if ((ch >= '0') && (ch <= '9'))
                                {
@@ -671,11 +706,12 @@ static int svf_copy_hexstring_to_binary(char *str, uint8_t **bin, int orig_bit_l
                }
        }
 
-       // consume optional leading '0' characters
-       while (str_len > 0 && str[str_len - 1] == '0')
+       /* consume optional leading '0' MSBs or whitespace */
+       while (str_len > 0 && ((str[str_len - 1] == '0')
+                               || isspace((int) str[str_len - 1])))
                str_len--;
 
-       // check valid
+       /* check validity: we must have consumed everything */
        if (str_len > 0 || (ch & ~((2 << ((bit_len - 1) % 4)) - 1)) != 0)
        {
                LOG_ERROR("value execeeds length");
@@ -687,22 +723,22 @@ static int svf_copy_hexstring_to_binary(char *str, uint8_t **bin, int orig_bit_l
 
 static int svf_check_tdo(void)
 {
-       int i, len, index;
+       int i, len, index_var;
 
        for (i = 0; i < svf_check_tdo_para_index; i++)
        {
-               index = svf_check_tdo_para[i].buffer_offset;
+               index_var = svf_check_tdo_para[i].buffer_offset;
                len = svf_check_tdo_para[i].bit_len;
                if ((svf_check_tdo_para[i].enabled)
-                       && buf_cmp_mask(&svf_tdi_buffer[index], &svf_tdo_buffer[index], &svf_mask_buffer[index], len))
+                       && buf_cmp_mask(&svf_tdi_buffer[index_var], &svf_tdo_buffer[index_var], &svf_mask_buffer[index_var], len))
                {
                        unsigned bitmask;
                        unsigned received, expected, tapmask;
                        bitmask = svf_get_mask_u32(svf_check_tdo_para[i].bit_len);
 
-                       memcpy(&received, svf_tdi_buffer + index, sizeof(unsigned));
-                       memcpy(&expected, svf_tdo_buffer + index, sizeof(unsigned));
-                       memcpy(&tapmask, svf_mask_buffer + index, sizeof(unsigned));
+                       memcpy(&received, svf_tdi_buffer + index_var, sizeof(unsigned));
+                       memcpy(&expected, svf_tdo_buffer + index_var, sizeof(unsigned));
+                       memcpy(&tapmask, svf_mask_buffer + index_var, sizeof(unsigned));
                        LOG_ERROR("tdo check error at line %d",
                                          svf_check_tdo_para[i].line_num);
                        LOG_ERROR("read = 0x%X, want = 0x%X, mask = 0x%X",
@@ -844,7 +880,7 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
                        // TODO: set jtag speed to
                        if (svf_para.frequency > 0)
                        {
-                               command_run_linef(cmd_ctx, "jtag_khz %d", (int)svf_para.frequency / 1000);
+                               command_run_linef(cmd_ctx, "adapter_khz %d", (int)svf_para.frequency / 1000);
                                LOG_DEBUG("\tfrequency = %f", svf_para.frequency);
                        }
                }
@@ -1044,12 +1080,11 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
                        {
                                svf_add_check_para(0, svf_buffer_index, i);
                        }
-                       field.tap = tap;
                        field.num_bits = i;
                        field.out_value = &svf_tdi_buffer[svf_buffer_index];
                        field.in_value = &svf_tdi_buffer[svf_buffer_index];
                        /* NOTE:  doesn't use SVF-specified state paths */
-                       jtag_add_plain_dr_scan(1, &field, svf_para.dr_end_state);
+                       jtag_add_plain_dr_scan(field.num_bits, field.out_value, field.in_value, svf_para.dr_end_state);
 
                        svf_buffer_index += (i + 7) >> 3;
                }
@@ -1140,12 +1175,12 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
                        {
                                svf_add_check_para(0, svf_buffer_index, i);
                        }
-                       field.tap = tap;
                        field.num_bits = i;
                        field.out_value = &svf_tdi_buffer[svf_buffer_index];
                        field.in_value = &svf_tdi_buffer[svf_buffer_index];
                        /* NOTE:  doesn't use SVF-specified state paths */
-                       jtag_add_plain_ir_scan(1, &field, svf_para.ir_end_state);
+                       jtag_add_plain_ir_scan(field.num_bits, field.out_value, field.in_value,
+                                       svf_para.ir_end_state);
 
                        svf_buffer_index += (i + 7) >> 3;
                }
@@ -1350,12 +1385,9 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
                                        return ERROR_FAIL;
                                }
                        }
-                       // no need to keep this memory, in jtag_add_pathmove, path will be duplicated
-                       if (NULL != path)
-                       {
-                               free(path);
-                               path = NULL;
-                       }
+
+                       free(path);
+                       path = NULL;
                }
                else
                {
@@ -1460,11 +1492,18 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
        return ERROR_OK;
 }
 
+static const struct command_registration svf_command_handlers[] = {
+       {
+               .name = "svf",
+               .handler = handle_svf_command,
+               .mode = COMMAND_EXEC,
+               .help = "Runs a SVF file.",
+               .usage = "filename ['quiet']",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
 int svf_register_commands(struct command_context *cmd_ctx)
 {
-       register_command(cmd_ctx, NULL, "svf",
-                       &handle_svf_command, COMMAND_EXEC,
-                       "run svf <file>");
-
-       return ERROR_OK;
+       return register_commands(cmd_ctx, NULL, svf_command_handlers);
 }

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)