semihosting: add semihosting_basedir command
[openocd.git] / src / target / target.c
index b72dc53e3e4f57f87d811dadaea944cc0a1df2a2..8edd632916a7877cacf4c5f25045f97b570221fe 100644 (file)
@@ -57,6 +57,7 @@
 #include "transport/transport.h"
 #include "arm_cti.h"
 #include "smp.h"
+#include "semihosting_common.h"
 
 /* default halt wait timeout (ms) */
 #define DEFAULT_HALT_TIMEOUT 5000
@@ -2258,6 +2259,8 @@ static void target_destroy(struct target *target)
        if (target->type->deinit_target)
                target->type->deinit_target(target);
 
+       if (target->semihosting)
+               free(target->semihosting->basedir);
        free(target->semihosting);
 
        jtag_unregister_event_callback(jtag_enable_callback, target);
@@ -3967,26 +3970,26 @@ static int handle_bp_command_list(struct command_invocation *cmd)
                if (breakpoint->type == BKPT_SOFT) {
                        char *buf = buf_to_hex_str(breakpoint->orig_instr,
                                        breakpoint->length);
-                       command_print(cmd, "IVA breakpoint: " TARGET_ADDR_FMT ", 0x%x, %i, 0x%s",
+                       command_print(cmd, "IVA breakpoint: " TARGET_ADDR_FMT ", 0x%x, 0x%s",
                                        breakpoint->address,
                                        breakpoint->length,
-                                       breakpoint->set, buf);
+                                       buf);
                        free(buf);
                } else {
                        if ((breakpoint->address == 0) && (breakpoint->asid != 0))
-                               command_print(cmd, "Context breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i",
+                               command_print(cmd, "Context breakpoint: 0x%8.8" PRIx32 ", 0x%x, %u",
                                                        breakpoint->asid,
-                                                       breakpoint->length, breakpoint->set);
+                                                       breakpoint->length, breakpoint->number);
                        else if ((breakpoint->address != 0) && (breakpoint->asid != 0)) {
-                               command_print(cmd, "Hybrid breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %i",
+                               command_print(cmd, "Hybrid breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %u",
                                                        breakpoint->address,
-                                                       breakpoint->length, breakpoint->set);
+                                                       breakpoint->length, breakpoint->number);
                                command_print(cmd, "\t|--->linked with ContextID: 0x%8.8" PRIx32,
                                                        breakpoint->asid);
                        } else
-                               command_print(cmd, "Breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %i",
+                               command_print(cmd, "Breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %u",
                                                        breakpoint->address,
-                                                       breakpoint->length, breakpoint->set);
+                                                       breakpoint->length, breakpoint->number);
                }
 
                breakpoint = breakpoint->next;
@@ -4431,27 +4434,12 @@ static int new_u64_array_element(Jim_Interp *interp, const char *varname, int id
        return result;
 }
 
