summaryrefslogtreecommitdiff
path: root/src/target
diff options
context:
space:
mode:
Diffstat (limited to 'src/target')
-rw-r--r--src/target/target.c361
1 files changed, 359 insertions, 2 deletions
diff --git a/src/target/target.c b/src/target/target.c
index 3f75d5c6..589f626f 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -74,9 +74,11 @@ int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args,
int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc);
int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
+static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
-/* targets
- */
+
+/* targets */
extern target_type_t arm7tdmi_target;
extern target_type_t arm720t_target;
extern target_type_t arm9tdmi_target;
@@ -937,6 +939,10 @@ int target_register_commands(struct command_context_s *cmd_ctx)
register_command(cmd_ctx, NULL, "virt2phys", handle_virt2phys_command, COMMAND_ANY, "virt2phys <virtual address>");
register_command(cmd_ctx, NULL, "profile", handle_profile_command, COMMAND_EXEC, "PRELIMINARY! - profile <seconds> <gmon.out>");
+
+ /* script procedures */
+ register_jim(cmd_ctx, "openocd_mem2array", jim_mem2array, "read memory and return as a TCL array for script processing");
+ register_jim(cmd_ctx, "openocd_array2mem", jim_mem2array, "convert a TCL array to memory locations and write the values");
return ERROR_OK;
}
@@ -2629,3 +2635,354 @@ int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **
return ERROR_OK;
}
+
+static int new_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 val)
+{
+ char *namebuf;
+ Jim_Obj *nameObjPtr, *valObjPtr;
+ int result;
+
+ namebuf = alloc_printf("%s(%d)", varname, idx);
+ if (!namebuf)
+ return JIM_ERR;
+
+ nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
+ valObjPtr = Jim_NewIntObj(interp, val);
+ if (!nameObjPtr || !valObjPtr)
+ {
+ free(namebuf);
+ return JIM_ERR;
+ }
+
+ Jim_IncrRefCount(nameObjPtr);
+ Jim_IncrRefCount(valObjPtr);
+ result = Jim_SetVariable(interp, nameObjPtr, valObjPtr);
+ Jim_DecrRefCount(interp, nameObjPtr);
+ Jim_DecrRefCount(interp, valObjPtr);
+ free(namebuf);
+ /* printf("%s(%d) <= 0%08x\n", varname, idx, val); */
+ return result;
+}
+
+static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ target_t *target;
+ command_context_t *context;
+ long l;
+ u32 width;
+ u32 len;
+ u32 addr;
+ u32 count;
+ u32 v;
+ const char *varname;
+ u8 buffer[4096];
+ int i, n, e, retval;
+
+ /* argv[1] = name of array to receive the data
+ * argv[2] = desired width
+ * argv[3] = memory address
+ * argv[4] = count of times to read
+ */
+ if (argc != 5) {
+ Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");
+ return JIM_ERR;
+ }
+ varname = Jim_GetString(argv[1], &len);
+ /* given "foo" get space for worse case "foo(%d)" .. add 20 */
+
+ e = Jim_GetLong(interp, argv[2], &l);
+ width = l;
+ if (e != JIM_OK) {
+ return e;
+ }
+
+ e = Jim_GetLong(interp, argv[3], &l);
+ addr = l;
+ if (e != JIM_OK) {
+ return e;
+ }
+ e = Jim_GetLong(interp, argv[4], &l);
+ len = l;
+ if (e != JIM_OK) {
+ return e;
+ }
+ switch (width) {
+ case 8:
+ width = 1;
+ break;
+ case 16:
+ width = 2;
+ break;
+ case 32:
+ width = 4;
+ break;
+ default:
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+ Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL );
+ return JIM_ERR;
+ }
+ if (len == 0) {
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: zero width read?", NULL);
+ return JIM_ERR;
+ }
+ if ((addr + (len * width)) < addr) {
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: addr + len - wraps to zero?", NULL);
+ return JIM_ERR;
+ }
+ /* absurd transfer size? */
+ if (len > 65536) {
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: absurd > 64K item request", NULL);
+ return JIM_ERR;
+ }
+
+ if ((width == 1) ||
+ ((width == 2) && ((addr & 1) == 0)) ||
+ ((width == 4) && ((addr & 3) == 0))) {
+ /* all is well */
+ } else {
+ char buf[100];
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+ sprintf(buf, "mem2array address: 0x%08x is not aligned for %d byte reads", addr, width);
+ Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);
+ return JIM_ERR;
+ }
+
+ context = Jim_GetAssocData(interp, "context");
+ if (context == NULL)
+ {
+ LOG_ERROR("mem2array: no command context");
+ return JIM_ERR;
+ }
+ target = get_current_target(context);
+ if (target == NULL)
+ {
+ LOG_ERROR("mem2array: no current target");
+ return JIM_ERR;
+ }
+
+ /* Transfer loop */
+
+ /* index counter */
+ n = 0;
+ /* assume ok */
+ e = JIM_OK;
+ while (len) {
+ /* Slurp... in buffer size chunks */
+
+ count = len; /* in objects.. */
+ if (count > (sizeof(buffer)/width)) {
+ count = (sizeof(buffer)/width);
+ }
+
+ retval = target->type->read_memory( target, addr, width, count, buffer );
+ if (retval != ERROR_OK) {
+ /* BOO !*/
+ LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count);
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL);
+ e = JIM_ERR;
+ len = 0;
+ } else {
+ v = 0; /* shut up gcc */
+ for (i = 0 ;i < count ;i++, n++) {
+ switch (width) {
+ 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] & 0x0ff;
+ break;
+ }
+ new_int_array_element(interp, varname, n, v);
+ }
+ len -= count;
+ }
+ }
+
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+
+ return JIM_OK;
+}
+
+static int get_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 *val)
+{
+ char *namebuf;
+ Jim_Obj *nameObjPtr, *valObjPtr;
+ int result;
+ long l;
+
+ namebuf = alloc_printf("%s(%d)", varname, idx);
+ if (!namebuf)
+ return JIM_ERR;
+
+ nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
+ if (!nameObjPtr)
+ {
+ free(namebuf);
+ return JIM_ERR;
+ }
+
+ Jim_IncrRefCount(nameObjPtr);
+ valObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_ERRMSG);
+ Jim_DecrRefCount(interp, nameObjPtr);
+ free(namebuf);
+ if (valObjPtr == NULL)
+ return JIM_ERR;
+
+ result = Jim_GetLong(interp, valObjPtr, &l);
+ /* printf("%s(%d) => 0%08x\n", varname, idx, val); */
+ *val = l;
+ return result;
+}
+
+static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ target_t *target;
+ command_context_t *context;
+ long l;
+ u32 width;
+ u32 len;
+ u32 addr;
+ u32 count;
+ u32 v;
+ const char *varname;
+ u8 buffer[4096];
+ int i, n, e, retval;
+
+ /* argv[1] = name of array to get the data
+ * argv[2] = desired width
+ * argv[3] = memory address
+ * argv[4] = count to write
+ */
+ if (argc != 5) {
+ Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");
+ return JIM_ERR;
+ }
+ varname = Jim_GetString(argv[1], &len);
+ /* given "foo" get space for worse case "foo(%d)" .. add 20 */
+
+ e = Jim_GetLong(interp, argv[2], &l);
+ width = l;
+ if (e != JIM_OK) {
+ return e;
+ }
+
+ e = Jim_GetLong(interp, argv[3], &l);
+ addr = l;
+ if (e != JIM_OK) {
+ return e;
+ }
+ e = Jim_GetLong(interp, argv[4], &l);
+ len = l;
+ if (e != JIM_OK) {
+ return e;
+ }
+ switch (width) {
+ case 8:
+ width = 1;
+ break;
+ case 16:
+ width = 2;
+ break;
+ case 32:
+ width = 4;
+ break;
+ default:
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+ Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL );
+ return JIM_ERR;
+ }
+ if (len == 0) {
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: zero width read?", NULL);
+ return JIM_ERR;
+ }
+ if ((addr + (len * width)) < addr) {
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: addr + len - wraps to zero?", NULL);
+ return JIM_ERR;
+ }
+ /* absurd transfer size? */
+ if (len > 65536) {
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: absurd > 64K item request", NULL);
+ return JIM_ERR;
+ }
+
+ if ((width == 1) ||
+ ((width == 2) && ((addr & 1) == 0)) ||
+ ((width == 4) && ((addr & 3) == 0))) {
+ /* all is well */
+ } else {
+ char buf[100];
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+ sprintf(buf, "array2mem address: 0x%08x is not aligned for %d byte reads", addr, width);
+ Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);
+ return JIM_ERR;
+ }
+
+ context = Jim_GetAssocData(interp, "context");
+ if (context == NULL)
+ {
+ LOG_ERROR("array2mem: no command context");
+ return JIM_ERR;
+ }
+ target = get_current_target(context);
+ if (target == NULL)
+ {
+ LOG_ERROR("array2mem: no current target");
+ return JIM_ERR;
+ }
+
+ /* Transfer loop */
+
+ /* index counter */
+ n = 0;
+ /* assume ok */
+ e = JIM_OK;
+ while (len) {
+ /* Slurp... in buffer size chunks */
+
+ count = len; /* in objects.. */
+ if (count > (sizeof(buffer)/width)) {
+ count = (sizeof(buffer)/width);
+ }
+
+ v = 0; /* shut up gcc */
+ for (i = 0 ;i < count ;i++, n++) {
+ get_int_array_element(interp, varname, n, &v);
+ switch (width) {
+ 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;
+ }
+ }
+ len -= count;
+
+ retval = target->type->write_memory(target, addr, width, count, buffer);
+ if (retval != ERROR_OK) {
+ /* BOO !*/
+ LOG_ERROR("array2mem: Write @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count);
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL);
+ e = JIM_ERR;
+ len = 0;
+ }
+ }
+
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+
+ return JIM_OK;
+}