]> git.sur5r.net Git - openocd/blobdiff - src/target/target.c
Tweaked logging output.
[openocd] / src / target / target.c
index 4020564230f0b349c56616fa534377b66148c688..377bb0dc07dbd9f9c9ea4dd19cdc8787778fd46d 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "replacements.h"
 #include "target.h"
+#include "target_request.h"
 
 #include "log.h"
 #include "configuration.h"
@@ -31,6 +32,7 @@
 
 #include <string.h>
 #include <stdlib.h>
+#include <inttypes.h>
 
 #include <sys/types.h>
 #include <sys/stat.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);
@@ -66,10 +70,12 @@ int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args,
 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);
 
 /* targets
  */
@@ -79,6 +85,10 @@ 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 feroceon_target;
+extern target_type_t xscale_target;
+extern target_type_t cortexm3_target;
+extern target_type_t arm11_target;
 
 target_type_t *target_types[] =
 {
@@ -88,6 +98,10 @@ target_type_t *target_types[] =
        &arm720t_target,
        &arm966e_target,
        &arm926ejs_target,
+       &feroceon_target,
+       &xscale_target,
+       &cortexm3_target,
+       &arm11_target,
        NULL,
 };
 
@@ -215,7 +229,7 @@ int target_init_handler(struct target_s *target, enum target_event event, void *
        {
                target_unregister_event_callback(target_init_handler, priv);
 
-               script = fopen(target->reset_script, "r");
+               script = open_file_from_path(target->reset_script, "r");
                if (!script)
                {
                        ERROR("couldn't open script file %s", target->reset_script);
@@ -245,7 +259,40 @@ int target_process_reset(struct command_context_s *cmd_ctx)
 {
        int retval = ERROR_OK;
        target_t *target;
-        
+       struct timeval timeout, now;
+       
+       /* prepare reset_halt where necessary */
+       target = targets;
+       while (target)
+       {
+               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;
+               }
+               target = target->next;
+       }
+       
        target = targets;
        while (target)
        {
@@ -292,9 +339,60 @@ int target_process_reset(struct command_context_s *cmd_ctx)
                target = target->next;
        }
        jtag_execute_queue();
+
+       /* Wait for reset to complete, maximum 5 seconds. */    
+       gettimeofday(&timeout, NULL);
+       timeval_add_time(&timeout, 5, 0);
+       for(;;)
+       {
+               gettimeofday(&now, NULL);
+               
+               target_call_timer_callbacks();
+               
+               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)))
+                                       {
+                                               command_print(cmd_ctx, "Timed out waiting for reset");
+                                               goto done;
+                                       }
+                                       usleep(100*1000); /* Do not eat all cpu */
+                                       goto again;
+                               }
+                       }
+                       target = target->next;
+               }
+               /* All targets we're waiting for are halted */
+               break;
+               
+               again:;
+       }
+       done:
+       
+       
+       /* We want any events to be processed before the prompt */
+       target_call_timer_callbacks();
        
        return retval;
-}      
+}
+
+static int default_virt2phys(struct target_s *target, u32 virtual, u32 *physical)
+{
+       *physical = virtual;
+       return ERROR_OK;
+}
+
+static int default_mmu(struct target_s *target, int *enabled)
+{
+       *enabled = 0;
+       return ERROR_OK;
+}
 
 int target_init(struct command_context_s *cmd_ctx)
 {
@@ -307,6 +405,16 @@ int target_init(struct command_context_s *cmd_ctx)
                        ERROR("target '%s' init failed", target->type->name);
                        exit(-1);
                }
+               
+               /* Set up default functions if none are provided by target */
+               if (target->type->virt2phys == NULL)
+               {
+                       target->type->virt2phys = default_virt2phys;
+               }
+               if (target->type->mmu == NULL)
+               {
+                       target->type->mmu = default_mmu;
+               }
                target = target->next;
        }
        
@@ -316,6 +424,11 @@ int target_init(struct command_context_s *cmd_ctx)
                target_register_timer_callback(handle_target, 100, 1, NULL);
        }
                