-static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
-       struct command_context *context;
-       struct target *target;
-
-       context = current_command_context(interp);
-       assert(context);
-
-       target = get_current_target(context);
-       if (!target) {
-               LOG_ERROR("mem2array: no current target");
-               return JIM_ERR;
-       }
-
-       return target_mem2array(interp, target, argc - 1, argv + 1);
-}
-
 static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv)
 {
        int e;
 
+       LOG_WARNING("DEPRECATED! use 'read_memory' not 'mem2array'");
+
        /* argv[0] = name of array to receive the data
         * argv[1] = desired element width in bits
         * argv[2] = memory address
@@ -4604,6 +4592,161 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc,
        return e;
 }
 
+static int target_jim_read_memory(Jim_Interp *interp, int argc,
+               Jim_Obj * const *argv)
+{
+       /*
+        * argv[1] = memory address
+        * argv[2] = desired element width in bits
+        * argv[3] = number of elements to read
+        * argv[4] = optional "phys"
+        */
+
+       if (argc < 4 || argc > 5) {
+               Jim_WrongNumArgs(interp, 1, argv, "address width count ['phys']");
+               return JIM_ERR;
+       }
+
+       /* Arg 1: Memory address. */
+       jim_wide wide_addr;
+       int e;
+       e = Jim_GetWide(interp, argv[1], &wide_addr);
+
+       if (e != JIM_OK)
+               return e;
+
+       target_addr_t addr = (target_addr_t)wide_addr;
+
+       /* Arg 2: Bit width of one element. */
+       long l;
+       e = Jim_GetLong(interp, argv[2], &l);
+
+       if (e != JIM_OK)
+               return e;
+
+       const unsigned int width_bits = l;
+
+       /* Arg 3: Number of elements to read. */
+       e = Jim_GetLong(interp, argv[3], &l);
+
+       if (e != JIM_OK)
+               return e;
+
+       size_t count = l;
+
+       /* Arg 4: Optional 'phys'. */
+       bool is_phys = false;
+
+       if (argc > 4) {
+               const char *phys = Jim_GetString(argv[4], NULL);
+
+               if (strcmp(phys, "phys")) {
+                       Jim_SetResultFormatted(interp, "invalid argument '%s', must be 'phys'", phys);
+                       return JIM_ERR;
+               }
+
+               is_phys = true;
+       }
+
+       switch (width_bits) {
+       case 8:
+       case 16:
+       case 32:
+       case 64:
+               break;
+       default:
+               Jim_SetResultString(interp, "invalid width, must be 8, 16, 32 or 64", -1);
+               return JIM_ERR;
+       }
+
+       const unsigned int width = width_bits / 8;
+
+       if ((addr + (count * width)) < addr) {
+               Jim_SetResultString(interp, "read_memory: addr + count wraps to zero", -1);
+               return JIM_ERR;
+       }
+
+       if (count > 65536) {
+               Jim_SetResultString(interp, "read_memory: too large read request, exeeds 64K elements", -1);
+               return JIM_ERR;
+       }
+
+       struct command_context *cmd_ctx = current_command_context(interp);
+       assert(cmd_ctx != NULL);
+       struct target *target = get_current_target(cmd_ctx);
+
+       const size_t buffersize = 4096;
+       uint8_t *buffer = malloc(buffersize);
+
+       if (!buffer) {
+               LOG_ERROR("Failed to allocate memory");
+               return JIM_ERR;
+       }
+
+       Jim_Obj *result_list = Jim_NewListObj(interp, NULL, 0);
+       Jim_IncrRefCount(result_list);
+
+       while (count > 0) {
+               const unsigned int max_chunk_len = buffersize / width;
+               const size_t chunk_len = MIN(count, max_chunk_len);
+
+               int retval;
+
+               if (is_phys)
+                       retval = target_read_phys_memory(target, addr, width, chunk_len, buffer);
+               else
+                       retval = target_read_memory(target, addr, width, chunk_len, buffer);
+
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("read_memory: read at " TARGET_ADDR_FMT " with width=%u and count=%zu failed",
+                               addr, width_bits, chunk_len);
+                       Jim_SetResultString(interp, "read_memory: failed to read memory", -1);
+                       e = JIM_ERR;
+                       break;
+               }
+
+               for (size_t i = 0; i < chunk_len ; i++) {
+                       uint64_t v = 0;
+
+                       switch (width) {
+                       case 8:
+                               v = target_buffer_get_u64(target, &buffer[i * width]);
+                               break;
+                       case 4:
+                               v = target_buffer_get_u32(target, &buffer[i * width]);
+                               break;
+                       case 2:
+                               v = target_buffer_get_u16(target, &buffer[i * width]);
+                               break;
+                       case 1:
+                               v = buffer[i];
+                               break;
+                       }
+
+                       char value_buf[11];
+                       snprintf(value_buf, sizeof(value_buf), "0x%" PRIx64, v);
+
+                       Jim_ListAppendElement(interp, result_list,
+                               Jim_NewStringObj(interp, value_buf, -1));
+               }
+
+               count -= chunk_len;
+               addr += chunk_len * width;
+       }
+
+       free(buffer);
+
+       if (e != JIM_OK) {
+               Jim_DecrRefCount(interp, result_list);
+               return e;
+       }
+
+       Jim_SetResult(interp, result_list);
+       Jim_DecrRefCount(interp, result_list);
+
+       return JIM_OK;
+}
+
 static int get_u64_array_element(Jim_Interp *interp, const char *varname, size_t idx, uint64_t *val)
 {
        char *namebuf = alloc_printf("%s(%zu)", varname, idx);
@@ -4629,28 +4772,13 @@ static int get_u64_array_element(Jim_Interp *interp, const char *varname, size_t
        return result;
 }
 
-static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
-       struct command_context *context;
-       struct target *target;
-
-       context = current_command_context(interp);
-       assert(context);
-
-       target = get_current_target(context);
-       if (!target) {
-               LOG_ERROR("array2mem: no current target");
-               return JIM_ERR;
-       }
-
-       return target_array2mem(interp, target, argc-1, argv + 1);
-}
-
 static int target_array2mem(Jim_Interp *interp, struct target *target,
                int argc, Jim_Obj *const *argv)
 {
        int e;
 
+       LOG_WARNING("DEPRECATED! use 'write_memory' not 'array2mem'");
+
        /* argv[0] = name of array from which to read the data
         * argv[1] = desired element width in bits
         * argv[2] = memory address
@@ -4814,6 +4942,144 @@ static int target_array2mem(Jim_Interp *interp, struct target *target,
        return e;
 }
 
+static int target_jim_write_memory(Jim_Interp *interp, int argc,
+               Jim_Obj * const *argv)
+{
+       /*
+        * argv[1] = memory address
+        * argv[2] = desired element width in bits
+        * argv[3] = list of data to write
+        * argv[4] = optional "phys"
+        */
+
+       if (argc < 4 || argc > 5) {
+               Jim_WrongNumArgs(interp, 1, argv, "address width data ['phys']");
+               return JIM_ERR;
+       }
+
+       /* Arg 1: Memory address. */
+       int e;
+       jim_wide wide_addr;
+       e = Jim_GetWide(interp, argv[1], &wide_addr);
+
+       if (e != JIM_OK)
+               return e;
+
+       target_addr_t addr = (target_addr_t)wide_addr;
+
+       /* Arg 2: Bit width of one element. */
+       long l;
+       e = Jim_GetLong(interp, argv[2], &l);
+
+       if (e != JIM_OK)
+               return e;
+
+       const unsigned int width_bits = l;
+       size_t count = Jim_ListLength(interp, argv[3]);
+
+       /* Arg 4: Optional 'phys'. */
+       bool is_phys = false;
+
+       if (argc > 4) {
+               const char *phys = Jim_GetString(argv[4], NULL);
+
+               if (strcmp(phys, "phys")) {
+                       Jim_SetResultFormatted(interp, "invalid argument '%s', must be 'phys'", phys);
+                       return JIM_ERR;
+               }
+
+               is_phys = true;
+       }
+
+       switch (width_bits) {
+       case 8:
+       case 16:
+       case 32:
+       case 64:
+               break;
+       default:
+               Jim_SetResultString(interp, "invalid width, must be 8, 16, 32 or 64", -1);
+               return JIM_ERR;
+       }
+
+       const unsigned int width = width_bits / 8;
+
+       if ((addr + (count * width)) < addr) {
+               Jim_SetResultString(interp, "write_memory: addr + len wraps to zero", -1);
+               return JIM_ERR;
+       }
+
+       if (count > 65536) {
+               Jim_SetResultString(interp, "write_memory: too large memory write request, exceeds 64K elements", -1);
+               return JIM_ERR;
+       }
+
+       struct command_context *cmd_ctx = current_command_context(interp);
+       assert(cmd_ctx != NULL);
+       struct target *target = get_current_target(cmd_ctx);
+
+       const size_t buffersize = 4096;
+       uint8_t *buffer = malloc(buffersize);
+
+       if (!buffer) {
+               LOG_ERROR("Failed to allocate memory");
+               return JIM_ERR;
+       }
+
+       size_t j = 0;
+
+       while (count > 0) {
+               const unsigned int max_chunk_len = buffersize / width;
+               const size_t chunk_len = MIN(count, max_chunk_len);
+
+               for (size_t i = 0; i < chunk_len; i++, j++) {
+                       Jim_Obj *tmp = Jim_ListGetIndex(interp, argv[3], j);
+                       jim_wide element_wide;
+                       Jim_GetWide(interp, tmp, &element_wide);
+
+                       const uint64_t v = element_wide;
+
+                       switch (width) {
+                       case 8:
+                               target_buffer_set_u64(target, &buffer[i * width], v);
+                               break;
+                       case 4:
+                               target_buffer_set_u32(target, &buffer[i * width], v);
+                               break;
+                       case 2:
+                               target_buffer_set_u16(target, &buffer[i * width], v);
+                               break;
+                       case 1:
+                               buffer[i] = v & 0x0ff;
+                               break;
+                       }
+               }
+
+               count -= chunk_len;
+
+               int retval;
+
+               if (is_phys)
+                       retval = target_write_phys_memory(target, addr, width, chunk_len, buffer);
+               else
+                       retval = target_write_memory(target, addr, width, chunk_len, buffer);
+
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("write_memory: write at " TARGET_ADDR_FMT " with width=%u and count=%zu failed",
+                               addr,  width_bits, chunk_len);
+                       Jim_SetResultString(interp, "write_memory: failed to write memory", -1);
+                       e = JIM_ERR;
+                       break;
+               }
+
+               addr += chunk_len * width;
+       }
+
+       free(buffer);
+
+       return e;
+}
+
 /* FIX? should we propagate errors here rather than printing them
  * and continuing?
  */
