Paulius Zaleckas <paulius.zaleckas@gmail.com>:
[openocd.git] / src / target / target.c
index f098ef3484ec648d82dd5ccae7b56aa996dc8aac..65142a9aa4b7ad7f1c6ddfbc9f1c1ab25edbe4e7 100644 (file)
@@ -2,6 +2,18 @@
  *   Copyright (C) 2005 by Dominic Rath                                    *
  *   Dominic.Rath@gmx.de                                                   *
  *                                                                         *
+ *   Copyright (C) 2007,2008 Ã˜yvind Harboe                                 *
+ *   oyvind.harboe@zylin.com                                               *
+ *                                                                         *
+ *   Copyright (C) 2008, Duane Ellis                                       *
+ *   openocd@duaneeellis.com                                               *
+ *                                                                         *
+ *   Copyright (C) 2008 by Spencer Oliver                                  *
+ *   spen@spen-soft.co.uk                                                  *
+ *                                                                         *
+ *   Copyright (C) 2008 by Rick Altherr                                    *
+ *   kc8apf@kc8apf.net>                                                    *
+ *                                                                         *
  *   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     *
 #include "config.h"
 #endif
 
-#include "replacements.h"
 #include "target.h"
+#include "target_type.h"
 #include "target_request.h"
-
-#include "log.h"
-#include "configuration.h"
-#include "binarybuffer.h"
+#include "time_support.h"
+#include "register.h"
+#include "trace.h"
+#include "image.h"
 #include "jtag.h"
 
-#include <string.h>
-#include <stdlib.h>
-#include <inttypes.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <sys/time.h>
-#include <time.h>
-
-#include <time_support.h>
-
-#include <fileio.h>
-#include <image.h>
-
-int cli_target_callback_event_handler(struct target_s *target, enum target_event event, void *priv);
-
-
-int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_daemon_startup_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-
-int handle_target_script_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_run_and_halt_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-
-int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-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);
-
-/* targets
- */
+
+static int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+static int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_test_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_fast_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+static int handle_fast_load_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);
+static int jim_target( Jim_Interp *interp, int argc, Jim_Obj *const *argv);
+
+static int target_array2mem(Jim_Interp *interp, target_t *target, int argc, Jim_Obj *const *argv);
+static int target_mem2array(Jim_Interp *interp, target_t *target, int argc, Jim_Obj *const *argv);
+
+/* targets */
 extern target_type_t arm7tdmi_target;
 extern target_type_t arm720t_target;
 extern target_type_t arm9tdmi_target;
 extern target_type_t arm920t_target;
 extern target_type_t arm966e_target;
 extern target_type_t arm926ejs_target;
+extern target_type_t fa526_target;
 extern target_type_t feroceon_target;
 extern target_type_t xscale_target;
 extern target_type_t cortexm3_target;
+extern target_type_t cortexa8_target;
 extern target_type_t arm11_target;
+extern target_type_t mips_m4k_target;
+extern target_type_t avr_target;
 
 target_type_t *target_types[] =
 {
@@ -99,45 +99,182 @@ target_type_t *target_types[] =
        &arm720t_target,
        &arm966e_target,
        &arm926ejs_target,
+       &fa526_target,
        &feroceon_target,
        &xscale_target,
        &cortexm3_target,
+       &cortexa8_target,
        &arm11_target,
+       &mips_m4k_target,
+       &avr_target,
        NULL,
 };
 
-target_t *targets = NULL;
+target_t *all_targets = NULL;
 target_event_callback_t *target_event_callbacks = NULL;
 target_timer_callback_t *target_timer_callbacks = NULL;
 