+       return ERROR_OK;
+}
+
+int target_init_reset(struct command_context_s *cmd_ctx)
+{
        if (startup_mode == DAEMON_RESET)
                target_process_reset(cmd_ctx);
        
@@ -498,6 +611,26 @@ int target_alloc_working_area(struct target_s *target, u32 size, working_area_t
        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)
+       {
+               int retval;
+               int enabled;
+               retval = target->type->mmu(target, &enabled);
+               if (retval != ERROR_OK)
+               {
+                       return retval;
+               }
+               if (enabled)
+               {
+                       target->working_area = target->working_area_virt;
+               }
+               else
+               {
+                       target->working_area = target->working_area_phys;
+               }
+       }
+       
        /* only allocate multiples of 4 byte */
        if (size % 4)
        {
@@ -536,7 +669,7 @@ int target_alloc_working_area(struct target_s *target, u32 size, working_area_t
                
                if (free_size < size)
                {
-                       WARNING("not enough working area available");
+                       WARNING("not enough working area available(requested %d, free %d)", size, free_size);
                        return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
                }
                
@@ -615,22 +748,43 @@ int target_register_commands(struct command_context_s *cmd_ctx)
        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, NULL);
-       register_command(cmd_ctx, NULL, "working_area", handle_working_area_command, COMMAND_CONFIG, NULL);
+       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>");
 
        return ERROR_OK;
 }
 
+int target_arch_state(struct target_s *target)
+{
+       int retval;
+       if (target==NULL)
+       {
+               USER("No target has been configured");
+               return ERROR_OK;
+       }
+       
+       USER("target state: %s", target_state_strings[target->state]);
+       
+       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 
+ * possible
+ */
 int target_write_buffer(struct target_s *target, u32 address, u32 size, u8 *buffer)
 {
        int retval;
        
        DEBUG("writing buffer of %i byte at 0x%8.8x", size, address);
        
-       /* handle writes of less than 4 byte */
-       if (size < 4)
+       if (((address % 2) == 0) && (size == 2))
        {
-               if ((retval = target->type->write_memory(target, address, 1, size, buffer)) != ERROR_OK)
-                       return retval;
+               return target->type->write_memory(target, address, 2, 1, buffer);
        }
        
        /* handle unaligned head bytes */
@@ -638,6 +792,9 @@ int target_write_buffer(struct target_s *target, u32 address, u32 size, u8 *buff
        {
                int unaligned = 4 - (address % 4);
                
+               if (unaligned > size)
+                       unaligned = size;
+
                if ((retval = target->type->write_memory(target, address, 1, unaligned, buffer)) != ERROR_OK)
                        return retval;
                
@@ -678,17 +835,20 @@ int target_write_buffer(struct target_s *target, u32 address, u32 size, u8 *buff
        return ERROR_OK;
 }
 
+
+/* 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 retval;
        
        DEBUG("reading buffer of %i byte at 0x%8.8x", size, address);
        
-       /* handle reads of less than 4 byte */
-       if (size < 4)
+       if (((address % 2) == 0) && (size == 2))
        {
-               if ((retval = target->type->read_memory(target, address, 1, size, buffer)) != ERROR_OK)
-                       return retval;
+               return target->type->read_memory(target, address, 2, 1, buffer);
        }
        
        /* handle unaligned head bytes */
@@ -696,6 +856,9 @@ int target_read_buffer(struct target_s *target, u32 address, u32 size, u8 *buffe
        {
                int unaligned = 4 - (address % 4);
                
+               if (unaligned > size)
+                       unaligned = size;
+
                if ((retval = target->type->read_memory(target, address, 1, unaligned, buffer)) != ERROR_OK)
                        return retval;
                
@@ -727,60 +890,147 @@ int target_read_buffer(struct target_s *target, u32 address, u32 size, u8 *buffe
        return ERROR_OK;
 }
 
-void target_read_u32(struct target_s *target, u32 address, u32 *value)
+int target_checksum_memory(struct target_s *target, u32 address, u32 size, u32* crc)
 {
-       u8 value_buf[4];
+       u8 *buffer;
+       int retval;
+       int i;
+       u32 checksum = 0;
+       
+       if ((retval = target->type->checksum_memory(target, address,
+               size, &checksum)) == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
+       {
+               buffer = malloc(size);
+               if (buffer == NULL)
+               {
+                       ERROR("error allocating buffer for section (%d bytes)", size);
+                       return ERROR_INVALID_ARGUMENTS;
+               }
+               retval = target_read_buffer(target, address, size, buffer);
+               if (retval != ERROR_OK)
+               {
+                       free(buffer);
+                       return retval;
+               }
+
+               /* convert to target endianess */
+               for (i = 0; i < (size/sizeof(u32)); 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);
+               }
+
+               retval = image_calculate_checksum( buffer, size, &checksum );
+               free(buffer);
+       }
        
-       target->type->read_memory(target, address, 4, 1, value_buf);
+       *crc = checksum;
        
-       *value = target_buffer_get_u32(target, value_buf);
+       return retval;
+}
+
+int target_read_u32(struct target_s *target, u32 address, u32 *value)
+{
+       u8 value_buf[4];
 
-       DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, *value);
+       int retval = target->type->read_memory(target, address, 4, 1, value_buf);
+       
+       if (retval == ERROR_OK)
+       {
+               *value = target_buffer_get_u32(target, value_buf);
+               DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, *value);
+       }
+       else
+       {
+               *value = 0x0;
+               DEBUG("address: 0x%8.8x failed", address);
+       }
+       
+       return retval;
 }
 
-void target_read_u16(struct target_s *target, u32 address, u16 *value)
+int target_read_u16(struct target_s *target, u32 address, u16 *value)
 {
        u8 value_buf[2];
        
-       target->type->read_memory(target, address, 2, 1, value_buf);
+       int retval = target->type->read_memory(target, address, 2, 1, value_buf);
        
-       *value = target_buffer_get_u16(target, value_buf);
-
-       DEBUG("address: 0x%8.8x, value: 0x%4.4x", address, *value);
+       if (retval == ERROR_OK)
+       {
+               *value = target_buffer_get_u16(target, value_buf);
+               DEBUG("address: 0x%8.8x, value: 0x%4.4x", address, *value);
+       }
+       else
+       {
+               *value = 0x0;
+               DEBUG("address: 0x%8.8x failed", address);
+       }
+       
+       return retval;
 }
 
-void target_read_u8(struct target_s *target, u32 address, u8 *value)
+int target_read_u8(struct target_s *target, u32 address, u8 *value)
 {
-       target->type->read_memory(target, address, 1, 1, value);
+       int retval = target->type->read_memory(target, address, 1, 1, value);
 
-       DEBUG("address: 0x%8.8x, value: 0x%2.2x", address, *value);
+       if (retval == ERROR_OK)
+       {
+               DEBUG("address: 0x%8.8x, value: 0x%2.2x", address, *value);
+       }
+       else
+       {
+               *value = 0x0;
+               DEBUG("address: 0x%8.8x failed", address);
+       }
+       
+       return retval;
 }
 
-void target_write_u32(struct target_s *target, u32 address, u32 value)
+int target_write_u32(struct target_s *target, u32 address, u32 value)
 {
+       int retval;
        u8 value_buf[4];
 
        DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, value);
 
        target_buffer_set_u32(target, value_buf, value);        
-       target->type->write_memory(target, address, 4, 1, value_buf);
+       if ((retval = target->type->write_memory(target, address, 4, 1, value_buf)) != ERROR_OK)
+       {
+               DEBUG("failed: %i", retval);
+       }
+       
+       return retval;
 }
 
-void target_write_u16(struct target_s *target, u32 address, u16 value)
+int target_write_u16(struct target_s *target, u32 address, u16 value)
 {
+       int retval;
        u8 value_buf[2];
        
        DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, value);
 
        target_buffer_set_u16(target, value_buf, value);        
-       target->type->write_memory(target, address, 2, 1, value_buf);
+       if ((retval = target->type->write_memory(target, address, 2, 1, value_buf)) != ERROR_OK)
+       {
+               DEBUG("failed: %i", retval);
+       }
+       
+       return retval;
 }
 
-void target_write_u8(struct target_s *target, u32 address, u8 value)
+int target_write_u8(struct target_s *target, u32 address, u8 value)
 {
+       int retval;
+       
        DEBUG("address: 0x%8.8x, value: 0x%2.2x", address, value);
 
-       target->type->read_memory(target, address, 1, 1, &value);
+       if ((retval = target->type->read_memory(target, address, 1, 1, &value)) != ERROR_OK)
+       {
+               DEBUG("failed: %i", retval);
+       }
+       
+       return retval;
 }
 
 int target_register_user_commands(struct command_context_s *cmd_ctx)
@@ -790,7 +1040,7 @@ int target_register_user_commands(struct command_context_s *cmd_ctx)
        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");
+       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, "soft_reset_halt", handle_soft_reset_halt_command, COMMAND_EXEC, "halt the target and do a soft reset");
 
@@ -807,11 +1057,15 @@ int target_register_user_commands(struct command_context_s *cmd_ctx)
        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']");
+       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, "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;
 }
 
@@ -916,6 +1170,7 @@ int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **a
                                (*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;
@@ -929,6 +1184,19 @@ int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **a
                                (*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;
@@ -984,6 +1252,12 @@ int handle_target_script_command(struct command_context_s *cmd_ctx, char *cmd, c
                        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
        {
                ERROR("unknown event type: '%s", args[1]);
@@ -1020,10 +1294,9 @@ int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, ch
 {
        target_t *target = NULL;
        
-       if (argc < 4)
+       if ((argc < 4) || (argc > 5))
        {
-               ERROR("incomplete working_area command. usage: working_area <target#> <address> <size> <'backup'|'nobackup'>");
-               exit(-1);
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
        
        target = get_target_by_num(strtoul(args[0], NULL, 0));
@@ -1033,8 +1306,13 @@ int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, ch
                ERROR("target number '%s' not defined", args[0]);
                exit(-1);
        }
+       target_free_all_working_areas(target);
        
-       target->working_area = strtoul(args[1], NULL, 0);
+       target->working_area_phys = target->working_area_virt = strtoul(args[1], NULL, 0);
+       if (argc == 5)
+       {
+               target->working_area_virt = strtoul(args[4], NULL, 0);
+       }
        target->working_area_size = strtoul(args[2], NULL, 0);
        
        if (strcmp(args[3], "backup") == 0)
@@ -1048,7 +1326,7 @@ int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, ch
        else
        {
                ERROR("unrecognized <backup|nobackup> argument (%s)", args[3]);
-               exit(-1);
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
        
        return ERROR_OK;
@@ -1067,10 +1345,9 @@ int handle_target(void *priv)
                if (target->state != TARGET_HALTED)
                {
                        if (target_continous_poll)
-                               if ((retval = target->type->poll(target)) < 0)
+                               if ((retval = target->type->poll(target)) != ERROR_OK)
                                {
-                                       ERROR("couldn't poll target, exiting");
-                                       exit(-1);
+                                       ERROR("couldn't poll target(%d). It's due for a reset.", retval);
                                }
                }
        
@@ -1087,7 +1364,7 @@ int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args
        int count = 0;
        char *value;
        
-       DEBUG("");
+       DEBUG("-");
        
        target = get_current_target(cmd_ctx);
        
@@ -1202,20 +1479,16 @@ int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args
        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)
 {
        target_t *target = get_current_target(cmd_ctx);
-       char buffer[512];
 
        if (argc == 0)
        {
-               command_print(cmd_ctx, "target state: %s", target_state_strings[target->type->poll(target)]);
-               if (target->state == TARGET_HALTED)
-               {
-                       target->type->arch_state(target, buffer, 512);
-                       buffer[511] = 0;
-                       command_print(cmd_ctx, "%s", buffer);
-               }
+               target->type->poll(target);
+                       target_arch_state(target);
        }
        else
        {
@@ -1227,6 +1500,10 @@ int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **arg
                {
                        target_continous_poll = 0;
                }
+               else
+               {
+                       command_print(cmd_ctx, "arg is \"on\" or \"off\"");
+               }
        }
        
        
@@ -1235,38 +1512,58 @@ int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **arg
 
 int handle_wait_halt_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;
+       int ms = 5000;
        
-       gettimeofday(&timeout, NULL);
-       if (!argc)
-               timeval_add_time(&timeout, 5, 0);
-       else {
+       if (argc > 0)
+       {
                char *end;
 
-               timeval_add_time(&timeout, strtoul(args[0], &end, 0), 0);
-               if (*end) {
-                       command_print(cmd_ctx, "usage: wait_halt [seconds]");
+               ms = strtoul(args[0], &end, 0) * 1000;
+               if (*end)
+               {
+                       command_print(cmd_ctx, "usage: %s [seconds]", cmd);
                        return ERROR_OK;
                }
        }
 
-       command_print(cmd_ctx, "waiting for target halted...");
+       return wait_state(cmd_ctx, cmd, TARGET_HALTED, ms); 
+}
 
-       while(target->type->poll(target))
+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();
+}
+
+static int wait_state(struct command_context_s *cmd_ctx, char *cmd, enum target_state state, int ms)
+{
+       int retval;
+       struct timeval timeout, now;
+       int once=1;
+       gettimeofday(&timeout, NULL);
+       timeval_add_time(&timeout, 0, ms * 1000);
+       
+       target_t *target = get_current_target(cmd_ctx);
+       for (;;)
        {
-               if (target->state == TARGET_HALTED)
+               if ((retval=target->type->poll(target))!=ERROR_OK)
+                       return retval;
+               target_call_timer_callbacks();
+               if (target->state == state)
                {
-                       command_print(cmd_ctx, "target halted");
                        break;
                }
-               target_call_timer_callbacks();
+               if (once)
+               {
+                       once=0;
+                       command_print(cmd_ctx, "waiting for target %s...", target_state_strings[state]);
+               }
                
                gettimeofday(&now, NULL);
-               if ((now.tv_sec >= timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec))
+               if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec)))
                {
-                       command_print(cmd_ctx, "timed out while waiting for target halt");
-                       ERROR("timed out while waiting for target halt");
+                       ERROR("timed out while waiting for target %s", target_state_strings[state]);
                        break;
                }
        }
@@ -1279,28 +1576,14 @@ int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **arg
        int retval;
        target_t *target = get_current_target(cmd_ctx);
 
-       DEBUG("");
-       
-       command_print(cmd_ctx, "requesting target halt...");
+       DEBUG("-");
 
        if ((retval = target->type->halt(target)) != ERROR_OK)
-       {       
-               switch (retval)
                {
-                       case ERROR_TARGET_ALREADY_HALTED:
-                               command_print(cmd_ctx, "target already halted");
-                               break;
-                       case ERROR_TARGET_TIMEOUT:
-                               command_print(cmd_ctx, "target timed out... shutting down");
-                               exit(-1);
-                       default:
-                               command_print(cmd_ctx, "unknown error... shutting down");
-                               exit(-1);
+                               return retval;
                }
-       }
        
-       return ERROR_OK;
-
+       return handle_wait_halt_command(cmd_ctx, cmd, args, argc);
 }
 
 /* what to do on daemon startup */
@@ -1351,9 +1634,10 @@ int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd,
 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 = RESET_RUN;
+       enum target_reset_mode reset_mode = target->reset_mode;
+       enum target_reset_mode save = target->reset_mode;
        
-       DEBUG("");
+       DEBUG("-");
        
        if (argc >= 1)
        {
@@ -1384,11 +1668,17 @@ int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **ar
                        command_print(cmd_ctx, "usage: reset ['run', 'halt', 'init', 'run_and_halt', 'run_and_init]");
                        return ERROR_OK;
                }
-               target->reset_mode = reset_mode;
        }
        
+       /* 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;
 }
 
@@ -1397,39 +1687,27 @@ int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **a
        int retval;
        target_t *target = get_current_target(cmd_ctx);
        
-       DEBUG("");
-       
        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
        {
-               command_print(cmd_ctx, "usage: resume [address]");
-               return ERROR_OK;
-       }
-       
-       if (retval != ERROR_OK)
-       {       
-               switch (retval)
-               {
-                       case ERROR_TARGET_NOT_HALTED:
-                               command_print(cmd_ctx, "target not halted");
-                               break;
-                       default:
-                               command_print(cmd_ctx, "unknown error... shutting down");
-                               exit(-1);
-               }
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
-       return ERROR_OK;
+       target_process_events(cmd_ctx);
+       
+       target_arch_state(target);
+       
+       return retval;
 }
 
 int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
        target_t *target = get_current_target(cmd_ctx);
        
-       DEBUG("");
+       DEBUG("-");
        
        if (argc == 0)
                target->type->step(target, 1, 0, 1); /* current pc, addr = 0, handle breakpoints */
@@ -1442,9 +1720,11 @@ int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **arg
 
 int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
+       const int line_bytecnt = 32;
        int count = 1;
        int size = 4;
        u32 address = 0;
+       int line_modulo;
        int i;
 
        char output[128];
@@ -1467,20 +1747,21 @@ int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args,
        switch (cmd[2])
        {
                case 'w':
-                       size = 4;
+                       size = 4; line_modulo = line_bytecnt / 4;
                        break;
                case 'h':
-                       size = 2;
+                       size = 2; line_modulo = line_bytecnt / 2;
                        break;
                case 'b':
-                       size = 1;
+                       size = 1; line_modulo = line_bytecnt / 1;
                        break;
                default:
                        return ERROR_OK;
        }
 
        buffer = calloc(count, size);
-       if ((retval  = target->type->read_memory(target, address, size, count, buffer)) != ERROR_OK)
+       retval  = target->type->read_memory(target, address, size, count, buffer);
+       if (retval != ERROR_OK)
        {
                switch (retval)
                {
@@ -1504,7 +1785,7 @@ int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args,
 
        for (i = 0; i < count; i++)
        {
-               if (i%8 == 0)
+               if (i%line_modulo == 0)
                        output_len += snprintf(output + output_len, 128 - output_len, "0x%8.8x: ", address + (i*size));
                
                switch (size)
@@ -1520,7 +1801,7 @@ int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args,
                                break;
                }
 
-               if ((i%8 == 7) || (i == count - 1))
+               if ((i%line_modulo == line_modulo-1) || (i == count - 1))
                {
                        command_print(cmd_ctx, output);
                        output_len = 0;
@@ -1588,61 +1869,75 @@ 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)
 {
-       u32 address;
        u8 *buffer;
        u32 buf_cnt;
-       u32 binary_size;
-       
-       fileio_t file;
-       enum fileio_pri_type pri_type = FILEIO_IMAGE;
-       fileio_image_t image_info;
-       enum fileio_sec_type sec_type;
+       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 < 2)
+       if (argc < 1)
        {
-               command_print(cmd_ctx, "usage: load_image <filename> <address> [type]");
+               command_print(cmd_ctx, "usage: load_image <filename> [address] [type]");
                return ERROR_OK;
        }
        
-       memset(&file, 0, sizeof(fileio_t));
-       fileio_identify_image_type(&sec_type, (argc == 3) ? args[2] : NULL);
-
-       image_info.base_address = strtoul(args[1], NULL, 0);
-       image_info.has_start_address = 0;
+       /* 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;
+       }
        
-       buffer = malloc(128 * 1024);
+       image.start_address_set = 0;
 
        duration_start_measure(&duration);
        
-       if (fileio_open(&file, args[0], FILEIO_READ, 
-               pri_type, &image_info, sec_type) != ERROR_OK)
+       if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
        {
-               command_print(cmd_ctx, "load_image error: %s", file.error_str);
                return ERROR_OK;
        }
        
-       binary_size = file.size;
-       address = image_info.base_address;
-       while ((binary_size > 0) &&
-               (fileio_read(&file, 128 * 1024, buffer, &buf_cnt) == ERROR_OK))
+       image_size = 0x0;
+       for (i = 0; i < image.num_sections; i++)
        {
-               target_write_buffer(target, address, buf_cnt, buffer);
-               address += buf_cnt;
-               binary_size -= buf_cnt;
+               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)
+               {
+                       ERROR("image_read_section failed with error code: %i", retval);
+                       command_print(cmd_ctx, "image reading failed, download aborted");
+                       free(buffer);
+                       image_close(&image);
+                       return ERROR_OK;
+               }
+               target_write_buffer(target, image.sections[i].base_address, buf_cnt, buffer);
+               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);
        }
 
-       free(buffer);
-       
        duration_stop_measure(&duration, &duration_text);
-       command_print(cmd_ctx, "downloaded %lli byte in %s", file.size, duration_text);
+       command_print(cmd_ctx, "downloaded %u byte in %s", image_size, duration_text);
        free(duration_text);
        
-       fileio_close(&file);
+       image_close(&image);
 
        return ERROR_OK;
 
@@ -1650,12 +1945,12 @@ 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)
 {
-       fileio_t file;
-       fileio_image_t image_info;
+       fileio_t fileio;
        
        u32 address;
        u32 size;
        u8 buffer[560];
+       int retval;
        
        duration_t duration;
        char *duration_text;
@@ -1677,13 +1972,8 @@ int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char
                return ERROR_OK;
        }
        
-       image_info.base_address = address;
-       image_info.has_start_address = 0;
-       
-       if (fileio_open(&file, args[0], FILEIO_WRITE, 
-               FILEIO_IMAGE, &image_info, FILEIO_PLAIN) != ERROR_OK)
+       if (fileio_open(&fileio, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
        {
-               command_print(cmd_ctx, "dump_image error: %s", file.error_str);
                return ERROR_OK;
        }
        
@@ -1694,21 +1984,157 @@ 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;
                
-               target->type->read_memory(target, address, 4, this_run_size / 4, buffer);
-               fileio_write(&file, this_run_size, buffer, &size_written);
+               retval = target->type->read_memory(target, address, 4, this_run_size / 4, buffer);
+               if (retval != ERROR_OK)
+               {
+                       command_print(cmd_ctx, "Reading memory failed %d", retval);
+                       break;
+               }
+               
+               fileio_write(&fileio, this_run_size, buffer, &size_written);
                
                size -= this_run_size;
                address += this_run_size;
        }
 
-       fileio_close(&file);
+       fileio_close(&fileio);
 
        duration_stop_measure(&duration, &duration_text);
-       command_print(cmd_ctx, "dumped %lli byte in %s", file.size, duration_text);
+       command_print(cmd_ctx, "dumped %"PRIi64" byte in %s", fileio.size, duration_text);
        free(duration_text);
        
        return ERROR_OK;
+}
 
+int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+       u8 *buffer;
+       u32 buf_cnt;
+       u32 image_size;
+       int i;
+       int retval;
+       u32 checksum = 0;
+       u32 mem_checksum = 0;
+
+       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;
+       }
+       
+       if (!target)
+       {
+               ERROR("no target selected");
+               return ERROR_OK;
+       }
+       
+       duration_start_measure(&duration);
+       
+       if (argc >= 2)
+       {
+               image.base_address_set = 1;
+               image.base_address = strtoul(args[1], NULL, 0);
+       }
+       else
+       {
+               image.base_address_set = 0;
+               image.base_address = 0x0;
+       }
+
+       image.start_address_set = 0;
+
+       if (image_open(&image, args[0], (argc == 3) ? args[2] : NULL) != ERROR_OK)
+       {
+               return ERROR_OK;
+       }
+       
+       image_size = 0x0;
+       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)
+               {
+                       ERROR("image_read_section failed with error code: %i", retval);
+                       command_print(cmd_ctx, "image reading failed, verify aborted");
+                       free(buffer);
+                       image_close(&image);
+                       return ERROR_OK;
+               }
+               
+               /* 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 )
+               {
+                       command_print(cmd_ctx, "could not calculate checksum, verify aborted");
+                       free(buffer);
+                       image_close(&image);
+                       return ERROR_OK;
+               }
+               
+               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)
+                       {
+                               size *= 4;
+                               count /= 4;
+                       }
+                       retval = target->type->read_memory(target, image.sections[i].base_address, size, count, data);
+       
+                       if (retval == ERROR_OK)
+                       {
+                               int t;
+                               for (t = 0; t < buf_cnt; t++)
+                               {
+                                       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);
+                                               image_close(&image);
+                                               return ERROR_OK;
+                                       }
+                               }
+                       }
+                       
+                       free(data);
+               }
+               
+               free(buffer);
+               image_size += buf_cnt;
+       }
+       
+       duration_stop_measure(&duration, &duration_text);
+       command_print(cmd_ctx, "verified %u bytes in %s", image_size, duration_text);
+       free(duration_text);
+       
+       image_close(&image);
+       
+       return ERROR_OK;
 }
 
 int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
@@ -1787,6 +2213,7 @@ int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args
 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)
        {
@@ -1830,7 +2257,23 @@ int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args,
                {
                        data_mask = strtoul(args[4], NULL, 0);
                }
-               watchpoint_add(target, strtoul(args[0], NULL, 0), strtoul(args[1], NULL, 0), type, data_value, data_mask);
+               
+               if ((retval = watchpoint_add(target, strtoul(args[0], NULL, 0),
+                               strtoul(args[1], NULL, 0), type, data_value, data_mask)) != ERROR_OK)
+               {
+                       switch (retval)
+                       {
+                               case ERROR_TARGET_NOT_HALTED:
+                                       command_print(cmd_ctx, "target must be halted to set watchpoints");
+                                       break;
+                               case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
+                                       command_print(cmd_ctx, "no more watchpoints available");
+                                       break;
+                               default:
+                                       command_print(cmd_ctx, "unknown error, watchpoint not set");
+                                       break;
+                       }       
+               }
        }
        else
        {
@@ -1850,3 +2293,29 @@ 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)
+{
+       int retval;
+       target_t *target = get_current_target(cmd_ctx);
+       u32 va;
+       u32 pa;
+
+       if (argc != 1)
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+       va = strtoul(args[0], NULL, 0);
+
+       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;
+}