@@ -4959,10 +5225,18 @@ static int target_jim_set_reg(Jim_Interp *interp, int argc,
        }
 
        int tmp;
+#if JIM_VERSION >= 80
        Jim_Obj **dict = Jim_DictPairs(interp, argv[1], &tmp);
 
        if (!dict)
                return JIM_ERR;
+#else
+       Jim_Obj **dict;
+       int ret = Jim_DictPairs(interp, argv[1], &dict, &tmp);
+
+       if (ret != JIM_OK)
+               return ret;
+#endif
 
        const unsigned int length = tmp;
        struct command_context *cmd_ctx = current_command_context(interp);
@@ -5797,6 +6071,20 @@ static const struct command_registration target_instance_command_handlers[] = {
                .help = "Set target register values",
                .usage = "dict",
        },
+       {
+               .name = "read_memory",
+               .mode = COMMAND_EXEC,
+               .jim_handler = target_jim_read_memory,
+               .help = "Read Tcl list of 8/16/32/64 bit numbers from target memory",
+               .usage = "address width count ['phys']",
+       },
+       {
+               .name = "write_memory",
+               .mode = COMMAND_EXEC,
+               .jim_handler = target_jim_write_memory,
+               .help = "Write Tcl list of 8/16/32/64 bit numbers to target memory",
+               .usage = "address width data ['phys']",
+       },
        {
                .name = "eventlist",
                .handler = handle_target_event_list,
@@ -6192,7 +6480,7 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        }
 
        if (target && target->rtos)
