diff --git a/src/flash/flash.c b/src/flash/flash.c
index 01bc6e70b3a340bf53ee6db5a8b0b559751fc634..16c2633b18edfdc32d24459aafe67de495c65bf7 100644
--- a/src/flash/flash.c
+++ b/src/flash/flash.c
@@ -41,10 +41,6 @@
 #include <errno.h>
 #include <inttypes.h>
 
-#include "jim.h"
-extern Jim_Interp *interp;
-
-
 /* command handlers */
 int handle_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 int handle_flash_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
@@ -143,7 +139,7 @@ int flash_register_commands(struct command_context_s *cmd_ctx)
 	return ERROR_OK;
 }
 
-static int Jim_Command_flash_banks(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+static int jim_flash_banks(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
 	if (argc != 1) {
 		Jim_WrongNumArgs(interp, 1, argv, "no arguments to flash_banks command");
@@ -174,7 +170,7 @@ static int Jim_Command_flash_banks(Jim_Interp *interp, int argc, Jim_Obj *const
 		Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "chip_width", -1));
 		Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->chip_width));
 		
-	    Jim_ListAppendElement(interp, list, elem);
+		Jim_ListAppendElement(interp, list, elem);
 	}
 
 	Jim_SetResult(interp, list);
@@ -187,7 +183,7 @@ int flash_init_drivers(struct command_context_s *cmd_ctx)
 {
 	if (flash_banks)
 	{
-		Jim_CreateCommand(interp, "openocd_flash_banks", Jim_Command_flash_banks, NULL, NULL );
+		register_jim(cmd_ctx, "openocd_flash_banks", jim_flash_banks, "return information about the flash banks");
 		
 		register_command(cmd_ctx, flash_cmd, "info", handle_flash_info_command, COMMAND_EXEC,
 						 "print info about flash bank <num>");
diff --git a/src/helper/command.c b/src/helper/command.c
index 3ec1f84d60e25c48a99cc98450b26e004ee0ecb9..7c5d77d65022a4f6e1492336470e15f9e1e71ee6 100644
--- a/src/helper/command.c
+++ b/src/helper/command.c
@@ -37,10 +37,10 @@
 #include <stdarg.h>
 #include <stdio.h>
 #include <unistd.h>
-
-#include <openocd_tcl.h>
+#include <errno.h>
 
 int fast_and_dangerous = 0;
+Jim_Interp *interp = NULL;
 
 int handle_sleep_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 int handle_fast_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
@@ -476,16 +476,175 @@ int command_done(command_context_t *context)
 	return ERROR_OK;
 }
 
+
+/* find full path to file */
+static int jim_find(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+	if (argc != 2)
+		return JIM_ERR;
+	const char *file = Jim_GetString(argv[1], NULL);
+	char *full_path = find_file(file);
+	if (full_path == NULL)
+		return JIM_ERR;
+	Jim_Obj *result = Jim_NewStringObj(interp, full_path, strlen(full_path));
+	free(full_path);
+	
+	Jim_SetResult(interp, result);
+	return JIM_OK;
+}
+
+static int jim_echo(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+	if (argc != 2)
+		return JIM_ERR;
+	const char *str = Jim_GetString(argv[1], NULL);
+	LOG_USER("%s", str);
+	return JIM_OK;
+}
+
+
+
+static size_t openocd_jim_fwrite(const void *_ptr, size_t size, size_t n, void *cookie)
+{
+	size_t nbytes;
+	const char *ptr;
+	Jim_Interp *interp;
+	command_context_t *context;
+
+	/* make it a char easier to read code */
+	ptr = _ptr;
+	interp = cookie;
+	nbytes = size * n;
+	if (ptr == NULL || interp == NULL || nbytes == 0) {
+		return 0;
+	}
+
+	context = Jim_GetAssocData(interp, "context");
+	if (context == NULL)
+	{
+		LOG_ERROR("openocd_jim_fwrite: no command context");
+		/* TODO: Where should this go? */		
+		return n;
+	}
+
+	/* do we have to chunk it? */
+	if (ptr[nbytes] == 0)
+	{
+		/* no it is a C style string */
+		command_output_text(context, ptr);
+		return strlen(ptr);
+	}
+	/* GRR we must chunk - not null terminated */
+	while (nbytes) {
+		char chunk[128+1];
+		int x;
+
+		x = nbytes;
+		if (x > 128) {
+			x = 128;
+		}
+		/* copy it */
+		memcpy(chunk, ptr, x);
+		/* terminate it */
+		chunk[n] = 0;
+		/* output it */
+		command_output_text(context, chunk);
+		ptr += x;
+		nbytes -= x;
+	}
+	
+	return n;
+}
+
+static size_t openocd_jim_fread(void *ptr, size_t size, size_t n, void *cookie)
+{
+	/* TCL wants to read... tell him no */
+	return 0;
+}
+
+static int openocd_jim_vfprintf(void *cookie, const char *fmt, va_list ap)
+{
+	char *cp;
+	int n;
+	Jim_Interp *interp;
+	command_context_t *context;
+
+	n = -1;
+	interp = cookie;
+	if (interp == NULL)
+		return n;
+
+	context = Jim_GetAssocData(interp, "context");
+	if (context == NULL)
+	{
+		LOG_ERROR("openocd_jim_vfprintf: no command context");
+		return n;
+	}
+
+	cp = alloc_vprintf(fmt, ap);
+	if (cp)
+	{
+		command_output_text(context, cp);
+		n = strlen(cp);
+		free(cp);
+	}
+	return n;
+}
+
+static int openocd_jim_fflush(void *cookie)
+{
+	/* nothing to flush */
+	return 0;
+}
+
+static char* openocd_jim_fgets(char *s, int size, void *cookie)
+{
+	/* not supported */
+	errno = ENOTSUP;
+	return NULL;
+}
+
 command_context_t* command_init()
 {
 	command_context_t* context = malloc(sizeof(command_context_t));
-	
+	extern unsigned const char startup_tcl[];
+
 	context->mode = COMMAND_EXEC;
 	context->commands = NULL;
 	context->current_target = 0;
 	context->output_handler = NULL;
 	context->output_handler_priv = NULL;
+
+#ifdef JIM_EMBEDDED
+	Jim_InitEmbedded();
+	/* Create an interpreter */
+	interp = Jim_CreateInterp();
+	/* Add all the Jim core commands */
+	Jim_RegisterCoreCommands(interp);
+#endif
+
+	Jim_CreateCommand(interp, "openocd_find", jim_find, NULL, NULL);
+	Jim_CreateCommand(interp, "echo", jim_echo, NULL, NULL);
+
+	/* Set Jim's STDIO */
+	interp->cookie_stdin = interp;
+	interp->cookie_stdout = interp;
+	interp->cookie_stderr = interp;
+	interp->cb_fwrite = openocd_jim_fwrite;
+	interp->cb_fread = openocd_jim_fread ;
+	interp->cb_vfprintf = openocd_jim_vfprintf;
+	interp->cb_fflush = openocd_jim_fflush;
+	interp->cb_fgets = openocd_jim_fgets;
 	
+	add_default_dirs();
+
+	if (Jim_Eval(interp, startup_tcl)==JIM_ERR)
+	{
+		LOG_ERROR("Failed to run startup.tcl (embedded into OpenOCD compile time)");
+		Jim_PrintErrorMessage(interp);
+		exit(-1);
+	}
+
 	register_command(context, NULL, "sleep", handle_sleep_command,
 					 COMMAND_ANY, "sleep for <n> milliseconds");
 	
@@ -529,3 +688,23 @@ int handle_fast_command(struct command_context_s *cmd_ctx, char *cmd, char **arg
 	
 	return ERROR_OK;
 }
+
+void register_jim(struct command_context_s *cmd_ctx, const char *name, int (*cmd)(Jim_Interp *interp, int argc, Jim_Obj *const *argv), const char *help)
+{
+	Jim_CreateCommand(interp, name, cmd, NULL, NULL);
+
+	/* FIX!!! it would be prettier to invoke add_help_text... 
+	   accumulate help text in Tcl helptext list.  */
+	Jim_Obj *helptext=Jim_GetGlobalVariableStr(interp, "ocd_helptext", JIM_ERRMSG);
+	if (Jim_IsShared(helptext))
+		helptext = Jim_DuplicateObj(interp, helptext);
+    
+	Jim_Obj *cmd_entry=Jim_NewListObj(interp, NULL, 0);
+	
+	Jim_Obj *cmd_list=Jim_NewListObj(interp, NULL, 0);
+	Jim_ListAppendElement(interp, cmd_list, Jim_NewStringObj(interp, name, -1));
+	
+	Jim_ListAppendElement(interp, cmd_entry, cmd_list);
+	Jim_ListAppendElement(interp, cmd_entry, Jim_NewStringObj(interp, help, -1));
+	Jim_ListAppendElement(interp, helptext, cmd_entry);
+}
diff --git a/src/helper/command.h b/src/helper/command.h
index c90ed0f69628a23a57eaa048dcb666d268e0aa8f..9aa66078d910a3d40daf2cdae9ca4d3b0393c6d3 100644
--- a/src/helper/command.h
+++ b/src/helper/command.h
@@ -83,4 +83,19 @@ extern void command_output_text(command_context_t *context, const char *data);
 
 extern int fast_and_dangerous;
 
+
+/* Integrate the JIM TCL interpretor into the command processing. */
+#include <stdarg.h>
+#ifdef __ECOS
+/* Jim is provied by eCos */
+#include <cyg/jimtcl/jim.h>
+#else
+#define JIM_EMBEDDED
+#include "jim.h"
+#endif
+
+extern Jim_Interp *interp;
+
+void register_jim(command_context_t *context, const char *name, int (*cmd)(Jim_Interp *interp, int argc, Jim_Obj *const *argv), const char *help);
+
 #endif /* COMMAND_H */
diff --git a/src/jtag/jtag.c b/src/jtag/jtag.c
index 2b1a56fb8df92505e5e512dada98fa05d6ab7e5f..3b1e8b0a2c90b47164e99ce18f238efe1a506c82 100644
--- a/src/jtag/jtag.c
+++ b/src/jtag/jtag.c
@@ -32,9 +32,6 @@
 #include "string.h"
 #include <unistd.h>
 
-#include "openocd_tcl.h"
-
-
 /* note that this is not marked as static as it must be available from outside jtag.c for those 
    that implement the jtag_xxx() minidriver layer 
 */
@@ -1498,7 +1495,7 @@ int jtag_register_commands(struct command_context_s *cmd_ctx)
 		COMMAND_EXEC, "move to Run-Test/Idle, and execute <num_cycles>");
 	register_command(cmd_ctx, NULL, "irscan", handle_irscan_command,
 		COMMAND_EXEC, "execute IR scan <device> <instr> [dev2] [instr2] ...");
-	add_jim("drscan", Jim_Command_drscan, "execute DR scan <device> <num_bits> <value> <num_bits1> <value2> ...");
+	register_jim(cmd_ctx, "drscan", Jim_Command_drscan, "execute DR scan <device> <num_bits> <value> <num_bits1> <value2> ...");
 
 	register_command(cmd_ctx, NULL, "verify_ircapture", handle_verify_ircapture_command,
 		COMMAND_ANY, "verify value captured during Capture-IR <enable|disable>");
diff --git a/src/openocd.c b/src/openocd.c
index f9c5d17c1e17de5f2184f6e85086c11f92d63835..1094dcd633c1ee9e2cbb57e1ee02934c710c0ceb 100644
--- a/src/openocd.c
+++ b/src/openocd.c
@@ -55,14 +55,6 @@
 #include <alloca.h>
 #endif
 
-#ifdef __ECOS
-/* Jim is provied by eCos */
-#include <cyg/jimtcl/jim.h>
-#else
-#define JIM_EMBEDDED
-#include "jim.h"
-#endif
-
 #include "replacements.h"
 
 
@@ -154,537 +146,6 @@ int handle_init_command(struct command_context_s *cmd_ctx, char *cmd, char **arg
 	return ERROR_OK;
 }
 
-Jim_Interp *interp;
-
-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_Command_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_Command_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;
-}
-
-
-
-/* find full path to file */
-static int Jim_Command_find(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
-	if (argc != 2)
-		return JIM_ERR;
-	const char *file = Jim_GetString(argv[1], NULL);
-	char *full_path = find_file(file);
-	if (full_path == NULL)
-		return JIM_ERR;
-	Jim_Obj *result = Jim_NewStringObj(interp, full_path, strlen(full_path));
-	free(full_path);
-	
-	Jim_SetResult(interp, result);
-	return JIM_OK;
-}
-
-static int Jim_Command_echo(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
-	if (argc != 2)
-		return JIM_ERR;
-	const char *str = Jim_GetString(argv[1], NULL);
-	LOG_USER("%s", str);
-	return JIM_OK;
-}
-
-
-
-static size_t openocd_jim_fwrite(const void *_ptr, size_t size, size_t n, void *cookie)
-{
-	size_t nbytes;
-	const char *ptr;
-	Jim_Interp *interp;
-	command_context_t *context;
-
-	/* make it a char easier to read code */
-	ptr = _ptr;
-	interp = cookie;
-	nbytes = size * n;
-	if (ptr == NULL || interp == NULL || nbytes == 0) {
-		return 0;
-	}
-
-	context = Jim_GetAssocData(interp, "context");
-	if (context == NULL)
-	{
-		LOG_ERROR("openocd_jim_fwrite: no command context");
-		/* TODO: Where should this go? */		
-		return n;
-	}
-
-	/* do we have to chunk it? */
-	if (ptr[nbytes] == 0)
-	{
-		/* no it is a C style string */
-		command_output_text(context, ptr);
-		return strlen(ptr);
-	}
-	/* GRR we must chunk - not null terminated */
-	while (nbytes) {
-		char chunk[128+1];
-		int x;
-
-		x = nbytes;
-		if (x > 128) {
-			x = 128;
-		}
-		/* copy it */
-		memcpy(chunk, ptr, x);
-		/* terminate it */
-		chunk[n] = 0;
-		/* output it */
-		command_output_text(context, chunk);
-		ptr += x;
-		nbytes -= x;
-	}
-	
-	return n;
-}
-
-static size_t openocd_jim_fread(void *ptr, size_t size, size_t n, void *cookie)
-{
-	/* TCL wants to read... tell him no */
-	return 0;
-}
-
-static int openocd_jim_vfprintf(void *cookie, const char *fmt, va_list ap)
-{
-	char *cp;
-	int n;
-	Jim_Interp *interp;
-	command_context_t *context;
-
-	n = -1;
-	interp = cookie;
-	if (interp == NULL)
-		return n;
-
-	context = Jim_GetAssocData(interp, "context");
-	if (context == NULL)
-	{
-		LOG_ERROR("openocd_jim_vfprintf: no command context");
-		return n;
-	}
-
-	cp = alloc_vprintf(fmt, ap);
-	if (cp)
-	{
-		command_output_text(context, cp);
-		n = strlen(cp);
-		free(cp);
-	}
-	return n;
-}
-
-static int openocd_jim_fflush(void *cookie)
-{
-	/* nothing to flush */
-	return 0;
-}
-
-static char* openocd_jim_fgets(char *s, int size, void *cookie)
-{
-	/* not supported */
-	errno = ENOTSUP;
-	return NULL;
-}
-
-void add_jim(const char *name, int (*cmd)(Jim_Interp *interp, int argc, Jim_Obj *const *argv), const char *help)
-{
-	Jim_CreateCommand(interp, name, cmd, NULL, NULL);
-	
-	/* FIX!!! it would be prettier to invoke add_help_text... 
-	accumulate help text in Tcl helptext list.  */
-    Jim_Obj *helptext=Jim_GetGlobalVariableStr(interp, "ocd_helptext", JIM_ERRMSG);
-    if (Jim_IsShared(helptext))
-        helptext = Jim_DuplicateObj(interp, helptext);
-    
-	Jim_Obj *cmd_entry=Jim_NewListObj(interp, NULL, 0);
-	
-	Jim_Obj *cmd_list=Jim_NewListObj(interp, NULL, 0);
-	Jim_ListAppendElement(interp, cmd_list, Jim_NewStringObj(interp, name, -1));
-	
-	Jim_ListAppendElement(interp, cmd_entry, cmd_list);
-	Jim_ListAppendElement(interp, cmd_entry, Jim_NewStringObj(interp, help, -1));
-	Jim_ListAppendElement(interp, helptext, cmd_entry);
-}
-
-extern unsigned const char startup_tcl[];
-
-void initJim(void)
-{
-	Jim_CreateCommand(interp, "openocd_find", Jim_Command_find, NULL, NULL);
-	Jim_CreateCommand(interp, "echo", Jim_Command_echo, NULL, NULL);
-	Jim_CreateCommand(interp, "mem2array", Jim_Command_mem2array, NULL, NULL );
-	Jim_CreateCommand(interp, "array2mem", Jim_Command_array2mem, NULL, NULL );
-
-	/* Set Jim's STDIO */
-	interp->cookie_stdin = interp;
-	interp->cookie_stdout = interp;
-	interp->cookie_stderr = interp;
-	interp->cb_fwrite = openocd_jim_fwrite;
-	interp->cb_fread = openocd_jim_fread ;
-	interp->cb_vfprintf = openocd_jim_vfprintf;
-	interp->cb_fflush = openocd_jim_fflush;
-	interp->cb_fgets = openocd_jim_fgets;
-	
-	add_default_dirs();
-	
-	if (Jim_Eval(interp, startup_tcl)==JIM_ERR)
-	{
-		LOG_ERROR("Failed to run startup.tcl (embedded into OpenOCD compile time)");
-		Jim_PrintErrorMessage(interp);
-		exit(-1);
-	}
-}
-
 command_context_t *setup_command_handler(void)
 {
 	command_context_t *cmd_ctx;
@@ -728,20 +189,11 @@ command_context_t *setup_command_handler(void)
  * application will have it's own implementation of main(). */
 int openocd_main(int argc, char *argv[])
 {
-#ifdef JIM_EMBEDDED
-	Jim_InitEmbedded();
-	/* Create an interpreter */
-	interp = Jim_CreateInterp();
-	/* Add all the Jim core commands */
-	Jim_RegisterCoreCommands(interp);
-#endif
-	
-	initJim();
-	
 	/* initialize commandline interface */
 	command_context_t *cmd_ctx;
-	cmd_ctx=setup_command_handler();
-	
+
+	cmd_ctx = setup_command_handler();
+
 	/* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
 	/* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
 	/* DANGER!!! make sure that the line below does not appear in a patch, do not remove */
diff --git a/src/openocd_tcl.h b/src/openocd_tcl.h
deleted file mode 100644
index af29fb7f24befea0d5bbc1c551e943983dd7a3e4..0000000000000000000000000000000000000000
--- a/src/openocd_tcl.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2008 by �yvind Harboe                                   *
- *   oyvind.harboe@zylin.com                                               *
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
- ***************************************************************************/
-#ifndef OPENOCD_TCL_H
-#define OPENOCD_TCL_H
-#include <jim.h>
-void add_jim(const char *name, int (*cmd)(Jim_Interp *interp, int argc, Jim_Obj *const *argv), const char *help);
-extern Jim_Interp *interp;
-#endif
diff --git a/src/target/target.c b/src/target/target.c
index 3f75d5c6ee5564cfcbca15f7f9b4d6bbe5418892..589f626f0902f61a6f551cca298eeada31614b03 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;
+}