--- /dev/null
+/***************************************************************************\r
+ * Copyright (C) 2007,2008 Øyvind Harboe *\r
+ * Copyright (C) 2008 Duane Ellis *\r
+ * *\r
+ * This program is free software; you can redistribute it and/or modify *\r
+ * it under the terms of the GNU General Public License as published by *\r
+ * the Free Software Foundation; either version 2 of the License, or *\r
+ * (at your option) any later version. *\r
+ * *\r
+ * This program is distributed in the hope that it will be useful, *\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *\r
+ * GNU General Public License for more details. *\r
+ * *\r
+ * You should have received a copy of the GNU General Public License *\r
+ * along with this program; if not, write to the *\r
+ * Free Software Foundation, Inc., *\r
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *\r
+ ***************************************************************************/\r
+#ifdef HAVE_CONFIG_H\r
+#include "config.h"\r
+#endif\r
+\r
+#include "replacements.h"\r
+#include "target.h"\r
+#include "target_request.h"\r
+\r
+#include "log.h"\r
+#include "configuration.h"\r
+#include "binarybuffer.h"\r
+#include "jtag.h"\r
+#include "flash.h"\r
+\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include <inttypes.h>\r
+\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+#include <unistd.h>\r
+#include <errno.h>\r
+\r
+#include <sys/time.h>\r
+#include <time.h>\r
+\r
+#include <time_support.h>\r
+\r
+#include <fileio.h>\r
+#include <image.h>\r
+\r
+static int new_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 val)\r
+{\r
+ char *namebuf;\r
+ Jim_Obj *nameObjPtr, *valObjPtr;\r
+ int result;\r
+\r
+ namebuf = alloc_printf("%s(%d)", varname, idx);\r
+ if (!namebuf)\r
+ return JIM_ERR;\r
+\r
+ nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);\r
+ valObjPtr = Jim_NewIntObj(interp, val);\r
+ if (!nameObjPtr || !valObjPtr)\r
+ {\r
+ free(namebuf);\r
+ return JIM_ERR;\r
+ }\r
+\r
+ Jim_IncrRefCount(nameObjPtr);\r
+ Jim_IncrRefCount(valObjPtr);\r
+ result = Jim_SetVariable(interp, nameObjPtr, valObjPtr);\r
+ Jim_DecrRefCount(interp, nameObjPtr);\r
+ Jim_DecrRefCount(interp, valObjPtr);\r
+ free(namebuf);\r
+ /* printf("%s(%d) <= 0%08x\n", varname, idx, val); */\r
+ return result;\r
+}\r
+\r
+static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv)\r
+{\r
+ target_t *target;\r
+ command_context_t *context;\r
+ long l;\r
+ u32 width;\r
+ u32 len;\r
+ u32 addr;\r
+ u32 count;\r
+ u32 v;\r
+ const char *varname;\r
+ u8 buffer[4096];\r
+ int i, n, e, retval;\r
+\r
+ /* argv[1] = name of array to receive the data\r
+ * argv[2] = desired width\r
+ * argv[3] = memory address\r
+ * argv[4] = count of times to read\r
+ */\r
+ if (argc != 5) {\r
+ Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");\r
+ return JIM_ERR;\r
+ }\r
+ varname = Jim_GetString(argv[1], &len);\r
+ /* given "foo" get space for worse case "foo(%d)" .. add 20 */\r
+\r
+ e = Jim_GetLong(interp, argv[2], &l);\r
+ width = l;\r
+ if (e != JIM_OK) {\r
+ return e;\r
+ }\r
+\r
+ e = Jim_GetLong(interp, argv[3], &l);\r
+ addr = l;\r
+ if (e != JIM_OK) {\r
+ return e;\r
+ }\r
+ e = Jim_GetLong(interp, argv[4], &l);\r
+ len = l;\r
+ if (e != JIM_OK) {\r
+ return e;\r
+ }\r
+ switch (width) {\r
+ case 8:\r
+ width = 1;\r
+ break;\r
+ case 16:\r
+ width = 2;\r
+ break;\r
+ case 32:\r
+ width = 4;\r
+ break;\r
+ default:\r
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
+ Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL );\r
+ return JIM_ERR;\r
+ }\r
+ if (len == 0) {\r
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: zero width read?", NULL);\r
+ return JIM_ERR;\r
+ }\r
+ if ((addr + (len * width)) < addr) {\r
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: addr + len - wraps to zero?", NULL);\r
+ return JIM_ERR;\r
+ }\r
+ /* absurd transfer size? */\r
+ if (len > 65536) {\r
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: absurd > 64K item request", NULL);\r
+ return JIM_ERR;\r
+ }\r
+\r
+ if ((width == 1) ||\r
+ ((width == 2) && ((addr & 1) == 0)) ||\r
+ ((width == 4) && ((addr & 3) == 0))) {\r
+ /* all is well */\r
+ } else {\r
+ char buf[100];\r
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
+ sprintf(buf, "mem2array address: 0x%08x is not aligned for %d byte reads", addr, width);\r
+ Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);\r
+ return JIM_ERR;\r
+ }\r
+\r
+ context = Jim_GetAssocData(interp, "context");\r
+ if (context == NULL)\r
+ {\r
+ LOG_ERROR("mem2array: no command context");\r
+ return JIM_ERR;\r
+ }\r
+ target = get_current_target(context);\r
+ if (target == NULL)\r
+ {\r
+ LOG_ERROR("mem2array: no current target");\r
+ return JIM_ERR;\r
+ }\r
+\r
+ /* Transfer loop */\r
+\r
+ /* index counter */\r
+ n = 0;\r
+ /* assume ok */\r
+ e = JIM_OK;\r
+ while (len) {\r
+ /* Slurp... in buffer size chunks */\r
+\r
+ count = len; /* in objects.. */\r
+ if (count > (sizeof(buffer)/width)) {\r
+ count = (sizeof(buffer)/width);\r
+ }\r
+\r
+ retval = target->type->read_memory( target, addr, width, count, buffer );\r
+ if (retval != ERROR_OK) {\r
+ /* BOO !*/\r
+ LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count);\r
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL);\r
+ e = JIM_ERR;\r
+ len = 0;\r
+ } else {\r
+ v = 0; /* shut up gcc */\r
+ for (i = 0 ;i < count ;i++, n++) {\r
+ switch (width) {\r
+ case 4:\r
+ v = target_buffer_get_u32(target, &buffer[i*width]);\r
+ break;\r
+ case 2:\r
+ v = target_buffer_get_u16(target, &buffer[i*width]);\r
+ break;\r
+ case 1:\r
+ v = buffer[i] & 0x0ff;\r
+ break;\r
+ }\r
+ new_int_array_element(interp, varname, n, v);\r
+ }\r
+ len -= count;\r
+ }\r
+ }\r
+\r
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
+\r
+ return JIM_OK;\r
+}\r
+\r
+static int get_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 *val)\r
+{\r
+ char *namebuf;\r
+ Jim_Obj *nameObjPtr, *valObjPtr;\r
+ int result;\r
+ long l;\r
+\r
+ namebuf = alloc_printf("%s(%d)", varname, idx);\r
+ if (!namebuf)\r
+ return JIM_ERR;\r
+\r
+ nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);\r
+ if (!nameObjPtr)\r
+ {\r
+ free(namebuf);\r
+ return JIM_ERR;\r
+ }\r
+\r
+ Jim_IncrRefCount(nameObjPtr);\r
+ valObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_ERRMSG);\r
+ Jim_DecrRefCount(interp, nameObjPtr);\r
+ free(namebuf);\r
+ if (valObjPtr == NULL)\r
+ return JIM_ERR;\r
+\r
+ result = Jim_GetLong(interp, valObjPtr, &l);\r
+ /* printf("%s(%d) => 0%08x\n", varname, idx, val); */\r
+ *val = l;\r
+ return result;\r
+}\r
+\r
+static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv)\r
+{\r
+ target_t *target;\r
+ command_context_t *context;\r
+ long l;\r
+ u32 width;\r
+ u32 len;\r
+ u32 addr;\r
+ u32 count;\r
+ u32 v;\r
+ const char *varname;\r
+ u8 buffer[4096];\r
+ int i, n, e, retval;\r
+\r
+ /* argv[1] = name of array to get the data\r
+ * argv[2] = desired width\r
+ * argv[3] = memory address\r
+ * argv[4] = count to write\r
+ */\r
+ if (argc != 5) {\r
+ Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");\r
+ return JIM_ERR;\r
+ }\r
+ varname = Jim_GetString(argv[1], &len);\r
+ /* given "foo" get space for worse case "foo(%d)" .. add 20 */\r
+\r
+ e = Jim_GetLong(interp, argv[2], &l);\r
+ width = l;\r
+ if (e != JIM_OK) {\r
+ return e;\r
+ }\r
+\r
+ e = Jim_GetLong(interp, argv[3], &l);\r
+ addr = l;\r
+ if (e != JIM_OK) {\r
+ return e;\r
+ }\r
+ e = Jim_GetLong(interp, argv[4], &l);\r
+ len = l;\r
+ if (e != JIM_OK) {\r
+ return e;\r
+ }\r
+ switch (width) {\r
+ case 8:\r
+ width = 1;\r
+ break;\r
+ case 16:\r
+ width = 2;\r
+ break;\r
+ case 32:\r
+ width = 4;\r
+ break;\r
+ default:\r
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
+ Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL );\r
+ return JIM_ERR;\r
+ }\r
+ if (len == 0) {\r
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: zero width read?", NULL);\r
+ return JIM_ERR;\r
+ }\r
+ if ((addr + (len * width)) < addr) {\r
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: addr + len - wraps to zero?", NULL);\r
+ return JIM_ERR;\r
+ }\r
+ /* absurd transfer size? */\r
+ if (len > 65536) {\r
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: absurd > 64K item request", NULL);\r
+ return JIM_ERR;\r
+ }\r
+\r
+ if ((width == 1) ||\r
+ ((width == 2) && ((addr & 1) == 0)) ||\r
+ ((width == 4) && ((addr & 3) == 0))) {\r
+ /* all is well */\r
+ } else {\r
+ char buf[100];\r
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
+ sprintf(buf, "array2mem address: 0x%08x is not aligned for %d byte reads", addr, width);\r
+ Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);\r
+ return JIM_ERR;\r
+ }\r
+\r
+ context = Jim_GetAssocData(interp, "context");\r
+ if (context == NULL)\r
+ {\r
+ LOG_ERROR("array2mem: no command context");\r
+ return JIM_ERR;\r
+ }\r
+ target = get_current_target(context);\r
+ if (target == NULL)\r
+ {\r
+ LOG_ERROR("array2mem: no current target");\r
+ return JIM_ERR;\r
+ }\r
+\r
+ /* Transfer loop */\r
+\r
+ /* index counter */\r
+ n = 0;\r
+ /* assume ok */\r
+ e = JIM_OK;\r
+ while (len) {\r
+ /* Slurp... in buffer size chunks */\r
+\r
+ count = len; /* in objects.. */\r
+ if (count > (sizeof(buffer)/width)) {\r
+ count = (sizeof(buffer)/width);\r
+ }\r
+\r
+ v = 0; /* shut up gcc */\r
+ for (i = 0 ;i < count ;i++, n++) {\r
+ get_int_array_element(interp, varname, n, &v);\r
+ switch (width) {\r
+ case 4:\r
+ target_buffer_set_u32(target, &buffer[i*width], v);\r
+ break;\r
+ case 2:\r
+ target_buffer_set_u16(target, &buffer[i*width], v);\r
+ break;\r
+ case 1:\r
+ buffer[i] = v & 0x0ff;\r
+ break;\r
+ }\r
+ }\r
+ len -= count;\r
+\r
+ retval = target->type->write_memory(target, addr, width, count, buffer);\r
+ if (retval != ERROR_OK) {\r
+ /* BOO !*/\r
+ LOG_ERROR("array2mem: Write @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count);\r
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL);\r
+ e = JIM_ERR;\r
+ len = 0;\r
+ }\r
+ }\r
+\r
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
+\r
+ return JIM_OK;\r
+}\r
+\r
+int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *args)\r
+{\r
+ int retval;\r
+ scan_field_t *fields;\r
+ int num_fields;\r
+ int field_count = 0;\r
+ int i, e;\r
+ long device;\r
+\r
+ /* args[1] = device\r
+ * args[2] = num_bits\r
+ * args[3] = hex string\r
+ * ... repeat num bits and hex string ...\r
+ */\r
+ if ((argc < 4) || ((argc % 2)!=0))\r
+ {\r
+ Jim_WrongNumArgs(interp, 1, args, "wrong arguments");\r
+ return JIM_ERR;\r
+ }\r
+\r
+ for (i = 2; i < argc; i+=2)\r
+ {\r
+ long bits;\r
+\r
+ e = Jim_GetLong(interp, args[i], &bits);\r
+ if (e != JIM_OK)\r
+ return e;\r
+ }\r
+\r
+ e = Jim_GetLong(interp, args[1], &device);\r
+ if (e != JIM_OK)\r
+ return e;\r
+\r
+ num_fields=(argc-2)/2;\r
+ fields = malloc(sizeof(scan_field_t) * num_fields);\r
+ for (i = 2; i < argc; i+=2)\r
+ {\r
+ long bits;\r
+ int len;\r
+ const char *str;\r
+\r
+ Jim_GetLong(interp, args[i], &bits);\r
+ str = Jim_GetString(args[i+1], &len);\r
+\r
+ fields[field_count].device = device;\r
+ fields[field_count].num_bits = bits;\r
+ fields[field_count].out_value = malloc(CEIL(bits, 8));\r
+ str_to_buf(str, len, fields[field_count].out_value, bits, 0);\r
+ fields[field_count].out_mask = NULL;\r
+ fields[field_count].in_value = fields[field_count].out_value;\r
+ fields[field_count].in_check_mask = NULL;\r
+ fields[field_count].in_check_value = NULL;\r
+ fields[field_count].in_handler = NULL;\r
+ fields[field_count++].in_handler_priv = NULL;\r
+ }\r
+\r
+ jtag_add_dr_scan(num_fields, fields, -1);\r
+ retval = jtag_execute_queue();\r
+ if (retval != ERROR_OK)\r
+ {\r
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));\r
+ Jim_AppendStrings(interp, Jim_GetResult(interp), "drscan: jtag execute failed", NULL);\r
+ return JIM_ERR;\r
+ }\r
+\r
+ field_count=0;\r
+ Jim_Obj *list = Jim_NewListObj(interp, NULL, 0);\r
+ for (i = 2; i < argc; i+=2)\r
+ {\r
+ long bits;\r
+ char *str;\r
+\r
+ Jim_GetLong(interp, args[i], &bits);\r
+ str = buf_to_str(fields[field_count].in_value, bits, 16);\r
+ free(fields[field_count].out_value);\r
+\r
+ Jim_ListAppendElement(interp, list, Jim_NewStringObj(interp, str, strlen(str)));\r
+ free(str);\r
+ field_count++;\r
+ }\r
+\r
+ Jim_SetResult(interp, list);\r
+\r
+ free(fields);\r
+\r
+ return JIM_OK;\r
+}\r
+\r
+static int jim_flash_banks(Jim_Interp *interp, int argc, Jim_Obj *const *argv)\r
+{\r
+ flash_bank_t *p;\r
+\r
+ if (argc != 1) {\r
+ Jim_WrongNumArgs(interp, 1, argv, "no arguments to flash_banks command");\r
+ return JIM_ERR;\r
+ }\r
+\r
+ if (!flash_banks)\r
+ {\r
+ return JIM_ERR;\r
+ }\r
+\r
+ Jim_Obj *list=Jim_NewListObj(interp, NULL, 0);\r
+ for (p = flash_banks; p; p = p->next)\r
+ {\r
+ Jim_Obj *elem=Jim_NewListObj(interp, NULL, 0);\r
+\r
+ Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "name", -1));\r
+ Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, p->driver->name, -1));\r
+ Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "base", -1));\r
+ Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->base));\r
+ Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "size", -1));\r
+ Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->size));\r
+ Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "bus_width", -1));\r
+ Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->bus_width));\r
+ Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "chip_width", -1));\r
+ Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->chip_width));\r
+\r
+ Jim_ListAppendElement(interp, list, elem);\r
+ }\r
+\r
+ Jim_SetResult(interp, list);\r
+\r
+ return JIM_OK;\r
+}\r
+\r
+\r
+int tclapi_register_commands()\r
+{\r
+ register_jim("ocd_mem2array", jim_mem2array, "read memory and return as a TCL array for script processing");\r
+ register_jim("ocd_array2mem", jim_array2mem, "convert a TCL array to memory locations and write the values");\r
+ register_jim("drscan", Jim_Command_drscan, "execute DR scan <device> <num_bits> <value> <num_bits1> <value2> ...");\r
+ register_jim("ocd_flash_banks", jim_flash_banks, "return information about the flash banks");\r
+\r
+}\r