Consolidate target selection code into single get_target() that handles both names...
[fw/openocd] / src / target / target.c
index c86ee8d4f07fd7ec13043fe26deb8d4a09bdd9fd..7571e4e358fc763a2f8e2a8d83421c354a3cddf4 100644 (file)
 #include "config.h"
 #endif
 
-#include "replacements.h"
 #include "target.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_targets_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);
+
+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);
@@ -99,8 +86,10 @@ extern target_type_t arm926ejs_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[] =
 {
@@ -113,8 +102,10 @@ target_type_t *target_types[] =
        &feroceon_target,
        &xscale_target,
        &cortexm3_target,
+       &cortexa8_target,
        &arm11_target,
        &mips_m4k_target,
+       &avr_target,
        NULL,
 };
 
@@ -229,7 +220,6 @@ const Jim_Nvp nvp_target_debug_reason [] = {
        { .name = NULL, .value = -1 },
 };
 
-
 const Jim_Nvp nvp_target_endian[] = {
        { .name = "big",    .value = TARGET_BIG_ENDIAN },
        { .name = "little", .value = TARGET_LITTLE_ENDIAN },
@@ -246,8 +236,7 @@ const Jim_Nvp nvp_reset_modes[] = {
        { .name = NULL     , .value = -1 },
 };
 
-static int
-max_target_number( void )
+static int max_target_number(void)
 {
        target_t *t;
        int x;
@@ -264,8 +253,7 @@ max_target_number( void )
 }
 
 /* determine the number of the new target */
-static int
-new_target_number( void )
+static int new_target_number(void)
 {
        target_t *t;
        int x;
@@ -332,8 +320,36 @@ void target_buffer_set_u8(target_t *target, u8 *buffer, u8 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;
+       char *endptr;
+       int num;
+
+       /* 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 */
+       num = strtoul(id, &endptr, 0);
+       if (*endptr != 0)
+               return NULL;
+
+       for (target = all_targets; target; target = target->next) {
+               if (target->target_number == 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 = all_targets;
 
@@ -926,15 +942,12 @@ int target_register_commands(struct command_context_s *cmd_ctx)
 {
 
        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_command(cmd_ctx, NULL, "virt2phys", handle_virt2phys_command, COMMAND_ANY, "translate a virtual address into a physical address");
-       register_command(cmd_ctx, NULL, "profile", handle_profile_command, COMMAND_EXEC, "profiling samples the CPU PC");
 
-       register_jim(cmd_ctx, "target", jim_target, "configure target" );
 
 
-       /* script procedures */
-       register_jim(cmd_ctx, "ocd_mem2array", jim_mem2array, "read memory and return as a TCL array for script processing");
-       register_jim(cmd_ctx, "ocd_array2mem", jim_array2mem, "convert a TCL array to memory locations and write the values");
+
+       register_jim(cmd_ctx, "target", jim_target, "configure target" );
+
        return ERROR_OK;
 }
 
@@ -987,7 +1000,7 @@ int target_write_buffer(struct target_s *target, u32 address, u32 size, u8 *buff
        /* handle unaligned head bytes */
        if (address % 4)
        {
-               int unaligned = 4 - (address % 4);
+               u32 unaligned = 4 - (address % 4);
 
                if (unaligned > size)
                        unaligned = size;
@@ -1062,7 +1075,7 @@ int target_read_buffer(struct target_s *target, u32 address, u32 size, u8 *buffe
        /* handle unaligned head bytes */
        if (address % 4)
        {
-               int unaligned = 4 - (address % 4);
+               u32 unaligned = 4 - (address % 4);
 
                if (unaligned > size)
                        unaligned = size;
@@ -1102,7 +1115,7 @@ int target_checksum_memory(struct target_s *target, u32 address, u32 size, u32*
 {
        u8 *buffer;
        int retval;
-       int i;
+       u32 i;
        u32 checksum = 0;
        if (!target->type->examined)
        {
@@ -1296,6 +1309,21 @@ int target_write_u8(struct target_s *target, u32 address, u8 value)
 int target_register_user_commands(struct command_context_s *cmd_ctx)
 {
        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)]");
@@ -1321,6 +1349,7 @@ int target_register_user_commands(struct command_context_s *cmd_ctx)
        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, "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;
@@ -1330,37 +1359,18 @@ int target_register_user_commands(struct command_context_s *cmd_ctx)
        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)
 {
-       char *cp;
        target_t *target = all_targets;
 
        if (argc == 1)
        {
-               /* try as tcltarget name */
-               for( target = all_targets ; target ; target = target->next ){
-                 if( target->cmd_name ){
-                       if( 0 == strcmp( args[0], target->cmd_name ) ){
-                               /* MATCH */
-                               goto Match;
-                       }
-                 }
-               }
-               /* no match, try as number */
-
-               int num = strtoul(args[0], &cp, 0 );
-               if( *cp != 0 ){
-                       /* then it was not a number */
-                       command_print( cmd_ctx, "Target: %s unknown, try one of:\n", args[0] );
-                       goto DumpTargets;
-               }
-
-               target = get_target_by_num( num );
-               if( target == NULL ){
+               target = get_target(args[0]);
+               if (target == NULL) {
                        command_print(cmd_ctx,"Target: %s is unknown, try one of:\n", args[0] );
                        goto DumpTargets;
                }
-       Match:
+
                cmd_ctx->current_target = target->target_number;
                return ERROR_OK;
        }
@@ -1526,7 +1536,7 @@ int handle_target(void *priv)
        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;
@@ -1637,7 +1647,7 @@ int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args
        return ERROR_OK;
 }
 
-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);
@@ -1672,7 +1682,7 @@ int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **arg
        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;
 
@@ -1692,32 +1702,41 @@ int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char
        return target_wait_state(target, TARGET_HALTED, 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);
 
        for (;;)
        {
                if ((retval=target_poll(target))!=ERROR_OK)
                        return retval;
-               keep_alive();
                if (target->state == state)
                {
                        break;
                }
+               cur = timeval_ms();
                if (once)
                {
                        once=0;
+                       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)
+               {
+                       keep_alive();
+               }
+
+               if ((cur-then)>ms)
                {
                        LOG_ERROR("timed out while waiting for target %s",
                                Jim_Nvp_value2name_simple(nvp_target_state,state)->name);
@@ -1728,7 +1747,7 @@ int target_wait_state(target_t *target, enum target_state state, int ms)
        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);
@@ -1740,10 +1759,20 @@ int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **arg
                return retval;
        }
 
+       if (argc == 1)
+       {
+               int wait;
+               char *end;
+
+               wait = strtoul(args[0], &end, 0);
+               if (!*end && !wait)
+                       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);
 
@@ -1754,7 +1783,7 @@ int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd,
        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)
 {
        const Jim_Nvp *n;
        enum target_reset_mode reset_mode = RESET_RUN;
@@ -1773,7 +1802,7 @@ int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **ar
 }
 
 
-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);
@@ -1792,7 +1821,7 @@ int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **a
        return retval;
 }
 
-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);
 
@@ -1807,7 +1836,7 @@ int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **arg
        return ERROR_OK;
 }
 
-int handle_md_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)
 {
        const int line_bytecnt = 32;
        int count = 1;
@@ -1884,7 +1913,7 @@ int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args,
        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;
@@ -1948,7 +1977,7 @@ int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args,
 
 }
 
-int handle_load_image_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)
 {
        u8 *buffer;
        u32 buf_cnt;
@@ -2072,7 +2101,7 @@ int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char
 
 }
 
-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;
 
@@ -2095,12 +2124,6 @@ int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char
        address = strtoul(args[1], NULL, 0);
        size = strtoul(args[2], NULL, 0);
 
-       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;
@@ -2113,7 +2136,7 @@ int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char
                u32 size_written;
                u32 this_run_size = (size > 560) ? 560 : size;
 
-               retval = target->type->read_memory(target, address, 4, this_run_size / 4, buffer);
+               retval = target_read_buffer(target, address, this_run_size, buffer);
                if (retval != ERROR_OK)
                {
                        break;
@@ -2138,13 +2161,13 @@ int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char
        if (retval==ERROR_OK)
        {
                command_print(cmd_ctx, "dumped %"PRIi64" 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;
@@ -2208,55 +2231,61 @@ int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, ch
                        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);
+                       /* calculate checksum of image */
+                       image_calculate_checksum( buffer, buf_cnt, &checksum );
 
-                       /* Can we use 32bit word accesses? */
-                       int size = 1;
-                       int count = buf_cnt;
-                       if ((count % 4) == 0)
+                       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 */
+                               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)
                                {
-                                       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)
+                                       size *= 4;
+                                       count /= 4;
+                               }
+                               retval = target->type->read_memory(target, image.sections[i].base_address, size, count, data);
+                               if (retval == ERROR_OK)
+                               {
+                                       u32 t;
+                                       for (t = 0; t < buf_cnt; t++)
                                        {
-                                               keep_alive();
+                                               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);
@@ -2281,7 +2310,17 @@ done:
        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)
+{
+       return handle_verify_image_command_internal(cmd_ctx, cmd, args, argc, 1);
+}
+
+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);
+}
+
+static int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        int retval;
        target_t *target = get_current_target(cmd_ctx);
@@ -2333,7 +2372,7 @@ int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args,
        return ERROR_OK;
 }
 