-char *target_state_strings[] =
-{
-       "unknown",
-       "running",
-       "halted",
-       "reset",
-       "debug_running",
+const Jim_Nvp nvp_assert[] = {
+       { .name = "assert", NVP_ASSERT },
+       { .name = "deassert", NVP_DEASSERT },
+       { .name = "T", NVP_ASSERT },
+       { .name = "F", NVP_DEASSERT },
+       { .name = "t", NVP_ASSERT },
+       { .name = "f", NVP_DEASSERT },
+       { .name = NULL, .value = -1 }
 };
 
-char *target_debug_reason_strings[] =
-{
-       "debug request", "breakpoint", "watchpoint",
-       "watchpoint and breakpoint", "single step",
-       "target not halted", "undefined"
+const Jim_Nvp nvp_error_target[] = {
+       { .value = ERROR_TARGET_INVALID, .name = "err-invalid" },
+       { .value = ERROR_TARGET_INIT_FAILED, .name = "err-init-failed" },
+       { .value = ERROR_TARGET_TIMEOUT, .name = "err-timeout" },
+       { .value = ERROR_TARGET_NOT_HALTED, .name = "err-not-halted" },
+       { .value = ERROR_TARGET_FAILURE, .name = "err-failure" },
+       { .value = ERROR_TARGET_UNALIGNED_ACCESS   , .name = "err-unaligned-access" },
+       { .value = ERROR_TARGET_DATA_ABORT , .name = "err-data-abort" },
+       { .value = ERROR_TARGET_RESOURCE_NOT_AVAILABLE , .name = "err-resource-not-available" },
+       { .value = ERROR_TARGET_TRANSLATION_FAULT  , .name = "err-translation-fault" },
+       { .value = ERROR_TARGET_NOT_RUNNING, .name = "err-not-running" },
+       { .value = ERROR_TARGET_NOT_EXAMINED, .name = "err-not-examined" },
+       { .value = -1, .name = NULL }
 };
 
-char *target_endianess_strings[] =
+const char *target_strerror_safe( int err )
 {
-       "big endian",
-       "little endian",
+       const Jim_Nvp *n;
+
+       n = Jim_Nvp_value2name_simple( nvp_error_target, err );
+       if( n->name == NULL ){
+               return "unknown";
+       } else {
+               return n->name;
+       }
+}
+
+static const Jim_Nvp nvp_target_event[] = {
+       { .value = TARGET_EVENT_OLD_gdb_program_config , .name = "old-gdb_program_config" },
+       { .value = TARGET_EVENT_OLD_pre_resume         , .name = "old-pre_resume" },
+
+       { .value = TARGET_EVENT_EARLY_HALTED, .name = "early-halted" },
+       { .value = TARGET_EVENT_HALTED, .name = "halted" },
+       { .value = TARGET_EVENT_RESUMED, .name = "resumed" },
+       { .value = TARGET_EVENT_RESUME_START, .name = "resume-start" },
+       { .value = TARGET_EVENT_RESUME_END, .name = "resume-end" },
+
+       { .name = "gdb-start", .value = TARGET_EVENT_GDB_START },
+       { .name = "gdb-end", .value = TARGET_EVENT_GDB_END },
+
+       /* historical name */
+
+       { .value = TARGET_EVENT_RESET_START, .name = "reset-start" },
+
+       { .value = TARGET_EVENT_RESET_ASSERT_PRE,    .name = "reset-assert-pre" },
+       { .value = TARGET_EVENT_RESET_ASSERT_POST,   .name = "reset-assert-post" },
+       { .value = TARGET_EVENT_RESET_DEASSERT_PRE,  .name = "reset-deassert-pre" },
+       { .value = TARGET_EVENT_RESET_DEASSERT_POST, .name = "reset-deassert-post" },
+       { .value = TARGET_EVENT_RESET_HALT_PRE,      .name = "reset-halt-pre" },
+       { .value = TARGET_EVENT_RESET_HALT_POST,     .name = "reset-halt-post" },
+       { .value = TARGET_EVENT_RESET_WAIT_PRE,      .name = "reset-wait-pre" },
+       { .value = TARGET_EVENT_RESET_WAIT_POST,     .name = "reset-wait-post" },
+       { .value = TARGET_EVENT_RESET_INIT , .name = "reset-init" },
+       { .value = TARGET_EVENT_RESET_END, .name = "reset-end" },
+
+       { .value = TARGET_EVENT_EXAMINE_START, .name = "examine-start" },
+       { .value = TARGET_EVENT_EXAMINE_END, .name = "examine-end" },
+
+       { .value = TARGET_EVENT_DEBUG_HALTED, .name = "debug-halted" },
+       { .value = TARGET_EVENT_DEBUG_RESUMED, .name = "debug-resumed" },
+
+       { .value = TARGET_EVENT_GDB_ATTACH, .name = "gdb-attach" },
+       { .value = TARGET_EVENT_GDB_DETACH, .name = "gdb-detach" },
+
+       { .value = TARGET_EVENT_GDB_FLASH_WRITE_START, .name = "gdb-flash-write-start" },
+       { .value = TARGET_EVENT_GDB_FLASH_WRITE_END  , .name = "gdb-flash-write-end"   },
+
+       { .value = TARGET_EVENT_GDB_FLASH_ERASE_START, .name = "gdb-flash-erase-start" },
+       { .value = TARGET_EVENT_GDB_FLASH_ERASE_END  , .name = "gdb-flash-erase-end" },
+
+       { .value = TARGET_EVENT_RESUME_START, .name = "resume-start" },
+       { .value = TARGET_EVENT_RESUMED     , .name = "resume-ok" },
+       { .value = TARGET_EVENT_RESUME_END  , .name = "resume-end" },
+
+       { .name = NULL, .value = -1 }
+};
+
+const Jim_Nvp nvp_target_state[] = {
+       { .name = "unknown", .value = TARGET_UNKNOWN },
+       { .name = "running", .value = TARGET_RUNNING },
+       { .name = "halted",  .value = TARGET_HALTED },
+       { .name = "reset",   .value = TARGET_RESET },
+       { .name = "debug-running", .value = TARGET_DEBUG_RUNNING },
+       { .name = NULL, .value = -1 },
+};
+
+const Jim_Nvp nvp_target_debug_reason [] = {
+       { .name = "debug-request"            , .value = DBG_REASON_DBGRQ },
+       { .name = "breakpoint"               , .value = DBG_REASON_BREAKPOINT },
+       { .name = "watchpoint"               , .value = DBG_REASON_WATCHPOINT },
+       { .name = "watchpoint-and-breakpoint", .value = DBG_REASON_WPTANDBKPT },
+       { .name = "single-step"              , .value = DBG_REASON_SINGLESTEP },
+       { .name = "target-not-halted"        , .value = DBG_REASON_NOTHALTED  },
+       { .name = "undefined"                , .value = DBG_REASON_UNDEFINED },
+       { .name = NULL, .value = -1 },
+};
+
+const Jim_Nvp nvp_target_endian[] = {
+       { .name = "big",    .value = TARGET_BIG_ENDIAN },
+       { .name = "little", .value = TARGET_LITTLE_ENDIAN },
+       { .name = "be",     .value = TARGET_BIG_ENDIAN },
+       { .name = "le",     .value = TARGET_LITTLE_ENDIAN },
+       { .name = NULL,     .value = -1 },
+};
+
+const Jim_Nvp nvp_reset_modes[] = {
+       { .name = "unknown", .value = RESET_UNKNOWN },
+       { .name = "run"    , .value = RESET_RUN },
+       { .name = "halt"   , .value = RESET_HALT },
+       { .name = "init"   , .value = RESET_INIT },
+       { .name = NULL     , .value = -1 },
 };
 
-enum daemon_startup_mode startup_mode = DAEMON_ATTACH;
+static int max_target_number(void)
+{
+       target_t *t;
+       int x;
+
+       x = -1;
+       t = all_targets;
+       while( t ){
+               if( x < t->target_number ){
+                       x = (t->target_number)+1;
+               }
+               t = t->next;
+       }
+       return x;
+}
+
+/* determine the number of the new target */
+static int new_target_number(void)
+{
+       target_t *t;
+       int x;
+
+       /* number is 0 based */
+       x = -1;
+       t = all_targets;
+       while(t){
+               if( x < t->target_number ){
+                       x = t->target_number;
+               }
+               t = t->next;
+       }
+       return x+1;
+}
 
-static int target_continous_poll = 1;
+static int target_continuous_poll = 1;
 
-/* read a u32 from a buffer in target memory endianness */
-u32 target_buffer_get_u32(target_t *target, u8 *buffer)
+/* read a uint32_t from a buffer in target memory endianness */
+uint32_t target_buffer_get_u32(target_t *target, const uint8_t *buffer)
 {
        if (target->endianness == TARGET_LITTLE_ENDIAN)
                return le_to_h_u32(buffer);
@@ -145,8 +282,8 @@ u32 target_buffer_get_u32(target_t *target, u8 *buffer)
                return be_to_h_u32(buffer);
 }
 
-/* read a u16 from a buffer in target memory endianness */
-u16 target_buffer_get_u16(target_t *target, u8 *buffer)
+/* read a uint16_t from a buffer in target memory endianness */
+uint16_t target_buffer_get_u16(target_t *target, const uint8_t *buffer)
 {
        if (target->endianness == TARGET_LITTLE_ENDIAN)
                return le_to_h_u16(buffer);
@@ -154,8 +291,14 @@ u16 target_buffer_get_u16(target_t *target, u8 *buffer)
                return be_to_h_u16(buffer);
 }
 
-/* write a u32 to a buffer in target memory endianness */
-void target_buffer_set_u32(target_t *target, u8 *buffer, u32 value)
+/* read a uint8_t from a buffer in target memory endianness */
+uint8_t target_buffer_get_u8(target_t *target, const uint8_t *buffer)
+{
+       return *buffer & 0x0ff;
+}
+
+/* write a uint32_t to a buffer in target memory endianness */
+void target_buffer_set_u32(target_t *target, uint8_t *buffer, uint32_t value)
 {
        if (target->endianness == TARGET_LITTLE_ENDIAN)
                h_u32_to_le(buffer, value);
@@ -163,8 +306,8 @@ void target_buffer_set_u32(target_t *target, u8 *buffer, u32 value)
                h_u32_to_be(buffer, value);
 }
 
-/* write a u16 to a buffer in target memory endianness */
-void target_buffer_set_u16(target_t *target, u8 *buffer, u16 value)
+/* write a uint16_t to a buffer in target memory endianness */
+void target_buffer_set_u16(target_t *target, uint8_t *buffer, uint16_t value)
 {
        if (target->endianness == TARGET_LITTLE_ENDIAN)
                h_u16_to_le(buffer, value);
@@ -172,18 +315,48 @@ void target_buffer_set_u16(target_t *target, u8 *buffer, u16 value)
                h_u16_to_be(buffer, value);
 }
 
+/* write a uint8_t to a buffer in target memory endianness */
+void target_buffer_set_u8(target_t *target, uint8_t *buffer, uint8_t value)
+{
+       *buffer = value;
+}
+
+/* return a pointer to a configured target; id is name or number */
+target_t *get_target(const char *id)
+{
+       target_t *target;
+
+       /* try as tcltarget name */
+       for (target = all_targets; target; target = target->next) {
+               if (target->cmd_name == NULL)
+                       continue;
+               if (strcmp(id, target->cmd_name) == 0)
+                       return target;
+       }
+
+       /* no match, try as number */
+       unsigned num;
+       if (parse_uint(id, &num) != ERROR_OK)
+               return NULL;
+
+       for (target = all_targets; target; target = target->next) {
+               if (target->target_number == (int)num)
+                       return target;
+       }
+
+       return NULL;
+}
+
 /* returns a pointer to the n-th configured target */
-target_t* get_target_by_num(int num)
+static target_t *get_target_by_num(int num)
 {
-       target_t *target = targets;
-       int i = 0;
+       target_t *target = all_targets;
 
-       while (target)
-       {
-               if (num == i)
+       while (target){
+               if( target->target_number == num ){
                        return target;
+               }
                target = target->next;
-               i++;
        }
 
        return NULL;
@@ -191,278 +364,357 @@ target_t* get_target_by_num(int num)
 
 int get_num_by_target(target_t *query_target)
 {
-       target_t *target = targets;
-       int i = 0;      
-       
-       while (target)
-       {
-               if (target == query_target)
-                       return i;
-               target = target->next;
-               i++;
-       }
-       
-       return -1;
+       return query_target->target_number;
 }
 
 target_t* get_current_target(command_context_t *cmd_ctx)
 {
        target_t *target = get_target_by_num(cmd_ctx->current_target);
-       
+
        if (target == NULL)
        {
                LOG_ERROR("BUG: current_target out of bounds");
                exit(-1);
        }
-       
+
        return target;
 }
 
-/* Process target initialization, when target entered debug out of reset
- * the handler is unregistered at the end of this function, so it's only called once
- */
-int target_init_handler(struct target_s *target, enum target_event event, void *priv)
+int target_poll(struct target_s *target)
 {
-       FILE *script;
-       struct command_context_s *cmd_ctx = priv;
-       
-       if ((event == TARGET_EVENT_HALTED) && (target->reset_script))
+       /* We can't poll until after examine */
+       if (!target_was_examined(target))
        {
-               target_unregister_event_callback(target_init_handler, priv);
+               /* Fail silently lest we pollute the log */
+               return ERROR_FAIL;
+       }
+       return target->type->poll(target);
+}
 
-               script = open_file_from_path(target->reset_script, "r");
-               if (!script)
-               {
-                       LOG_ERROR("couldn't open script file %s", target->reset_script);
-                               return ERROR_OK;
-               }
+int target_halt(struct target_s *target)
+{
+       /* We can't poll until after examine */
+       if (!target_was_examined(target))
+       {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+       return target->type->halt(target);
+}
 
-               LOG_INFO("executing reset script '%s'", target->reset_script);
-               command_run_file(cmd_ctx, script, COMMAND_EXEC);
-               fclose(script);
+int target_resume(struct target_s *target, int current, uint32_t address, int handle_breakpoints, int debug_execution)
+{
+       int retval;
 
-               jtag_execute_queue();
+       /* We can't poll until after examine */
+       if (!target_was_examined(target))
+       {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
        }
-       
+
+       /* note that resume *must* be asynchronous. The CPU can halt before we poll. The CPU can
+        * even halt at the current PC as a result of a software breakpoint being inserted by (a bug?)
+        * the application.
+        */
+       if ((retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution)) != ERROR_OK)
+               return retval;
+
+       return retval;
+}
+
+int target_process_reset(struct command_context_s *cmd_ctx, enum target_reset_mode reset_mode)
+{
+       char buf[100];
+       int retval;
+       Jim_Nvp *n;
+       n = Jim_Nvp_value2name_simple( nvp_reset_modes, reset_mode );
+       if( n->name == NULL ){
+               LOG_ERROR("invalid reset mode");
+               return ERROR_FAIL;
+       }
+
+       /* disable polling during reset to make reset event scripts
+        * more predictable, i.e. dr/irscan & pathmove in events will
+        * not have JTAG operations injected into the middle of a sequence.
+        */
+       int save_poll = target_continuous_poll;
+       target_continuous_poll = 0;
+
+       sprintf( buf, "ocd_process_reset %s", n->name );
+       retval = Jim_Eval( interp, buf );
+
+       target_continuous_poll = save_poll;
+
+       if(retval != JIM_OK) {
+               Jim_PrintErrorMessage(interp);
+               return ERROR_FAIL;
+       }
+
+       /* We want any events to be processed before the prompt */
+       retval = target_call_timer_callbacks_now();
+
+       return retval;
+}
+
+static int default_virt2phys(struct target_s *target, uint32_t virtual, uint32_t *physical)
+{
+       *physical = virtual;
        return ERROR_OK;
 }
 
-int target_run_and_halt_handler(void *priv)
+static int default_mmu(struct target_s *target, int *enabled)
 {
-       target_t *target = priv;
-       
-       target->type->halt(target);
-       
+       *enabled = 0;
+       return ERROR_OK;
+}
+
+static int default_examine(struct target_s *target)
+{
+       target_set_examined(target);
        return ERROR_OK;
 }
 
-int target_process_reset(struct command_context_s *cmd_ctx)
+int target_examine_one(struct target_s *target)
+{
+       return target->type->examine(target);
+}
+
+static int jtag_enable_callback(enum jtag_event event, void *priv)
+{
+       target_t *target = priv;
+
+       if (event != JTAG_TAP_EVENT_ENABLE || !target->tap->enabled)
+               return ERROR_OK;
+
+       jtag_unregister_event_callback(jtag_enable_callback, target);
+       return target_examine_one(target);
+}
+
+
+/* Targets that correctly implement init+examine, i.e.
+ * no communication with target during init:
+ *
+ * XScale
+ */
+int target_examine(void)
 {
        int retval = ERROR_OK;
        target_t *target;
-       struct timeval timeout, now;
 
-       jtag->speed(jtag_speed);
-
-       /* prepare reset_halt where necessary */
-       target = targets;
-       while (target)
+       for (target = all_targets; target; target = target->next)
        {
-               if (jtag_reset_config & RESET_SRST_PULLS_TRST)
-               {
-                       switch (target->reset_mode)
-                       {
-                               case RESET_HALT:
-                                       command_print(cmd_ctx, "nSRST pulls nTRST, falling back to \"reset run_and_halt\"");
-                                       target->reset_mode = RESET_RUN_AND_HALT;
-                                       break;
-                               case RESET_INIT:
-                                       command_print(cmd_ctx, "nSRST pulls nTRST, falling back to \"reset run_and_init\"");
-                                       target->reset_mode = RESET_RUN_AND_INIT;
-                                       break;
-                               default:
-                                       break;
-                       } 
-               }
-               switch (target->reset_mode)
-               {
-                       case RESET_HALT:
-                       case RESET_INIT:
-                               target->type->prepare_reset_halt(target);
-                               break;
-                       default:
-                               break;
+               /* defer examination, but don't skip it */
+               if (!target->tap->enabled) {
+                       jtag_register_event_callback(jtag_enable_callback,
+                                       target);
+                       continue;
                }
-               target = target->next;
+               if ((retval = target_examine_one(target)) != ERROR_OK)
+                       return retval;
        }
-       
-       target = targets;
-       while (target)
+       return retval;
+}
+const char *target_get_name(struct target_s *target)
+{
+       return target->type->name;
+}
+
+static int target_write_memory_imp(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       if (!target_was_examined(target))
        {
-               target->type->assert_reset(target);
-               target = target->next;
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
        }
-       jtag_execute_queue();
-       
-       /* request target halt if necessary, and schedule further action */
-       target = targets;
-       while (target)
+       return target->type->write_memory_imp(target, address, size, count, buffer);
+}
+
+static int target_read_memory_imp(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       if (!target_was_examined(target))
        {
-               switch (target->reset_mode)
-               {
-                       case RESET_RUN:
-                               /* nothing to do if target just wants to be run */
-                               break;
-                       case RESET_RUN_AND_HALT:
-                               /* schedule halt */
-                               target_register_timer_callback(target_run_and_halt_handler, target->run_and_halt_time, 0, target);
-                               break;
-                       case RESET_RUN_AND_INIT:
-                               /* schedule halt */
-                               target_register_timer_callback(target_run_and_halt_handler, target->run_and_halt_time, 0, target);
-                               target_register_event_callback(target_init_handler, cmd_ctx);
-                               break;
-                       case RESET_HALT:
-                               target->type->halt(target);
-                               break;
-                       case RESET_INIT:
-                               target->type->halt(target);
-                               target_register_event_callback(target_init_handler, cmd_ctx);
-                               break;
-                       default:
-                               LOG_ERROR("BUG: unknown target->reset_mode");
-               }
-               target = target->next;
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
        }
-       
-       target = targets;
-       while (target)
+       return target->type->read_memory_imp(target, address, size, count, buffer);
+}
+
+static int target_soft_reset_halt_imp(struct target_s *target)
+{
+       if (!target_was_examined(target))
        {
-               target->type->deassert_reset(target);
-               target = target->next;
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
        }
-       jtag_execute_queue();
-       
-       /* Wait for reset to complete, maximum 5 seconds. */    
-       gettimeofday(&timeout, NULL);
-       timeval_add_time(&timeout, 5, 0);
-       for(;;)
+       return target->type->soft_reset_halt_imp(target);
+}
+
+static int target_run_algorithm_imp(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_param, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info)
+{
+       if (!target_was_examined(target))
        {
-               gettimeofday(&now, NULL);
-               
-               target_call_timer_callbacks_now();
-               
-               target = targets;
-               while (target)
-               {
-                       target->type->poll(target);
-                       if ((target->reset_mode == RESET_RUN_AND_INIT) || (target->reset_mode == RESET_RUN_AND_HALT))
-                       {
-                               if (target->state != TARGET_HALTED)
-                               {
-                                       if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec)))
-                                       {
-                                               LOG_USER("Timed out waiting for reset");
-                                               goto done;
-                                       }
-                                       /* this will send alive messages on e.g. GDB remote protocol. */
-                                       usleep(500*1000); 
-                                       LOG_USER_N("%s", ""); /* avoid warning about zero length formatting message*/ 
-                                       goto again;
-                               }
-                       }
-                       target = target->next;
-               }
-               /* All targets we're waiting for are halted */
-               break;
-               
-               again:;
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
        }
-       done:
-       
-       
-       /* We want any events to be processed before the prompt */
-       target_call_timer_callbacks_now();
+       return target->type->run_algorithm_imp(target, num_mem_params, mem_params, num_reg_params, reg_param, entry_point, exit_point, timeout_ms, arch_info);
+}
 
-       jtag->speed(jtag_speed_post_reset);
-       
-       return retval;
+int target_read_memory(struct target_s *target,
+               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       return target->type->read_memory(target, address, size, count, buffer);
 }
 
-static int default_virt2phys(struct target_s *target, u32 virtual, u32 *physical)
+int target_write_memory(struct target_s *target,
+               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
 {
-       *physical = virtual;
-       return ERROR_OK;
+       return target->type->write_memory(target, address, size, count, buffer);
+}
+int target_bulk_write_memory(struct target_s *target,
+               uint32_t address, uint32_t count, uint8_t *buffer)
+{
+       return target->type->bulk_write_memory(target, address, count, buffer);
 }
 
-static int default_mmu(struct target_s *target, int *enabled)
+int target_add_breakpoint(struct target_s *target,
+               struct breakpoint_s *breakpoint)
 {
-       *enabled = 0;
-       return ERROR_OK;
+       return target->type->add_breakpoint(target, breakpoint);
+}
+int target_remove_breakpoint(struct target_s *target,
+               struct breakpoint_s *breakpoint)
+{
+       return target->type->remove_breakpoint(target, breakpoint);
+}
+
+int target_add_watchpoint(struct target_s *target,
+               struct watchpoint_s *watchpoint)
+{
+       return target->type->add_watchpoint(target, watchpoint);
+}
+int target_remove_watchpoint(struct target_s *target,
+               struct watchpoint_s *watchpoint)
+{
+       return target->type->remove_watchpoint(target, watchpoint);
+}
+
+int target_get_gdb_reg_list(struct target_s *target,
+               struct reg_s **reg_list[], int *reg_list_size)
+{
+       return target->type->get_gdb_reg_list(target, reg_list, reg_list_size);
+}
+int target_step(struct target_s *target,
+               int current, uint32_t address, int handle_breakpoints)
+{
+       return target->type->step(target, current, address, handle_breakpoints);
+}
+
+
+int target_run_algorithm(struct target_s *target,
+               int num_mem_params, mem_param_t *mem_params,
+               int num_reg_params, reg_param_t *reg_param,
+               uint32_t entry_point, uint32_t exit_point,
+               int timeout_ms, void *arch_info)
+{
+       return target->type->run_algorithm(target,
+                       num_mem_params, mem_params, num_reg_params, reg_param,
+                       entry_point, exit_point, timeout_ms, arch_info);
+}
+
+/// @returns @c true if the target has been examined.
+bool target_was_examined(struct target_s *target)
+{
+       return target->type->examined;
+}
+/// Sets the @c examined flag for the given target.
+void target_set_examined(struct target_s *target)
+{
+       target->type->examined = true;
+}
+// Reset the @c examined flag for the given target.
+void target_reset_examined(struct target_s *target)
+{
+       target->type->examined = false;
 }
 
+
 int target_init(struct command_context_s *cmd_ctx)
 {
-       target_t *target = targets;
-       
+       target_t *target = all_targets;
+       int retval;
+
        while (target)
        {
-               if (target->type->init_target(cmd_ctx, target) != ERROR_OK)
+               target_reset_examined(target);
+               if (target->type->examine == NULL)
+               {
+                       target->type->examine = default_examine;
+               }
+
+               if ((retval = target->type->init_target(cmd_ctx, target)) != ERROR_OK)
                {
-                       LOG_ERROR("target '%s' init failed", target->type->name);
-                       exit(-1);
+                       LOG_ERROR("target '%s' init failed", target_get_name(target));
+                       return retval;
                }
-               
+
                /* Set up default functions if none are provided by target */
                if (target->type->virt2phys == NULL)
                {
                        target->type->virt2phys = default_virt2phys;
                }
+               target->type->virt2phys = default_virt2phys;
+               /* a non-invasive way(in terms of patches) to add some code that
+                * runs before the type->write/read_memory implementation
+                */
+               target->type->write_memory_imp = target->type->write_memory;
+               target->type->write_memory = target_write_memory_imp;
+               target->type->read_memory_imp = target->type->read_memory;
+               target->type->read_memory = target_read_memory_imp;
+               target->type->soft_reset_halt_imp = target->type->soft_reset_halt;
+               target->type->soft_reset_halt = target_soft_reset_halt_imp;
+               target->type->run_algorithm_imp = target->type->run_algorithm;
+               target->type->run_algorithm = target_run_algorithm_imp;
+
                if (target->type->mmu == NULL)
                {
                        target->type->mmu = default_mmu;
                }
                target = target->next;
        }
-       
-       if (targets)
+
+       if (all_targets)
        {
-               target_register_user_commands(cmd_ctx);
-               target_register_timer_callback(handle_target, 100, 1, NULL);
+               if((retval = target_register_user_commands(cmd_ctx)) != ERROR_OK)
+                       return retval;
+               if((retval = target_register_timer_callback(handle_target, 100, 1, NULL)) != ERROR_OK)
+                       return retval;
        }
-               
-       return ERROR_OK;
-}
 
-int target_init_reset(struct command_context_s *cmd_ctx)
-{
-       if (startup_mode == DAEMON_RESET)
-               target_process_reset(cmd_ctx);
-       
        return ERROR_OK;
 }
 
 int target_register_event_callback(int (*callback)(struct target_s *target, enum target_event event, void *priv), void *priv)
 {
        target_event_callback_t **callbacks_p = &target_event_callbacks;
-       
+
        if (callback == NULL)
        {
                return ERROR_INVALID_ARGUMENTS;
        }
-       
+
        if (*callbacks_p)
        {
                while ((*callbacks_p)->next)
                        callbacks_p = &((*callbacks_p)->next);
                callbacks_p = &((*callbacks_p)->next);
        }
-       
+
        (*callbacks_p) = malloc(sizeof(target_event_callback_t));
        (*callbacks_p)->callback = callback;
        (*callbacks_p)->priv = priv;
        (*callbacks_p)->next = NULL;
-       
+
        return ERROR_OK;
 }
 
@@ -470,24 +722,24 @@ int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int
 {
        target_timer_callback_t **callbacks_p = &target_timer_callbacks;
        struct timeval now;
-       
+
        if (callback == NULL)
        {
                return ERROR_INVALID_ARGUMENTS;
        }
-       
+
        if (*callbacks_p)
        {
                while ((*callbacks_p)->next)
                        callbacks_p = &((*callbacks_p)->next);
                callbacks_p = &((*callbacks_p)->next);
        }
-       
+
        (*callbacks_p) = malloc(sizeof(target_timer_callback_t));
        (*callbacks_p)->callback = callback;
        (*callbacks_p)->periodic = periodic;
        (*callbacks_p)->time_ms = time_ms;
-       
+
        gettimeofday(&now, NULL);
        (*callbacks_p)->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000;
        time_ms -= (time_ms % 1000);
@@ -497,10 +749,10 @@ int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int
                (*callbacks_p)->when.tv_usec = (*callbacks_p)->when.tv_usec - 1000000;
                (*callbacks_p)->when.tv_sec += 1;
        }
-       
+
        (*callbacks_p)->priv = priv;
        (*callbacks_p)->next = NULL;
-       
+
        return ERROR_OK;
 }
 
@@ -508,12 +760,12 @@ int target_unregister_event_callback(int (*callback)(struct target_s *target, en
 {
        target_event_callback_t **p = &target_event_callbacks;
        target_event_callback_t *c = target_event_callbacks;
-       
+
        if (callback == NULL)
        {
                return ERROR_INVALID_ARGUMENTS;
        }
-               
+
        while (c)
        {
                target_event_callback_t *next = c->next;
@@ -527,7 +779,7 @@ int target_unregister_event_callback(int (*callback)(struct target_s *target, en
                        p = &(c->next);
                c = next;
        }
-       
+
        return ERROR_OK;
 }
 
@@ -535,12 +787,12 @@ int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
 {
        target_timer_callback_t **p = &target_timer_callbacks;
        target_timer_callback_t *c = target_timer_callbacks;
-       
+
        if (callback == NULL)
        {
                return ERROR_INVALID_ARGUMENTS;
        }
-               
+
        while (c)
        {
                target_timer_callback_t *next = c->next;
@@ -554,7 +806,7 @@ int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
                        p = &(c->next);
                c = next;
        }
-       
+
        return ERROR_OK;
 }
 
@@ -562,75 +814,103 @@ int target_call_event_callbacks(target_t *target, enum target_event event)
 {
        target_event_callback_t *callback = target_event_callbacks;
        target_event_callback_t *next_callback;
-       
-       LOG_DEBUG("target event %i", event);
-       
+
+       if (event == TARGET_EVENT_HALTED)
+       {
+               /* execute early halted first */
+               target_call_event_callbacks(target, TARGET_EVENT_EARLY_HALTED);
+       }
+
+       LOG_DEBUG("target event %i (%s)",
+                         event,
+                         Jim_Nvp_value2name_simple( nvp_target_event, event )->name );
+
+       target_handle_event( target, event );
+
        while (callback)
        {
                next_callback = callback->next;
                callback->callback(target, event, callback->priv);
                callback = next_callback;
        }
-       
+
+       return ERROR_OK;
+}
+
+static int target_timer_callback_periodic_restart(
+               target_timer_callback_t *cb, struct timeval *now)
+{
+       int time_ms = cb->time_ms;
+       cb->when.tv_usec = now->tv_usec + (time_ms % 1000) * 1000;
+       time_ms -= (time_ms % 1000);
+       cb->when.tv_sec = now->tv_sec + time_ms / 1000;
+       if (cb->when.tv_usec > 1000000)
+       {
+               cb->when.tv_usec = cb->when.tv_usec - 1000000;
+               cb->when.tv_sec += 1;
+       }
        return ERROR_OK;
 }
 
+static int target_call_timer_callback(target_timer_callback_t *cb,
+               struct timeval *now)
+{
+       cb->callback(cb->priv);
+
+       if (cb->periodic)
+               return target_timer_callback_periodic_restart(cb, now);
+
+       return target_unregister_timer_callback(cb->callback, cb->priv);
+}
+
 static int target_call_timer_callbacks_check_time(int checktime)
 {
-       target_timer_callback_t *callback = target_timer_callbacks;
-       target_timer_callback_t *next_callback;
-       struct timeval now;
+       keep_alive();
 
+       struct timeval now;
        gettimeofday(&now, NULL);
-       
+
+       target_timer_callback_t *callback = target_timer_callbacks;
        while (callback)
        {
-               next_callback = callback->next;
-               
-               if ((!checktime&&callback->periodic)||
-                               (((now.tv_sec >= callback->when.tv_sec) && (now.tv_usec >= callback->when.tv_usec))
-                                               || (now.tv_sec > callback->when.tv_sec)))
+               // cleaning up may unregister and free this callback
+               target_timer_callback_t *next_callback = callback->next;
+
+               bool call_it = callback->callback &&
+                       ((!checktime && callback->periodic) ||
+                         now.tv_sec > callback->when.tv_sec ||
+                        (now.tv_sec == callback->when.tv_sec &&
+                         now.tv_usec >= callback->when.tv_usec));
+
+               if (call_it)
                {
-                       callback->callback(callback->priv);
-                       if (callback->periodic)
-                       {
-                               int time_ms = callback->time_ms;
-                               callback->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000;
-                               time_ms -= (time_ms % 1000);
-                               callback->when.tv_sec = now.tv_sec + time_ms / 1000;
-                               if (callback->when.tv_usec > 1000000)
-                               {
-                                       callback->when.tv_usec = callback->when.tv_usec - 1000000;
-                                       callback->when.tv_sec += 1;
-                               }
-                       }
-                       else
-                               target_unregister_timer_callback(callback->callback, callback->priv);
+                       int retval = target_call_timer_callback(callback, &now);
+                       if (retval != ERROR_OK)
+                               return retval;
                }
-                       
+
                callback = next_callback;
        }
-       
+
        return ERROR_OK;
 }
 
-int target_call_timer_callbacks()
+int target_call_timer_callbacks(void)
 {
        return target_call_timer_callbacks_check_time(1);
 }
 
 /* invoke periodic callbacks immediately */
-int target_call_timer_callbacks_now()
+int target_call_timer_callbacks_now(void)
 {
-       return target_call_timer_callbacks(0);
+       return target_call_timer_callbacks_check_time(0);
 }
 
-
-int target_alloc_working_area(struct target_s *target, u32 size, working_area_t **area)
+int target_alloc_working_area(struct target_s *target, uint32_t size, working_area_t **area)
 {
        working_area_t *c = target->working_areas;
        working_area_t *new_wa = NULL;
-       
+
        /* Reevaluate working area address based on MMU state*/
        if (target->working_areas == NULL)
        {
@@ -650,14 +930,14 @@ int target_alloc_working_area(struct target_s *target, u32 size, working_area_t
                        target->working_area = target->working_area_phys;
                }
        }
-       
+
        /* only allocate multiples of 4 byte */
        if (size % 4)
        {
                LOG_ERROR("BUG: code tried to allocate unaligned number of bytes, padding");
                size = CEIL(size, 4);
        }
-       
+
        /* see if there's already a matching working area */
        while (c)
        {
@@ -668,16 +948,16 @@ int target_alloc_working_area(struct target_s *target, u32 size, working_area_t
                }
                c = c->next;
        }
-       
+
        /* if not, allocate a new one */
        if (!new_wa)
        {
                working_area_t **p = &target->working_areas;
-               u32 first_free = target->working_area;
-               u32 free_size = target->working_area_size;
-               
+               uint32_t first_free = target->working_area;
+               uint32_t free_size = target->working_area_size;
+
                LOG_DEBUG("allocating new working area");
-               
+
                c = target->working_areas;
                while (c)
                {
@@ -686,91 +966,111 @@ int target_alloc_working_area(struct target_s *target, u32 size, working_area_t
                        p = &c->next;
                        c = c->next;
                }
-               
+
                if (free_size < size)
                {
                        LOG_WARNING("not enough working area available(requested %d, free %d)", size, free_size);
                        return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
                }
-               
+
                new_wa = malloc(sizeof(working_area_t));
                new_wa->next = NULL;
                new_wa->size = size;
                new_wa->address = first_free;
-               
+
                if (target->backup_working_area)
                {
+                       int retval;
                        new_wa->backup = malloc(new_wa->size);
-                       target->type->read_memory(target, new_wa->address, 4, new_wa->size / 4, new_wa->backup);
+                       if((retval = target_read_memory(target, new_wa->address, 4, new_wa->size / 4, new_wa->backup)) != ERROR_OK)
+                       {
+                               free(new_wa->backup);
+                               free(new_wa);
+                               return retval;
+                       }
                }
                else
                {
                        new_wa->backup = NULL;
                }
-               
+
                /* put new entry in list */
                *p = new_wa;
        }
-       
+
        /* mark as used, and return the new (reused) area */
        new_wa->free = 0;
        *area = new_wa;
-       
+
        /* user pointer */
        new_wa->user = area;
-       
+
        return ERROR_OK;
 }
 
-int target_free_working_area(struct target_s *target, working_area_t *area)
+int target_free_working_area_restore(struct target_s *target, working_area_t *area, int restore)
 {
        if (area->free)
                return ERROR_OK;
-       
-       if (target->backup_working_area)
-               target->type->write_memory(target, area->address, 4, area->size / 4, area->backup);
-       
+
+       if (restore&&target->backup_working_area)
+       {
+               int retval;
+               if((retval = target_write_memory(target, area->address, 4, area->size / 4, area->backup)) != ERROR_OK)
+                       return retval;
+       }
+
        area->free = 1;
-       
+
        /* mark user pointer invalid */
        *area->user = NULL;
        area->user = NULL;
-       
+
        return ERROR_OK;
 }
 
-int target_free_all_working_areas(struct target_s *target)
+int target_free_working_area(struct target_s *target, working_area_t *area)
+{
+       return target_free_working_area_restore(target, area, 1);
+}
+
+/* free resources and restore memory, if restoring memory fails,
+ * free up resources anyway
+ */
+void target_free_all_working_areas_restore(struct target_s *target, int restore)
 {
        working_area_t *c = target->working_areas;
 
        while (c)
        {
                working_area_t *next = c->next;
-               target_free_working_area(target, c);
-               
+               target_free_working_area_restore(target, c, restore);
+
                if (c->backup)
                        free(c->backup);
-               
+
                free(c);
-               
+
                c = next;
        }
-       
+
        target->working_areas = NULL;
-       
-       return ERROR_OK;
+}
+
+void target_free_all_working_areas(struct target_s *target)
+{
+       target_free_all_working_areas_restore(target, 1);
 }
 
 int target_register_commands(struct command_context_s *cmd_ctx)
 {
-       register_command(cmd_ctx, NULL, "target", handle_target_command, COMMAND_CONFIG, NULL);
-       register_command(cmd_ctx, NULL, "targets", handle_targets_command, COMMAND_EXEC, NULL);
-       register_command(cmd_ctx, NULL, "daemon_startup", handle_daemon_startup_command, COMMAND_CONFIG, NULL);
-       register_command(cmd_ctx, NULL, "target_script", handle_target_script_command, COMMAND_CONFIG, NULL);
-       register_command(cmd_ctx, NULL, "run_and_halt_time", handle_run_and_halt_time_command, COMMAND_CONFIG, "<target> <run time ms>");
-       register_command(cmd_ctx, NULL, "working_area", handle_working_area_command, COMMAND_ANY, "working_area <target#> <address> <size> <'backup'|'nobackup'> [virtual address]");
-       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>");
+
+       register_command(cmd_ctx, NULL, "targets", handle_targets_command, COMMAND_EXEC, "change the current command line target (one parameter) or lists targets (with no parameter)");
+
+
+
+
+       register_jim(cmd_ctx, "target", jim_target, "configure target" );
 
        return ERROR_OK;
 }
@@ -783,52 +1083,69 @@ int target_arch_state(struct target_s *target)
                LOG_USER("No target has been configured");
                return ERROR_OK;
        }
-       
-       LOG_USER("target state: %s", target_state_strings[target->state]);
-       
+
+       LOG_USER("target state: %s",
+                Jim_Nvp_value2name_simple(nvp_target_state,target->state)->name);
+
        if (target->state!=TARGET_HALTED)
                return ERROR_OK;
-       
+
        retval=target->type->arch_state(target);
        return retval;
 }
 
-/* Single aligned words are guaranteed to use 16 or 32 bit access 
- * mode respectively, otherwise data is handled as quickly as 
+/* Single aligned words are guaranteed to use 16 or 32 bit access
+ * mode respectively, otherwise data is handled as quickly as
  * possible
  */
-int target_write_buffer(struct target_s *target, u32 address, u32 size, u8 *buffer)
+int target_write_buffer(struct target_s *target, uint32_t address, uint32_t size, uint8_t *buffer)
 {
        int retval;
-       
        LOG_DEBUG("writing buffer of %i byte at 0x%8.8x", size, address);
-       
+
+       if (!target_was_examined(target))
+       {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
+       if (size == 0) {
+               return ERROR_OK;
+       }
+
+       if ((address + size - 1) < address)
+       {
+               /* GDB can request this when e.g. PC is 0xfffffffc*/
+               LOG_ERROR("address+size wrapped(0x%08x, 0x%08x)", address, size);
+               return ERROR_FAIL;
+       }
+
        if (((address % 2) == 0) && (size == 2))
        {
-               return target->type->write_memory(target, address, 2, 1, buffer);
+               return target_write_memory(target, address, 2, 1, buffer);
        }
-       
+
        /* handle unaligned head bytes */
        if (address % 4)
        {
-               int unaligned = 4 - (address % 4);
-               
+               uint32_t unaligned = 4 - (address % 4);
+
                if (unaligned > size)
                        unaligned = size;
 
-               if ((retval = target->type->write_memory(target, address, 1, unaligned, buffer)) != ERROR_OK)
+               if ((retval = target_write_memory(target, address, 1, unaligned, buffer)) != ERROR_OK)
                        return retval;
-               
+
                buffer += unaligned;
                address += unaligned;
                size -= unaligned;
        }
-               
+
        /* handle aligned words */
        if (size >= 4)
        {
                int aligned = size - (size % 4);
-       
+
                /* use bulk writes above a certain limit. This may have to be changed */
                if (aligned > 128)
                {
@@ -837,89 +1154,109 @@ int target_write_buffer(struct target_s *target, u32 address, u32 size, u8 *buff
                }
                else
                {
-                       if ((retval = target->type->write_memory(target, address, 4, aligned / 4, buffer)) != ERROR_OK)
+                       if ((retval = target_write_memory(target, address, 4, aligned / 4, buffer)) != ERROR_OK)
                                return retval;
                }
-               
+
                buffer += aligned;
                address += aligned;
                size -= aligned;
        }
-       
+
        /* handle tail writes of less than 4 bytes */
        if (size > 0)
        {
-               if ((retval = target->type->write_memory(target, address, 1, size, buffer)) != ERROR_OK)
+               if ((retval = target_write_memory(target, address, 1, size, buffer)) != ERROR_OK)
                        return retval;
        }
-       
+
        return ERROR_OK;
 }
 
-
-/* Single aligned words are guaranteed to use 16 or 32 bit access 
- * mode respectively, otherwise data is handled as quickly as 
+/* Single aligned words are guaranteed to use 16 or 32 bit access
+ * mode respectively, otherwise data is handled as quickly as
  * possible
  */
-int target_read_buffer(struct target_s *target, u32 address, u32 size, u8 *buffer)
+int target_read_buffer(struct target_s *target, uint32_t address, uint32_t size, uint8_t *buffer)
 {
        int retval;
-       
        LOG_DEBUG("reading buffer of %i byte at 0x%8.8x", size, address);
-       
+
+       if (!target_was_examined(target))
+       {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
+       if (size == 0) {
+               return ERROR_OK;
+       }
+
+       if ((address + size - 1) < address)
+       {
+               /* GDB can request this when e.g. PC is 0xfffffffc*/
+               LOG_ERROR("address+size wrapped(0x%08x, 0x%08x)", address, size);
+               return ERROR_FAIL;
+       }
+
        if (((address % 2) == 0) && (size == 2))
        {
-               return target->type->read_memory(target, address, 2, 1, buffer);
+               return target_read_memory(target, address, 2, 1, buffer);
        }
-       
+
        /* handle unaligned head bytes */
        if (address % 4)
        {
-               int unaligned = 4 - (address % 4);
-               
+               uint32_t unaligned = 4 - (address % 4);
+
                if (unaligned > size)
                        unaligned = size;
 
-               if ((retval = target->type->read_memory(target, address, 1, unaligned, buffer)) != ERROR_OK)
+               if ((retval = target_read_memory(target, address, 1, unaligned, buffer)) != ERROR_OK)
                        return retval;
-               
+
                buffer += unaligned;
                address += unaligned;
                size -= unaligned;
        }
-               
+
        /* handle aligned words */
        if (size >= 4)
        {
                int aligned = size - (size % 4);
-       
-               if ((retval = target->type->read_memory(target, address, 4, aligned / 4, buffer)) != ERROR_OK)
+
+               if ((retval = target_read_memory(target, address, 4, aligned / 4, buffer)) != ERROR_OK)
                        return retval;
-               
+
                buffer += aligned;
                address += aligned;
                size -= aligned;
        }
-       
+
        /* handle tail writes of less than 4 bytes */
        if (size > 0)
        {
-               if ((retval = target->type->read_memory(target, address, 1, size, buffer)) != ERROR_OK)
+               if ((retval = target_read_memory(target, address, 1, size, buffer)) != ERROR_OK)
                        return retval;
        }
-       
+
        return ERROR_OK;
 }
 
-int target_checksum_memory(struct target_s *target, u32 address, u32 size, u32* crc)
+int target_checksum_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t* crc)
 {
-       u8 *buffer;
+       uint8_t *buffer;
        int retval;
-       int i;
-       u32 checksum = 0;
-       
+       uint32_t i;
+       uint32_t checksum = 0;
+       if (!target_was_examined(target))
+       {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
        if ((retval = target->type->checksum_memory(target, address,
-               size, &checksum)) == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
+               size, &checksum)) != ERROR_OK)
        {
                buffer = malloc(size);
                if (buffer == NULL)
@@ -935,28 +1272,50 @@ int target_checksum_memory(struct target_s *target, u32 address, u32 size, u32*
                }
 
                /* convert to target endianess */
-               for (i = 0; i < (size/sizeof(u32)); i++)
+               for (i = 0; i < (size/sizeof(uint32_t)); i++)
                {
-                       u32 target_data;
-                       target_data = target_buffer_get_u32(target, &buffer[i*sizeof(u32)]);
-                       target_buffer_set_u32(target, &buffer[i*sizeof(u32)], target_data);
+                       uint32_t target_data;
+                       target_data = target_buffer_get_u32(target, &buffer[i*sizeof(uint32_t)]);
+                       target_buffer_set_u32(target, &buffer[i*sizeof(uint32_t)], target_data);
                }
 
                retval = image_calculate_checksum( buffer, size, &checksum );
                free(buffer);
        }
-       
+
        *crc = checksum;
-       
+
        return retval;
 }
 
-int target_read_u32(struct target_s *target, u32 address, u32 *value)
+int target_blank_check_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t* blank)
 {
-       u8 value_buf[4];
+       int retval;
+       if (!target_was_examined(target))
+       {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
+       if (target->type->blank_check_memory == 0)
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+
+       retval = target->type->blank_check_memory(target, address, size, blank);
+
+       return retval;
+}
+
+int target_read_u32(struct target_s *target, uint32_t address, uint32_t *value)
+{
+       uint8_t value_buf[4];
+       if (!target_was_examined(target))
+       {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
+       int retval = target_read_memory(target, address, 4, 1, value_buf);
 
-       int retval = target->type->read_memory(target, address, 4, 1, value_buf);
-       
        if (retval == ERROR_OK)
        {
                *value = target_buffer_get_u32(target, value_buf);
@@ -967,16 +1326,21 @@ int target_read_u32(struct target_s *target, u32 address, u32 *value)
                *value = 0x0;
                LOG_DEBUG("address: 0x%8.8x failed", address);
        }
-       
+
        return retval;
 }
 
-int target_read_u16(struct target_s *target, u32 address, u16 *value)
+int target_read_u16(struct target_s *target, uint32_t address, uint16_t *value)
 {
-       u8 value_buf[2];
-       
-       int retval = target->type->read_memory(target, address, 2, 1, value_buf);
-       
+       uint8_t value_buf[2];
+       if (!target_was_examined(target))
+       {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
+       int retval = target_read_memory(target, address, 2, 1, value_buf);
+
        if (retval == ERROR_OK)
        {
                *value = target_buffer_get_u16(target, value_buf);
@@ -987,13 +1351,18 @@ int target_read_u16(struct target_s *target, u32 address, u16 *value)
                *value = 0x0;
                LOG_DEBUG("address: 0x%8.8x failed", address);
        }
-       
+
        return retval;
 }
 
-int target_read_u8(struct target_s *target, u32 address, u8 *value)
+int target_read_u8(struct target_s *target, uint32_t address, uint8_t *value)
 {
-       int retval = target->type->read_memory(target, address, 1, 1, value);
+       int retval = target_read_memory(target, address, 1, 1, value);
+       if (!target_was_examined(target))
+       {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
 
        if (retval == ERROR_OK)
        {
@@ -1004,390 +1373,339 @@ int target_read_u8(struct target_s *target, u32 address, u8 *value)
                *value = 0x0;
                LOG_DEBUG("address: 0x%8.8x failed", address);
        }
-       
+
        return retval;
 }
 
-int target_write_u32(struct target_s *target, u32 address, u32 value)
+int target_write_u32(struct target_s *target, uint32_t address, uint32_t value)
 {
        int retval;
-       u8 value_buf[4];
+       uint8_t value_buf[4];
+       if (!target_was_examined(target))
+       {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
 
        LOG_DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, value);
 
-       target_buffer_set_u32(target, value_buf, value);        
-       if ((retval = target->type->write_memory(target, address, 4, 1, value_buf)) != ERROR_OK)
+       target_buffer_set_u32(target, value_buf, value);
+       if ((retval = target_write_memory(target, address, 4, 1, value_buf)) != ERROR_OK)
        {
                LOG_DEBUG("failed: %i", retval);
        }
-       
+
        return retval;
 }
 
-int target_write_u16(struct target_s *target, u32 address, u16 value)
+int target_write_u16(struct target_s *target, uint32_t address, uint16_t value)
 {
        int retval;
-       u8 value_buf[2];
-       
+       uint8_t value_buf[2];
+       if (!target_was_examined(target))
+       {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
        LOG_DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, value);
 
-       target_buffer_set_u16(target, value_buf, value);        
-       if ((retval = target->type->write_memory(target, address, 2, 1, value_buf)) != ERROR_OK)
+       target_buffer_set_u16(target, value_buf, value);
+       if ((retval = target_write_memory(target, address, 2, 1, value_buf)) != ERROR_OK)
        {
                LOG_DEBUG("failed: %i", retval);
        }
-       
+
        return retval;
 }
 
-int target_write_u8(struct target_s *target, u32 address, u8 value)
+int target_write_u8(struct target_s *target, uint32_t address, uint8_t value)
 {
        int retval;
-       
+       if (!target_was_examined(target))
+       {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
        LOG_DEBUG("address: 0x%8.8x, value: 0x%2.2x", address, value);
 
-       if ((retval = target->type->read_memory(target, address, 1, 1, &value)) != ERROR_OK)
+       if ((retval = target_write_memory(target, address, 1, 1, &value)) != ERROR_OK)
        {
                LOG_DEBUG("failed: %i", retval);
        }
-       
+
        return retval;
 }
 
 int target_register_user_commands(struct command_context_s *cmd_ctx)
 {
-       register_command(cmd_ctx,  NULL, "reg", handle_reg_command, COMMAND_EXEC, NULL);
+       int retval = ERROR_OK;
+
+
+       /* script procedures */
+       register_command(cmd_ctx, NULL, "profile", handle_profile_command, COMMAND_EXEC, "profiling samples the CPU PC");
+       register_jim(cmd_ctx, "ocd_mem2array", jim_mem2array, "read memory and return as a TCL array for script processing <ARRAYNAME> <WIDTH=32/16/8> <ADDRESS> <COUNT>");
+       register_jim(cmd_ctx, "ocd_array2mem", jim_array2mem, "convert a TCL array to memory locations and write the values  <ARRAYNAME> <WIDTH=32/16/8> <ADDRESS> <COUNT>");
+
+       register_command(cmd_ctx, NULL, "fast_load_image", handle_fast_load_image_command, COMMAND_ANY,
+                       "same args as load_image, image stored in memory - mainly for profiling purposes");
+
+       register_command(cmd_ctx, NULL, "fast_load", handle_fast_load_command, COMMAND_ANY,
+                       "loads active fast load image to current target - mainly for profiling purposes");
+
+
+       register_command(cmd_ctx, NULL, "virt2phys", handle_virt2phys_command, COMMAND_ANY, "translate a virtual address into a physical address");
+       register_command(cmd_ctx,  NULL, "reg", handle_reg_command, COMMAND_EXEC, "display or set a register");
        register_command(cmd_ctx,  NULL, "poll", handle_poll_command, COMMAND_EXEC, "poll target state");
        register_command(cmd_ctx,  NULL, "wait_halt", handle_wait_halt_command, COMMAND_EXEC, "wait for target halt [time (s)]");
        register_command(cmd_ctx,  NULL, "halt", handle_halt_command, COMMAND_EXEC, "halt target");
        register_command(cmd_ctx,  NULL, "resume", handle_resume_command, COMMAND_EXEC, "resume target [addr]");
        register_command(cmd_ctx,  NULL, "step", handle_step_command, COMMAND_EXEC, "step one instruction from current PC or [addr]");
-       register_command(cmd_ctx,  NULL, "reset", handle_reset_command, COMMAND_EXEC, "reset target [run|halt|init|run_and_halt|run_and_init]");
+       register_command(cmd_ctx,  NULL, "reset", handle_reset_command, COMMAND_EXEC, "reset target [run|halt|init] - default is run");
        register_command(cmd_ctx,  NULL, "soft_reset_halt", handle_soft_reset_halt_command, COMMAND_EXEC, "halt the target and do a soft reset");
 
        register_command(cmd_ctx,  NULL, "mdw", handle_md_command, COMMAND_EXEC, "display memory words <addr> [count]");
        register_command(cmd_ctx,  NULL, "mdh", handle_md_command, COMMAND_EXEC, "display memory half-words <addr> [count]");
        register_command(cmd_ctx,  NULL, "mdb", handle_md_command, COMMAND_EXEC, "display memory bytes <addr> [count]");
-       
+
        register_command(cmd_ctx,  NULL, "mww", handle_mw_command, COMMAND_EXEC, "write memory word <addr> <value> [count]");
        register_command(cmd_ctx,  NULL, "mwh", handle_mw_command, COMMAND_EXEC, "write memory half-word <addr> <value> [count]");
        register_command(cmd_ctx,  NULL, "mwb", handle_mw_command, COMMAND_EXEC, "write memory byte <addr> <value> [count]");
-       
-       register_command(cmd_ctx,  NULL, "bp", handle_bp_command, COMMAND_EXEC, "set breakpoint <address> <length> [hw]");      
+
+       register_command(cmd_ctx,  NULL, "bp", handle_bp_command, COMMAND_EXEC, "set breakpoint <address> <length> [hw]");
        register_command(cmd_ctx,  NULL, "rbp", handle_rbp_command, COMMAND_EXEC, "remove breakpoint <adress>");
-       register_command(cmd_ctx,  NULL, "wp", handle_wp_command, COMMAND_EXEC, "set watchpoint <address> <length> <r/w/a> [value] [mask]");    
+       register_command(cmd_ctx,  NULL, "wp", handle_wp_command, COMMAND_EXEC, "set watchpoint <address> <length> <r/w/a> [value] [mask]");
        register_command(cmd_ctx,  NULL, "rwp", handle_rwp_command, COMMAND_EXEC, "remove watchpoint <adress>");
-       
-       register_command(cmd_ctx,  NULL, "load_image", handle_load_image_command, COMMAND_EXEC, "load_image <file> <address> ['bin'|'ihex'|'elf'|'s19']");
+
+       register_command(cmd_ctx,  NULL, "load_image", handle_load_image_command, COMMAND_EXEC, "load_image <file> <address> ['bin'|'ihex'|'elf'|'s19'] [min_address] [max_length]");
        register_command(cmd_ctx,  NULL, "dump_image", handle_dump_image_command, COMMAND_EXEC, "dump_image <file> <address> <size>");
        register_command(cmd_ctx,  NULL, "verify_image", handle_verify_image_command, COMMAND_EXEC, "verify_image <file> [offset] [type]");
-       register_command(cmd_ctx,  NULL, "load_binary", handle_load_image_command, COMMAND_EXEC, "[DEPRECATED] load_binary <file> <address>");
-       register_command(cmd_ctx,  NULL, "dump_binary", handle_dump_image_command, COMMAND_EXEC, "[DEPRECATED] dump_binary <file> <address> <size>");
-       
-       target_request_register_commands(cmd_ctx);
-       trace_register_commands(cmd_ctx);
-       
-       return ERROR_OK;
+       register_command(cmd_ctx,  NULL, "test_image", handle_test_image_command, COMMAND_EXEC, "test_image <file> [offset] [type]");
+
+       if((retval = target_request_register_commands(cmd_ctx)) != ERROR_OK)
+               return retval;
+       if((retval = trace_register_commands(cmd_ctx)) != ERROR_OK)
+               return retval;
+
+       return retval;
 }
 
-int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
-       target_t *target = targets;
-       int count = 0;
-       
+       target_t *target = all_targets;
+
        if (argc == 1)
        {
-               int num = strtoul(args[0], NULL, 0);
-               
-               while (target)
-               {
-                       count++;
-                       target = target->next;
+               target = get_target(args[0]);
+               if (target == NULL) {
+                       command_print(cmd_ctx,"Target: %s is unknown, try one of:\n", args[0] );
+                       goto DumpTargets;
                }
-               
-               if (num < count)
-                       cmd_ctx->current_target = num;
-               else
-                       command_print(cmd_ctx, "%i is out of bounds, only %i targets are configured", num, count);
-                       
+               if (!target->tap->enabled) {
+                       command_print(cmd_ctx,"Target: TAP %s is disabled, "
+                                       "can't be the current target\n",
+                                       target->tap->dotted_name);
+                       return ERROR_FAIL;
+               }
+
+               cmd_ctx->current_target = target->target_number;
                return ERROR_OK;
        }
-               
+DumpTargets:
+
+       target = all_targets;
+       command_print(cmd_ctx, "    TargetName         Type       Endian TapName            State       ");
+       command_print(cmd_ctx, "--  ------------------ ---------- ------ ------------------ ------------");
        while (target)
        {
-               command_print(cmd_ctx, "%i: %s (%s), state: %s", count++, target->type->name, target_endianess_strings[target->endianness], target_state_strings[target->state]);
+               const char *state;
+               char marker = ' ';
+
+               if (target->tap->enabled)
+                       state = Jim_Nvp_value2name_simple(nvp_target_state,
+                                       target->state)->name;
+               else
+                       state = "tap-disabled";
+
+               if (cmd_ctx->current_target == target->target_number)
+                       marker = '*';
+
+               /* keep columns lined up to match the headers above */
+               command_print(cmd_ctx, "%2d%c %-18s %-10s %-6s %-18s %s",
+                                         target->target_number,
+                                         marker,
+                                         target->cmd_name,
+                                         target_get_name(target),
+                                         Jim_Nvp_value2name_simple(nvp_target_endian,
+                                                               target->endianness)->name,
+                                         target->tap->dotted_name,
+                                         state);
                target = target->next;
        }
-       
+
        return ERROR_OK;
 }
 
-int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-       int i;
-       int found = 0;
-       
-       if (argc < 3)
-       {
-               return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-       
-       /* search for the specified target */
-       if (args[0] && (args[0][0] != 0))
-       {
-               for (i = 0; target_types[i]; i++)
-               {
-                       if (strcmp(args[0], target_types[i]->name) == 0)
-                       {
-                               target_t **last_target_p = &targets;
-                               
-                               /* register target specific commands */
-                               if (target_types[i]->register_commands(cmd_ctx) != ERROR_OK)
-                               {
-                                       LOG_ERROR("couldn't register '%s' commands", args[0]);
-                                       exit(-1);
-                               }
-
-                               if (*last_target_p)
-                               {
-                                       while ((*last_target_p)->next)
-                                               last_target_p = &((*last_target_p)->next);
-                                       last_target_p = &((*last_target_p)->next);
-                               }
+/* every 300ms we check for reset & powerdropout and issue a "reset halt" if so. */
 
-                               *last_target_p = malloc(sizeof(target_t));
-                               
-                               (*last_target_p)->type = target_types[i];
-                               
-                               if (strcmp(args[1], "big") == 0)
-                                       (*last_target_p)->endianness = TARGET_BIG_ENDIAN;
-                               else if (strcmp(args[1], "little") == 0)
-                                       (*last_target_p)->endianness = TARGET_LITTLE_ENDIAN;
-                               else
-                               {
-                                       LOG_ERROR("endianness must be either 'little' or 'big', not '%s'", args[1]);
-                                       return ERROR_COMMAND_SYNTAX_ERROR;
-                               }
-                               
-                               /* what to do on a target reset */
-                               if (strcmp(args[2], "reset_halt") == 0)
-                                       (*last_target_p)->reset_mode = RESET_HALT;
-                               else if (strcmp(args[2], "reset_run") == 0)
-                                       (*last_target_p)->reset_mode = RESET_RUN;
-                               else if (strcmp(args[2], "reset_init") == 0)
-                                       (*last_target_p)->reset_mode = RESET_INIT;
-                               else if (strcmp(args[2], "run_and_halt") == 0)
-                                       (*last_target_p)->reset_mode = RESET_RUN_AND_HALT;
-                               else if (strcmp(args[2], "run_and_init") == 0)
-                                       (*last_target_p)->reset_mode = RESET_RUN_AND_INIT;
-                               else
-                               {
-                                       LOG_ERROR("unknown target startup mode %s", args[2]);
-                                       return ERROR_COMMAND_SYNTAX_ERROR;
-                               }
-                               (*last_target_p)->run_and_halt_time = 1000; /* default 1s */
-                               
-                               (*last_target_p)->reset_script = NULL;
-                               (*last_target_p)->post_halt_script = NULL;
-                               (*last_target_p)->pre_resume_script = NULL;
-                               (*last_target_p)->gdb_program_script = NULL;
-                               
-                               (*last_target_p)->working_area = 0x0;
-                               (*last_target_p)->working_area_size = 0x0;
-                               (*last_target_p)->working_areas = NULL;
-                               (*last_target_p)->backup_working_area = 0;
-                               
-                               (*last_target_p)->state = TARGET_UNKNOWN;
-                               (*last_target_p)->debug_reason = DBG_REASON_UNDEFINED;
-                               (*last_target_p)->reg_cache = NULL;
-                               (*last_target_p)->breakpoints = NULL;
-                               (*last_target_p)->watchpoints = NULL;
-                               (*last_target_p)->next = NULL;
-                               (*last_target_p)->arch_info = NULL;
-                               
-                               /* initialize trace information */
-                               (*last_target_p)->trace_info = malloc(sizeof(trace_t));
-                               (*last_target_p)->trace_info->num_trace_points = 0;
-                               (*last_target_p)->trace_info->trace_points_size = 0;
-                               (*last_target_p)->trace_info->trace_points = NULL;
-                               (*last_target_p)->trace_info->trace_history_size = 0;
-                               (*last_target_p)->trace_info->trace_history = NULL;
-                               (*last_target_p)->trace_info->trace_history_pos = 0;
-                               (*last_target_p)->trace_info->trace_history_overflowed = 0;
-                               
-                               (*last_target_p)->dbgmsg = NULL;
-                               (*last_target_p)->dbg_msg_enabled = 0;
-                                                               
-                               (*last_target_p)->type->target_command(cmd_ctx, cmd, args, argc, *last_target_p);
-                               
-                               found = 1;
-                               break;
-                       }
-               }
-       }
-       
-       /* no matching target found */
-       if (!found)
-       {
-               LOG_ERROR("target '%s' not found", args[0]);
-               return ERROR_COMMAND_SYNTAX_ERROR;
-       }
+static int powerDropout;
+static int srstAsserted;
 
-       return ERROR_OK;
-}
+static int runPowerRestore;
+static int runPowerDropout;
+static int runSrstAsserted;
+static int runSrstDeasserted;
 
-/* usage: target_script <target#> <event> <script_file> */
-int handle_target_script_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int sense_handler(void)
 {
-       target_t *target = NULL;
-       
-       if (argc < 3)
-       {
-               LOG_ERROR("incomplete target_script command");
-               return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-       
-       target = get_target_by_num(strtoul(args[0], NULL, 0));
-       
-       if (!target)
-       {
-               return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-       
-       if (strcmp(args[1], "reset") == 0)
-       {
-               if (target->reset_script)
-                       free(target->reset_script);
-               target->reset_script = strdup(args[2]);
-       }
-       else if (strcmp(args[1], "post_halt") == 0)
-       {
-               if (target->post_halt_script)
-                       free(target->post_halt_script);
-               target->post_halt_script = strdup(args[2]);
-       }
-       else if (strcmp(args[1], "pre_resume") == 0)
-       {
-               if (target->pre_resume_script)
-                       free(target->pre_resume_script);
-               target->pre_resume_script = strdup(args[2]);
-       }
-       else if (strcmp(args[1], "gdb_program_config") == 0)
-       {
-               if (target->gdb_program_script)
-                       free(target->gdb_program_script);
-               target->gdb_program_script = strdup(args[2]);
-       }
-       else
-       {
-               LOG_ERROR("unknown event type: '%s", args[1]);
-               return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-       
-       return ERROR_OK;
-}
+       static int prevSrstAsserted = 0;
+       static int prevPowerdropout = 0;
 
-int handle_run_and_halt_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-       target_t *target = NULL;
-       
-       if (argc < 2)
-       {
-               return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-       
-       target = get_target_by_num(strtoul(args[0], NULL, 0));
-       if (!target)
-       {
-               return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-       
-       target->run_and_halt_time = strtoul(args[1], NULL, 0);
-       
-       return ERROR_OK;
-}
+       int retval;
+       if ((retval=jtag_power_dropout(&powerDropout))!=ERROR_OK)
+               return retval;
 
-int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-       target_t *target = NULL;
-       
-       if ((argc < 4) || (argc > 5))
-       {
-               return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-       
-       target = get_target_by_num(strtoul(args[0], NULL, 0));
-       if (!target)
+       int powerRestored;
+       powerRestored = prevPowerdropout && !powerDropout;
+       if (powerRestored)
        {
-               return ERROR_COMMAND_SYNTAX_ERROR;
+               runPowerRestore = 1;
        }
-       target_free_all_working_areas(target);
-       
-       target->working_area_phys = target->working_area_virt = strtoul(args[1], NULL, 0);
-       if (argc == 5)
+
+       long long current = timeval_ms();
+       static long long lastPower = 0;
+       int waitMore = lastPower + 2000 > current;
+       if (powerDropout && !waitMore)
        {
-               target->working_area_virt = strtoul(args[4], NULL, 0);
+               runPowerDropout = 1;
+               lastPower = current;
        }
-       target->working_area_size = strtoul(args[2], NULL, 0);
-       
-       if (strcmp(args[3], "backup") == 0)
+
+       if ((retval=jtag_srst_asserted(&srstAsserted))!=ERROR_OK)
+               return retval;
+
+       int srstDeasserted;
+       srstDeasserted = prevSrstAsserted && !srstAsserted;
+
+       static long long lastSrst = 0;
+       waitMore = lastSrst + 2000 > current;
+       if (srstDeasserted && !waitMore)
        {
-               target->backup_working_area = 1;
+               runSrstDeasserted = 1;
+               lastSrst = current;
        }
-       else if (strcmp(args[3], "nobackup") == 0)
+
+       if (!prevSrstAsserted && srstAsserted)
        {
-               target->backup_working_area = 0;
+               runSrstAsserted = 1;
        }
-       else
+
+       prevSrstAsserted = srstAsserted;
+       prevPowerdropout = powerDropout;
+
+       if (srstDeasserted || powerRestored)
        {
-               LOG_ERROR("unrecognized <backup|nobackup> argument (%s)", args[3]);
-               return ERROR_COMMAND_SYNTAX_ERROR;
+               /* Other than logging the event we can't do anything here.
+                * Issuing a reset is a particularly bad idea as we might
+                * be inside a reset already.
+                */
        }
-       
+
        return ERROR_OK;
 }
 
-
 /* process target state changes */
 int handle_target(void *priv)
 {
-       int retval;
-       target_t *target = targets;
-       
-       while (target)
+       int retval = ERROR_OK;
+
+       /* we do not want to recurse here... */
+       static int recursive = 0;
+       if (! recursive)
        {
-               /* only poll if target isn't already halted */
-               if (target->state != TARGET_HALTED)
+               recursive = 1;
+               sense_handler();
+               /* danger! running these procedures can trigger srst assertions and power dropouts.
+                * We need to avoid an infinite loop/recursion here and we do that by
+                * clearing the flags after running these events.
+                */
+               int did_something = 0;
+               if (runSrstAsserted)
                {
-                       if (target_continous_poll)
-                               if ((retval = target->type->poll(target)) != ERROR_OK)
-                               {
-                                       LOG_ERROR("couldn't poll target(%d). It's due for a reset.", retval);
-                               }
+                       Jim_Eval( interp, "srst_asserted");
+                       did_something = 1;
                }
-       
-               target = target->next;
+               if (runSrstDeasserted)
+               {
+                       Jim_Eval( interp, "srst_deasserted");
+                       did_something = 1;
+               }
+               if (runPowerDropout)
+               {
+                       Jim_Eval( interp, "power_dropout");
+                       did_something = 1;
+               }
+               if (runPowerRestore)
+               {
+                       Jim_Eval( interp, "power_restore");
+                       did_something = 1;
+               }
+
+               if (did_something)
+               {
+                       /* clear detect flags */
+                       sense_handler();
+               }
+
+               /* clear action flags */
+
+               runSrstAsserted=0;
+               runSrstDeasserted=0;
+               runPowerRestore=0;
+               runPowerDropout=0;
+
+               recursive = 0;
        }
-       
-       return ERROR_OK;
+
+       /* Poll targets for state changes unless that's globally disabled.
+        * Skip targets that are currently disabled.
+        */
+       for (target_t *target = all_targets;
+                       target_continuous_poll && target;
+                       target = target->next)
+       {
+               if (!target->tap->enabled)
+                       continue;
+
+               /* only poll target if we've got power and srst isn't asserted */
+               if (!powerDropout && !srstAsserted)
+               {
+                       /* polling may fail silently until the target has been examined */
+                       if((retval = target_poll(target)) != ERROR_OK)
+                               return retval;
+               }
+       }
+
+       return retval;
 }
 
-int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        target_t *target;
        reg_t *reg = NULL;
        int count = 0;
        char *value;
-       
+
        LOG_DEBUG("-");
-       
+
        target = get_current_target(cmd_ctx);
-       
+
        /* list all available registers for the current target */
        if (argc == 0)
        {
                reg_cache_t *cache = target->reg_cache;
-               
+
                count = 0;
                while(cache)
                {
@@ -1400,23 +1718,26 @@ int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args
                        }
                        cache = cache->next;
                }
-               
+
                return ERROR_OK;
        }
-       
+
        /* access a single register by its ordinal number */
        if ((args[0][0] >= '0') && (args[0][0] <= '9'))
        {
-               int num = strtoul(args[0], NULL, 0);
+               unsigned num;
+               int retval = parse_uint(args[0], &num);
+               if (ERROR_OK != retval)
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+
                reg_cache_t *cache = target->reg_cache;
-               
                count = 0;
                while(cache)
                {
                        int i;
                        for (i = 0; i < cache->num_regs; i++)
                        {
-                               if (count++ == num)
+                               if (count++ == (int)num)
                                {
                                        reg = &cache->reg_list[i];
                                        break;
@@ -1426,7 +1747,7 @@ int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args
                                break;
                        cache = cache->next;
                }
-               
+
                if (!reg)
                {
                        command_print(cmd_ctx, "%i is out of bounds, the current target has only %i registers (0 - %i)", num, count, count - 1);
@@ -1435,7 +1756,7 @@ int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args
        } else /* access a single register by its name */
        {
                reg = register_get_by_name(target->reg_cache, args[0], 1);
-               
+
                if (!reg)
                {
                        command_print(cmd_ctx, "register %s not found in current target", args[0]);
@@ -1448,15 +1769,10 @@ int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args
        {
                if ((argc == 2) && (strcmp(args[1], "force") == 0))
                        reg->valid = 0;
-               
+
                if (reg->valid == 0)
                {
                        reg_arch_type_t *arch_type = register_get_arch_type(reg->arch_type);
-                       if (arch_type == NULL)
-                       {
-                               LOG_ERROR("BUG: encountered unregistered arch type");
-                               return ERROR_OK;
-                       }
                        arch_type->get(reg);
                }
                value = buf_to_str(reg->value, reg->size, 16);
@@ -1464,361 +1780,350 @@ int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args
                free(value);
                return ERROR_OK;
        }
-       
+
        /* set register value */
        if (argc == 2)
        {
-               u8 *buf = malloc(CEIL(reg->size, 8));
+               uint8_t *buf = malloc(CEIL(reg->size, 8));
                str_to_buf(args[1], strlen(args[1]), buf, reg->size, 0);
 
                reg_arch_type_t *arch_type = register_get_arch_type(reg->arch_type);
-               if (arch_type == NULL)
-               {
-                       LOG_ERROR("BUG: encountered unregistered arch type");
-                       return ERROR_OK;
-               }
-               
                arch_type->set(reg, buf);
-               
+
                value = buf_to_str(reg->value, reg->size, 16);
                command_print(cmd_ctx, "%s (/%i): 0x%s", reg->name, reg->size, value);
                free(value);
-               
+
                free(buf);
-               
+
                return ERROR_OK;
        }
-       
+
        command_print(cmd_ctx, "usage: reg <#|name> [value]");
-       
+
        return ERROR_OK;
 }
 
-static int wait_state(struct command_context_s *cmd_ctx, char *cmd, enum target_state state, int ms);
-
-int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
+       int retval = ERROR_OK;
        target_t *target = get_current_target(cmd_ctx);
 
        if (argc == 0)
        {
-               target->type->poll(target);
-               target_arch_state(target);
+               command_print(cmd_ctx, "background polling: %s",
+                               target_continuous_poll ?  "on" : "off");
+               command_print(cmd_ctx, "TAP: %s (%s)",
+                               target->tap->dotted_name,
+                               target->tap->enabled ? "enabled" : "disabled");
+               if (!target->tap->enabled)
+                       return ERROR_OK;
+               if ((retval = target_poll(target)) != ERROR_OK)
+                       return retval;
+               if ((retval = target_arch_state(target)) != ERROR_OK)
+                       return retval;
+
        }
-       else
+       else if (argc==1)
        {
                if (strcmp(args[0], "on") == 0)
                {
-                       target_continous_poll = 1;
+                       target_continuous_poll = 1;
                }
                else if (strcmp(args[0], "off") == 0)
                {
-                       target_continous_poll = 0;
+                       target_continuous_poll = 0;
                }
                else
                {
                        command_print(cmd_ctx, "arg is \"on\" or \"off\"");
                }
+       } else
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
-       
-       
-       return ERROR_OK;
+
+       return retval;
 }
 
-int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
-       int ms = 5000;
-       
-       if (argc > 0)
-       {
-               char *end;
+       if (argc > 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
 
-               ms = strtoul(args[0], &end, 0) * 1000;
-               if (*end)
+       unsigned ms = 5000;
+       if (1 == argc)
+       {
+               int retval = parse_uint(args[0], &ms);
+               if (ERROR_OK != retval)
                {
                        command_print(cmd_ctx, "usage: %s [seconds]", cmd);
-                       return ERROR_OK;
+                       return ERROR_COMMAND_SYNTAX_ERROR;
                }
+               // convert seconds (given) to milliseconds (needed)
+               ms *= 1000;
        }
 
-       return wait_state(cmd_ctx, cmd, TARGET_HALTED, ms); 
-}
-
-static void target_process_events(struct command_context_s *cmd_ctx)
-{
        target_t *target = get_current_target(cmd_ctx);
-       target->type->poll(target);
-       target_call_timer_callbacks_now();
+       return target_wait_state(target, TARGET_HALTED, ms);
 }
 
-static int wait_state(struct command_context_s *cmd_ctx, char *cmd, enum target_state state, int ms)
+/* wait for target state to change. The trick here is to have a low
+ * latency for short waits and not to suck up all the CPU time
+ * on longer waits.
+ *
+ * After 500ms, keep_alive() is invoked
+ */
+int target_wait_state(target_t *target, enum target_state state, int ms)
 {
        int retval;
-       struct timeval timeout, now;
+       long long then=0, cur;
        int once=1;
-       gettimeofday(&timeout, NULL);
-       timeval_add_time(&timeout, 0, ms * 1000);
-       
-       target_t *target = get_current_target(cmd_ctx);
+
        for (;;)
        {
-               if ((retval=target->type->poll(target))!=ERROR_OK)
+               if ((retval=target_poll(target))!=ERROR_OK)
                        return retval;
-               target_call_timer_callbacks_now();
                if (target->state == state)
                {
                        break;
                }
+               cur = timeval_ms();
                if (once)
                {
                        once=0;
-                       command_print(cmd_ctx, "waiting for target %s...", target_state_strings[state]);
+                       then = timeval_ms();
+                       LOG_DEBUG("waiting for target %s...",
+                               Jim_Nvp_value2name_simple(nvp_target_state,state)->name);
                }
-               
-               gettimeofday(&now, NULL);
-               if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec)))
+
+               if (cur-then>500)
                {
-                       LOG_ERROR("timed out while waiting for target %s", target_state_strings[state]);
-                       break;
+                       keep_alive();
+               }
+
+               if ((cur-then)>ms)
+               {
+                       LOG_ERROR("timed out while waiting for target %s",
+                               Jim_Nvp_value2name_simple(nvp_target_state,state)->name);
+                       return ERROR_FAIL;
                }
        }
-       
+
        return ERROR_OK;
 }
 
-int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
-       int retval;
-       target_t *target = get_current_target(cmd_ctx);
-
        LOG_DEBUG("-");
 
-       if ((retval = target->type->halt(target)) != ERROR_OK)
-       {
+       target_t *target = get_current_target(cmd_ctx);
+       int retval = target_halt(target);
+       if (ERROR_OK != retval)
                return retval;
-       }
-       
-       return handle_wait_halt_command(cmd_ctx, cmd, args, argc);
-}
 
-/* what to do on daemon startup */
-int handle_daemon_startup_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
        if (argc == 1)
        {
-               if (strcmp(args[0], "attach") == 0)
-               {
-                       startup_mode = DAEMON_ATTACH;
-                       return ERROR_OK;
-               }
-               else if (strcmp(args[0], "reset") == 0)
-               {
-                       startup_mode = DAEMON_RESET;
+               unsigned wait;
+               retval = parse_uint(args[0], &wait);
+               if (ERROR_OK != retval)
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+               if (!wait)
                        return ERROR_OK;
-               }
        }
-       
-       LOG_WARNING("invalid daemon_startup configuration directive: %s", args[0]);
-       return ERROR_OK;
 
+       return handle_wait_halt_command(cmd_ctx, cmd, args, argc);
 }
-               
-int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+
+static int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        target_t *target = get_current_target(cmd_ctx);
-       
+
        LOG_USER("requesting target halt and executing a soft reset");
-       
+
        target->type->soft_reset_halt(target);
-       
+
        return ERROR_OK;
 }
 
-int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
-       target_t *target = get_current_target(cmd_ctx);
-       enum target_reset_mode reset_mode = target->reset_mode;
-       enum target_reset_mode save = target->reset_mode;
-       
-       LOG_DEBUG("-");
-       
-       if (argc >= 1)
-       {
-               if (strcmp("run", args[0]) == 0)
-                       reset_mode = RESET_RUN;
-               else if (strcmp("halt", args[0]) == 0)
-                       reset_mode = RESET_HALT;
-               else if (strcmp("init", args[0]) == 0)
-                       reset_mode = RESET_INIT;
-               else if (strcmp("run_and_halt", args[0]) == 0)
-               {
-                       reset_mode = RESET_RUN_AND_HALT;
-                       if (argc >= 2)
-                       {
-                               target->run_and_halt_time = strtoul(args[1], NULL, 0);
-                       }
-               }
-               else if (strcmp("run_and_init", args[0]) == 0)
-               {
-                       reset_mode = RESET_RUN_AND_INIT;
-                       if (argc >= 2)
-                       {
-                               target->run_and_halt_time = strtoul(args[1], NULL, 0);
-                       }
-               }
-               else
-               {
-                       command_print(cmd_ctx, "usage: reset ['run', 'halt', 'init', 'run_and_halt', 'run_and_init]");
-                       return ERROR_OK;
+       if (argc > 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       enum target_reset_mode reset_mode = RESET_RUN;
+       if (argc == 1)
+       {
+               const Jim_Nvp *n;
+               n = Jim_Nvp_name2value_simple( nvp_reset_modes, args[0] );
+               if( (n->name == NULL) || (n->value == RESET_UNKNOWN) ){
+                       return ERROR_COMMAND_SYNTAX_ERROR;
                }
+               reset_mode = n->value;
        }
-       
-       /* temporarily modify mode of current reset target */
-       target->reset_mode = reset_mode;
 
        /* reset *all* targets */
-       target_process_reset(cmd_ctx);
-       
-       /* Restore default reset mode for this target */
-    target->reset_mode = save;
-       
-       return ERROR_OK;
+       return target_process_reset(cmd_ctx, reset_mode);
 }
 
-int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+
+static int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
-       int retval;
-       target_t *target = get_current_target(cmd_ctx);
-       
-       if (argc == 0)
-               retval = target->type->resume(target, 1, 0, 1, 0); /* current pc, addr = 0, handle breakpoints, not debugging */
-       else if (argc == 1)
-               retval = target->type->resume(target, 0, strtoul(args[0], NULL, 0), 1, 0); /* addr = args[0], handle breakpoints, not debugging */
-       else
-       {
+       if (argc > 1)
                return ERROR_COMMAND_SYNTAX_ERROR;
-       }
 
-       target_process_events(cmd_ctx);
-       
-       return retval;
+       target_t *target = get_current_target(cmd_ctx);
+       target_handle_event(target, TARGET_EVENT_OLD_pre_resume);
+
+       /* with no args, resume from current pc, addr = 0,
+        * with one arguments, addr = args[0],
+        * handle breakpoints, not debugging */
+       uint32_t addr = 0;
+       if (argc == 1)
+       {
+               int retval = parse_u32(args[0], &addr);
+               if (ERROR_OK != retval)
+                       return retval;
+       }
+
+       return target_resume(target, 0, addr, 1, 0);
 }
 
-int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
-       target_t *target = get_current_target(cmd_ctx);
-       
+       if (argc > 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
        LOG_DEBUG("-");
-       
-       if (argc == 0)
-               target->type->step(target, 1, 0, 1); /* current pc, addr = 0, handle breakpoints */
 
+       /* with no args, step from current pc, addr = 0,
+        * with one argument addr = args[0],
+        * handle breakpoints, debugging */
+       uint32_t addr = 0;
        if (argc == 1)
-               target->type->step(target, 0, strtoul(args[0], NULL, 0), 1); /* addr = args[0], handle breakpoints */
-       
-       return ERROR_OK;
+       {
+               int retval = parse_u32(args[0], &addr);
+               if (ERROR_OK != retval)
+                       return retval;
+       }
+
+       target_t *target = get_current_target(cmd_ctx);
+       return target->type->step(target, 0, addr, 1);
 }
 
-int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static void handle_md_output(struct command_context_s *cmd_ctx,
+               struct target_s *target, uint32_t address, unsigned size,
+               unsigned count, const uint8_t *buffer)
 {
-       const int line_bytecnt = 32;
-       int count = 1;
-       int size = 4;
-       u32 address = 0;
-       int line_modulo;
-       int i;
+       const unsigned line_bytecnt = 32;
+       unsigned line_modulo = line_bytecnt / size;
+
+       char output[line_bytecnt * 4 + 1];
+       unsigned output_len = 0;
+
+       const char *value_fmt;
+       switch (size) {
+       case 4: value_fmt = "%8.8x "; break;
+       case 2: value_fmt = "%4.2x "; break;
+       case 1: value_fmt = "%2.2x "; break;
+       default:
+               LOG_ERROR("invalid memory read size: %u", size);
+               exit(-1);
+       }
 
-       char output[128];
-       int output_len;
+       for (unsigned i = 0; i < count; i++)
+       {
+               if (i % line_modulo == 0)
+               {
+                       output_len += snprintf(output + output_len,
+                                       sizeof(output) - output_len,
+                                       "0x%8.8x: ", address + (i*size));
+               }
 
-       int retval;
+               uint32_t value=0;
+               const uint8_t *value_ptr = buffer + i * size;
+               switch (size) {
+               case 4: value = target_buffer_get_u32(target, value_ptr); break;
+               case 2: value = target_buffer_get_u16(target, value_ptr); break;
+               case 1: value = *value_ptr;
+               }
+               output_len += snprintf(output + output_len,
+                               sizeof(output) - output_len,
+                               value_fmt, value);
 
-       u8 *buffer;
-       target_t *target = get_current_target(cmd_ctx);
+               if ((i % line_modulo == line_modulo - 1) || (i == count - 1))
+               {
+                       command_print(cmd_ctx, "%s", output);
+                       output_len = 0;
+               }
+       }
+}
 
+static int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
        if (argc < 1)
-               return ERROR_OK;
+               return ERROR_COMMAND_SYNTAX_ERROR;
 
-       if (argc == 2)
-               count = strtoul(args[1], NULL, 0);
+       unsigned size = 0;
+       switch (cmd[2]) {
+       case 'w': size = 4; break;
+       case 'h': size = 2; break;
+       case 'b': size = 1; break;
+       default: return ERROR_COMMAND_SYNTAX_ERROR;
+       }
 
-       address = strtoul(args[0], NULL, 0);
-       
+       uint32_t address;
+       int retval = parse_u32(args[0], &address);
+       if (ERROR_OK != retval)
+               return retval;
 
-       switch (cmd[2])
+       unsigned count = 1;
+       if (argc == 2)
        {
-               case 'w':
-                       size = 4; line_modulo = line_bytecnt / 4;
-                       break;
-               case 'h':
-                       size = 2; line_modulo = line_bytecnt / 2;
-                       break;
-               case 'b':
-                       size = 1; line_modulo = line_bytecnt / 1;
-                       break;
-               default:
-                       return ERROR_OK;
+               retval = parse_uint(args[1], &count);
+               if (ERROR_OK != retval)
+                       return retval;
        }
 
-       buffer = calloc(count, size);
-       retval  = target->type->read_memory(target, address, size, count, buffer);
-       if (retval == ERROR_OK)
-       {
-               output_len = 0;
-       
-               for (i = 0; i < count; i++)
-               {
-                       if (i%line_modulo == 0)
-                               output_len += snprintf(output + output_len, 128 - output_len, "0x%8.8x: ", address + (i*size));
-                       
-                       switch (size)
-                       {
-                               case 4:
-                                       output_len += snprintf(output + output_len, 128 - output_len, "%8.8x ", target_buffer_get_u32(target, &buffer[i*4]));
-                                       break;
-                               case 2:
-                                       output_len += snprintf(output + output_len, 128 - output_len, "%4.4x ", target_buffer_get_u16(target, &buffer[i*2]));
-                                       break;
-                               case 1:
-                                       output_len += snprintf(output + output_len, 128 - output_len, "%2.2x ", buffer[i*1]);
-                                       break;
-                       }
-       
-                       if ((i%line_modulo == line_modulo-1) || (i == count - 1))
-                       {
-                               command_print(cmd_ctx, output);
-                               output_len = 0;
-                       }
-               }
-       } else
-       {
-               LOG_ERROR("Failure examining memory");
-       }
+       uint8_t *buffer = calloc(count, size);
+
+       target_t *target = get_current_target(cmd_ctx);
+       retval = target_read_memory(target,
+                               address, size, count, buffer);
+       if (ERROR_OK == retval)
+               handle_md_output(cmd_ctx, target, address, size, count, buffer);
 
        free(buffer);
-       
-       return ERROR_OK;
+
+       return retval;
 }
 
-int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
-       u32 address = 0;
-       u32 value = 0;
-       int count = 1;
-       int i;
-       int wordsize;
-       target_t *target = get_current_target(cmd_ctx);
-       u8 value_buf[4];
-
         if ((argc < 2) || (argc > 3))
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       address = strtoul(args[0], NULL, 0);
-       value = strtoul(args[1], NULL, 0);
-       if (argc == 3)
-               count = strtoul(args[2], NULL, 0);
+       uint32_t address;
+       int retval = parse_u32(args[0], &address);
+       if (ERROR_OK != retval)
+               return retval;
+
+       uint32_t value;
+       retval = parse_u32(args[1], &value);
+       if (ERROR_OK != retval)
+               return retval;
 
+       unsigned count = 1;
+       if (argc == 3)
+       {
+               retval = parse_uint(args[2], &count);
+               if (ERROR_OK != retval)
+                       return retval;
+       }
 
+       target_t *target = get_current_target(cmd_ctx);
+       unsigned wordsize;
+       uint8_t value_buf[4];
        switch (cmd[2])
        {
                case 'w':
@@ -1836,74 +2141,90 @@ int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args,
                default:
                        return ERROR_COMMAND_SYNTAX_ERROR;
        }
-       for (i=0; i<count; i++)
+       for (unsigned i = 0; i < count; i++)
        {
-               int retval;
-               switch (wordsize)
-               {
-                       case 4:
-                               retval = target->type->write_memory(target, address + i*wordsize, 4, 1, value_buf);
-                               break;
-                       case 2:
-                               retval = target->type->write_memory(target, address + i*wordsize, 2, 1, value_buf);
-                               break;
-                       case 1:
-                               retval = target->type->write_memory(target, address + i*wordsize, 1, 1, value_buf);
-                       break;
-                       default:
-                       return ERROR_OK;
-               }
-               if (retval!=ERROR_OK)
-               {
+               retval = target_write_memory(target,
+                               address + i * wordsize, wordsize, 1, value_buf);
+               if (ERROR_OK != retval)
                        return retval;
-               }
+               keep_alive();
        }
 
        return ERROR_OK;
 
 }
 
-int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int parse_load_image_command_args(char **args, int argc,
+               image_t *image, uint32_t *min_address, uint32_t *max_address)
 {
-       u8 *buffer;
-       u32 buf_cnt;
-       u32 image_size;
-       int i;
-       int retval;
-
-       image_t image;  
-       
-       duration_t duration;
-       char *duration_text;
-       
-       target_t *target = get_current_target(cmd_ctx);
+       if (argc < 1 || argc > 5)
+               return ERROR_COMMAND_SYNTAX_ERROR;
 
-       if (argc < 1)
-       {
-               command_print(cmd_ctx, "usage: load_image <filename> [address] [type]");
-               return ERROR_OK;
-       }
-       
-       /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
+       /* a base address isn't always necessary,
+        * default to 0x0 (i.e. don't relocate) */
        if (argc >= 2)
        {
-               image.base_address_set = 1;
-               image.base_address = strtoul(args[1], NULL, 0);
+               uint32_t addr;
+               int retval = parse_u32(args[1], &addr);
+               if (ERROR_OK != retval)
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+               image->base_address = addr;
+               image->base_address_set = 1;
        }
        else
+               image->base_address_set = 0;
+
+       image->start_address_set = 0;
+
+       if (argc >= 4)
        {
-               image.base_address_set = 0;
+               int retval = parse_u32(args[3], min_address);
+               if (ERROR_OK != retval)
+                       return ERROR_COMMAND_SYNTAX_ERROR;
        }
+       if (argc == 5)
+       {
+               int retval = parse_u32(args[4], max_address);
+               if (ERROR_OK != retval)
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+               // use size (given) to find max (required)
+               *max_address += *min_address;
+       }
+
+       if (*min_address > *max_address)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       return ERROR_OK;
+}
+
+static int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       uint8_t *buffer;
+       uint32_t buf_cnt;
+       uint32_t image_size;
+       uint32_t min_address = 0;
+       uint32_t max_address = 0xffffffff;
+       int i;
+       int retvaltemp;
+
+       image_t image;
+
+       duration_t duration;
+       char *duration_text;
        
-       image.start_address_set = 0;
+       int retval = parse_load_image_command_args(args, argc,
+                       &image, &min_address, &max_address);
+       if (ERROR_OK != retval)
+               return retval;
 
+       target_t *target = get_current_target(cmd_ctx);
        duration_start_measure(&duration);
-       
+
        if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
        {
                return ERROR_OK;
        }
-       
+
        image_size = 0x0;
        retval = ERROR_OK;
        for (i = 0; i < image.num_sections; i++)
@@ -1914,48 +2235,73 @@ int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char
                        command_print(cmd_ctx, "error allocating buffer for section (%d bytes)", image.sections[i].size);
                        break;
                }
-               
+
                if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
                {
                        free(buffer);
                        break;
                }
-               if ((retval = target_write_buffer(target, image.sections[i].base_address, buf_cnt, buffer)) != ERROR_OK)
+
+               uint32_t offset=0;
+               uint32_t length=buf_cnt;
+
+               /* DANGER!!! beware of unsigned comparision here!!! */
+
+               if ((image.sections[i].base_address+buf_cnt>=min_address)&&
+                               (image.sections[i].base_address<max_address))
                {
-                       free(buffer);
-                       break;
+                       if (image.sections[i].base_address<min_address)
+                       {
+                               /* clip addresses below */
+                               offset+=min_address-image.sections[i].base_address;
+                               length-=offset;
+                       }
+
+                       if (image.sections[i].base_address+buf_cnt>max_address)
+                       {
+                               length-=(image.sections[i].base_address+buf_cnt)-max_address;
+                       }
+
+                       if ((retval = target_write_buffer(target, image.sections[i].base_address+offset, length, buffer+offset)) != ERROR_OK)
+                       {
+                               free(buffer);
+                               break;
+                       }
+                       image_size += length;
+                       command_print(cmd_ctx, "%u byte written at address 0x%8.8x", length, image.sections[i].base_address+offset);
                }
-               image_size += buf_cnt;
-               command_print(cmd_ctx, "%u byte written at address 0x%8.8x", buf_cnt, image.sections[i].base_address);
-               
+
                free(buffer);
        }
 
-       duration_stop_measure(&duration, &duration_text);
+       if((retvaltemp = duration_stop_measure(&duration, &duration_text)) != ERROR_OK)
+       {
+               image_close(&image);
+               return retvaltemp;
+       }
+
        if (retval==ERROR_OK)
        {
                command_print(cmd_ctx, "downloaded %u byte in %s", image_size, duration_text);
        }
        free(duration_text);
-       
+
        image_close(&image);
 
        return retval;
 
 }
 
-int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        fileio_t fileio;
-       
-       u32 address;
-       u32 size;
-       u8 buffer[560];
-       int retval=ERROR_OK;
-       
+
+       uint8_t buffer[560];
+       int retvaltemp;
+
        duration_t duration;
        char *duration_text;
-       
+
        target_t *target = get_current_target(cmd_ctx);
 
        if (argc != 3)
@@ -1964,90 +2310,98 @@ int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char
                return ERROR_OK;
        }
 
-       address = strtoul(args[1], NULL, 0);
-       size = strtoul(args[2], NULL, 0);
+       uint32_t address;
+       int retval = parse_u32(args[1], &address);
+       if (ERROR_OK != retval)
+               return retval;
+
+       uint32_t size;
+       retval = parse_u32(args[2], &size);
+       if (ERROR_OK != retval)
+               return retval;
 
-       if ((address & 3) || (size & 3))
-       {
-               command_print(cmd_ctx, "only 32-bit aligned address and size are supported");
-               return ERROR_OK;
-       }
-       
        if (fileio_open(&fileio, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
        {
                return ERROR_OK;
        }
-       
+
        duration_start_measure(&duration);
-       
+
        while (size > 0)
        {
-               u32 size_written;
-               u32 this_run_size = (size > 560) ? 560 : size;
-               
-               retval = target->type->read_memory(target, address, 4, this_run_size / 4, buffer);
+               uint32_t size_written;
+               uint32_t this_run_size = (size > 560) ? 560 : size;
+
+               retval = target_read_buffer(target, address, this_run_size, buffer);
                if (retval != ERROR_OK)
                {
                        break;
                }
-               
+
                retval = fileio_write(&fileio, this_run_size, buffer, &size_written);
                if (retval != ERROR_OK)
                {
                        break;
                }
-               
+
                size -= this_run_size;
                address += this_run_size;
        }
 
-       fileio_close(&fileio);
+       if((retvaltemp = fileio_close(&fileio)) != ERROR_OK)
+               return retvaltemp;
+
+       if((retvaltemp = duration_stop_measure(&duration, &duration_text)) != ERROR_OK)
+               return retvaltemp;
 
-       duration_stop_measure(&duration, &duration_text);
        if (retval==ERROR_OK)
        {
-               command_print(cmd_ctx, "dumped %"PRIi64" byte in %s", fileio.size, duration_text);
+               command_print(cmd_ctx, "dumped %lld byte in %s",
+                               fileio.size, duration_text);
+               free(duration_text);
        }
-       free(duration_text);
-       
-       return ERROR_OK;
+
+       return retval;
 }
 
-int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_verify_image_command_internal(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, int verify)
 {
-       u8 *buffer;
-       u32 buf_cnt;
-       u32 image_size;
+       uint8_t *buffer;
+       uint32_t buf_cnt;
+       uint32_t image_size;
        int i;
-       int retval;
-       u32 checksum = 0;
-       u32 mem_checksum = 0;
+       int retval, retvaltemp;
+       uint32_t checksum = 0;
+       uint32_t mem_checksum = 0;
+
+       image_t image;
 
-       image_t image;  
-       
        duration_t duration;
        char *duration_text;
-       
+
        target_t *target = get_current_target(cmd_ctx);
-       
+
        if (argc < 1)
        {
-               command_print(cmd_ctx, "usage: verify_image <file> [offset] [type]");
-               return ERROR_OK;
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
-       
+
        if (!target)
        {
                LOG_ERROR("no target selected");
-               return ERROR_OK;
+               return ERROR_FAIL;
        }
-       
+
        duration_start_measure(&duration);
-       
+
        if (argc >= 2)
        {
+               uint32_t addr;
+               retval = parse_u32(args[1], &addr);
+               if (ERROR_OK != retval)
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+               image.base_address = addr;
                image.base_address_set = 1;
-               image.base_address = strtoul(args[1], NULL, 0);
        }
        else
        {
@@ -2057,11 +2411,11 @@ int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, ch
 
        image.start_address_set = 0;
 
-       if (image_open(&image, args[0], (argc == 3) ? args[2] : NULL) != ERROR_OK)
+       if ((retval=image_open(&image, args[0], (argc == 3) ? args[2] : NULL)) != ERROR_OK)
        {
-               return ERROR_OK;
+               return retval;
        }
-       
+
        image_size = 0x0;
        retval=ERROR_OK;
        for (i = 0; i < image.num_sections; i++)
@@ -2077,136 +2431,187 @@ int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, ch
                        free(buffer);
                        break;
                }
-               
-               /* calculate checksum of image */
-               image_calculate_checksum( buffer, buf_cnt, &checksum );
-               
-               retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum);
-               if( retval != ERROR_OK )
+
+               if (verify)
                {
-                       free(buffer);
-                       break;
-               }
-               
-               if( checksum != mem_checksum )
-               {
-                       /* failed crc checksum, fall back to a binary compare */
-                       u8 *data;
-                       
-                       command_print(cmd_ctx, "checksum mismatch - attempting binary compare");
-                       
-                       data = (u8*)malloc(buf_cnt);
-                       
-                       /* Can we use 32bit word accesses? */
-                       int size = 1;
-                       int count = buf_cnt;
-                       if ((count % 4) == 0)
+                       /* calculate checksum of image */
+                       image_calculate_checksum( buffer, buf_cnt, &checksum );
+
+                       retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum);
+                       if( retval != ERROR_OK )
                        {
-                               size *= 4;
-                               count /= 4;
+                               free(buffer);
+                               break;
                        }
-                       retval = target->type->read_memory(target, image.sections[i].base_address, size, count, data);
-                       if (retval == ERROR_OK)
+
+                       if( checksum != mem_checksum )
                        {
-                               int t;
-                               for (t = 0; t < buf_cnt; t++)
+                               /* failed crc checksum, fall back to a binary compare */
+                               uint8_t *data;
+
+                               command_print(cmd_ctx, "checksum mismatch - attempting binary compare");
+
+                               data = (uint8_t*)malloc(buf_cnt);
+
+                               /* Can we use 32bit word accesses? */
+                               int size = 1;
+                               int count = buf_cnt;
+                               if ((count % 4) == 0)
+                               {
+                                       size *= 4;
+                                       count /= 4;
+                               }
+                               retval = target_read_memory(target, image.sections[i].base_address, size, count, data);
+                               if (retval == ERROR_OK)
                                {
-                                       if (data[t] != buffer[t])
+                                       uint32_t t;
+                                       for (t = 0; t < buf_cnt; t++)
                                        {
-                                               command_print(cmd_ctx, "Verify operation failed address 0x%08x. Was 0x%02x instead of 0x%02x\n", t + image.sections[i].base_address, data[t], buffer[t]);
-                                               free(data);
-                                               free(buffer);
-                                               retval=ERROR_FAIL;
-                                               goto done;
+                                               if (data[t] != buffer[t])
+                                               {
+                                                       command_print(cmd_ctx, "Verify operation failed address 0x%08x. Was 0x%02x instead of 0x%02x\n", t + image.sections[i].base_address, data[t], buffer[t]);
+                                                       free(data);
+                                                       free(buffer);
+                                                       retval=ERROR_FAIL;
+                                                       goto done;
+                                               }
+                                               if ((t%16384)==0)
+                                               {
+                                                       keep_alive();
+                                               }
                                        }
                                }
+
+                               free(data);
                        }
-                       
-                       free(data);
+               } else
+               {
+                       command_print(cmd_ctx, "address 0x%08x length 0x%08x", image.sections[i].base_address, buf_cnt);
                }
-               
+
                free(buffer);
                image_size += buf_cnt;
        }
-done:  
-       duration_stop_measure(&duration, &duration_text);
+done:
+
+       if((retvaltemp = duration_stop_measure(&duration, &duration_text)) != ERROR_OK)
+       {
+               image_close(&image);
+               return retvaltemp;
+       }
+
        if (retval==ERROR_OK)
        {
                command_print(cmd_ctx, "verified %u bytes in %s", image_size, duration_text);
        }
        free(duration_text);
-       
+
        image_close(&image);
-       
+
        return retval;
 }
 
-int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
-       int retval;
-       target_t *target = get_current_target(cmd_ctx);
+       return handle_verify_image_command_internal(cmd_ctx, cmd, args, argc, 1);
+}
 
-       if (argc == 0)
-       {
-               breakpoint_t *breakpoint = target->breakpoints;
+static int handle_test_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       return handle_verify_image_command_internal(cmd_ctx, cmd, args, argc, 0);
+}
 
-               while (breakpoint)
+static int handle_bp_command_list(struct command_context_s *cmd_ctx)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       breakpoint_t *breakpoint = target->breakpoints;
+       while (breakpoint)
+       {
+               if (breakpoint->type == BKPT_SOFT)
                {
-                       if (breakpoint->type == BKPT_SOFT)
-                       {
-                               char* buf = buf_to_str(breakpoint->orig_instr, breakpoint->length, 16);
-                               command_print(cmd_ctx, "0x%8.8x, 0x%x, %i, 0x%s", breakpoint->address, breakpoint->length, breakpoint->set, buf);
-                               free(buf);
-                       }
-                       else
-                       {
-                               command_print(cmd_ctx, "0x%8.8x, 0x%x, %i", breakpoint->address, breakpoint->length, breakpoint->set);
-                       }
-                       breakpoint = breakpoint->next;
-               }
-       }
-       else if (argc >= 2)
-       {
-               int hw = BKPT_SOFT;
-               u32 length = 0;
-
-               length = strtoul(args[1], NULL, 0);
-               
-               if (argc >= 3)
-                       if (strcmp(args[2], "hw") == 0)
-                               hw = BKPT_HARD;
-
-               if ((retval = breakpoint_add(target, strtoul(args[0], NULL, 0), length, hw)) != ERROR_OK)
-               {
-                       LOG_ERROR("Failure setting breakpoints");
+                       char* buf = buf_to_str(breakpoint->orig_instr,
+                                       breakpoint->length, 16);
+                       command_print(cmd_ctx, "0x%8.8x, 0x%x, %i, 0x%s",
+                                       breakpoint->address, breakpoint->length,
+                                       breakpoint->set, buf);
+                       free(buf);
                }
                else
                {
-                       command_print(cmd_ctx, "breakpoint added at address 0x%8.8x", strtoul(args[0], NULL, 0));
+                       command_print(cmd_ctx, "0x%8.8x, 0x%x, %i",
+                                       breakpoint->address, breakpoint->length, breakpoint->set);
                }
+
+               breakpoint = breakpoint->next;
        }
+       return ERROR_OK;
+}
+
+static int handle_bp_command_set(struct command_context_s *cmd_ctx,
+               uint32_t addr, uint32_t length, int hw)
+{
+       target_t *target = get_current_target(cmd_ctx);
+       int retval = breakpoint_add(target, addr, length, hw);
+       if (ERROR_OK == retval)
+               command_print(cmd_ctx, "breakpoint set at 0x%8.8x", addr);
        else
+               LOG_ERROR("Failure setting breakpoint");
+       return retval;
+}
+
+static int handle_bp_command(struct command_context_s *cmd_ctx,
+               char *cmd, char **args, int argc)
+{
+       if (argc == 0)
+               return handle_bp_command_list(cmd_ctx);
+
+       if (argc < 2 || argc > 3)
        {
                command_print(cmd_ctx, "usage: bp <address> <length> ['hw']");
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
-       return ERROR_OK;
+       uint32_t addr;
+       int retval = parse_u32(args[0], &addr);
+       if (ERROR_OK != retval)
+               return retval;
+
+       uint32_t length;
+       retval = parse_u32(args[1], &length);
+       if (ERROR_OK != retval)
+               return retval;
+
+       int hw = BKPT_SOFT;
+       if (argc == 3)
+       {
+               if (strcmp(args[2], "hw") == 0)
+                       hw = BKPT_HARD;
+               else
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       return handle_bp_command_set(cmd_ctx, addr, length, hw);
 }
 
-int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
-       target_t *target = get_current_target(cmd_ctx);
+       if (argc != 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       uint32_t addr;
+       int retval = parse_u32(args[0], &addr);
+       if (ERROR_OK != retval)
+               return retval;
 
-       if (argc > 0)
-               breakpoint_remove(target, strtoul(args[0], NULL, 0));
+       target_t *target = get_current_target(cmd_ctx);
+       breakpoint_remove(target, addr);
 
        return ERROR_OK;
 }
 
-int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        target_t *target = get_current_target(cmd_ctx);
-       int retval;
 
        if (argc == 0)
        {
@@ -2214,128 +2619,155 @@ int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args,
 
                while (watchpoint)
                {
-                       command_print(cmd_ctx, "address: 0x%8.8x, mask: 0x%8.8x, r/w/a: %i, value: 0x%8.8x, mask: 0x%8.8x", watchpoint->address, watchpoint->length, watchpoint->rw, watchpoint->value, watchpoint->mask);
+                       command_print(cmd_ctx, "address: 0x%8.8x, len: 0x%8.8x, r/w/a: %i, value: 0x%8.8x, mask: 0x%8.8x", watchpoint->address, watchpoint->length, watchpoint->rw, watchpoint->value, watchpoint->mask);
                        watchpoint = watchpoint->next;
                }
-       } 
-       else if (argc >= 2)
+               return ERROR_OK;
+       }
+
+       enum watchpoint_rw type = WPT_ACCESS;
+       uint32_t addr = 0;
+       uint32_t length = 0;
+       uint32_t data_value = 0x0;
+       uint32_t data_mask = 0xffffffff;
+       int retval;
+
+       switch (argc)
        {
-               enum watchpoint_rw type = WPT_ACCESS;
-               u32 data_value = 0x0;
-               u32 data_mask = 0xffffffff;
-               
-               if (argc >= 3)
-               {
-                       switch(args[2][0])
-                       {
-                               case 'r':
-                                       type = WPT_READ;
-                                       break;
-                               case 'w':
-                                       type = WPT_WRITE;
-                                       break;
-                               case 'a':
-                                       type = WPT_ACCESS;
-                                       break;
-                               default:
-                                       command_print(cmd_ctx, "usage: wp <address> <length> [r/w/a] [value] [mask]");
-                                       return ERROR_OK;
-                       }
-               }
-               if (argc >= 4)
-               {
-                       data_value = strtoul(args[3], NULL, 0);
-               }
-               if (argc >= 5)
-               {
-                       data_mask = strtoul(args[4], NULL, 0);
-               }
-               
-               if ((retval = watchpoint_add(target, strtoul(args[0], NULL, 0),
-                               strtoul(args[1], NULL, 0), type, data_value, data_mask)) != ERROR_OK)
+       case 5:
+               retval = parse_u32(args[4], &data_mask);
+               if (ERROR_OK != retval)
+                       return retval;
+               // fall through
+       case 4:
+               retval = parse_u32(args[3], &data_value);
+               if (ERROR_OK != retval)
+                       return retval;
+               // fall through
+       case 3:
+               switch(args[2][0])
                {
-                       LOG_ERROR("Failure setting breakpoints");
+               case 'r':
+                       type = WPT_READ;
+                       break;
+               case 'w':
+                       type = WPT_WRITE;
+                       break;
+               case 'a':
+                       type = WPT_ACCESS;
+                       break;
+               default:
+                       LOG_ERROR("invalid watchpoint mode ('%c')", args[2][0]);
+                       return ERROR_COMMAND_SYNTAX_ERROR;
                }
-       }
-       else
-       {
+               // fall through
+       case 2:
+               retval = parse_u32(args[1], &length);
+               if (ERROR_OK != retval)
+                       return retval;
+               retval = parse_u32(args[0], &addr);
+               if (ERROR_OK != retval)
+                       return retval;
+               break;
+
+       default:
                command_print(cmd_ctx, "usage: wp <address> <length> [r/w/a] [value] [mask]");
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
-               
-       return ERROR_OK;
+
+       retval = watchpoint_add(target, addr, length, type,
+                       data_value, data_mask);
+       if (ERROR_OK != retval)
+               LOG_ERROR("Failure setting watchpoints");
+
+       return retval;
 }
 
-int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
+       if (argc != 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       uint32_t addr;
+       int retval = parse_u32(args[0], &addr);
+       if (ERROR_OK != retval)
+               return retval;
+
        target_t *target = get_current_target(cmd_ctx);
+       watchpoint_remove(target, addr);
 
-       if (argc > 0)
-               watchpoint_remove(target, strtoul(args[0], NULL, 0));
-       
        return ERROR_OK;
 }
 
-int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
-{
-       int retval;
-       target_t *target = get_current_target(cmd_ctx);
-       u32 va;
-       u32 pa;
 
+/**
+ * Translate a virtual address to a physical address.
+ *
+ * The low-level target implementation must have logged a detailed error
+ * which is forwarded to telnet/GDB session.
+ */
+static int handle_virt2phys_command(command_context_t *cmd_ctx,
+               char *cmd, char **args, int argc)
+{
        if (argc != 1)
-       {
                return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-       va = strtoul(args[0], NULL, 0);
 
+       uint32_t va;
+       int retval = parse_u32(args[0], &va);
+       if (ERROR_OK != retval)
+               return retval;
+       uint32_t pa;
+
+       target_t *target = get_current_target(cmd_ctx);
        retval = target->type->virt2phys(target, va, &pa);
        if (retval == ERROR_OK)
-       {
                command_print(cmd_ctx, "Physical address 0x%08x", pa);
-       }
-       else
-       {
-               /* lower levels will have logged a detailed error which is 
-                * forwarded to telnet/GDB session.  
-                */
-       }
+
        return retval;
 }
+
+static void writeData(FILE *f, const void *data, size_t len)
+{
+       size_t written = fwrite(data, 1, len, f);
+       if (written != len)
+               LOG_ERROR("failed to write %zu bytes: %s", len, strerror(errno));
+}
+
 static void writeLong(FILE *f, int l)
 {
        int i;
        for (i=0; i<4; i++)
        {
                char c=(l>>(i*8))&0xff;
-               fwrite(&c, 1, 1, f); 
+               writeData(f, &c, 1);
        }
-       
+
 }
+
 static void writeString(FILE *f, char *s)
 {
-       fwrite(s, 1, strlen(s), f); 
+       writeData(f, s, strlen(s));
 }
 
-
-
-// Dump a gmon.out histogram file.
-static void writeGmon(u32 *samples, int sampleNum, char *filename)
+/* Dump a gmon.out histogram file. */
+static void writeGmon(uint32_t *samples, uint32_t sampleNum, char *filename)
 {
-       int i;
+       uint32_t i;
        FILE *f=fopen(filename, "w");
        if (f==NULL)
                return;
-       fwrite("gmon", 1, 4, f);
-       writeLong(f, 0x00000001); // Version
-       writeLong(f, 0); // padding
-       writeLong(f, 0); // padding
-       writeLong(f, 0); // padding
-                               
-       fwrite("", 1, 1, f);  // GMON_TAG_TIME_HIST 
-
-       // figure out bucket size
-       u32 min=samples[0];
-       u32 max=samples[0];
+       writeString(f, "gmon");
+       writeLong(f, 0x00000001); /* Version */
+       writeLong(f, 0); /* padding */
+       writeLong(f, 0); /* padding */
+       writeLong(f, 0); /* padding */
+
+       uint8_t zero = 0;  /* GMON_TAG_TIME_HIST */
+       writeData(f, &zero, 1);
+
+       /* figure out bucket size */
+       uint32_t min=samples[0];
+       uint32_t max=samples[0];
        for (i=0; i<sampleNum; i++)
        {
                if (min>samples[i])
@@ -2349,12 +2781,12 @@ static void writeGmon(u32 *samples, int sampleNum, char *filename)
        }
 
        int addressSpace=(max-min+1);
-       
-       static int const maxBuckets=256*1024; // maximum buckets.
-       int length=addressSpace;
+
+       static const uint32_t maxBuckets = 256 * 1024; /* maximum buckets. */
+       uint32_t length = addressSpace;
        if (length > maxBuckets)
        {
-               length=maxBuckets; 
+               length=maxBuckets;
        }
        int *buckets=malloc(sizeof(int)*length);
        if (buckets==NULL)
@@ -2365,28 +2797,26 @@ static void writeGmon(u32 *samples, int sampleNum, char *filename)
        memset(buckets, 0, sizeof(int)*length);
        for (i=0; i<sampleNum;i++)
        {
-               u32 address=samples[i];
+               uint32_t address=samples[i];
                long long a=address-min;
                long long b=length-1;
                long long c=addressSpace-1;
-               int index=(a*b)/c; // danger!!!! int32 overflows 
+               int index=(a*b)/c; /* danger!!!! int32 overflows */
                buckets[index]++;
        }
-       
-       //                         append binary memory gmon.out &profile_hist_hdr ((char*)&profile_hist_hdr + sizeof(struct gmon_hist_hdr))
-       writeLong(f, min);                                      // low_pc
-       writeLong(f, max);              // high_pc
-       writeLong(f, length);           // # of samples
-       writeLong(f, 64000000);                         // 64MHz
+
+       /* append binary memory gmon.out &profile_hist_hdr ((char*)&profile_hist_hdr + sizeof(struct gmon_hist_hdr)) */
+       writeLong(f, min);                      /* low_pc */
+       writeLong(f, max);                      /* high_pc */
+       writeLong(f, length);           /* # of samples */
+       writeLong(f, 64000000);         /* 64MHz */
        writeString(f, "seconds");
        for (i=0; i<(15-strlen("seconds")); i++)
-       {
-               fwrite("", 1, 1, f);  // padding
-       }
+               writeData(f, &zero, 1);
        writeString(f, "s");
-               
-//                        append binary memory gmon.out profile_hist_data (profile_hist_data + profile_hist_hdr.hist_size)
-       
+
+       /*append binary memory gmon.out profile_hist_data (profile_hist_data + profile_hist_hdr.hist_size) */
+
        char *data=malloc(2*length);
        if (data!=NULL)
        {
@@ -2402,7 +2832,7 @@ static void writeGmon(u32 *samples, int sampleNum, char *filename)
                        data[i*2+1]=(val>>8)&0xff;
                }
                free(buckets);
-               fwrite(data, 1, length*2, f);
+               writeData(f, data, length * 2);
                free(data);
        } else
        {
@@ -2413,49 +2843,52 @@ static void writeGmon(u32 *samples, int sampleNum, char *filename)
 }
 
 /* profiling samples the CPU PC as quickly as OpenOCD is able, which will be used as a random sampling of PC */
-int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+static int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        target_t *target = get_current_target(cmd_ctx);
        struct timeval timeout, now;
-       
+
        gettimeofday(&timeout, NULL);
        if (argc!=2)
        {
                return ERROR_COMMAND_SYNTAX_ERROR;
        }
-       char *end;
-       timeval_add_time(&timeout, strtoul(args[0], &end, 0), 0);
-       if (*end) 
-       {
-               return ERROR_OK;
-       }
-       
+       unsigned offset;
+       int retval = parse_uint(args[0], &offset);
+       if (ERROR_OK != retval)
+               return retval;
+
+       timeval_add_time(&timeout, offset, 0);
+
        command_print(cmd_ctx, "Starting profiling. Halting and resuming the target as often as we can...");
 
        static const int maxSample=10000;
-       u32 *samples=malloc(sizeof(u32)*maxSample);
+       uint32_t *samples=malloc(sizeof(uint32_t)*maxSample);
        if (samples==NULL)
                return ERROR_OK;
-       
+
        int numSamples=0;
-       int retval=ERROR_OK;
-       // hopefully it is safe to cache! We want to stop/restart as quickly as possible.
+       /* hopefully it is safe to cache! We want to stop/restart as quickly as possible. */
        reg_t *reg = register_get_by_name(target->reg_cache, "pc", 1);
-       
+
        for (;;)
        {
-               target->type->poll(target);
+               target_poll(target);
                if (target->state == TARGET_HALTED)
                {
-                       u32 t=*((u32 *)reg->value);
+                       uint32_t t=*((uint32_t *)reg->value);
                        samples[numSamples++]=t;
-                       retval = target->type->resume(target, 1, 0, 0, 0); /* current pc, addr = 0, do not handle breakpoints, not debugging */
-                       target->type->poll(target);
-                       usleep(10*1000); // sleep 10ms, i.e. <100 samples/second.
+                       retval = target_resume(target, 1, 0, 0, 0); /* current pc, addr = 0, do not handle breakpoints, not debugging */
+                       target_poll(target);
+                       alive_sleep(10); /* sleep 10ms, i.e. <100 samples/second. */
                } else if (target->state == TARGET_RUNNING)
                {
-                       // We want to quickly sample the PC.
-                       target->type->halt(target);
+                       /* We want to quickly sample the PC. */
+                       if((retval = target_halt(target)) != ERROR_OK)
+                       {
+                               free(samples);
+                               return retval;
+                       }
                } else
                {
                        command_print(cmd_ctx, "Target not halted or running");
@@ -2466,24 +2899,1576 @@ int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **
                {
                        break;
                }
-               
+
                gettimeofday(&now, NULL);
                if ((numSamples>=maxSample) || ((now.tv_sec >= timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec)))
                {
                        command_print(cmd_ctx, "Profiling completed. %d samples.", numSamples);
-                       target->type->poll(target);
+                       if((retval = target_poll(target)) != ERROR_OK)
+                       {
+                               free(samples);
+                               return retval;
+                       }
                        if (target->state == TARGET_HALTED)
                        {
-                               target->type->resume(target, 1, 0, 0, 0); /* current pc, addr = 0, do not handle breakpoints, not debugging */
+                               target_resume(target, 1, 0, 0, 0); /* current pc, addr = 0, do not handle breakpoints, not debugging */
+                       }
+                       if((retval = target_poll(target)) != ERROR_OK)
+                       {
+                               free(samples);
+                               return retval;
                        }
-                       target->type->poll(target);
                        writeGmon(samples, numSamples, args[1]);
                        command_print(cmd_ctx, "Wrote %s", args[1]);
                        break;
                }
        }
        free(samples);
-       
+
        return ERROR_OK;
 }
 
+static int new_int_array_element(Jim_Interp * interp, const char *varname, int idx, uint32_t 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)
+{
+       command_context_t *context;
+       target_t *target;
+
+       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;
+       }
+
+       return  target_mem2array(interp, target, argc-1, argv+1);
+}
+
+static int target_mem2array(Jim_Interp *interp, target_t *target, int argc, Jim_Obj *const *argv)
+{
+       long l;
+       uint32_t width;
+       int len;
+       uint32_t addr;
+       uint32_t count;
+       uint32_t v;
+       const char *varname;
+       uint8_t buffer[4096];
+       int  n, e, retval;
+       uint32_t i;
+
+       /* 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 != 4) {
+               Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");
+               return JIM_ERR;
+       }
+       varname = Jim_GetString(argv[0], &len);
+       /* given "foo" get space for worse case "foo(%d)" .. add 20 */
+
+       e = Jim_GetLong(interp, argv[1], &l);
+       width = l;
+       if (e != JIM_OK) {
+               return e;
+       }
+
+       e = Jim_GetLong(interp, argv[2], &l);
+       addr = l;
+       if (e != JIM_OK) {
+               return e;
+       }
+       e = Jim_GetLong(interp, argv[3], &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;
+       }
+
+       /* 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_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, uint32_t *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)
+{
+       command_context_t *context;
+       target_t *target;
+
+       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;
+       }
+
+       return target_array2mem( interp,target, argc-1, argv+1 );
+}
+
+static int target_array2mem(Jim_Interp *interp, target_t *target, int argc, Jim_Obj *const *argv)
+{
+       long l;
+       uint32_t width;
+       int len;
+       uint32_t addr;
+       uint32_t count;
+       uint32_t v;
+       const char *varname;
+       uint8_t buffer[4096];
+       int  n, e, retval;
+       uint32_t i;
+
+       /* argv[1] = name of array to get the data
+        * argv[2] = desired width
+        * argv[3] = memory address
+        * argv[4] = count to write
+        */
+       if (argc != 4) {
+               Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");
+               return JIM_ERR;
+       }
+       varname = Jim_GetString(argv[0], &len);
+       /* given "foo" get space for worse case "foo(%d)" .. add 20 */
+
+       e = Jim_GetLong(interp, argv[1], &l);
+       width = l;
+       if (e != JIM_OK) {
+               return e;
+       }
+
+       e = Jim_GetLong(interp, argv[2], &l);
+       addr = l;
+       if (e != JIM_OK) {
+               return e;
+       }
+       e = Jim_GetLong(interp, argv[3], &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;
+       }
+
+       /* 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_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), "array2mem: cannot read memory", NULL);
+                       e = JIM_ERR;
+                       len = 0;
+               }
+       }
+
+       Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+
+       return JIM_OK;
+}
+
+void target_all_handle_event( enum target_event e )
+{
+       target_t *target;
+
+       LOG_DEBUG( "**all*targets: event: %d, %s",
+                       e,
+                       Jim_Nvp_value2name_simple( nvp_target_event, e )->name );
+
+       target = all_targets;
+       while (target){
+               target_handle_event( target, e );
+               target = target->next;
+       }
+}
+
+void target_handle_event( target_t *target, enum target_event e )
+{
+       target_event_action_t *teap;
+       int done;
+
+       teap = target->event_action;
+
+       done = 0;
+       while( teap ){
+               if( teap->event == e ){
+                       done = 1;
+                       LOG_DEBUG( "target: (%d) %s (%s) event: %d (%s) action: %s\n",
+                                          target->target_number,
+                                          target->cmd_name,
+                                          target_get_name(target),
+                                          e,
+                                          Jim_Nvp_value2name_simple( nvp_target_event, e )->name,
+                                          Jim_GetString( teap->body, NULL ) );
+                       if (Jim_EvalObj( interp, teap->body )!=JIM_OK)
+                       {
+                               Jim_PrintErrorMessage(interp);
+                       }
+               }
+               teap = teap->next;
+       }
+       if( !done ){
+               LOG_DEBUG( "event: %d %s - no action",
+                                  e,
+                                  Jim_Nvp_value2name_simple( nvp_target_event, e )->name );
+       }
+}
+
+enum target_cfg_param {
+       TCFG_TYPE,
+       TCFG_EVENT,
+       TCFG_WORK_AREA_VIRT,
+       TCFG_WORK_AREA_PHYS,
+       TCFG_WORK_AREA_SIZE,
+       TCFG_WORK_AREA_BACKUP,
+       TCFG_ENDIAN,
+       TCFG_VARIANT,
+       TCFG_CHAIN_POSITION,
+};
+
+static Jim_Nvp nvp_config_opts[] = {
+       { .name = "-type",             .value = TCFG_TYPE },
+       { .name = "-event",            .value = TCFG_EVENT },
+       { .name = "-work-area-virt",   .value = TCFG_WORK_AREA_VIRT },
+       { .name = "-work-area-phys",   .value = TCFG_WORK_AREA_PHYS },
+       { .name = "-work-area-size",   .value = TCFG_WORK_AREA_SIZE },
+       { .name = "-work-area-backup", .value = TCFG_WORK_AREA_BACKUP },
+       { .name = "-endian" ,          .value = TCFG_ENDIAN },
+       { .name = "-variant",          .value = TCFG_VARIANT },
+       { .name = "-chain-position",   .value = TCFG_CHAIN_POSITION },
+
+       { .name = NULL, .value = -1 }
+};
+
+static int target_configure( Jim_GetOptInfo *goi, target_t *target )
+{
+       Jim_Nvp *n;
+       Jim_Obj *o;
+       jim_wide w;
+       char *cp;
+       int e;
+
+       /* parse config or cget options ... */
+       while( goi->argc > 0 ){
+               Jim_SetEmptyResult( goi->interp );
+               /* Jim_GetOpt_Debug( goi ); */
+
+               if( target->type->target_jim_configure ){
+                       /* target defines a configure function */
+                       /* target gets first dibs on parameters */
+                       e = (*(target->type->target_jim_configure))( target, goi );
+                       if( e == JIM_OK ){
+                               /* more? */
+                               continue;
+                       }
+                       if( e == JIM_ERR ){
+                               /* An error */
+                               return e;
+                       }
+                       /* otherwise we 'continue' below */
+               }
+               e = Jim_GetOpt_Nvp( goi, nvp_config_opts, &n );
+               if( e != JIM_OK ){
+                       Jim_GetOpt_NvpUnknown( goi, nvp_config_opts, 0 );
+                       return e;
+               }
+               switch( n->value ){
+               case TCFG_TYPE:
+                       /* not setable */
+                       if( goi->isconfigure ){
+                               Jim_SetResult_sprintf( goi->interp, "not setable: %s", n->name );
+                               return JIM_ERR;
+                       } else {
+                       no_params:
+                               if( goi->argc != 0 ){
+                                       Jim_WrongNumArgs( goi->interp, goi->argc, goi->argv, "NO PARAMS");
+                                       return JIM_ERR;
+                               }
+                       }
+                       Jim_SetResultString( goi->interp, target_get_name(target), -1 );
+                       /* loop for more */
+                       break;
+               case TCFG_EVENT:
+                       if( goi->argc == 0 ){
+                               Jim_WrongNumArgs( goi->interp, goi->argc, goi->argv, "-event ?event-name? ...");
+                               return JIM_ERR;
+                       }
+
+                       e = Jim_GetOpt_Nvp( goi, nvp_target_event, &n );
+                       if( e != JIM_OK ){
+                               Jim_GetOpt_NvpUnknown( goi, nvp_target_event, 1 );
+                               return e;
+                       }
+
+                       if( goi->isconfigure ){
+                               if( goi->argc != 1 ){
+                                       Jim_WrongNumArgs( goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?");
+                                       return JIM_ERR;
+                               }
+                       } else {
+                               if( goi->argc != 0 ){
+                                       Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name?");
+                                       return JIM_ERR;
+                               }
+                       }
+
+                       {
+                               target_event_action_t *teap;
+
+                               teap = target->event_action;
+                               /* replace existing? */
+                               while( teap ){
+                                       if( teap->event == (enum target_event)n->value ){
+                                               break;
+                                       }
+                                       teap = teap->next;
+                               }
+
+                               if( goi->isconfigure ){
+                                       if( teap == NULL ){
+                                               /* create new */
+                                               teap = calloc( 1, sizeof(*teap) );
+                                       }
+                                       teap->event = n->value;
+                                       Jim_GetOpt_Obj( goi, &o );
+                                       if( teap->body ){
+                                               Jim_DecrRefCount( interp, teap->body );
+                                       }
+                                       teap->body  = Jim_DuplicateObj( goi->interp, o );
+                                       /*
+                                        * FIXME:
+                                        *     Tcl/TK - "tk events" have a nice feature.
+                                        *     See the "BIND" command.
+                                        *    We should support that here.
+                                        *     You can specify %X and %Y in the event code.
+                                        *     The idea is: %T - target name.
+                                        *     The idea is: %N - target number
+                                        *     The idea is: %E - event name.
+                                        */
+                                       Jim_IncrRefCount( teap->body );
+
+                                       /* add to head of event list */
+                                       teap->next = target->event_action;
+                                       target->event_action = teap;
+                                       Jim_SetEmptyResult(goi->interp);
+                               } else {
+                                       /* get */
+                                       if( teap == NULL ){
+                                               Jim_SetEmptyResult( goi->interp );
+                                       } else {
+                                               Jim_SetResult( goi->interp, Jim_DuplicateObj( goi->interp, teap->body ) );
+                                       }
+                               }
+                       }
+                       /* loop for more */
+                       break;
+
+               case TCFG_WORK_AREA_VIRT:
+                       if( goi->isconfigure ){
+                               target_free_all_working_areas(target);
+                               e = Jim_GetOpt_Wide( goi, &w );
+                               if( e != JIM_OK ){
+                                       return e;
+                               }
+                               target->working_area_virt = w;
+                       } else {
+                               if( goi->argc != 0 ){
+                                       goto no_params;
+                               }
+                       }
+                       Jim_SetResult( interp, Jim_NewIntObj( goi->interp, target->working_area_virt ) );
+                       /* loop for more */
+                       break;
+
+               case TCFG_WORK_AREA_PHYS:
+                       if( goi->isconfigure ){
+                               target_free_all_working_areas(target);
+                               e = Jim_GetOpt_Wide( goi, &w );
+                               if( e != JIM_OK ){
+                                       return e;
+                               }
+                               target->working_area_phys = w;
+                       } else {
+                               if( goi->argc != 0 ){
+                                       goto no_params;
+                               }
+                       }
+                       Jim_SetResult( interp, Jim_NewIntObj( goi->interp, target->working_area_phys ) );
+                       /* loop for more */
+                       break;
+
+               case TCFG_WORK_AREA_SIZE:
+                       if( goi->isconfigure ){
+                               target_free_all_working_areas(target);
+                               e = Jim_GetOpt_Wide( goi, &w );
+                               if( e != JIM_OK ){
+                                       return e;
+                               }
+                               target->working_area_size = w;
+                       } else {
+                               if( goi->argc != 0 ){
+                                       goto no_params;
+                               }
+                       }
+                       Jim_SetResult( interp, Jim_NewIntObj( goi->interp, target->working_area_size ) );
+                       /* loop for more */
+                       break;
+
+               case TCFG_WORK_AREA_BACKUP:
+                       if( goi->isconfigure ){
+                               target_free_all_working_areas(target);
+                               e = Jim_GetOpt_Wide( goi, &w );
+                               if( e != JIM_OK ){
+                                       return e;
+                               }
+                               /* make this exactly 1 or 0 */
+                               target->backup_working_area = (!!w);
+                       } else {
+                               if( goi->argc != 0 ){
+                                       goto no_params;
+                               }
+                       }
+                       Jim_SetResult(interp, Jim_NewIntObj(goi->interp, target->backup_working_area));
+                       /* loop for more e*/
+                       break;
+
+               case TCFG_ENDIAN:
+                       if( goi->isconfigure ){
+                               e = Jim_GetOpt_Nvp( goi, nvp_target_endian, &n );
+                               if( e != JIM_OK ){
+                                       Jim_GetOpt_NvpUnknown( goi, nvp_target_endian, 1 );
+                                       return e;
+                               }
+                               target->endianness = n->value;
+                       } else {
+                               if( goi->argc != 0 ){
+                                       goto no_params;
+                               }
+                       }
+                       n = Jim_Nvp_value2name_simple( nvp_target_endian, target->endianness );
+                       if( n->name == NULL ){
+                               target->endianness = TARGET_LITTLE_ENDIAN;
+                               n = Jim_Nvp_value2name_simple( nvp_target_endian, target->endianness );
+                       }
+                       Jim_SetResultString( goi->interp, n->name, -1 );
+                       /* loop for more */
+                       break;
+
+               case TCFG_VARIANT:
+                       if( goi->isconfigure ){
+                               if( goi->argc < 1 ){
+                                       Jim_SetResult_sprintf( goi->interp,
+                                                                                  "%s ?STRING?",
+                                                                                  n->name );
+                                       return JIM_ERR;
+                               }
+                               if( target->variant ){
+                                       free((void *)(target->variant));
+                               }
+                               e = Jim_GetOpt_String( goi, &cp, NULL );
+                               target->variant = strdup(cp);
+                       } else {
+                               if( goi->argc != 0 ){
+                                       goto no_params;
+                               }
+                       }
+                       Jim_SetResultString( goi->interp, target->variant,-1 );
+                       /* loop for more */
+                       break;
+               case TCFG_CHAIN_POSITION:
+                       if( goi->isconfigure ){
+                               Jim_Obj *o;
+                               jtag_tap_t *tap;
+                               target_free_all_working_areas(target);
+                               e = Jim_GetOpt_Obj( goi, &o );
+                               if( e != JIM_OK ){
+                                       return e;
+                               }
+                               tap = jtag_tap_by_jim_obj( goi->interp, o );
+                               if( tap == NULL ){
+                                       return JIM_ERR;
+                               }
+                               /* make this exactly 1 or 0 */
+                               target->tap = tap;
+                       } else {
+                               if( goi->argc != 0 ){
+                                       goto no_params;
+                               }
+                       }
+                       Jim_SetResultString( interp, target->tap->dotted_name, -1 );
+                       /* loop for more e*/
+                       break;
+               }
+       } /* while( goi->argc ) */
+
+
+               /* done - we return */
+       return JIM_OK;
+}
+
+/** this is the 'tcl' handler for the target specific command */
+static int tcl_target_func( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
+{
+       Jim_GetOptInfo goi;
+       jim_wide a,b,c;
+       int x,y,z;
+       uint8_t  target_buf[32];
+       Jim_Nvp *n;
+       target_t *target;
+       struct command_context_s *cmd_ctx;
+       int e;
+
+       enum {
+               TS_CMD_CONFIGURE,
+               TS_CMD_CGET,
+
+               TS_CMD_MWW, TS_CMD_MWH, TS_CMD_MWB,
+               TS_CMD_MDW, TS_CMD_MDH, TS_CMD_MDB,
+               TS_CMD_MRW, TS_CMD_MRH, TS_CMD_MRB,
+               TS_CMD_MEM2ARRAY, TS_CMD_ARRAY2MEM,
+               TS_CMD_EXAMINE,
+               TS_CMD_POLL,
+               TS_CMD_RESET,
+               TS_CMD_HALT,
+               TS_CMD_WAITSTATE,
+               TS_CMD_EVENTLIST,
+               TS_CMD_CURSTATE,
+               TS_CMD_INVOKE_EVENT,
+       };
+
+       static const Jim_Nvp target_options[] = {
+               { .name = "configure", .value = TS_CMD_CONFIGURE },
+               { .name = "cget", .value = TS_CMD_CGET },
+               { .name = "mww", .value = TS_CMD_MWW },
+               { .name = "mwh", .value = TS_CMD_MWH },
+               { .name = "mwb", .value = TS_CMD_MWB },
+               { .name = "mdw", .value = TS_CMD_MDW },
+               { .name = "mdh", .value = TS_CMD_MDH },
+               { .name = "mdb", .value = TS_CMD_MDB },
+               { .name = "mem2array", .value = TS_CMD_MEM2ARRAY },
+               { .name = "array2mem", .value = TS_CMD_ARRAY2MEM },
+               { .name = "eventlist", .value = TS_CMD_EVENTLIST },
+               { .name = "curstate",  .value = TS_CMD_CURSTATE },
+
+               { .name = "arp_examine", .value = TS_CMD_EXAMINE },
+               { .name = "arp_poll", .value = TS_CMD_POLL },
+               { .name = "arp_reset", .value = TS_CMD_RESET },
+               { .name = "arp_halt", .value = TS_CMD_HALT },
+               { .name = "arp_waitstate", .value = TS_CMD_WAITSTATE },
+               { .name = "invoke-event", .value = TS_CMD_INVOKE_EVENT },
+
+               { .name = NULL, .value = -1 },
+       };
+
+       /* go past the "command" */
+       Jim_GetOpt_Setup( &goi, interp, argc-1, argv+1 );
+
+       target = Jim_CmdPrivData( goi.interp );
+       cmd_ctx = Jim_GetAssocData(goi.interp, "context");
+
+       /* commands here are in an NVP table */
+       e = Jim_GetOpt_Nvp( &goi, target_options, &n );
+       if( e != JIM_OK ){
+               Jim_GetOpt_NvpUnknown( &goi, target_options, 0 );
+               return e;
+       }
+       /* Assume blank result */
+       Jim_SetEmptyResult( goi.interp );
+
+       switch( n->value ){
+       case TS_CMD_CONFIGURE:
+               if( goi.argc < 2 ){
+                       Jim_WrongNumArgs( goi.interp, goi.argc, goi.argv, "missing: -option VALUE ...");
+                       return JIM_ERR;
+               }
+               goi.isconfigure = 1;
+               return target_configure( &goi, target );
+       case TS_CMD_CGET:
+               // some things take params
+               if( goi.argc < 1 ){
+                       Jim_WrongNumArgs( goi.interp, 0, goi.argv, "missing: ?-option?");
+                       return JIM_ERR;
+               }
+               goi.isconfigure = 0;
+               return target_configure( &goi, target );
+               break;
+       case TS_CMD_MWW:
+       case TS_CMD_MWH:
+       case TS_CMD_MWB:
+               /* argv[0] = cmd
+                * argv[1] = address
+                * argv[2] = data
+                * argv[3] = optional count.
+                */
+
+               if( (goi.argc == 2) || (goi.argc == 3) ){
+                       /* all is well */
+               } else {
+               mwx_error:
+                       Jim_SetResult_sprintf( goi.interp, "expected: %s ADDR DATA [COUNT]", n->name );
+                       return JIM_ERR;
+               }
+
+               e = Jim_GetOpt_Wide( &goi, &a );
+               if( e != JIM_OK ){
+                       goto mwx_error;
+               }
+
+               e = Jim_GetOpt_Wide( &goi, &b );
+               if( e != JIM_OK ){
+                       goto mwx_error;
+               }
+               if (goi.argc == 3) {
+                       e = Jim_GetOpt_Wide( &goi, &c );
+                       if( e != JIM_OK ){
+                               goto mwx_error;
+                       }
+               } else {
+                       c = 1;
+               }
+
+               switch( n->value ){
+               case TS_CMD_MWW:
+                       target_buffer_set_u32( target, target_buf, b );
+                       b = 4;
+                       break;
+               case TS_CMD_MWH:
+                       target_buffer_set_u16( target, target_buf, b );
+                       b = 2;
+                       break;
+               case TS_CMD_MWB:
+                       target_buffer_set_u8( target, target_buf, b );
+                       b = 1;
+                       break;
+               }
+               for( x = 0 ; x < c ; x++ ){
+                       e = target_write_memory( target, a, b, 1, target_buf );
+                       if( e != ERROR_OK ){
+                               Jim_SetResult_sprintf( interp, "Error writing @ 0x%08x: %d\n", (int)(a), e );
+                               return JIM_ERR;
+                       }
+                       /* b = width */
+                       a = a + b;
+               }
+               return JIM_OK;
+               break;
+
+               /* display */
+       case TS_CMD_MDW:
+       case TS_CMD_MDH:
+       case TS_CMD_MDB:
+               /* argv[0] = command
+                * argv[1] = address
+                * argv[2] = optional count
+                */
+               if( (goi.argc == 2) || (goi.argc == 3) ){
+                       Jim_SetResult_sprintf( goi.interp, "expected: %s ADDR [COUNT]", n->name );
+                       return JIM_ERR;
+               }
+               e = Jim_GetOpt_Wide( &goi, &a );
+               if( e != JIM_OK ){
+                       return JIM_ERR;
+               }
+               if( goi.argc ){
+                       e = Jim_GetOpt_Wide( &goi, &c );
+                       if( e != JIM_OK ){
+                               return JIM_ERR;
+                       }
+               } else {
+                       c = 1;
+               }
+               b = 1; /* shut up gcc */
+               switch( n->value ){
+               case TS_CMD_MDW:
+                       b =  4;
+                       break;
+               case TS_CMD_MDH:
+                       b = 2;
+                       break;
+               case TS_CMD_MDB:
+                       b = 1;
+                       break;
+               }
+
+               /* convert to "bytes" */
+               c = c * b;
+               /* count is now in 'BYTES' */
+               while( c > 0 ){
+                       y = c;
+                       if( y > 16 ){
+                               y = 16;
+                       }
+                       e = target_read_memory( target, a, b, y / b, target_buf );
+                       if( e != ERROR_OK ){
+                               Jim_SetResult_sprintf( interp, "error reading target @ 0x%08lx", (int)(a) );
+                               return JIM_ERR;
+                       }
+
+                       Jim_fprintf( interp, interp->cookie_stdout, "0x%08x ", (int)(a) );
+                       switch( b ){
+                       case 4:
+                               for( x = 0 ; (x < 16) && (x < y) ; x += 4 ){
+                                       z = target_buffer_get_u32( target, &(target_buf[ x * 4 ]) );
+                                       Jim_fprintf( interp, interp->cookie_stdout, "%08x ", (int)(z) );
+                               }
+                               for( ; (x < 16) ; x += 4 ){
+                                       Jim_fprintf( interp, interp->cookie_stdout, "         " );
+                               }
+                               break;
+                       case 2:
+                               for( x = 0 ; (x < 16) && (x < y) ; x += 2 ){
+                                       z = target_buffer_get_u16( target, &(target_buf[ x * 2 ]) );
+                                       Jim_fprintf( interp, interp->cookie_stdout, "%04x ", (int)(z) );
+                               }
+                               for( ; (x < 16) ; x += 2 ){
+                                       Jim_fprintf( interp, interp->cookie_stdout, "     " );
+                               }
+                               break;
+                       case 1:
+                       default:
+                               for( x = 0 ; (x < 16) && (x < y) ; x += 1 ){
+                                       z = target_buffer_get_u8( target, &(target_buf[ x * 4 ]) );
+                                       Jim_fprintf( interp, interp->cookie_stdout, "%02x ", (int)(z) );
+                               }
+                               for( ; (x < 16) ; x += 1 ){
+                                       Jim_fprintf( interp, interp->cookie_stdout, "   " );
+                               }
+                               break;
+                       }
+                       /* ascii-ify the bytes */
+                       for( x = 0 ; x < y ; x++ ){
+                               if( (target_buf[x] >= 0x20) &&
+                                       (target_buf[x] <= 0x7e) ){
+                                       /* good */
+                               } else {
+                                       /* smack it */
+                                       target_buf[x] = '.';
+                               }
+                       }
+                       /* space pad  */
+                       while( x < 16 ){
+                               target_buf[x] = ' ';
+                               x++;
+                       }
+                       /* terminate */
+                       target_buf[16] = 0;
+                       /* print - with a newline */
+                       Jim_fprintf( interp, interp->cookie_stdout, "%s\n", target_buf );
+                       /* NEXT... */
+                       c -= 16;
+                       a += 16;
+               }
+               return JIM_OK;
+       case TS_CMD_MEM2ARRAY:
+               return target_mem2array( goi.interp, target, goi.argc, goi.argv );
+               break;
+       case TS_CMD_ARRAY2MEM:
+               return target_array2mem( goi.interp, target, goi.argc, goi.argv );
+               break;
+       case TS_CMD_EXAMINE:
+               if( goi.argc ){
+                       Jim_WrongNumArgs( goi.interp, 2, argv, "[no parameters]");
+                       return JIM_ERR;
+               }
+               if (!target->tap->enabled)
+                       goto err_tap_disabled;
+               e = target->type->examine( target );
+               if( e != ERROR_OK ){
+                       Jim_SetResult_sprintf( interp, "examine-fails: %d", e );
+                       return JIM_ERR;
+               }
+               return JIM_OK;
+       case TS_CMD_POLL:
+               if( goi.argc ){
+                       Jim_WrongNumArgs( goi.interp, 2, argv, "[no parameters]");
+                       return JIM_ERR;
+               }
+               if (!target->tap->enabled)
+                       goto err_tap_disabled;
+               if( !(target_was_examined(target)) ){
+                       e = ERROR_TARGET_NOT_EXAMINED;
+               } else {
+                       e = target->type->poll( target );
+               }
+               if( e != ERROR_OK ){
+                       Jim_SetResult_sprintf( interp, "poll-fails: %d", e );
+                       return JIM_ERR;
+               } else {
+                       return JIM_OK;
+               }
+               break;
+       case TS_CMD_RESET:
+               if( goi.argc != 2 ){
+                       Jim_WrongNumArgs( interp, 2, argv, "t|f|assert|deassert BOOL");
+                       return JIM_ERR;
+               }
+               e = Jim_GetOpt_Nvp( &goi, nvp_assert, &n );
+               if( e != JIM_OK ){
+                       Jim_GetOpt_NvpUnknown( &goi, nvp_assert, 1 );
+                       return e;
+               }
+               /* the halt or not param */
+               e = Jim_GetOpt_Wide( &goi, &a);
+               if( e != JIM_OK ){
+                       return e;
+               }
+               if (!target->tap->enabled)
+                       goto err_tap_disabled;
+               /* determine if we should halt or not. */
+               target->reset_halt = !!a;
+               /* When this happens - all workareas are invalid. */
+               target_free_all_working_areas_restore(target, 0);
+
+               /* do the assert */
+               if( n->value == NVP_ASSERT ){
+                       target->type->assert_reset( target );
+               } else {
+                       target->type->deassert_reset( target );
+               }
+               return JIM_OK;
+       case TS_CMD_HALT:
+               if( goi.argc ){
+                       Jim_WrongNumArgs( goi.interp, 0, argv, "halt [no parameters]");
+                       return JIM_ERR;
+               }
+               if (!target->tap->enabled)
+                       goto err_tap_disabled;
+               target->type->halt( target );
+               return JIM_OK;
+       case TS_CMD_WAITSTATE:
+               /* params:  <name>  statename timeoutmsecs */
+               if( goi.argc != 2 ){
+                       Jim_SetResult_sprintf( goi.interp, "%s STATENAME TIMEOUTMSECS", n->name );
+                       return JIM_ERR;
+               }
+               e = Jim_GetOpt_Nvp( &goi, nvp_target_state, &n );
+               if( e != JIM_OK ){
+                       Jim_GetOpt_NvpUnknown( &goi, nvp_target_state,1 );
+                       return e;
+               }
+               e = Jim_GetOpt_Wide( &goi, &a );
+               if( e != JIM_OK ){
+                       return e;
+               }
+               if (!target->tap->enabled)
+                       goto err_tap_disabled;
+               e = target_wait_state( target, n->value, a );
+               if( e != ERROR_OK ){
+                       Jim_SetResult_sprintf( goi.interp,
+                                                                  "target: %s wait %s fails (%d) %s",
+                                                                  target->cmd_name,
+                                                                  n->name,
+                                                                  e, target_strerror_safe(e) );
+                       return JIM_ERR;
+               } else {
+                       return JIM_OK;
+               }
+       case TS_CMD_EVENTLIST:
+               /* List for human, Events defined for this target.
+                * scripts/programs should use 'name cget -event NAME'
+                */
+               {
+                       target_event_action_t *teap;
+                       teap = target->event_action;
+                       command_print( cmd_ctx, "Event actions for target (%d) %s\n",
+                                                  target->target_number,
+                                                  target->cmd_name );
+                       command_print( cmd_ctx, "%-25s | Body", "Event");
+                       command_print( cmd_ctx, "------------------------- | ----------------------------------------");
+                       while( teap ){
+                               command_print( cmd_ctx,
+                                                          "%-25s | %s",
+                                                          Jim_Nvp_value2name_simple( nvp_target_event, teap->event )->name,
+                                                          Jim_GetString( teap->body, NULL ) );
+                               teap = teap->next;
+                       }
+                       command_print( cmd_ctx, "***END***");
+                       return JIM_OK;
+               }
+       case TS_CMD_CURSTATE:
+               if( goi.argc != 0 ){
+                       Jim_WrongNumArgs( goi.interp, 0, argv, "[no parameters]");
+                       return JIM_ERR;
+               }
+               Jim_SetResultString( goi.interp,
+                                                        Jim_Nvp_value2name_simple(nvp_target_state,target->state)->name,-1);
+               return JIM_OK;
+       case TS_CMD_INVOKE_EVENT:
+               if( goi.argc != 1 ){
+                       Jim_SetResult_sprintf( goi.interp, "%s ?EVENTNAME?",n->name);
+                       return JIM_ERR;
+               }
+               e = Jim_GetOpt_Nvp( &goi, nvp_target_event, &n );
+               if( e != JIM_OK ){
+                       Jim_GetOpt_NvpUnknown( &goi, nvp_target_event, 1 );
+                       return e;
+               }
+               target_handle_event( target, n->value );
+               return JIM_OK;
+       }
+       return JIM_ERR;
+
+err_tap_disabled:
+       Jim_SetResult_sprintf(interp, "[TAP is disabled]");
+       return JIM_ERR;
+}
+
+static int target_create( Jim_GetOptInfo *goi )
+{
+       Jim_Obj *new_cmd;
+       Jim_Cmd *cmd;
+       const char *cp;
+       char *cp2;
+       int e;
+       int x;
+       target_t *target;
+       struct command_context_s *cmd_ctx;
+
+       cmd_ctx = Jim_GetAssocData(goi->interp, "context");
+       if( goi->argc < 3 ){
+               Jim_WrongNumArgs( goi->interp, 1, goi->argv, "?name? ?type? ..options...");
+               return JIM_ERR;
+       }
+
+       /* COMMAND */
+       Jim_GetOpt_Obj( goi, &new_cmd );
+       /* does this command exist? */
+       cmd = Jim_GetCommand( goi->interp, new_cmd, JIM_ERRMSG );
+       if( cmd ){
+               cp = Jim_GetString( new_cmd, NULL );
+               Jim_SetResult_sprintf(goi->interp, "Command/target: %s Exists", cp);
+               return JIM_ERR;
+       }
+
+       /* TYPE */
+       e = Jim_GetOpt_String( goi, &cp2, NULL );
+       cp = cp2;
+       /* now does target type exist */
+       for( x = 0 ; target_types[x] ; x++ ){
+               if( 0 == strcmp( cp, target_types[x]->name ) ){
+                       /* found */
+                       break;
+               }
+       }
+       if( target_types[x] == NULL ){
+               Jim_SetResult_sprintf( goi->interp, "Unknown target type %s, try one of ", cp );
+               for( x = 0 ; target_types[x] ; x++ ){
+                       if( target_types[x+1] ){
+                               Jim_AppendStrings( goi->interp,
+                                                                  Jim_GetResult(goi->interp),
+                                                                  target_types[x]->name,
+                                                                  ", ", NULL);
+                       } else {
+                               Jim_AppendStrings( goi->interp,
+                                                                  Jim_GetResult(goi->interp),
+                                                                  " or ",
+                                                                  target_types[x]->name,NULL );
+                       }
+               }
+               return JIM_ERR;
+       }
+
+       /* Create it */
+       target = calloc(1,sizeof(target_t));
+       /* set target number */
+       target->target_number = new_target_number();
+
+       /* allocate memory for each unique target type */
+       target->type = (target_type_t*)calloc(1,sizeof(target_type_t));
+
+       memcpy( target->type, target_types[x], sizeof(target_type_t));
+
+       /* will be set by "-endian" */
+       target->endianness = TARGET_ENDIAN_UNKNOWN;
+
+       target->working_area        = 0x0;
+       target->working_area_size   = 0x0;
+       target->working_areas       = NULL;
+       target->backup_working_area = 0;
+
+       target->state               = TARGET_UNKNOWN;
+       target->debug_reason        = DBG_REASON_UNDEFINED;
+       target->reg_cache           = NULL;
+       target->breakpoints         = NULL;
+       target->watchpoints         = NULL;
+       target->next                = NULL;
+       target->arch_info           = NULL;
+
+       target->display             = 1;
+
+       /* initialize trace information */
+       target->trace_info = malloc(sizeof(trace_t));
+       target->trace_info->num_trace_points         = 0;
+       target->trace_info->trace_points_size        = 0;
+       target->trace_info->trace_points             = NULL;
+       target->trace_info->trace_history_size       = 0;
+       target->trace_info->trace_history            = NULL;
+       target->trace_info->trace_history_pos        = 0;
+       target->trace_info->trace_history_overflowed = 0;
+
+       target->dbgmsg          = NULL;
+       target->dbg_msg_enabled = 0;
+
+       target->endianness = TARGET_ENDIAN_UNKNOWN;
+
+       /* Do the rest as "configure" options */
+       goi->isconfigure = 1;
+       e = target_configure( goi, target);
+
+       if (target->tap == NULL)
+       {
+               Jim_SetResultString( interp, "-chain-position required when creating target", -1);
+               e=JIM_ERR;
+       }
+
+       if( e != JIM_OK ){
+               free( target->type );
+               free( target );
+               return e;
+       }
+
+       if( target->endianness == TARGET_ENDIAN_UNKNOWN ){
+               /* default endian to little if not specified */
+               target->endianness = TARGET_LITTLE_ENDIAN;
+       }
+
+       /* incase variant is not set */
+       if (!target->variant)
+               target->variant = strdup("");
+
+       /* create the target specific commands */
+       if( target->type->register_commands ){
+               (*(target->type->register_commands))( cmd_ctx );
+       }
+       if( target->type->target_create ){
+               (*(target->type->target_create))( target, goi->interp );
+       }
+
+       /* append to end of list */
+       {
+               target_t **tpp;
+               tpp = &(all_targets);
+               while( *tpp ){
+                       tpp = &( (*tpp)->next );
+               }
+               *tpp = target;
+       }
+
+       cp = Jim_GetString( new_cmd, NULL );
+       target->cmd_name = strdup(cp);
+
+       /* now - create the new target name command */
+       e = Jim_CreateCommand( goi->interp,
+                                                  /* name */
+                                                  cp,
+                                                  tcl_target_func, /* C function */
+                                                  target, /* private data */
+                                                  NULL ); /* no del proc */
+
+       return e;
+}
+
+static int jim_target( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
+{
+       int x,r,e;
+       jim_wide w;
+       struct command_context_s *cmd_ctx;
+       target_t *target;
+       Jim_GetOptInfo goi;
+       enum tcmd {
+               /* TG = target generic */
+               TG_CMD_CREATE,
+               TG_CMD_TYPES,
+               TG_CMD_NAMES,
+               TG_CMD_CURRENT,
+               TG_CMD_NUMBER,
+               TG_CMD_COUNT,
+       };
+       const char *target_cmds[] = {
+               "create", "types", "names", "current", "number",
+               "count",
+               NULL /* terminate */
+       };
+
+       LOG_DEBUG("Target command params:");
+       LOG_DEBUG("%s", Jim_Debug_ArgvString(interp, argc, argv));
+
+       cmd_ctx = Jim_GetAssocData( interp, "context" );
+
+       Jim_GetOpt_Setup( &goi, interp, argc-1, argv+1 );
+
+       if( goi.argc == 0 ){
+               Jim_WrongNumArgs(interp, 1, argv, "missing: command ...");
+               return JIM_ERR;
+       }
+
+       /* Jim_GetOpt_Debug( &goi ); */
+       r = Jim_GetOpt_Enum( &goi, target_cmds, &x   );
+       if( r != JIM_OK ){
+               return r;
+       }
+
+       switch(x){
+       default:
+               Jim_Panic(goi.interp,"Why am I here?");
+               return JIM_ERR;
+       case TG_CMD_CURRENT:
+               if( goi.argc != 0 ){
+                       Jim_WrongNumArgs( goi.interp, 1, goi.argv, "Too many parameters");
+                       return JIM_ERR;
+               }
+               Jim_SetResultString( goi.interp, get_current_target( cmd_ctx )->cmd_name, -1 );
+               return JIM_OK;
+       case TG_CMD_TYPES:
+               if( goi.argc != 0 ){
+                       Jim_WrongNumArgs( goi.interp, 1, goi.argv, "Too many parameters" );
+                       return JIM_ERR;
+               }
+               Jim_SetResult( goi.interp, Jim_NewListObj( goi.interp, NULL, 0 ) );
+               for( x = 0 ; target_types[x] ; x++ ){
+                       Jim_ListAppendElement( goi.interp,
+                                                                  Jim_GetResult(goi.interp),
+                                                                  Jim_NewStringObj( goi.interp, target_types[x]->name, -1 ) );
+               }
+               return JIM_OK;
+       case TG_CMD_NAMES:
+               if( goi.argc != 0 ){
+                       Jim_WrongNumArgs( goi.interp, 1, goi.argv, "Too many parameters" );
+                       return JIM_ERR;
+               }
+               Jim_SetResult( goi.interp, Jim_NewListObj( goi.interp, NULL, 0 ) );
+               target = all_targets;
+               while( target ){
+                       Jim_ListAppendElement( goi.interp,
+                                                                  Jim_GetResult(goi.interp),
+                                                                  Jim_NewStringObj( goi.interp, target->cmd_name, -1 ) );
+                       target = target->next;
+               }
+               return JIM_OK;
+       case TG_CMD_CREATE:
+               if( goi.argc < 3 ){
+                       Jim_WrongNumArgs( goi.interp, goi.argc, goi.argv, "?name  ... config options ...");
+                       return JIM_ERR;
+               }
+               return target_create( &goi );
+               break;
+       case TG_CMD_NUMBER:
+               if( goi.argc != 1 ){
+                       Jim_SetResult_sprintf( goi.interp, "expected: target number ?NUMBER?");
+                       return JIM_ERR;
+               }
+               e = Jim_GetOpt_Wide( &goi, &w );
+               if( e != JIM_OK ){
+                       return JIM_ERR;
+               }
+               {
+                       target_t *t;
+                       t = get_target_by_num(w);
+                       if( t == NULL ){
+                               Jim_SetResult_sprintf( goi.interp,"Target: number %d does not exist", (int)(w));
+                               return JIM_ERR;
+                       }
+                       Jim_SetResultString( goi.interp, t->cmd_name, -1 );
+                       return JIM_OK;
+               }
+       case TG_CMD_COUNT:
+               if( goi.argc != 0 ){
+                       Jim_WrongNumArgs( goi.interp, 0, goi.argv, "<no parameters>");
+                       return JIM_ERR;
+               }
+               Jim_SetResult( goi.interp,
+                                          Jim_NewIntObj( goi.interp, max_target_number()));
+               return JIM_OK;
+       }
+
+       return JIM_ERR;
+}
+
+
+struct FastLoad
+{
+       uint32_t address;
+       uint8_t *data;
+       int length;
+
+};
+
+static int fastload_num;
+static struct FastLoad *fastload;
+
+static void free_fastload(void)
+{
+       if (fastload!=NULL)
+       {
+               int i;
+               for (i=0; i<fastload_num; i++)
+               {
+                       if (fastload[i].data)
+                               free(fastload[i].data);
+               }
+               free(fastload);
+               fastload=NULL;
+       }
+}
+
+
+
+
+static int handle_fast_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       uint8_t *buffer;
+       uint32_t buf_cnt;
+       uint32_t image_size;
+       uint32_t min_address=0;
+       uint32_t max_address=0xffffffff;
+       int i;
+
+       image_t image;
+
+       duration_t duration;
+       char *duration_text;
+
+       int retval = parse_load_image_command_args(args, argc,
+                       &image, &min_address, &max_address);
+       if (ERROR_OK != retval)
+               return retval;
+
+       duration_start_measure(&duration);
+
+       if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
+       {
+               return ERROR_OK;
+       }
+
+       image_size = 0x0;
+       retval = ERROR_OK;
+       fastload_num=image.num_sections;
+       fastload=(struct FastLoad *)malloc(sizeof(struct FastLoad)*image.num_sections);
+       if (fastload==NULL)
+       {
+               image_close(&image);
+               return ERROR_FAIL;
+       }
+       memset(fastload, 0, sizeof(struct FastLoad)*image.num_sections);
+       for (i = 0; i < image.num_sections; i++)
+       {
+               buffer = malloc(image.sections[i].size);
+               if (buffer == NULL)
+               {
+                       command_print(cmd_ctx, "error allocating buffer for section (%d bytes)", image.sections[i].size);
+                       break;
+               }
+
+               if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
+               {
+                       free(buffer);
+                       break;
+               }
+
+               uint32_t offset=0;
+               uint32_t length=buf_cnt;
+
+
+               /* DANGER!!! beware of unsigned comparision here!!! */
+
+               if ((image.sections[i].base_address+buf_cnt>=min_address)&&
+                               (image.sections[i].base_address<max_address))
+               {
+                       if (image.sections[i].base_address<min_address)
+                       {
+                               /* clip addresses below */
+                               offset+=min_address-image.sections[i].base_address;
+                               length-=offset;
+                       }
+
+                       if (image.sections[i].base_address+buf_cnt>max_address)
+                       {
+                               length-=(image.sections[i].base_address+buf_cnt)-max_address;
+                       }
+
+                       fastload[i].address=image.sections[i].base_address+offset;
+                       fastload[i].data=malloc(length);
+                       if (fastload[i].data==NULL)
+                       {
+                               free(buffer);
+                               break;
+                       }
+                       memcpy(fastload[i].data, buffer+offset, length);
+                       fastload[i].length=length;
+
+                       image_size += length;
+                       command_print(cmd_ctx, "%u byte written at address 0x%8.8x", length, image.sections[i].base_address+offset);
+               }
+
+               free(buffer);
+       }
+
+       duration_stop_measure(&duration, &duration_text);
+       if (retval==ERROR_OK)
+       {
+               command_print(cmd_ctx, "Loaded %u bytes in %s", image_size, duration_text);
+               command_print(cmd_ctx, "NB!!! image has not been loaded to target, issue a subsequent 'fast_load' to do so.");
+       }
+       free(duration_text);
+
+       image_close(&image);
+
+       if (retval!=ERROR_OK)
+       {
+               free_fastload();
+       }
+
+       return retval;
+}
+
+static int handle_fast_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       if (argc>0)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       if (fastload==NULL)
+       {
+               LOG_ERROR("No image in memory");
+               return ERROR_FAIL;
+       }
+       int i;
+       int ms=timeval_ms();
+       int size=0;
+       int retval=ERROR_OK;
+       for (i=0; i<fastload_num;i++)
+       {
+               target_t *target = get_current_target(cmd_ctx);
+               command_print(cmd_ctx, "Write to 0x%08x, length 0x%08x", fastload[i].address, fastload[i].length);
+               if (retval==ERROR_OK)
+               {
+                       retval = target_write_buffer(target, fastload[i].address, fastload[i].length, fastload[i].data);
+               }
+               size+=fastload[i].length;
+       }
+       int after=timeval_ms();
+       command_print(cmd_ctx, "Loaded image %f kBytes/s", (float)(size/1024.0)/((float)(after-ms)/1000.0));
+       return retval;
+}

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)