-               retval = rtos_smp_init(head->target);
+               retval = rtos_smp_init(target);
 
        return retval;
 }
@@ -6863,22 +7151,6 @@ static const struct command_registration target_exec_command_handlers[] = {
                .mode = COMMAND_EXEC,
                .usage = "filename [offset [type]]",
        },
-       {
-               .name = "mem2array",
-               .mode = COMMAND_EXEC,
-               .jim_handler = jim_mem2array,
-               .help = "read 8/16/32 bit memory and return as a TCL array "
-                       "for script processing",
-               .usage = "arrayname bitwidth address count",
-       },
-       {
-               .name = "array2mem",
-               .mode = COMMAND_EXEC,
-               .jim_handler = jim_array2mem,
-               .help = "convert a TCL array to memory locations "
-                       "and write the 8/16/32 bit values",
-               .usage = "arrayname bitwidth address count",
-       },
        {
                .name = "get_reg",
                .mode = COMMAND_EXEC,
@@ -6893,6 +7165,20 @@ static const struct command_registration target_exec_command_handlers[] = {
                .help = "Set target register values",
                .usage = "dict",
        },
+       {
+               .name = "read_memory",
+               .mode = COMMAND_EXEC,
+               .jim_handler = target_jim_read_memory,
+               .help = "Read Tcl list of 8/16/32/64 bit numbers from target memory",
+               .usage = "address width count ['phys']",
+       },
+       {
+               .name = "write_memory",
+               .mode = COMMAND_EXEC,
+               .jim_handler = target_jim_write_memory,
+               .help = "Write Tcl list of 8/16/32/64 bit numbers to target memory",
+               .usage = "address width data ['phys']",
+       },
        {
                .name = "reset_nag",
                .handler = handle_target_reset_nag,

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)