-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);
 
@@ -2343,7 +2382,7 @@ int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args
        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;
@@ -2405,7 +2444,7 @@ int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args,
        return ERROR_OK;
 }
 
-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)
 {
        target_t *target = get_current_target(cmd_ctx);
 
@@ -2415,7 +2454,7 @@ int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args
        return ERROR_OK;
 }
 
-int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+static 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);
@@ -2442,36 +2481,44 @@ int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args,
        return retval;
 }
 
+static void writeData(FILE *f, const void *data, size_t len)
+{
+       size_t written = fwrite(data, len, 1, 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)
+static void writeGmon(u32 *samples, u32 sampleNum, char *filename)
 {
-       int i;
+       u32 i;
        FILE *f=fopen(filename, "w");
        if (f==NULL)
                return;
-       fwrite("gmon", 1, 4, f);
+       writeString(f, "gmon");
        writeLong(f, 0x00000001); /* Version */
        writeLong(f, 0); /* padding */
        writeLong(f, 0); /* padding */
        writeLong(f, 0); /* padding */
 
-       fwrite("", 1, 1, f);  /* GMON_TAG_TIME_HIST */
+       u8 zero = 0;  /* GMON_TAG_TIME_HIST */
+       writeData(f, &zero, 1);
 
        /* figure out bucket size */
        u32 min=samples[0];
@@ -2490,8 +2537,8 @@ 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 u32 maxBuckets = 256 * 1024; /* maximum buckets. */
+       u32 length = addressSpace;
        if (length > maxBuckets)
        {
                length=maxBuckets;
@@ -2520,9 +2567,7 @@ static void writeGmon(u32 *samples, int sampleNum, char *filename)
        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) */
@@ -2542,7 +2587,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
        {
@@ -2553,7 +2598,7 @@ 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;
@@ -2685,7 +2730,7 @@ static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
                return JIM_ERR;
        }
 
-       return  target_mem2array(interp, target, argc,argv);
+       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)
@@ -2698,32 +2743,33 @@ static int target_mem2array(Jim_Interp *interp, target_t *target, int argc, Jim_
        u32 v;
        const char *varname;
        u8 buffer[4096];
-       int  i, n, e, retval;
+       int  n, e, retval;
+       u32 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 != 5) {
+       if (argc != 4) {
                Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");
                return JIM_ERR;
        }
-       varname = Jim_GetString(argv[1], &len);
+       varname = Jim_GetString(argv[0], &len);
        /* given "foo" get space for worse case "foo(%d)" .. add 20 */
 
-       e = Jim_GetLong(interp, argv[2], &l);
+       e = Jim_GetLong(interp, argv[1], &l);
        width = l;
        if (e != JIM_OK) {
                return e;
        }
 
-       e = Jim_GetLong(interp, argv[3], &l);
+       e = Jim_GetLong(interp, argv[2], &l);
        addr = l;
        if (e != JIM_OK) {
                return e;
        }
-       e = Jim_GetLong(interp, argv[4], &l);
+       e = Jim_GetLong(interp, argv[3], &l);
        len = l;
        if (e != JIM_OK) {
                return e;
@@ -2866,7 +2912,7 @@ static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
                return JIM_ERR;
        }
 
-       return target_array2mem( interp,target, argc, argv );
+       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)
@@ -2879,32 +2925,33 @@ static int target_array2mem(Jim_Interp *interp, target_t *target, int argc, Jim_
        u32 v;
        const char *varname;
        u8 buffer[4096];
-       int  i, n, e, retval;
+       int  n, e, retval;
+       u32 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 != 5) {
+       if (argc != 4) {
                Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");
                return JIM_ERR;
        }
-       varname = Jim_GetString(argv[1], &len);
+       varname = Jim_GetString(argv[0], &len);
        /* given "foo" get space for worse case "foo(%d)" .. add 20 */
 
-       e = Jim_GetLong(interp, argv[2], &l);
+       e = Jim_GetLong(interp, argv[1], &l);
        width = l;
        if (e != JIM_OK) {
                return e;
        }
 
-       e = Jim_GetLong(interp, argv[3], &l);
+       e = Jim_GetLong(interp, argv[2], &l);
        addr = l;
        if (e != JIM_OK) {
                return e;
        }
-       e = Jim_GetLong(interp, argv[4], &l);
+       e = Jim_GetLong(interp, argv[3], &l);
        len = l;
        if (e != JIM_OK) {
                return e;
@@ -3151,7 +3198,7 @@ static int target_configure( Jim_GetOptInfo *goi, target_t *target )
                                teap = target->event_action;
                                /* replace existing? */
                                while( teap ){
-                                       if( teap->event == n->value ){
+                                       if( teap->event == (enum target_event)n->value ){
                                                break;
                                        }
                                        teap = teap->next;
@@ -3333,6 +3380,8 @@ static int target_configure( Jim_GetOptInfo *goi, target_t *target )
                        break;
                }
        } /* while( goi->argc ) */
+
+
                /* done - we return */
        return JIM_OK;
 }
@@ -3831,6 +3880,13 @@ static int target_create( Jim_GetOptInfo *goi )
        /* 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 );
@@ -3845,7 +3901,7 @@ static int target_create( Jim_GetOptInfo *goi )
        /* 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 );
@@ -3901,7 +3957,7 @@ static int jim_target( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
        };
 
        LOG_DEBUG("Target command params:");
-       LOG_DEBUG(Jim_Debug_ArgvString( interp, argc, argv) );
+       LOG_DEBUG("%s", Jim_Debug_ArgvString(interp, argc, argv));
 
        cmd_ctx = Jim_GetAssocData( interp, "context" );
 
@@ -3993,3 +4049,197 @@ static int jim_target( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
 
        return JIM_ERR;
 }
+
+
+struct FastLoad
+{
+       u32 address;
+       u8 *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)
+{
+       u8 *buffer;
+       u32 buf_cnt;
+       u32 image_size;
+       u32 min_address=0;
+       u32 max_address=0xffffffff;
+       int i;
+       int retval;
+
+       image_t image;
+
+       duration_t duration;
+       char *duration_text;
+
+       if ((argc < 1)||(argc > 5))
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       /* 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);
+       }
+       else
+       {
+               image.base_address_set = 0;
+       }
+
+
+       image.start_address_set = 0;
+
+       if (argc>=4)
+       {
+               min_address=strtoul(args[3], NULL, 0);
+       }
+       if (argc>=5)
+       {
+               max_address=strtoul(args[4], NULL, 0)+min_address;
+       }
+
+       if (min_address>max_address)
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       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;
+               }
+
+               u32 offset=0;
+               u32 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;
+}