X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Ftarget.c;h=e1341a0a3e8ae42bb0ca2dfec515742a8bb5e3fe;hb=06d501a192e36986ba0f81c7ddff9298dd0a389e;hp=03b04e38b8ce12d1bb395aa0a7fc574682e2680b;hpb=3b2a068ea997323eb37251b31be8034c57ff9def;p=openocd.git diff --git a/src/target/target.c b/src/target/target.c index 03b04e38b8..e1341a0a3e 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -49,12 +49,9 @@ int cli_target_callback_event_handler(struct target_s *target, enum target_event event, void *priv); - int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -int handle_daemon_startup_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -int handle_target_script_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_run_and_halt_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); @@ -77,9 +74,11 @@ int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc); int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv); +static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv); -/* targets - */ + +/* targets */ extern target_type_t arm7tdmi_target; extern target_type_t arm720t_target; extern target_type_t arm9tdmi_target; @@ -132,8 +131,6 @@ char *target_endianess_strings[] = "little endian", }; -enum daemon_startup_mode startup_mode = DAEMON_ATTACH; - static int target_continous_poll = 1; /* read a u32 from a buffer in target memory endianness */ @@ -211,7 +208,7 @@ target_t* get_current_target(command_context_t *cmd_ctx) if (target == NULL) { - ERROR("BUG: current_target out of bounds"); + LOG_ERROR("BUG: current_target out of bounds"); exit(-1); } @@ -223,24 +220,12 @@ target_t* get_current_target(command_context_t *cmd_ctx) */ int target_init_handler(struct target_s *target, enum target_event event, void *priv) { - FILE *script; struct command_context_s *cmd_ctx = priv; - if ((event == TARGET_EVENT_HALTED) && (target->reset_script)) + if (event == TARGET_EVENT_HALTED) { target_unregister_event_callback(target_init_handler, priv); - - script = open_file_from_path(target->reset_script, "r"); - if (!script) - { - ERROR("couldn't open script file %s", target->reset_script); - return ERROR_OK; - } - - INFO("executing reset script '%s'", target->reset_script); - command_run_file(cmd_ctx, script, COMMAND_EXEC); - fclose(script); - + target_invoke_script(cmd_ctx, target, "post_reset"); jtag_execute_queue(); } @@ -251,64 +236,109 @@ int target_run_and_halt_handler(void *priv) { target_t *target = priv; - target->type->halt(target); + target_halt(target); return ERROR_OK; } -int target_process_reset(struct command_context_s *cmd_ctx) +int target_poll(struct target_s *target) +{ + /* We can't poll until after examine */ + if (!target->type->examined) + { + /* Fail silently lest we pollute the log */ + return ERROR_FAIL; + } + return target->type->poll(target); +} + +int target_halt(struct target_s *target) +{ + /* We can't poll until after examine */ + if (!target->type->examined) + { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + return target->type->halt(target); +} + +int target_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution) +{ + int retval; + + /* We can't poll until after examine */ + if (!target->type->examined) + { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + /* note that resume *must* be asynchronous. The CPU can halt before we poll. The CPU can + * even halt at the current PC as a result of a software breakpoint being inserted by (a bug?) + * the application. + */ + if ((retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution)) != ERROR_OK) + return retval; + + return retval; +} + +int target_process_reset(struct command_context_s *cmd_ctx, enum target_reset_mode reset_mode) { int retval = ERROR_OK; target_t *target; struct timeval timeout, now; - jtag->speed(jtag_speed); - - /* 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_invoke_script(cmd_ctx, target, "pre_reset"); target = target->next; } + if ((retval = jtag_init_reset(cmd_ctx)) != ERROR_OK) + return retval; + + keep_alive(); /* we might be running on a very slow JTAG clk */ + + /* First time this is executed after launching OpenOCD, it will read out + * the type of CPU, etc. and init Embedded ICE registers in host + * memory. + * + * It will also set up ICE registers in the target. + * + * However, if we assert TRST later, we need to set up the registers again. + * + * For the "reset halt/init" case we must only set up the registers here. + */ + if ((retval = target_examine(cmd_ctx)) != ERROR_OK) + return retval; + + keep_alive(); /* we might be running on a very slow JTAG clk */ + target = targets; while (target) { + /* we have no idea what state the target is in, so we + * have to drop working areas + */ + target_free_all_working_areas_restore(target, 0); + target->reset_halt=((reset_mode==RESET_HALT)||(reset_mode==RESET_INIT)); target->type->assert_reset(target); target = target->next; } - jtag_execute_queue(); + if ((retval = jtag_execute_queue()) != ERROR_OK) + { + LOG_WARNING("JTAG communication failed asserting reset."); + retval = ERROR_OK; + } /* request target halt if necessary, and schedule further action */ target = targets; while (target) { - switch (target->reset_mode) + switch (reset_mode) { case RESET_RUN: /* nothing to do if target just wants to be run */ @@ -323,25 +353,55 @@ int target_process_reset(struct command_context_s *cmd_ctx) target_register_event_callback(target_init_handler, cmd_ctx); break; case RESET_HALT: - target->type->halt(target); + if ((jtag_reset_config & RESET_SRST_PULLS_TRST)==0) + target_halt(target); break; case RESET_INIT: - target->type->halt(target); + if ((jtag_reset_config & RESET_SRST_PULLS_TRST)==0) + target_halt(target); target_register_event_callback(target_init_handler, cmd_ctx); break; default: - ERROR("BUG: unknown target->reset_mode"); + LOG_ERROR("BUG: unknown target->reset_mode"); } target = target->next; } + if ((retval = jtag_execute_queue()) != ERROR_OK) + { + LOG_WARNING("JTAG communication failed while reset was asserted. Consider using srst_only for reset_config."); + retval = ERROR_OK; + } + target = targets; while (target) { target->type->deassert_reset(target); + /* We can fail to bring the target into the halted state */ + target_poll(target); + if (target->reset_halt&&((target->state != TARGET_HALTED))) + { + LOG_WARNING("Failed to reset target into halted mode - issuing halt"); + target->type->halt(target); + } + target = target->next; } - jtag_execute_queue(); + + if ((retval = jtag_execute_queue()) != ERROR_OK) + { + LOG_WARNING("JTAG communication failed while deasserting reset."); + retval = ERROR_OK; + } + + if (jtag_reset_config & RESET_SRST_PULLS_TRST) + { + /* If TRST was asserted we need to set up registers again */ + if ((retval = target_examine(cmd_ctx)) != ERROR_OK) + return retval; + } + + LOG_DEBUG("Waiting for halted stated as appropriate"); /* Wait for reset to complete, maximum 5 seconds. */ gettimeofday(&timeout, NULL); @@ -355,19 +415,23 @@ int target_process_reset(struct command_context_s *cmd_ctx) target = targets; while (target) { - target->type->poll(target); - if ((target->reset_mode == RESET_RUN_AND_INIT) || (target->reset_mode == RESET_RUN_AND_HALT)) + LOG_DEBUG("Polling target"); + target_poll(target); + if ((reset_mode == RESET_RUN_AND_INIT) || + (reset_mode == RESET_RUN_AND_HALT) || + (reset_mode == RESET_HALT) || + (reset_mode == RESET_INIT)) { if (target->state != TARGET_HALTED) { if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec))) { - USER("Timed out waiting for reset"); + LOG_USER("Timed out waiting for halt after reset"); goto done; } /* this will send alive messages on e.g. GDB remote protocol. */ usleep(500*1000); - USER_N("%s", ""); /* avoid warning about zero length formatting message*/ + LOG_USER_N("%s", ""); /* avoid warning about zero length formatting message*/ goto again; } } @@ -384,7 +448,14 @@ int target_process_reset(struct command_context_s *cmd_ctx) /* We want any events to be processed before the prompt */ target_call_timer_callbacks_now(); - jtag->speed(jtag_speed_post_reset); + /* if we timed out we need to unregister these handlers */ + target = targets; + while (target) + { + target_unregister_timer_callback(target_run_and_halt_handler, target); + target = target->next; + } + target_unregister_event_callback(target_init_handler, cmd_ctx); return retval; } @@ -401,15 +472,86 @@ static int default_mmu(struct target_s *target, int *enabled) return ERROR_OK; } +static int default_examine(struct command_context_s *cmd_ctx, struct target_s *target) +{ + target->type->examined = 1; + return ERROR_OK; +} + + +/* Targets that correctly implement init+examine, i.e. + * no communication with target during init: + * + * XScale + */ +int target_examine(struct command_context_s *cmd_ctx) +{ + int retval = ERROR_OK; + target_t *target = targets; + while (target) + { + if ((retval = target->type->examine(cmd_ctx, target))!=ERROR_OK) + return retval; + target = target->next; + } + return retval; +} + +static int target_write_memory_imp(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer) +{ + if (!target->type->examined) + { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + return target->type->write_memory_imp(target, address, size, count, buffer); +} + +static int target_read_memory_imp(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer) +{ + if (!target->type->examined) + { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + return target->type->read_memory_imp(target, address, size, count, buffer); +} + +static int target_soft_reset_halt_imp(struct target_s *target) +{ + if (!target->type->examined) + { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + return target->type->soft_reset_halt_imp(target); +} + +static int target_run_algorithm_imp(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_param, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info) +{ + if (!target->type->examined) + { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + return target->type->run_algorithm_imp(target, num_mem_params, mem_params, num_reg_params, reg_param, entry_point, exit_point, timeout_ms, arch_info); +} + int target_init(struct command_context_s *cmd_ctx) { target_t *target = targets; while (target) { + target->type->examined = 0; + if (target->type->examine == NULL) + { + target->type->examine = default_examine; + } + if (target->type->init_target(cmd_ctx, target) != ERROR_OK) { - ERROR("target '%s' init failed", target->type->name); + LOG_ERROR("target '%s' init failed", target->type->name); exit(-1); } @@ -418,6 +560,20 @@ int target_init(struct command_context_s *cmd_ctx) { target->type->virt2phys = default_virt2phys; } + target->type->virt2phys = default_virt2phys; + /* a non-invasive way(in terms of patches) to add some code that + * runs before the type->write/read_memory implementation + */ + target->type->write_memory_imp = target->type->write_memory; + target->type->write_memory = target_write_memory_imp; + target->type->read_memory_imp = target->type->read_memory; + target->type->read_memory = target_read_memory_imp; + target->type->soft_reset_halt_imp = target->type->soft_reset_halt; + target->type->soft_reset_halt = target_soft_reset_halt_imp; + target->type->run_algorithm_imp = target->type->run_algorithm; + target->type->run_algorithm = target_run_algorithm_imp; + + if (target->type->mmu == NULL) { target->type->mmu = default_mmu; @@ -434,14 +590,6 @@ int target_init(struct command_context_s *cmd_ctx) return ERROR_OK; } -int target_init_reset(struct command_context_s *cmd_ctx) -{ - if (startup_mode == DAEMON_RESET) - target_process_reset(cmd_ctx); - - return ERROR_OK; -} - int target_register_event_callback(int (*callback)(struct target_s *target, enum target_event event, void *priv), void *priv) { target_event_callback_t **callbacks_p = &target_event_callbacks; @@ -563,7 +711,7 @@ int target_call_event_callbacks(target_t *target, enum target_event event) target_event_callback_t *callback = target_event_callbacks; target_event_callback_t *next_callback; - DEBUG("target event %i", event); + LOG_DEBUG("target event %i", event); while (callback) { @@ -575,36 +723,42 @@ int target_call_event_callbacks(target_t *target, enum target_event event) return ERROR_OK; } -int target_call_timer_callbacks() +static int target_call_timer_callbacks_check_time(int checktime) { target_timer_callback_t *callback = target_timer_callbacks; target_timer_callback_t *next_callback; struct timeval now; + keep_alive(); + gettimeofday(&now, NULL); while (callback) { next_callback = callback->next; - if (((now.tv_sec >= callback->when.tv_sec) && (now.tv_usec >= callback->when.tv_usec)) - || (now.tv_sec > callback->when.tv_sec)) + if ((!checktime&&callback->periodic)|| + (((now.tv_sec >= callback->when.tv_sec) && (now.tv_usec >= callback->when.tv_usec)) + || (now.tv_sec > callback->when.tv_sec))) { - callback->callback(callback->priv); - if (callback->periodic) + if(callback->callback != NULL) { - int time_ms = callback->time_ms; - callback->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000; - time_ms -= (time_ms % 1000); - callback->when.tv_sec = now.tv_sec + time_ms / 1000; - if (callback->when.tv_usec > 1000000) + callback->callback(callback->priv); + if (callback->periodic) { - callback->when.tv_usec = callback->when.tv_usec - 1000000; - callback->when.tv_sec += 1; + int time_ms = callback->time_ms; + callback->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000; + time_ms -= (time_ms % 1000); + callback->when.tv_sec = now.tv_sec + time_ms / 1000; + if (callback->when.tv_usec > 1000000) + { + callback->when.tv_usec = callback->when.tv_usec - 1000000; + callback->when.tv_sec += 1; + } } + else + target_unregister_timer_callback(callback->callback, callback->priv); } - else - target_unregister_timer_callback(callback->callback, callback->priv); } callback = next_callback; @@ -613,15 +767,16 @@ int target_call_timer_callbacks() return ERROR_OK; } -int target_call_timer_callbacks_now() +int target_call_timer_callbacks() { - /* TODO: this should invoke the timer callbacks now. This is used to ensure that - * any outstanding polls, etc. are in fact invoked before a synchronous command - * completes. - */ - return target_call_timer_callbacks(); + return target_call_timer_callbacks_check_time(1); } +/* invoke periodic callbacks immediately */ +int target_call_timer_callbacks_now() +{ + return target_call_timer_callbacks(0); +} int target_alloc_working_area(struct target_s *target, u32 size, working_area_t **area) { @@ -651,7 +806,7 @@ int target_alloc_working_area(struct target_s *target, u32 size, working_area_t /* only allocate multiples of 4 byte */ if (size % 4) { - ERROR("BUG: code tried to allocate unaligned number of bytes, padding"); + LOG_ERROR("BUG: code tried to allocate unaligned number of bytes, padding"); size = CEIL(size, 4); } @@ -673,7 +828,7 @@ int target_alloc_working_area(struct target_s *target, u32 size, working_area_t u32 first_free = target->working_area; u32 free_size = target->working_area_size; - DEBUG("allocating new working area"); + LOG_DEBUG("allocating new working area"); c = target->working_areas; while (c) @@ -686,7 +841,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(requested %d, free %d)", size, free_size); + LOG_WARNING("not enough working area available(requested %d, free %d)", size, free_size); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -719,12 +874,12 @@ int target_alloc_working_area(struct target_s *target, u32 size, working_area_t return ERROR_OK; } -int target_free_working_area(struct target_s *target, working_area_t *area) +int target_free_working_area_restore(struct target_s *target, working_area_t *area, int restore) { if (area->free) return ERROR_OK; - if (target->backup_working_area) + if (restore&&target->backup_working_area) target->type->write_memory(target, area->address, 4, area->size / 4, area->backup); area->free = 1; @@ -736,14 +891,19 @@ int target_free_working_area(struct target_s *target, working_area_t *area) return ERROR_OK; } -int target_free_all_working_areas(struct target_s *target) +int target_free_working_area(struct target_s *target, working_area_t *area) +{ + return target_free_working_area_restore(target, area, 1); +} + +int target_free_all_working_areas_restore(struct target_s *target, int restore) { working_area_t *c = target->working_areas; while (c) { working_area_t *next = c->next; - target_free_working_area(target, c); + target_free_working_area_restore(target, c, restore); if (c->backup) free(c->backup); @@ -758,17 +918,24 @@ int target_free_all_working_areas(struct target_s *target) return ERROR_OK; } +int target_free_all_working_areas(struct target_s *target) +{ + return target_free_all_working_areas_restore(target, 1); +} + int target_register_commands(struct command_context_s *cmd_ctx) { - register_command(cmd_ctx, NULL, "target", handle_target_command, COMMAND_CONFIG, NULL); + register_command(cmd_ctx, NULL, "target", handle_target_command, COMMAND_CONFIG, "target [reset_init default - DEPRECATED] [cpu type specifc args]"); register_command(cmd_ctx, NULL, "targets", handle_targets_command, COMMAND_EXEC, NULL); - register_command(cmd_ctx, NULL, "daemon_startup", handle_daemon_startup_command, COMMAND_CONFIG, NULL); - register_command(cmd_ctx, NULL, "target_script", handle_target_script_command, COMMAND_CONFIG, NULL); register_command(cmd_ctx, NULL, "run_and_halt_time", handle_run_and_halt_time_command, COMMAND_CONFIG, " "); register_command(cmd_ctx, NULL, "working_area", handle_working_area_command, COMMAND_ANY, "working_area
<'backup'|'nobackup'> [virtual address]"); register_command(cmd_ctx, NULL, "virt2phys", handle_virt2phys_command, COMMAND_ANY, "virt2phys "); register_command(cmd_ctx, NULL, "profile", handle_profile_command, COMMAND_EXEC, "PRELIMINARY! - profile "); + + /* 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"); return ERROR_OK; } @@ -777,11 +944,11 @@ int target_arch_state(struct target_s *target) int retval; if (target==NULL) { - USER("No target has been configured"); + LOG_USER("No target has been configured"); return ERROR_OK; } - USER("target state: %s", target_state_strings[target->state]); + LOG_USER("target state: %s", target_state_strings[target->state]); if (target->state!=TARGET_HALTED) return ERROR_OK; @@ -797,8 +964,13 @@ int target_arch_state(struct target_s *target) int target_write_buffer(struct target_s *target, u32 address, u32 size, u8 *buffer) { int retval; + if (!target->type->examined) + { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } - DEBUG("writing buffer of %i byte at 0x%8.8x", size, address); + LOG_DEBUG("writing buffer of %i byte at 0x%8.8x", size, address); if (((address % 2) == 0) && (size == 2)) { @@ -861,8 +1033,13 @@ int target_write_buffer(struct target_s *target, u32 address, u32 size, u8 *buff 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); + if (!target->type->examined) + { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + LOG_DEBUG("reading buffer of %i byte at 0x%8.8x", size, address); if (((address % 2) == 0) && (size == 2)) { @@ -914,6 +1091,11 @@ int target_checksum_memory(struct target_s *target, u32 address, u32 size, u32* int retval; int i; u32 checksum = 0; + if (!target->type->examined) + { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } if ((retval = target->type->checksum_memory(target, address, size, &checksum)) == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) @@ -921,7 +1103,7 @@ int target_checksum_memory(struct target_s *target, u32 address, u32 size, u32* buffer = malloc(size); if (buffer == NULL) { - ERROR("error allocating buffer for section (%d bytes)", size); + LOG_ERROR("error allocating buffer for section (%d bytes)", size); return ERROR_INVALID_ARGUMENTS; } retval = target_read_buffer(target, address, size, buffer); @@ -948,21 +1130,43 @@ int target_checksum_memory(struct target_s *target, u32 address, u32 size, u32* return retval; } +int target_blank_check_memory(struct target_s *target, u32 address, u32 size, u32* blank) +{ + int retval; + if (!target->type->examined) + { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + if (target->type->blank_check_memory == 0) + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + + retval = target->type->blank_check_memory(target, address, size, blank); + + return retval; +} + int target_read_u32(struct target_s *target, u32 address, u32 *value) { u8 value_buf[4]; + if (!target->type->examined) + { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } 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); + LOG_DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, *value); } else { *value = 0x0; - DEBUG("address: 0x%8.8x failed", address); + LOG_DEBUG("address: 0x%8.8x failed", address); } return retval; @@ -971,18 +1175,23 @@ int target_read_u32(struct target_s *target, u32 address, u32 *value) int target_read_u16(struct target_s *target, u32 address, u16 *value) { u8 value_buf[2]; - + if (!target->type->examined) + { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + int retval = target->type->read_memory(target, address, 2, 1, value_buf); if (retval == ERROR_OK) { *value = target_buffer_get_u16(target, value_buf); - DEBUG("address: 0x%8.8x, value: 0x%4.4x", address, *value); + LOG_DEBUG("address: 0x%8.8x, value: 0x%4.4x", address, *value); } else { *value = 0x0; - DEBUG("address: 0x%8.8x failed", address); + LOG_DEBUG("address: 0x%8.8x failed", address); } return retval; @@ -991,15 +1200,20 @@ int target_read_u16(struct target_s *target, u32 address, u16 *value) int target_read_u8(struct target_s *target, u32 address, u8 *value) { int retval = target->type->read_memory(target, address, 1, 1, value); + if (!target->type->examined) + { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } if (retval == ERROR_OK) { - DEBUG("address: 0x%8.8x, value: 0x%2.2x", address, *value); + LOG_DEBUG("address: 0x%8.8x, value: 0x%2.2x", address, *value); } else { *value = 0x0; - DEBUG("address: 0x%8.8x failed", address); + LOG_DEBUG("address: 0x%8.8x failed", address); } return retval; @@ -1009,13 +1223,18 @@ int target_write_u32(struct target_s *target, u32 address, u32 value) { int retval; u8 value_buf[4]; + if (!target->type->examined) + { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } - DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, value); + LOG_DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, value); target_buffer_set_u32(target, value_buf, value); if ((retval = target->type->write_memory(target, address, 4, 1, value_buf)) != ERROR_OK) { - DEBUG("failed: %i", retval); + LOG_DEBUG("failed: %i", retval); } return retval; @@ -1025,13 +1244,18 @@ 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); + if (!target->type->examined) + { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + LOG_DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, value); target_buffer_set_u16(target, value_buf, value); if ((retval = target->type->write_memory(target, address, 2, 1, value_buf)) != ERROR_OK) { - DEBUG("failed: %i", retval); + LOG_DEBUG("failed: %i", retval); } return retval; @@ -1040,12 +1264,17 @@ int target_write_u16(struct target_s *target, u32 address, u16 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); + if (!target->type->examined) + { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + LOG_DEBUG("address: 0x%8.8x, value: 0x%2.2x", address, value); if ((retval = target->type->read_memory(target, address, 1, 1, &value)) != ERROR_OK) { - DEBUG("failed: %i", retval); + LOG_DEBUG("failed: %i", retval); } return retval; @@ -1066,9 +1295,9 @@ int target_register_user_commands(struct command_context_s *cmd_ctx) register_command(cmd_ctx, NULL, "mdh", handle_md_command, COMMAND_EXEC, "display memory half-words [count]"); register_command(cmd_ctx, NULL, "mdb", handle_md_command, COMMAND_EXEC, "display memory bytes [count]"); - register_command(cmd_ctx, NULL, "mww", handle_mw_command, COMMAND_EXEC, "write memory word "); - register_command(cmd_ctx, NULL, "mwh", handle_mw_command, COMMAND_EXEC, "write memory half-word "); - register_command(cmd_ctx, NULL, "mwb", handle_mw_command, COMMAND_EXEC, "write memory byte "); + register_command(cmd_ctx, NULL, "mww", handle_mw_command, COMMAND_EXEC, "write memory word [count]"); + register_command(cmd_ctx, NULL, "mwh", handle_mw_command, COMMAND_EXEC, "write memory half-word [count]"); + register_command(cmd_ctx, NULL, "mwb", handle_mw_command, COMMAND_EXEC, "write memory byte [count]"); register_command(cmd_ctx, NULL, "bp", handle_bp_command, COMMAND_EXEC, "set breakpoint
[hw]"); register_command(cmd_ctx, NULL, "rbp", handle_rbp_command, COMMAND_EXEC, "remove breakpoint "); @@ -1141,7 +1370,7 @@ int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **a /* register target specific commands */ if (target_types[i]->register_commands(cmd_ctx) != ERROR_OK) { - ERROR("couldn't register '%s' commands", args[0]); + LOG_ERROR("couldn't register '%s' commands", args[0]); exit(-1); } @@ -1154,7 +1383,9 @@ int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **a *last_target_p = malloc(sizeof(target_t)); - (*last_target_p)->type = target_types[i]; + /* allocate memory for each unique target type */ + (*last_target_p)->type = (target_type_t*)malloc(sizeof(target_type_t)); + *((*last_target_p)->type) = *target_types[i]; if (strcmp(args[1], "big") == 0) (*last_target_p)->endianness = TARGET_BIG_ENDIAN; @@ -1162,33 +1393,43 @@ int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **a (*last_target_p)->endianness = TARGET_LITTLE_ENDIAN; else { - ERROR("endianness must be either 'little' or 'big', not '%s'", args[1]); + LOG_ERROR("endianness must be either 'little' or 'big', not '%s'", args[1]); return ERROR_COMMAND_SYNTAX_ERROR; } - /* what to do on a target reset */ if (strcmp(args[2], "reset_halt") == 0) - (*last_target_p)->reset_mode = RESET_HALT; + { + LOG_WARNING("reset_mode argument is obsolete."); + return ERROR_COMMAND_SYNTAX_ERROR; + } else if (strcmp(args[2], "reset_run") == 0) - (*last_target_p)->reset_mode = RESET_RUN; + { + LOG_WARNING("reset_mode argument is obsolete."); + return ERROR_COMMAND_SYNTAX_ERROR; + } else if (strcmp(args[2], "reset_init") == 0) - (*last_target_p)->reset_mode = RESET_INIT; + { + LOG_WARNING("reset_mode argument is obsolete."); + return ERROR_COMMAND_SYNTAX_ERROR; + } else if (strcmp(args[2], "run_and_halt") == 0) - (*last_target_p)->reset_mode = RESET_RUN_AND_HALT; + { + LOG_WARNING("reset_mode argument is obsolete."); + return ERROR_COMMAND_SYNTAX_ERROR; + } else if (strcmp(args[2], "run_and_init") == 0) - (*last_target_p)->reset_mode = RESET_RUN_AND_INIT; - else { - ERROR("unknown target startup mode %s", args[2]); + LOG_WARNING("reset_mode argument is obsolete."); return ERROR_COMMAND_SYNTAX_ERROR; } + else + { + /* Kludge! we want to make this reset arg optional while remaining compatible! */ + args--; + argc++; + } (*last_target_p)->run_and_halt_time = 1000; /* default 1s */ - (*last_target_p)->reset_script = NULL; - (*last_target_p)->post_halt_script = NULL; - (*last_target_p)->pre_resume_script = NULL; - (*last_target_p)->gdb_program_script = NULL; - (*last_target_p)->working_area = 0x0; (*last_target_p)->working_area_size = 0x0; (*last_target_p)->working_areas = NULL; @@ -1226,62 +1467,18 @@ int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **a /* no matching target found */ if (!found) { - ERROR("target '%s' not found", args[0]); + LOG_ERROR("target '%s' not found", args[0]); return ERROR_COMMAND_SYNTAX_ERROR; } return ERROR_OK; } -/* usage: target_script */ -int handle_target_script_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +int target_invoke_script(struct command_context_s *cmd_ctx, target_t *target, char *name) { - target_t *target = NULL; - - if (argc < 3) - { - ERROR("incomplete target_script command"); - return ERROR_COMMAND_SYNTAX_ERROR; - } - - target = get_target_by_num(strtoul(args[0], NULL, 0)); - - if (!target) - { - return ERROR_COMMAND_SYNTAX_ERROR; - } - - if (strcmp(args[1], "reset") == 0) - { - if (target->reset_script) - free(target->reset_script); - target->reset_script = strdup(args[2]); - } - else if (strcmp(args[1], "post_halt") == 0) - { - if (target->post_halt_script) - free(target->post_halt_script); - target->post_halt_script = strdup(args[2]); - } - else if (strcmp(args[1], "pre_resume") == 0) - { - if (target->pre_resume_script) - free(target->pre_resume_script); - target->pre_resume_script = strdup(args[2]); - } - else if (strcmp(args[1], "gdb_program_config") == 0) - { - if (target->gdb_program_script) - free(target->gdb_program_script); - target->gdb_program_script = strdup(args[2]); - } - else - { - ERROR("unknown event type: '%s", args[1]); - return ERROR_COMMAND_SYNTAX_ERROR; - } - - return ERROR_OK; + return command_run_linef(cmd_ctx, " if {[catch {info body target_%d_%s} t]==0} {target_%d_%s}", + get_num_by_target(target), name, + get_num_by_target(target), name); } int handle_run_and_halt_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) @@ -1337,7 +1534,7 @@ int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, ch } else { - ERROR("unrecognized argument (%s)", args[3]); + LOG_ERROR("unrecognized argument (%s)", args[3]); return ERROR_COMMAND_SYNTAX_ERROR; } @@ -1348,19 +1545,14 @@ int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, ch /* process target state changes */ int handle_target(void *priv) { - int retval; target_t *target = targets; while (target) { - /* only poll if target isn't already halted */ - if (target->state != TARGET_HALTED) + if (target_continous_poll) { - if (target_continous_poll) - if ((retval = target->type->poll(target)) != ERROR_OK) - { - ERROR("couldn't poll target(%d). It's due for a reset.", retval); - } + /* polling may fail silently until the target has been examined */ + target_poll(target); } target = target->next; @@ -1376,7 +1568,7 @@ int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args int count = 0; char *value; - DEBUG("-"); + LOG_DEBUG("-"); target = get_current_target(cmd_ctx); @@ -1451,7 +1643,7 @@ int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args reg_arch_type_t *arch_type = register_get_arch_type(reg->arch_type); if (arch_type == NULL) { - ERROR("BUG: encountered unregistered arch type"); + LOG_ERROR("BUG: encountered unregistered arch type"); return ERROR_OK; } arch_type->get(reg); @@ -1471,7 +1663,7 @@ int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args reg_arch_type_t *arch_type = register_get_arch_type(reg->arch_type); if (arch_type == NULL) { - ERROR("BUG: encountered unregistered arch type"); + LOG_ERROR("BUG: encountered unregistered arch type"); return ERROR_OK; } @@ -1491,7 +1683,6 @@ 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) { @@ -1499,8 +1690,8 @@ int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **arg if (argc == 0) { - target->type->poll(target); - target_arch_state(target); + target_poll(target); + target_arch_state(target); } else { @@ -1537,18 +1728,12 @@ int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char return ERROR_OK; } } - - return wait_state(cmd_ctx, cmd, TARGET_HALTED, ms); -} - -static void target_process_events(struct command_context_s *cmd_ctx) -{ target_t *target = get_current_target(cmd_ctx); - target->type->poll(target); - target_call_timer_callbacks_now(); + + return target_wait_state(target, TARGET_HALTED, ms); } -static int wait_state(struct command_context_s *cmd_ctx, char *cmd, enum target_state state, int ms) +int target_wait_state(target_t *target, enum target_state state, int ms) { int retval; struct timeval timeout, now; @@ -1556,10 +1741,9 @@ static int wait_state(struct command_context_s *cmd_ctx, char *cmd, enum target_ gettimeofday(&timeout, NULL); timeval_add_time(&timeout, 0, ms * 1000); - target_t *target = get_current_target(cmd_ctx); for (;;) { - if ((retval=target->type->poll(target))!=ERROR_OK) + if ((retval=target_poll(target))!=ERROR_OK) return retval; target_call_timer_callbacks_now(); if (target->state == state) @@ -1569,13 +1753,13 @@ static int wait_state(struct command_context_s *cmd_ctx, char *cmd, enum target_ if (once) { once=0; - command_print(cmd_ctx, "waiting for target %s...", target_state_strings[state]); + LOG_USER("waiting for target %s...", target_state_strings[state]); } gettimeofday(&now, NULL); if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec))) { - ERROR("timed out while waiting for target %s", target_state_strings[state]); + LOG_ERROR("timed out while waiting for target %s", target_state_strings[state]); break; } } @@ -1588,9 +1772,9 @@ 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("-"); + LOG_DEBUG("-"); - if ((retval = target->type->halt(target)) != ERROR_OK) + if ((retval = target_halt(target)) != ERROR_OK) { return retval; } @@ -1598,33 +1782,11 @@ int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **arg return handle_wait_halt_command(cmd_ctx, cmd, args, argc); } -/* what to do on daemon startup */ -int handle_daemon_startup_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) -{ - if (argc == 1) - { - if (strcmp(args[0], "attach") == 0) - { - startup_mode = DAEMON_ATTACH; - return ERROR_OK; - } - else if (strcmp(args[0], "reset") == 0) - { - startup_mode = DAEMON_RESET; - return ERROR_OK; - } - } - - WARNING("invalid daemon_startup configuration directive: %s", args[0]); - return ERROR_OK; - -} - 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); - USER("requesting target halt and executing a soft reset"); + LOG_USER("requesting target halt and executing a soft reset"); target->type->soft_reset_halt(target); @@ -1634,10 +1796,9 @@ 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 = target->reset_mode; - enum target_reset_mode save = target->reset_mode; + enum target_reset_mode reset_mode = RESET_RUN; - DEBUG("-"); + LOG_DEBUG("-"); if (argc >= 1) { @@ -1670,14 +1831,8 @@ int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **ar } } - /* 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; + target_process_reset(cmd_ctx, reset_mode); return ERROR_OK; } @@ -1687,16 +1842,16 @@ int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **a int retval; target_t *target = get_current_target(cmd_ctx); + target_invoke_script(cmd_ctx, target, "pre_resume"); + if (argc == 0) - retval = target->type->resume(target, 1, 0, 1, 0); /* current pc, addr = 0, handle breakpoints, not debugging */ + retval = target_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 */ + retval = target_resume(target, 0, strtoul(args[0], NULL, 0), 1, 0); /* addr = args[0], handle breakpoints, not debugging */ else { return ERROR_COMMAND_SYNTAX_ERROR; } - - target_process_events(cmd_ctx); return retval; } @@ -1705,7 +1860,7 @@ int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **arg { target_t *target = get_current_target(cmd_ctx); - DEBUG("-"); + LOG_DEBUG("-"); if (argc == 0) target->type->step(target, 1, 0, 1); /* current pc, addr = 0, handle breakpoints */ @@ -1787,50 +1942,69 @@ int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, output_len = 0; } } - } else - { - ERROR("Failure examining memory"); } free(buffer); - return ERROR_OK; + return retval; } int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { u32 address = 0; u32 value = 0; - int retval; + int count = 1; + int i; + int wordsize; target_t *target = get_current_target(cmd_ctx); u8 value_buf[4]; - if (argc < 2) - return ERROR_OK; + if ((argc < 2) || (argc > 3)) + return ERROR_COMMAND_SYNTAX_ERROR; address = strtoul(args[0], NULL, 0); value = strtoul(args[1], NULL, 0); - + if (argc == 3) + count = strtoul(args[2], NULL, 0); + switch (cmd[2]) { case 'w': + wordsize = 4; target_buffer_set_u32(target, value_buf, value); - retval = target->type->write_memory(target, address, 4, 1, value_buf); break; case 'h': + wordsize = 2; target_buffer_set_u16(target, value_buf, value); - retval = target->type->write_memory(target, address, 2, 1, value_buf); break; case 'b': + wordsize = 1; value_buf[0] = value; - retval = target->type->write_memory(target, address, 1, 1, value_buf); break; default: - return ERROR_OK; + return ERROR_COMMAND_SYNTAX_ERROR; } - if (retval!=ERROR_OK) + for (i=0; itype->write_memory(target, address + i*wordsize, 4, 1, value_buf); + break; + case 2: + retval = target->type->write_memory(target, address + i*wordsize, 2, 1, value_buf); + break; + case 1: + retval = target->type->write_memory(target, address + i*wordsize, 1, 1, value_buf); + break; + default: + return ERROR_OK; + } + if (retval!=ERROR_OK) + { + return retval; + } } return ERROR_OK; @@ -2006,14 +2180,13 @@ int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, ch if (argc < 1) { - command_print(cmd_ctx, "usage: verify_image [offset] [type]"); - return ERROR_OK; + return ERROR_COMMAND_SYNTAX_ERROR; } if (!target) { - ERROR("no target selected"); - return ERROR_OK; + LOG_ERROR("no target selected"); + return ERROR_FAIL; } duration_start_measure(&duration); @@ -2031,9 +2204,9 @@ int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, ch image.start_address_set = 0; - if (image_open(&image, args[0], (argc == 3) ? args[2] : NULL) != ERROR_OK) + if ((retval=image_open(&image, args[0], (argc == 3) ? args[2] : NULL)) != ERROR_OK) { - return ERROR_OK; + return retval; } image_size = 0x0; @@ -2152,7 +2325,7 @@ int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, if ((retval = breakpoint_add(target, strtoul(args[0], NULL, 0), length, hw)) != ERROR_OK) { - ERROR("Failure setting breakpoints"); + LOG_ERROR("Failure setting breakpoints"); } else { @@ -2188,7 +2361,7 @@ int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, while (watchpoint) { - command_print(cmd_ctx, "address: 0x%8.8x, mask: 0x%8.8x, r/w/a: %i, value: 0x%8.8x, mask: 0x%8.8x", watchpoint->address, watchpoint->length, watchpoint->rw, watchpoint->value, watchpoint->mask); + command_print(cmd_ctx, "address: 0x%8.8x, len: 0x%8.8x, r/w/a: %i, value: 0x%8.8x, mask: 0x%8.8x", watchpoint->address, watchpoint->length, watchpoint->rw, watchpoint->value, watchpoint->mask); watchpoint = watchpoint->next; } } @@ -2228,7 +2401,7 @@ int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, if ((retval = watchpoint_add(target, strtoul(args[0], NULL, 0), strtoul(args[1], NULL, 0), type, data_value, data_mask)) != ERROR_OK) { - ERROR("Failure setting breakpoints"); + LOG_ERROR("Failure setting breakpoints"); } } else @@ -2418,18 +2591,18 @@ int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, char ** for (;;) { - target->type->poll(target); + target_poll(target); if (target->state == TARGET_HALTED) { u32 t=*((u32 *)reg->value); samples[numSamples++]=t; - retval = target->type->resume(target, 1, 0, 0, 0); /* current pc, addr = 0, do not handle breakpoints, not debugging */ - target->type->poll(target); + retval = target_resume(target, 1, 0, 0, 0); /* current pc, addr = 0, do not handle breakpoints, not debugging */ + target_poll(target); usleep(10*1000); // sleep 10ms, i.e. <100 samples/second. } else if (target->state == TARGET_RUNNING) { // We want to quickly sample the PC. - target->type->halt(target); + target_halt(target); } else { command_print(cmd_ctx, "Target not halted or running"); @@ -2445,12 +2618,12 @@ int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, char ** if ((numSamples>=maxSample) || ((now.tv_sec >= timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec))) { command_print(cmd_ctx, "Profiling completed. %d samples.", numSamples); - target->type->poll(target); + target_poll(target); if (target->state == TARGET_HALTED) { - target->type->resume(target, 1, 0, 0, 0); /* current pc, addr = 0, do not handle breakpoints, not debugging */ + target_resume(target, 1, 0, 0, 0); /* current pc, addr = 0, do not handle breakpoints, not debugging */ } - target->type->poll(target); + target_poll(target); writeGmon(samples, numSamples, args[1]); command_print(cmd_ctx, "Wrote %s", args[1]); break; @@ -2461,3 +2634,353 @@ int handle_profile_command(struct command_context_s *cmd_ctx, char *cmd, char ** return ERROR_OK; } +static int new_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 val) +{ + char *namebuf; + Jim_Obj *nameObjPtr, *valObjPtr; + int result; + + namebuf = alloc_printf("%s(%d)", varname, idx); + if (!namebuf) + return JIM_ERR; + + nameObjPtr = Jim_NewStringObj(interp, namebuf, -1); + valObjPtr = Jim_NewIntObj(interp, val); + if (!nameObjPtr || !valObjPtr) + { + free(namebuf); + return JIM_ERR; + } + + Jim_IncrRefCount(nameObjPtr); + Jim_IncrRefCount(valObjPtr); + result = Jim_SetVariable(interp, nameObjPtr, valObjPtr); + Jim_DecrRefCount(interp, nameObjPtr); + Jim_DecrRefCount(interp, valObjPtr); + free(namebuf); + /* printf("%s(%d) <= 0%08x\n", varname, idx, val); */ + return result; +} + +static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + target_t *target; + command_context_t *context; + long l; + u32 width; + u32 len; + u32 addr; + u32 count; + u32 v; + const char *varname; + u8 buffer[4096]; + int i, n, e, retval; + + /* argv[1] = name of array to receive the data + * argv[2] = desired width + * argv[3] = memory address + * argv[4] = count of times to read + */ + if (argc != 5) { + Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems"); + return JIM_ERR; + } + varname = Jim_GetString(argv[1], &len); + /* given "foo" get space for worse case "foo(%d)" .. add 20 */ + + e = Jim_GetLong(interp, argv[2], &l); + width = l; + if (e != JIM_OK) { + return e; + } + + e = Jim_GetLong(interp, argv[3], &l); + addr = l; + if (e != JIM_OK) { + return e; + } + e = Jim_GetLong(interp, argv[4], &l); + len = l; + if (e != JIM_OK) { + return e; + } + switch (width) { + case 8: + width = 1; + break; + case 16: + width = 2; + break; + case 32: + width = 4; + break; + default: + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL ); + return JIM_ERR; + } + if (len == 0) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: zero width read?", NULL); + return JIM_ERR; + } + if ((addr + (len * width)) < addr) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: addr + len - wraps to zero?", NULL); + return JIM_ERR; + } + /* absurd transfer size? */ + if (len > 65536) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: absurd > 64K item request", NULL); + return JIM_ERR; + } + + if ((width == 1) || + ((width == 2) && ((addr & 1) == 0)) || + ((width == 4) && ((addr & 3) == 0))) { + /* all is well */ + } else { + char buf[100]; + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + sprintf(buf, "mem2array address: 0x%08x is not aligned for %d byte reads", addr, width); + Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL); + return JIM_ERR; + } + + context = Jim_GetAssocData(interp, "context"); + if (context == NULL) + { + LOG_ERROR("mem2array: no command context"); + return JIM_ERR; + } + target = get_current_target(context); + if (target == NULL) + { + LOG_ERROR("mem2array: no current target"); + return JIM_ERR; + } + + /* Transfer loop */ + + /* index counter */ + n = 0; + /* assume ok */ + e = JIM_OK; + while (len) { + /* Slurp... in buffer size chunks */ + + count = len; /* in objects.. */ + if (count > (sizeof(buffer)/width)) { + count = (sizeof(buffer)/width); + } + + retval = target->type->read_memory( target, addr, width, count, buffer ); + if (retval != ERROR_OK) { + /* BOO !*/ + LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count); + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL); + e = JIM_ERR; + len = 0; + } else { + v = 0; /* shut up gcc */ + for (i = 0 ;i < count ;i++, n++) { + switch (width) { + case 4: + v = target_buffer_get_u32(target, &buffer[i*width]); + break; + case 2: + v = target_buffer_get_u16(target, &buffer[i*width]); + break; + case 1: + v = buffer[i] & 0x0ff; + break; + } + new_int_array_element(interp, varname, n, v); + } + len -= count; + } + } + + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + + return JIM_OK; +} + +static int get_int_array_element(Jim_Interp * interp, const char *varname, int idx, u32 *val) +{ + char *namebuf; + Jim_Obj *nameObjPtr, *valObjPtr; + int result; + long l; + + namebuf = alloc_printf("%s(%d)", varname, idx); + if (!namebuf) + return JIM_ERR; + + nameObjPtr = Jim_NewStringObj(interp, namebuf, -1); + if (!nameObjPtr) + { + free(namebuf); + return JIM_ERR; + } + + Jim_IncrRefCount(nameObjPtr); + valObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_ERRMSG); + Jim_DecrRefCount(interp, nameObjPtr); + free(namebuf); + if (valObjPtr == NULL) + return JIM_ERR; + + result = Jim_GetLong(interp, valObjPtr, &l); + /* printf("%s(%d) => 0%08x\n", varname, idx, val); */ + *val = l; + return result; +} + +static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + target_t *target; + command_context_t *context; + long l; + u32 width; + u32 len; + u32 addr; + u32 count; + u32 v; + const char *varname; + u8 buffer[4096]; + int i, n, e, retval; + + /* argv[1] = name of array to get the data + * argv[2] = desired width + * argv[3] = memory address + * argv[4] = count to write + */ + if (argc != 5) { + Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems"); + return JIM_ERR; + } + varname = Jim_GetString(argv[1], &len); + /* given "foo" get space for worse case "foo(%d)" .. add 20 */ + + e = Jim_GetLong(interp, argv[2], &l); + width = l; + if (e != JIM_OK) { + return e; + } + + e = Jim_GetLong(interp, argv[3], &l); + addr = l; + if (e != JIM_OK) { + return e; + } + e = Jim_GetLong(interp, argv[4], &l); + len = l; + if (e != JIM_OK) { + return e; + } + switch (width) { + case 8: + width = 1; + break; + case 16: + width = 2; + break; + case 32: + width = 4; + break; + default: + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings( interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL ); + return JIM_ERR; + } + if (len == 0) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: zero width read?", NULL); + return JIM_ERR; + } + if ((addr + (len * width)) < addr) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: addr + len - wraps to zero?", NULL); + return JIM_ERR; + } + /* absurd transfer size? */ + if (len > 65536) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: absurd > 64K item request", NULL); + return JIM_ERR; + } + + if ((width == 1) || + ((width == 2) && ((addr & 1) == 0)) || + ((width == 4) && ((addr & 3) == 0))) { + /* all is well */ + } else { + char buf[100]; + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + sprintf(buf, "array2mem address: 0x%08x is not aligned for %d byte reads", addr, width); + Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL); + return JIM_ERR; + } + + context = Jim_GetAssocData(interp, "context"); + if (context == NULL) + { + LOG_ERROR("array2mem: no command context"); + return JIM_ERR; + } + target = get_current_target(context); + if (target == NULL) + { + LOG_ERROR("array2mem: no current target"); + return JIM_ERR; + } + + /* Transfer loop */ + + /* index counter */ + n = 0; + /* assume ok */ + e = JIM_OK; + while (len) { + /* Slurp... in buffer size chunks */ + + count = len; /* in objects.. */ + if (count > (sizeof(buffer)/width)) { + count = (sizeof(buffer)/width); + } + + v = 0; /* shut up gcc */ + for (i = 0 ;i < count ;i++, n++) { + get_int_array_element(interp, varname, n, &v); + switch (width) { + case 4: + target_buffer_set_u32(target, &buffer[i*width], v); + break; + case 2: + target_buffer_set_u16(target, &buffer[i*width], v); + break; + case 1: + buffer[i] = v & 0x0ff; + break; + } + } + len -= count; + + retval = target->type->write_memory(target, addr, width, count, buffer); + if (retval != ERROR_OK) { + /* BOO !*/ + LOG_ERROR("array2mem: Write @ 0x%08x, w=%d, cnt=%d, failed", addr, width, count); + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL); + e = JIM_ERR; + len = 0; + } + } + + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + + return JIM_OK; +}