X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Ftarget.c;h=bd9d56b04673395718209eb8a463be98b05b556c;hp=d71828c0fc7aeccb59cac2b4d02da015a983277e;hb=7ad11de2fa37b504fc84f608ee355cf02221429a;hpb=f906c65fed5f3f2df54c6aaf2ea28d9742d44db4 diff --git a/src/target/target.c b/src/target/target.c index d71828c0fc..bd9d56b046 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -58,9 +58,9 @@ /* default halt wait timeout (ms) */ #define DEFAULT_HALT_TIMEOUT 5000 -static int target_read_buffer_default(struct target *target, uint32_t address, +static int target_read_buffer_default(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer); -static int target_write_buffer_default(struct target *target, uint32_t address, +static int target_write_buffer_default(struct target *target, target_addr_t address, uint32_t count, const uint8_t *buffer); static int target_array2mem(Jim_Interp *interp, struct target *target, int argc, Jim_Obj * const *argv); @@ -88,6 +88,7 @@ extern struct target_type dragonite_target; extern struct target_type xscale_target; extern struct target_type cortexm_target; extern struct target_type cortexa_target; +extern struct target_type aarch64_target; extern struct target_type cortexr4_target; extern struct target_type arm11_target; extern struct target_type ls1_sap_target; @@ -104,6 +105,7 @@ extern struct target_type nds32_v3m_target; extern struct target_type or1k_target; extern struct target_type quark_x10xx_target; extern struct target_type quark_d20xx_target; +extern struct target_type stm8_target; static struct target_type *target_types[] = { &arm7tdmi_target, @@ -135,6 +137,10 @@ static struct target_type *target_types[] = { &or1k_target, &quark_x10xx_target, &quark_d20xx_target, + &stm8_target, +#if BUILD_TARGET64 + &aarch64_target, +#endif NULL, }; @@ -198,10 +204,6 @@ static const Jim_Nvp nvp_target_event[] = { { .value = TARGET_EVENT_RESET_ASSERT_POST, .name = "reset-assert-post" }, { .value = TARGET_EVENT_RESET_DEASSERT_PRE, .name = "reset-deassert-pre" }, { .value = TARGET_EVENT_RESET_DEASSERT_POST, .name = "reset-deassert-post" }, - { .value = TARGET_EVENT_RESET_HALT_PRE, .name = "reset-halt-pre" }, - { .value = TARGET_EVENT_RESET_HALT_POST, .name = "reset-halt-post" }, - { .value = TARGET_EVENT_RESET_WAIT_PRE, .name = "reset-wait-pre" }, - { .value = TARGET_EVENT_RESET_WAIT_POST, .name = "reset-wait-post" }, { .value = TARGET_EVENT_RESET_INIT, .name = "reset-init" }, { .value = TARGET_EVENT_RESET_END, .name = "reset-end" }, @@ -283,6 +285,10 @@ const char *target_state_name(struct target *t) LOG_ERROR("Invalid target state: %d", (int)(t->state)); cp = "(*BUG*unknown*BUG*)"; } + + if (!target_was_examined(t) && t->defer_examine) + cp = "examine deferred"; + return cp; } @@ -504,7 +510,9 @@ struct target *get_target_by_num(int num) struct target *get_current_target(struct command_context *cmd_ctx) { - struct target *target = get_target_by_num(cmd_ctx->current_target); + struct target *target = cmd_ctx->current_target_override + ? cmd_ctx->current_target_override + : cmd_ctx->current_target; if (target == NULL) { LOG_ERROR("BUG: current_target out of bounds"); @@ -532,7 +540,7 @@ int target_poll(struct target *target) if (target->state == TARGET_HALTED) target->halt_issued = false; else { - long long t = timeval_ms() - target->halt_issued_time; + int64_t t = timeval_ms() - target->halt_issued_time; if (t > DEFAULT_HALT_TIMEOUT) { target->halt_issued = false; LOG_INFO("Halt timed out, wake up GDB."); @@ -593,7 +601,8 @@ int target_halt(struct target *target) * hand the infrastructure for running such helpers might use this * procedure but rely on hardware breakpoint to detect termination.) */ -int target_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) +int target_resume(struct target *target, int current, target_addr_t address, + int handle_breakpoints, int debug_execution) { int retval; @@ -664,7 +673,7 @@ static int target_process_reset(struct command_context *cmd_ctx, enum target_res } static int identity_virt2phys(struct target *target, - uint32_t virtual, uint32_t *physical) + target_addr_t virtual, target_addr_t *physical) { *physical = virtual; return ERROR_OK; @@ -731,6 +740,9 @@ int target_examine(void) continue; } + if (target->defer_examine) + continue; + retval = target_examine_one(target); if (retval != ERROR_OK) return retval; @@ -798,8 +810,7 @@ done: } /** - * Downloads a target-specific native code algorithm to the target, - * executes and leaves it running. + * Executes a target-specific native code algorithm and leaves it running. * * @param target used to run the algorithm * @param arch_info target-specific description of the algorithm. @@ -872,12 +883,45 @@ done: } /** - * Executes a target-specific native code algorithm in the target. - * It differs from target_run_algorithm in that the algorithm is asynchronous. - * Because of this it requires an compliant algorithm: - * see contrib/loaders/flash/stm32f1x.S for example. + * Streams data to a circular buffer on target intended for consumption by code + * running asynchronously on target. + * + * This is intended for applications where target-specific native code runs + * on the target, receives data from the circular buffer, does something with + * it (most likely writing it to a flash memory), and advances the circular + * buffer pointer. + * + * This assumes that the helper algorithm has already been loaded to the target, + * but has not been started yet. Given memory and register parameters are passed + * to the algorithm. + * + * The buffer is defined by (buffer_start, buffer_size) arguments and has the + * following format: + * + * [buffer_start + 0, buffer_start + 4): + * Write Pointer address (aka head). Written and updated by this + * routine when new data is written to the circular buffer. + * [buffer_start + 4, buffer_start + 8): + * Read Pointer address (aka tail). Updated by code running on the + * target after it consumes data. + * [buffer_start + 8, buffer_start + buffer_size): + * Circular buffer contents. + * + * See contrib/loaders/flash/stm32f1x.S for an example. * * @param target used to run the algorithm + * @param buffer address on the host where data to be sent is located + * @param count number of blocks to send + * @param block_size size in bytes of each block + * @param num_mem_params count of memory-based params to pass to algorithm + * @param mem_params memory-based params to pass to algorithm + * @param num_reg_params count of register-based params to pass to algorithm + * @param reg_params memory-based params to pass to algorithm + * @param buffer_start address on the target of the circular buffer structure + * @param buffer_size size of the circular buffer structure + * @param entry_point address on the target to execute to start the algorithm + * @param exit_point address at which to set a breakpoint to catch the + * end of the algorithm; can be 0 if target triggers a breakpoint itself */ int target_run_flash_async_algorithm(struct target *target, @@ -1014,11 +1058,20 @@ int target_run_flash_async_algorithm(struct target *target, retval = retval2; } + if (retval == ERROR_OK) { + /* check if algorithm set rp = 0 after fifo writer loop finished */ + retval = target_read_u32(target, rp_addr, &rp); + if (retval == ERROR_OK && rp == 0) { + LOG_ERROR("flash write algorithm aborted by target"); + retval = ERROR_FLASH_OPERATION_FAILED; + } + } + return retval; } int target_read_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); @@ -1032,7 +1085,7 @@ int target_read_memory(struct target *target, } int target_read_phys_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); @@ -1046,7 +1099,7 @@ int target_read_phys_memory(struct target *target, } int target_write_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); @@ -1060,7 +1113,7 @@ int target_write_memory(struct target *target, } int target_write_phys_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); @@ -1077,7 +1130,7 @@ int target_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { if ((target->state != TARGET_HALTED) && (breakpoint->type != BKPT_HARD)) { - LOG_WARNING("target %s is not halted", target_name(target)); + LOG_WARNING("target %s is not halted (add breakpoint)", target_name(target)); return ERROR_TARGET_NOT_HALTED; } return target->type->add_breakpoint(target, breakpoint); @@ -1087,7 +1140,7 @@ int target_add_context_breakpoint(struct target *target, struct breakpoint *breakpoint) { if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted", target_name(target)); + LOG_WARNING("target %s is not halted (add context breakpoint)", target_name(target)); return ERROR_TARGET_NOT_HALTED; } return target->type->add_context_breakpoint(target, breakpoint); @@ -1097,7 +1150,7 @@ int target_add_hybrid_breakpoint(struct target *target, struct breakpoint *breakpoint) { if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted", target_name(target)); + LOG_WARNING("target %s is not halted (add hybrid breakpoint)", target_name(target)); return ERROR_TARGET_NOT_HALTED; } return target->type->add_hybrid_breakpoint(target, breakpoint); @@ -1113,7 +1166,7 @@ int target_add_watchpoint(struct target *target, struct watchpoint *watchpoint) { if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted", target_name(target)); + LOG_WARNING("target %s is not halted (add watchpoint)", target_name(target)); return ERROR_TARGET_NOT_HALTED; } return target->type->add_watchpoint(target, watchpoint); @@ -1127,7 +1180,7 @@ int target_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoint) { if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted", target->cmd_name); + LOG_WARNING("target %s is not halted (hit watchpoint)", target->cmd_name); return ERROR_TARGET_NOT_HALTED; } @@ -1148,7 +1201,7 @@ int target_get_gdb_reg_list(struct target *target, return target->type->get_gdb_reg_list(target, reg_list, reg_list_size, reg_class); } int target_step(struct target *target, - int current, uint32_t address, int handle_breakpoints) + int current, target_addr_t address, int handle_breakpoints) { return target->type->step(target, current, address, handle_breakpoints); } @@ -1156,7 +1209,7 @@ int target_step(struct target *target, int target_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info) { if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted", target->cmd_name); + LOG_WARNING("target %s is not halted (gdb fileio)", target->cmd_name); return ERROR_TARGET_NOT_HALTED; } return target->type->get_gdb_fileio_info(target, fileio_info); @@ -1165,7 +1218,7 @@ int target_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fi int target_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c) { if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted", target->cmd_name); + LOG_WARNING("target %s is not halted (gdb fileio end)", target->cmd_name); return ERROR_TARGET_NOT_HALTED; } return target->type->gdb_fileio_end(target, retcode, fileio_errno, ctrl_c); @@ -1175,7 +1228,7 @@ int target_profiling(struct target *target, uint32_t *samples, uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds) { if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted", target->cmd_name); + LOG_WARNING("target %s is not halted (profiling)", target->cmd_name); return ERROR_TARGET_NOT_HALTED; } return target->type->profiling(target, samples, max_num_samples, @@ -1378,7 +1431,6 @@ int target_register_trace_callback(int (*callback)(struct target *target, int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int periodic, void *priv) { struct target_timer_callback **callbacks_p = &target_timer_callbacks; - struct timeval now; if (callback == NULL) return ERROR_COMMAND_SYNTAX_ERROR; @@ -1395,14 +1447,8 @@ int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int (*callbacks_p)->time_ms = time_ms; (*callbacks_p)->removed = false; - gettimeofday(&now, NULL); - (*callbacks_p)->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000; - time_ms -= (time_ms % 1000); - (*callbacks_p)->when.tv_sec = now.tv_sec + (time_ms / 1000); - if ((*callbacks_p)->when.tv_usec > 1000000) { - (*callbacks_p)->when.tv_usec = (*callbacks_p)->when.tv_usec - 1000000; - (*callbacks_p)->when.tv_sec += 1; - } + gettimeofday(&(*callbacks_p)->when, NULL); + timeval_add_time(&(*callbacks_p)->when, 0, time_ms * 1000); (*callbacks_p)->priv = priv; (*callbacks_p)->next = NULL; @@ -1537,14 +1583,8 @@ int target_call_trace_callbacks(struct target *target, size_t len, uint8_t *data static int target_timer_callback_periodic_restart( struct target_timer_callback *cb, struct timeval *now) { - int time_ms = cb->time_ms; - cb->when.tv_usec = now->tv_usec + (time_ms % 1000) * 1000; - time_ms -= (time_ms % 1000); - cb->when.tv_sec = now->tv_sec + time_ms / 1000; - if (cb->when.tv_usec > 1000000) { - cb->when.tv_usec = cb->when.tv_usec - 1000000; - cb->when.tv_sec += 1; - } + cb->when = *now; + timeval_add_time(&cb->when, 0, cb->time_ms * 1000L); return ERROR_OK; } @@ -1588,9 +1628,7 @@ static int target_call_timer_callbacks_check_time(int checktime) bool call_it = (*callback)->callback && ((!checktime && (*callback)->periodic) || - now.tv_sec > (*callback)->when.tv_sec || - (now.tv_sec == (*callback)->when.tv_sec && - now.tv_usec >= (*callback)->when.tv_usec)); + timeval_compare(&now, &(*callback)->when) >= 0); if (call_it) target_call_timer_callback(*callback, &now); @@ -1619,7 +1657,7 @@ static void print_wa_layout(struct target *target) struct working_area *c = target->working_areas; while (c) { - LOG_DEBUG("%c%c 0x%08"PRIx32"-0x%08"PRIx32" (%"PRIu32" bytes)", + LOG_DEBUG("%c%c " TARGET_ADDR_FMT "-" TARGET_ADDR_FMT " (%" PRIu32 " bytes)", c->backup ? 'b' : ' ', c->free ? ' ' : '*', c->address, c->address + c->size - 1, c->size); c = c->next; @@ -1704,7 +1742,7 @@ int target_alloc_working_area_try(struct target *target, uint32_t size, struct w if (!enabled) { if (target->working_area_phys_spec) { LOG_DEBUG("MMU disabled, using physical " - "address for working memory 0x%08"PRIx32, + "address for working memory " TARGET_ADDR_FMT, target->working_area_phys); target->working_area = target->working_area_phys; } else { @@ -1715,7 +1753,7 @@ int target_alloc_working_area_try(struct target *target, uint32_t size, struct w } else { if (target->working_area_virt_spec) { LOG_DEBUG("MMU enabled, using virtual " - "address for working memory 0x%08"PRIx32, + "address for working memory " TARGET_ADDR_FMT, target->working_area_virt); target->working_area = target->working_area_virt; } else { @@ -1758,7 +1796,8 @@ int target_alloc_working_area_try(struct target *target, uint32_t size, struct w /* Split the working area into the requested size */ target_split_working_area(c, size); - LOG_DEBUG("allocated new working area of %"PRIu32" bytes at address 0x%08"PRIx32, size, c->address); + LOG_DEBUG("allocated new working area of %" PRIu32 " bytes at address " TARGET_ADDR_FMT, + size, c->address); if (target->backup_working_area) { if (c->backup == NULL) { @@ -1802,7 +1841,7 @@ static int target_restore_working_area(struct target *target, struct working_are if (target->backup_working_area && area->backup != NULL) { retval = target_write_memory(target, area->address, 4, area->size / 4, area->backup); if (retval != ERROR_OK) - LOG_ERROR("failed to restore %"PRIu32" bytes of working area at address 0x%08"PRIx32, + LOG_ERROR("failed to restore %" PRIu32 " bytes of working area at address " TARGET_ADDR_FMT, area->size, area->address); } @@ -1826,7 +1865,7 @@ static int target_free_working_area_restore(struct target *target, struct workin area->free = true; - LOG_DEBUG("freed %"PRIu32" bytes of working area at address 0x%08"PRIx32, + LOG_DEBUG("freed %" PRIu32 " bytes of working area at address " TARGET_ADDR_FMT, area->size, area->address); /* mark user pointer invalid */ @@ -1848,6 +1887,33 @@ int target_free_working_area(struct target *target, struct working_area *area) return target_free_working_area_restore(target, area, 1); } +static void target_destroy(struct target *target) +{ + if (target->type->deinit_target) + target->type->deinit_target(target); + + struct target_event_action *teap = target->event_action; + while (teap) { + struct target_event_action *next = teap->next; + Jim_DecrRefCount(teap->interp, teap->body); + free(teap); + teap = next; + } + + target_free_all_working_areas(target); + /* Now we have none or only one working area marked as free */ + if (target->working_areas) { + free(target->working_areas->backup); + free(target->working_areas); + } + + free(target->type); + free(target->trace_info); + free(target->fileio_info); + free(target->cmd_name); + free(target); +} + void target_quit(void) { struct target_event_callback *pe = target_event_callbacks; @@ -1866,11 +1932,15 @@ void target_quit(void) } target_timer_callbacks = NULL; - for (struct target *target = all_targets; - target; target = target->next) { - if (target->type->deinit_target) - target->type->deinit_target(target); + for (struct target *target = all_targets; target;) { + struct target *tmp; + + tmp = target->next; + target_destroy(target); + target = tmp; } + + all_targets = NULL; } /* free resources and restore memory, if restoring memory fails, @@ -1928,13 +1998,10 @@ int target_arch_state(struct target *target) { int retval; if (target == NULL) { - LOG_USER("No target has been configured"); + LOG_WARNING("No target has been configured"); return ERROR_OK; } - LOG_USER("%s: target state: %s", target_name(target), - target_state_name(target)); - if (target->state != TARGET_HALTED) return ERROR_OK; @@ -1996,8 +2063,7 @@ static int target_profiling_default(struct target *target, uint32_t *samples, break; gettimeofday(&now, NULL); - if ((sample_count >= max_num_samples) || - ((now.tv_sec >= timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec))) { + if ((sample_count >= max_num_samples) || timeval_compare(&now, &timeout) >= 0) { LOG_INFO("Profiling completed. %" PRIu32 " samples.", sample_count); break; } @@ -2011,10 +2077,10 @@ static int target_profiling_default(struct target *target, uint32_t *samples, * mode respectively, otherwise data is handled as quickly as * possible */ -int target_write_buffer(struct target *target, uint32_t address, uint32_t size, const uint8_t *buffer) +int target_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer) { - LOG_DEBUG("writing buffer of %i byte at 0x%8.8x", - (int)size, (unsigned)address); + LOG_DEBUG("writing buffer of %" PRIi32 " byte at " TARGET_ADDR_FMT, + size, address); if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); @@ -2025,17 +2091,18 @@ int target_write_buffer(struct target *target, uint32_t address, uint32_t size, return ERROR_OK; if ((address + size - 1) < address) { - /* GDB can request this when e.g. PC is 0xfffffffc*/ - LOG_ERROR("address + size wrapped(0x%08x, 0x%08x)", - (unsigned)address, - (unsigned)size); + /* GDB can request this when e.g. PC is 0xfffffffc */ + LOG_ERROR("address + size wrapped (" TARGET_ADDR_FMT ", 0x%08" PRIx32 ")", + address, + size); return ERROR_FAIL; } return target->type->write_buffer(target, address, size, buffer); } -static int target_write_buffer_default(struct target *target, uint32_t address, uint32_t count, const uint8_t *buffer) +static int target_write_buffer_default(struct target *target, + target_addr_t address, uint32_t count, const uint8_t *buffer) { uint32_t size; @@ -2072,10 +2139,10 @@ static int target_write_buffer_default(struct target *target, uint32_t address, * mode respectively, otherwise data is handled as quickly as * possible */ -int target_read_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer) +int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer) { - LOG_DEBUG("reading buffer of %i byte at 0x%8.8x", - (int)size, (unsigned)address); + LOG_DEBUG("reading buffer of %" PRIi32 " byte at " TARGET_ADDR_FMT, + size, address); if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); @@ -2086,8 +2153,8 @@ int target_read_buffer(struct target *target, uint32_t address, uint32_t size, u return ERROR_OK; if ((address + size - 1) < address) { - /* GDB can request this when e.g. PC is 0xfffffffc*/ - LOG_ERROR("address + size wrapped(0x%08" PRIx32 ", 0x%08" PRIx32 ")", + /* GDB can request this when e.g. PC is 0xfffffffc */ + LOG_ERROR("address + size wrapped (" TARGET_ADDR_FMT ", 0x%08" PRIx32 ")", address, size); return ERROR_FAIL; @@ -2096,7 +2163,7 @@ int target_read_buffer(struct target *target, uint32_t address, uint32_t size, u return target->type->read_buffer(target, address, size, buffer); } -static int target_read_buffer_default(struct target *target, uint32_t address, uint32_t count, uint8_t *buffer) +static int target_read_buffer_default(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer) { uint32_t size; @@ -2129,7 +2196,7 @@ static int target_read_buffer_default(struct target *target, uint32_t address, u return ERROR_OK; } -int target_checksum_memory(struct target *target, uint32_t address, uint32_t size, uint32_t* crc) +int target_checksum_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t* crc) { uint8_t *buffer; int retval; @@ -2144,7 +2211,7 @@ int target_checksum_memory(struct target *target, uint32_t address, uint32_t siz if (retval != ERROR_OK) { buffer = malloc(size); if (buffer == NULL) { - LOG_ERROR("error allocating buffer for section (%d bytes)", (int)size); + LOG_ERROR("error allocating buffer for section (%" PRId32 " bytes)", size); return ERROR_COMMAND_SYNTAX_ERROR; } retval = target_read_buffer(target, address, size, buffer); @@ -2169,7 +2236,8 @@ int target_checksum_memory(struct target *target, uint32_t address, uint32_t siz return retval; } -int target_blank_check_memory(struct target *target, uint32_t address, uint32_t size, uint32_t* blank) +int target_blank_check_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t* blank, + uint8_t erased_value) { int retval; if (!target_was_examined(target)) { @@ -2180,12 +2248,12 @@ int target_blank_check_memory(struct target *target, uint32_t address, uint32_t if (target->type->blank_check_memory == 0) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - retval = target->type->blank_check_memory(target, address, size, blank); + retval = target->type->blank_check_memory(target, address, size, blank, erased_value); return retval; } -int target_read_u64(struct target *target, uint64_t address, uint64_t *value) +int target_read_u64(struct target *target, target_addr_t address, uint64_t *value) { uint8_t value_buf[8]; if (!target_was_examined(target)) { @@ -2197,19 +2265,19 @@ int target_read_u64(struct target *target, uint64_t address, uint64_t *value) if (retval == ERROR_OK) { *value = target_buffer_get_u64(target, value_buf); - LOG_DEBUG("address: 0x%" PRIx64 ", value: 0x%16.16" PRIx64 "", + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%16.16" PRIx64 "", address, *value); } else { *value = 0x0; - LOG_DEBUG("address: 0x%" PRIx64 " failed", + LOG_DEBUG("address: " TARGET_ADDR_FMT " failed", address); } return retval; } -int target_read_u32(struct target *target, uint32_t address, uint32_t *value) +int target_read_u32(struct target *target, target_addr_t address, uint32_t *value) { uint8_t value_buf[4]; if (!target_was_examined(target)) { @@ -2221,19 +2289,19 @@ int target_read_u32(struct target *target, uint32_t address, uint32_t *value) if (retval == ERROR_OK) { *value = target_buffer_get_u32(target, value_buf); - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8" PRIx32 "", + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx32 "", address, *value); } else { *value = 0x0; - LOG_DEBUG("address: 0x%8.8" PRIx32 " failed", + LOG_DEBUG("address: " TARGET_ADDR_FMT " failed", address); } return retval; } -int target_read_u16(struct target *target, uint32_t address, uint16_t *value) +int target_read_u16(struct target *target, target_addr_t address, uint16_t *value) { uint8_t value_buf[2]; if (!target_was_examined(target)) { @@ -2245,19 +2313,19 @@ int target_read_u16(struct target *target, uint32_t address, uint16_t *value) if (retval == ERROR_OK) { *value = target_buffer_get_u16(target, value_buf); - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%4.4x", + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%4.4" PRIx16, address, *value); } else { *value = 0x0; - LOG_DEBUG("address: 0x%8.8" PRIx32 " failed", + LOG_DEBUG("address: " TARGET_ADDR_FMT " failed", address); } return retval; } -int target_read_u8(struct target *target, uint32_t address, uint8_t *value) +int target_read_u8(struct target *target, target_addr_t address, uint8_t *value) { if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); @@ -2267,19 +2335,19 @@ int target_read_u8(struct target *target, uint32_t address, uint8_t *value) int retval = target_read_memory(target, address, 1, 1, value); if (retval == ERROR_OK) { - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%2.2x", + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%2.2" PRIx8, address, *value); } else { *value = 0x0; - LOG_DEBUG("address: 0x%8.8" PRIx32 " failed", + LOG_DEBUG("address: " TARGET_ADDR_FMT " failed", address); } return retval; } -int target_write_u64(struct target *target, uint64_t address, uint64_t value) +int target_write_u64(struct target *target, target_addr_t address, uint64_t value) { int retval; uint8_t value_buf[8]; @@ -2288,7 +2356,7 @@ int target_write_u64(struct target *target, uint64_t address, uint64_t value) return ERROR_FAIL; } - LOG_DEBUG("address: 0x%" PRIx64 ", value: 0x%16.16" PRIx64 "", + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%16.16" PRIx64 "", address, value); @@ -2300,7 +2368,7 @@ int target_write_u64(struct target *target, uint64_t address, uint64_t value) return retval; } -int target_write_u32(struct target *target, uint32_t address, uint32_t value) +int target_write_u32(struct target *target, target_addr_t address, uint32_t value) { int retval; uint8_t value_buf[4]; @@ -2309,7 +2377,7 @@ int target_write_u32(struct target *target, uint32_t address, uint32_t value) return ERROR_FAIL; } - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8" PRIx32 "", + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx32 "", address, value); @@ -2321,7 +2389,7 @@ int target_write_u32(struct target *target, uint32_t address, uint32_t value) return retval; } -int target_write_u16(struct target *target, uint32_t address, uint16_t value) +int target_write_u16(struct target *target, target_addr_t address, uint16_t value) { int retval; uint8_t value_buf[2]; @@ -2330,7 +2398,7 @@ int target_write_u16(struct target *target, uint32_t address, uint16_t value) return ERROR_FAIL; } - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8x", + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx16, address, value); @@ -2342,7 +2410,7 @@ int target_write_u16(struct target *target, uint32_t address, uint16_t value) return retval; } -int target_write_u8(struct target *target, uint32_t address, uint8_t value) +int target_write_u8(struct target *target, target_addr_t address, uint8_t value) { int retval; if (!target_was_examined(target)) { @@ -2350,7 +2418,7 @@ int target_write_u8(struct target *target, uint32_t address, uint8_t value) return ERROR_FAIL; } - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%2.2x", + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%2.2" PRIx8, address, value); retval = target_write_memory(target, address, 1, 1, &value); @@ -2360,6 +2428,87 @@ int target_write_u8(struct target *target, uint32_t address, uint8_t value) return retval; } +int target_write_phys_u64(struct target *target, target_addr_t address, uint64_t value) +{ + int retval; + uint8_t value_buf[8]; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%16.16" PRIx64 "", + address, + value); + + target_buffer_set_u64(target, value_buf, value); + retval = target_write_phys_memory(target, address, 8, 1, value_buf); + if (retval != ERROR_OK) + LOG_DEBUG("failed: %i", retval); + + return retval; +} + +int target_write_phys_u32(struct target *target, target_addr_t address, uint32_t value) +{ + int retval; + uint8_t value_buf[4]; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx32 "", + address, + value); + + target_buffer_set_u32(target, value_buf, value); + retval = target_write_phys_memory(target, address, 4, 1, value_buf); + if (retval != ERROR_OK) + LOG_DEBUG("failed: %i", retval); + + return retval; +} + +int target_write_phys_u16(struct target *target, target_addr_t address, uint16_t value) +{ + int retval; + uint8_t value_buf[2]; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx16, + address, + value); + + target_buffer_set_u16(target, value_buf, value); + retval = target_write_phys_memory(target, address, 2, 1, value_buf); + if (retval != ERROR_OK) + LOG_DEBUG("failed: %i", retval); + + return retval; +} + +int target_write_phys_u8(struct target *target, target_addr_t address, uint8_t value) +{ + int retval; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%2.2" PRIx8, + address, value); + + retval = target_write_phys_memory(target, address, 1, 1, &value); + if (retval != ERROR_OK) + LOG_DEBUG("failed: %i", retval); + + return retval; +} + static int find_target(struct command_context *cmd_ctx, const char *name) { struct target *target = get_target(name); @@ -2374,7 +2523,10 @@ static int find_target(struct command_context *cmd_ctx, const char *name) return ERROR_FAIL; } - cmd_ctx->current_target = target->target_number; + cmd_ctx->current_target = target; + if (cmd_ctx->current_target_override) + cmd_ctx->current_target_override = target; + return ERROR_OK; } @@ -2402,7 +2554,7 @@ COMMAND_HANDLER(handle_targets_command) else state = "tap-disabled"; - if (CMD_CTX->current_target == target->target_number) + if (CMD_CTX->current_target == target) marker = '*'; /* keep columns lined up to match the headers above */ @@ -2446,9 +2598,9 @@ static int sense_handler(void) if (powerRestored) runPowerRestore = 1; - long long current = timeval_ms(); - static long long lastPower; - int waitMore = lastPower + 2000 > current; + int64_t current = timeval_ms(); + static int64_t lastPower; + bool waitMore = lastPower + 2000 > current; if (powerDropout && !waitMore) { runPowerDropout = 1; lastPower = current; @@ -2461,7 +2613,7 @@ static int sense_handler(void) int srstDeasserted; srstDeasserted = prevSrstAsserted && !srstAsserted; - static long long lastSrst; + static int64_t lastSrst; waitMore = lastSrst + 2000 > current; if (srstDeasserted && !waitMore) { runSrstDeasserted = 1; @@ -2771,8 +2923,8 @@ COMMAND_HANDLER(handle_wait_halt_command) int target_wait_state(struct target *target, enum target_state state, int ms) { int retval; - long long then = 0, cur; - int once = 1; + int64_t then = 0, cur; + bool once = true; for (;;) { retval = target_poll(target); @@ -2782,7 +2934,7 @@ int target_wait_state(struct target *target, enum target_state state, int ms) break; cur = timeval_ms(); if (once) { - once = 0; + once = false; then = timeval_ms(); LOG_DEBUG("waiting for target %s...", Jim_Nvp_value2name_simple(nvp_target_state, state)->name); @@ -2863,9 +3015,9 @@ COMMAND_HANDLER(handle_resume_command) /* with no CMD_ARGV, resume from current pc, addr = 0, * with one arguments, addr = CMD_ARGV[0], * handle breakpoints, not debugging */ - uint32_t addr = 0; + target_addr_t addr = 0; if (CMD_ARGC == 1) { - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); current = 0; } @@ -2882,10 +3034,10 @@ COMMAND_HANDLER(handle_step_command) /* with no CMD_ARGV, step from current pc, addr = 0, * with one argument addr = CMD_ARGV[0], * handle breakpoints, debugging */ - uint32_t addr = 0; + target_addr_t addr = 0; int current_pc = 1; if (CMD_ARGC == 1) { - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); current_pc = 0; } @@ -2895,7 +3047,7 @@ COMMAND_HANDLER(handle_step_command) } static void handle_md_output(struct command_context *cmd_ctx, - struct target *target, uint32_t address, unsigned size, + struct target *target, target_addr_t address, unsigned size, unsigned count, const uint8_t *buffer) { const unsigned line_bytecnt = 32; @@ -2906,14 +3058,17 @@ static void handle_md_output(struct command_context *cmd_ctx, const char *value_fmt; switch (size) { + case 8: + value_fmt = "%16.16"PRIx64" "; + break; case 4: - value_fmt = "%8.8x "; + value_fmt = "%8.8"PRIx64" "; break; case 2: - value_fmt = "%4.4x "; + value_fmt = "%4.4"PRIx64" "; break; case 1: - value_fmt = "%2.2x "; + value_fmt = "%2.2"PRIx64" "; break; default: /* "can't happen", caller checked */ @@ -2925,13 +3080,16 @@ static void handle_md_output(struct command_context *cmd_ctx, if (i % line_modulo == 0) { output_len += snprintf(output + output_len, sizeof(output) - output_len, - "0x%8.8x: ", - (unsigned)(address + (i*size))); + TARGET_ADDR_FMT ": ", + (address + (i * size))); } - uint32_t value = 0; + uint64_t value = 0; const uint8_t *value_ptr = buffer + i * size; switch (size) { + case 8: + value = target_buffer_get_u64(target, value_ptr); + break; case 4: value = target_buffer_get_u32(target, value_ptr); break; @@ -2959,6 +3117,9 @@ COMMAND_HANDLER(handle_md_command) unsigned size = 0; switch (CMD_NAME[2]) { + case 'd': + size = 8; + break; case 'w': size = 4; break; @@ -2974,7 +3135,7 @@ COMMAND_HANDLER(handle_md_command) bool physical = strcmp(CMD_ARGV[0], "phys") == 0; int (*fn)(struct target *target, - uint32_t address, uint32_t size_value, uint32_t count, uint8_t *buffer); + target_addr_t address, uint32_t size_value, uint32_t count, uint8_t *buffer); if (physical) { CMD_ARGC--; CMD_ARGV++; @@ -2984,14 +3145,18 @@ COMMAND_HANDLER(handle_md_command) if ((CMD_ARGC < 1) || (CMD_ARGC > 2)) return ERROR_COMMAND_SYNTAX_ERROR; - uint32_t address; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); + target_addr_t address; + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address); unsigned count = 1; if (CMD_ARGC == 2) COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], count); uint8_t *buffer = calloc(count, size); + if (buffer == NULL) { + LOG_ERROR("Failed to allocate md read buffer"); + return ERROR_FAIL; + } struct target *target = get_current_target(CMD_CTX); int retval = fn(target, address, size, count, buffer); @@ -3004,14 +3169,14 @@ COMMAND_HANDLER(handle_md_command) } typedef int (*target_write_fn)(struct target *target, - uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); static int target_fill_mem(struct target *target, - uint32_t address, + target_addr_t address, target_write_fn fn, unsigned data_size, /* value */ - uint32_t b, + uint64_t b, /* count */ unsigned c) { @@ -3026,6 +3191,9 @@ static int target_fill_mem(struct target *target, for (unsigned i = 0; i < chunk_size; i++) { switch (data_size) { + case 8: + target_buffer_set_u64(target, target_buf + i * data_size, b); + break; case 4: target_buffer_set_u32(target, target_buf + i * data_size, b); break; @@ -3074,11 +3242,11 @@ COMMAND_HANDLER(handle_mw_command) if ((CMD_ARGC < 2) || (CMD_ARGC > 3)) return ERROR_COMMAND_SYNTAX_ERROR; - uint32_t address; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); + target_addr_t address; + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address); - uint32_t value; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); + target_addr_t value; + COMMAND_PARSE_ADDRESS(CMD_ARGV[1], value); unsigned count = 1; if (CMD_ARGC == 3) @@ -3087,6 +3255,9 @@ COMMAND_HANDLER(handle_mw_command) struct target *target = get_current_target(CMD_CTX); unsigned wordsize; switch (CMD_NAME[2]) { + case 'd': + wordsize = 8; + break; case 'w': wordsize = 4; break; @@ -3104,7 +3275,7 @@ COMMAND_HANDLER(handle_mw_command) } static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image, - uint32_t *min_address, uint32_t *max_address) + target_addr_t *min_address, target_addr_t *max_address) { if (CMD_ARGC < 1 || CMD_ARGC > 5) return ERROR_COMMAND_SYNTAX_ERROR; @@ -3112,8 +3283,8 @@ static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image, /* a base address isn't always necessary, * default to 0x0 (i.e. don't relocate) */ if (CMD_ARGC >= 2) { - uint32_t addr; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr); + target_addr_t addr; + COMMAND_PARSE_ADDRESS(CMD_ARGV[1], addr); image->base_address = addr; image->base_address_set = 1; } else @@ -3122,9 +3293,9 @@ static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image, image->start_address_set = 0; if (CMD_ARGC >= 4) - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], *min_address); + COMMAND_PARSE_ADDRESS(CMD_ARGV[3], *min_address); if (CMD_ARGC == 5) { - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], *max_address); + COMMAND_PARSE_ADDRESS(CMD_ARGV[4], *max_address); /* use size (given) to find max (required) */ *max_address += *min_address; } @@ -3140,8 +3311,8 @@ COMMAND_HANDLER(handle_load_image_command) uint8_t *buffer; size_t buf_cnt; uint32_t image_size; - uint32_t min_address = 0; - uint32_t max_address = 0xffffffff; + target_addr_t min_address = 0; + target_addr_t max_address = -1; int i; struct image image; @@ -3156,7 +3327,7 @@ COMMAND_HANDLER(handle_load_image_command) duration_start(&bench); if (image_open(&image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK) - return ERROR_OK; + return ERROR_FAIL; image_size = 0x0; retval = ERROR_OK; @@ -3166,6 +3337,7 @@ COMMAND_HANDLER(handle_load_image_command) command_print(CMD_CTX, "error allocating buffer for section (%d bytes)", (int)(image.sections[i].size)); + retval = ERROR_FAIL; break; } @@ -3199,7 +3371,7 @@ COMMAND_HANDLER(handle_load_image_command) break; } image_size += length; - command_print(CMD_CTX, "%u bytes written at address 0x%8.8" PRIx32 "", + command_print(CMD_CTX, "%u bytes written at address " TARGET_ADDR_FMT "", (unsigned int)length, image.sections[i].base_address + offset); } @@ -3224,15 +3396,15 @@ COMMAND_HANDLER(handle_dump_image_command) struct fileio *fileio; uint8_t *buffer; int retval, retvaltemp; - uint32_t address, size; + target_addr_t address, size; struct duration bench; struct target *target = get_current_target(CMD_CTX); if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], address); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], size); + COMMAND_PARSE_ADDRESS(CMD_ARGV[1], address); + COMMAND_PARSE_ADDRESS(CMD_ARGV[2], size); uint32_t buf_size = (size > 4096) ? 4096 : size; buffer = malloc(buf_size); @@ -3281,7 +3453,13 @@ COMMAND_HANDLER(handle_dump_image_command) return retval; } -static COMMAND_HELPER(handle_verify_image_command_internal, int verify) +enum verify_mode { + IMAGE_TEST = 0, + IMAGE_VERIFY = 1, + IMAGE_CHECKSUM_ONLY = 2 +}; + +static COMMAND_HELPER(handle_verify_image_command_internal, enum verify_mode verify) { uint8_t *buffer; size_t buf_cnt; @@ -3307,8 +3485,8 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify) duration_start(&bench); if (CMD_ARGC >= 2) { - uint32_t addr; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr); + target_addr_t addr; + COMMAND_PARSE_ADDRESS(CMD_ARGV[1], addr); image.base_address = addr; image.base_address_set = 1; } else { @@ -3339,7 +3517,7 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify) break; } - if (verify) { + if (verify >= IMAGE_VERIFY) { /* calculate checksum of image */ retval = image_calculate_checksum(buffer, buf_cnt, &checksum); if (retval != ERROR_OK) { @@ -3352,7 +3530,12 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify) free(buffer); break; } - + if ((checksum != mem_checksum) && (verify == IMAGE_CHECKSUM_ONLY)) { + LOG_ERROR("checksum mismatch"); + free(buffer); + retval = ERROR_FAIL; + goto done; + } if (checksum != mem_checksum) { /* failed crc checksum, fall back to a binary compare */ uint8_t *data; @@ -3393,7 +3576,7 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify) free(data); } } else { - command_print(CMD_CTX, "address 0x%08" PRIx32 " length 0x%08zx", + command_print(CMD_CTX, "address " TARGET_ADDR_FMT " length 0x%08zx", image.sections[i].base_address, buf_cnt); } @@ -3417,14 +3600,19 @@ done: return retval; } +COMMAND_HANDLER(handle_verify_image_checksum_command) +{ + return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, IMAGE_CHECKSUM_ONLY); +} + COMMAND_HANDLER(handle_verify_image_command) { - return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, 1); + return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, IMAGE_VERIFY); } COMMAND_HANDLER(handle_test_image_command) { - return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, 0); + return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, IMAGE_TEST); } static int handle_bp_command_list(struct command_context *cmd_ctx) @@ -3435,7 +3623,7 @@ static int handle_bp_command_list(struct command_context *cmd_ctx) if (breakpoint->type == BKPT_SOFT) { char *buf = buf_to_str(breakpoint->orig_instr, breakpoint->length, 16); - command_print(cmd_ctx, "IVA breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i, 0x%s", + command_print(cmd_ctx, "IVA breakpoint: " TARGET_ADDR_FMT ", 0x%x, %i, 0x%s", breakpoint->address, breakpoint->length, breakpoint->set, buf); @@ -3446,13 +3634,13 @@ static int handle_bp_command_list(struct command_context *cmd_ctx) breakpoint->asid, breakpoint->length, breakpoint->set); else if ((breakpoint->address != 0) && (breakpoint->asid != 0)) { - command_print(cmd_ctx, "Hybrid breakpoint(IVA): 0x%8.8" PRIx32 ", 0x%x, %i", + command_print(cmd_ctx, "Hybrid breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %i", breakpoint->address, breakpoint->length, breakpoint->set); command_print(cmd_ctx, "\t|--->linked with ContextID: 0x%8.8" PRIx32, breakpoint->asid); } else - command_print(cmd_ctx, "Breakpoint(IVA): 0x%8.8" PRIx32 ", 0x%x, %i", + command_print(cmd_ctx, "Breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %i", breakpoint->address, breakpoint->length, breakpoint->set); } @@ -3463,7 +3651,7 @@ static int handle_bp_command_list(struct command_context *cmd_ctx) } static int handle_bp_command_set(struct command_context *cmd_ctx, - uint32_t addr, uint32_t asid, uint32_t length, int hw) + target_addr_t addr, uint32_t asid, uint32_t length, int hw) { struct target *target = get_current_target(cmd_ctx); int retval; @@ -3471,7 +3659,7 @@ static int handle_bp_command_set(struct command_context *cmd_ctx, if (asid == 0) { retval = breakpoint_add(target, addr, length, hw); if (ERROR_OK == retval) - command_print(cmd_ctx, "breakpoint set at 0x%8.8" PRIx32 "", addr); + command_print(cmd_ctx, "breakpoint set at " TARGET_ADDR_FMT "", addr); else { LOG_ERROR("Failure setting breakpoint, the same address(IVA) is already used"); return retval; @@ -3506,7 +3694,7 @@ static int handle_bp_command_set(struct command_context *cmd_ctx, COMMAND_HANDLER(handle_bp_command) { - uint32_t addr; + target_addr_t addr; uint32_t asid; uint32_t length; int hw = BKPT_SOFT; @@ -3517,17 +3705,15 @@ COMMAND_HANDLER(handle_bp_command) case 2: asid = 0; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); case 3: if (strcmp(CMD_ARGV[2], "hw") == 0) { hw = BKPT_HARD; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); - + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); - asid = 0; return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); } else if (strcmp(CMD_ARGV[2], "hw_ctx") == 0) { @@ -3537,10 +3723,10 @@ COMMAND_HANDLER(handle_bp_command) addr = 0; return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); } - + /* fallthrough */ case 4: hw = BKPT_HARD; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], asid); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], length); return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); @@ -3555,8 +3741,8 @@ COMMAND_HANDLER(handle_rbp_command) if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - uint32_t addr; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); + target_addr_t addr; + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); struct target *target = get_current_target(CMD_CTX); breakpoint_remove(target, addr); @@ -3572,7 +3758,7 @@ COMMAND_HANDLER(handle_wp_command) struct watchpoint *watchpoint = target->watchpoints; while (watchpoint) { - command_print(CMD_CTX, "address: 0x%8.8" PRIx32 + command_print(CMD_CTX, "address: " TARGET_ADDR_FMT ", len: 0x%8.8" PRIx32 ", r/w/a: %i, value: 0x%8.8" PRIx32 ", mask: 0x%8.8" PRIx32, @@ -3657,14 +3843,14 @@ COMMAND_HANDLER(handle_virt2phys_command) if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - uint32_t va; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], va); - uint32_t pa; + target_addr_t va; + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], va); + target_addr_t pa; struct target *target = get_current_target(CMD_CTX); int retval = target->type->virt2phys(target, va, &pa); if (retval == ERROR_OK) - command_print(CMD_CTX, "Physical address 0x%08" PRIx32 "", pa); + command_print(CMD_CTX, "Physical address " TARGET_ADDR_FMT "", pa); return retval; } @@ -3693,7 +3879,7 @@ typedef unsigned char UNIT[2]; /* unit of profiling */ /* Dump a gmon.out histogram file. */ static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filename, bool with_range, - uint32_t start_address, uint32_t end_address, struct target *target) + uint32_t start_address, uint32_t end_address, struct target *target, uint32_t duration_ms) { uint32_t i; FILE *f = fopen(filename, "w"); @@ -3761,7 +3947,8 @@ static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filena writeLong(f, min, target); /* low_pc */ writeLong(f, max, target); /* high_pc */ writeLong(f, numBuckets, target); /* # of buckets */ - writeLong(f, 100, target); /* KLUDGE! We lie, ca. 100Hz best case. */ + float sample_rate = sampleNum / (duration_ms / 1000.0); + writeLong(f, sample_rate, target); writeString(f, "seconds"); for (i = 0; i < (15-strlen("seconds")); i++) writeData(f, &zero, 1); @@ -3810,6 +3997,7 @@ COMMAND_HANDLER(handle_profile_command) return ERROR_FAIL; } + uint64_t timestart_ms = timeval_ms(); /** * Some cores let us sample the PC without the * annoying halt/resume step; for example, ARMv7 PCSR. @@ -3821,6 +4009,7 @@ COMMAND_HANDLER(handle_profile_command) free(samples); return retval; } + uint32_t duration_ms = timeval_ms() - timestart_ms; assert(num_of_samples <= MAX_PROFILE_SAMPLE_NUM); @@ -3853,7 +4042,7 @@ COMMAND_HANDLER(handle_profile_command) } write_gmon(samples, num_of_samples, CMD_ARGV[1], - with_range, start_address, end_address, target); + with_range, start_address, end_address, target, duration_ms); command_print(CMD_CTX, "Wrote %s", CMD_ARGV[1]); free(samples); @@ -3913,6 +4102,8 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, uint32_t count; uint32_t v; const char *varname; + const char *phys; + bool is_phys; int n, e, retval; uint32_t i; @@ -3921,8 +4112,8 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, * argv[3] = memory address * argv[4] = count of times to read */ - if (argc != 4) { - Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems"); + if (argc < 4 || argc > 5) { + Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems [phys]"); return JIM_ERR; } varname = Jim_GetString(argv[0], &len); @@ -3941,6 +4132,14 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, len = l; if (e != JIM_OK) return e; + is_phys = false; + if (argc > 4) { + phys = Jim_GetString(argv[4], &n); + if (!strncmp(phys, "phys", n)) + is_phys = true; + else + return JIM_ERR; + } switch (width) { case 8: width = 1; @@ -3983,7 +4182,7 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, sprintf(buf, "mem2array address: 0x%08" PRIx32 " is not aligned for %" PRId32 " byte reads", addr, width); - Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL); + Jim_AppendStrings(interp, Jim_GetResult(interp), buf, NULL); return JIM_ERR; } @@ -4006,13 +4205,16 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, if (count > (buffersize / width)) count = (buffersize / width); - retval = target_read_memory(target, addr, width, count, buffer); + if (is_phys) + retval = target_read_phys_memory(target, addr, width, count, buffer); + else + retval = target_read_memory(target, addr, width, count, buffer); if (retval != ERROR_OK) { /* BOO !*/ - LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed", - (unsigned int)addr, - (int)width, - (int)count); + LOG_ERROR("mem2array: Read @ 0x%08" PRIx32 ", w=%" PRId32 ", cnt=%" PRId32 ", failed", + addr, + width, + count); Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL); e = JIM_ERR; @@ -4102,6 +4304,8 @@ static int target_array2mem(Jim_Interp *interp, struct target *target, uint32_t count; uint32_t v; const char *varname; + const char *phys; + bool is_phys; int n, e, retval; uint32_t i; @@ -4110,8 +4314,8 @@ static int target_array2mem(Jim_Interp *interp, struct target *target, * argv[3] = memory address * argv[4] = count to write */ - if (argc != 4) { - Jim_WrongNumArgs(interp, 0, argv, "varname width addr nelems"); + if (argc < 4 || argc > 5) { + Jim_WrongNumArgs(interp, 0, argv, "varname width addr nelems [phys]"); return JIM_ERR; } varname = Jim_GetString(argv[0], &len); @@ -4130,6 +4334,14 @@ static int target_array2mem(Jim_Interp *interp, struct target *target, len = l; if (e != JIM_OK) return e; + is_phys = false; + if (argc > 4) { + phys = Jim_GetString(argv[4], &n); + if (!strncmp(phys, "phys", n)) + is_phys = true; + else + return JIM_ERR; + } switch (width) { case 8: width = 1; @@ -4173,10 +4385,10 @@ static int target_array2mem(Jim_Interp *interp, struct target *target, } else { char buf[100]; Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - sprintf(buf, "array2mem address: 0x%08x is not aligned for %d byte reads", - (unsigned int)addr, - (int)width); - Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL); + sprintf(buf, "array2mem address: 0x%08" PRIx32 " is not aligned for %" PRId32 " byte reads", + addr, + width); + Jim_AppendStrings(interp, Jim_GetResult(interp), buf, NULL); return JIM_ERR; } @@ -4216,13 +4428,16 @@ static int target_array2mem(Jim_Interp *interp, struct target *target, } len -= count; - retval = target_write_memory(target, addr, width, count, buffer); + if (is_phys) + retval = target_write_phys_memory(target, addr, width, count, buffer); + else + retval = target_write_memory(target, addr, width, count, buffer); if (retval != ERROR_OK) { /* BOO !*/ - LOG_ERROR("array2mem: Write @ 0x%08x, w=%d, cnt=%d, failed", - (unsigned int)addr, - (int)width, - (int)count); + LOG_ERROR("array2mem: Write @ 0x%08" PRIx32 ", w=%" PRId32 ", cnt=%" PRId32 ", failed", + addr, + width, + count); Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: cannot read memory", NULL); e = JIM_ERR; @@ -4247,17 +4462,28 @@ void target_handle_event(struct target *target, enum target_event e) for (teap = target->event_action; teap != NULL; teap = teap->next) { if (teap->event == e) { - LOG_DEBUG("target: (%d) %s (%s) event: %d (%s) action: %s", + LOG_DEBUG("target(%d): %s (%s) event: %d (%s) action: %s", target->target_number, target_name(target), target_type_name(target), e, Jim_Nvp_value2name_simple(nvp_target_event, e)->name, Jim_GetString(teap->body, NULL)); + + /* Override current target by the target an event + * is issued from (lot of scripts need it). + * Return back to previous override as soon + * as the handler processing is done */ + struct command_context *cmd_ctx = current_command_context(teap->interp); + struct target *saved_target_override = cmd_ctx->current_target_override; + cmd_ctx->current_target_override = target; + if (Jim_EvalObj(teap->interp, teap->body) != JIM_OK) { Jim_MakeErrorMessage(teap->interp); command_print(NULL, "%s\n", Jim_GetString(Jim_GetResult(teap->interp), NULL)); } + + cmd_ctx->current_target_override = saved_target_override; } } } @@ -4287,7 +4513,9 @@ enum target_cfg_param { TCFG_COREID, TCFG_CHAIN_POSITION, TCFG_DBGBASE, + TCFG_CTIBASE, TCFG_RTOS, + TCFG_DEFER_EXAMINE, }; static Jim_Nvp nvp_config_opts[] = { @@ -4301,7 +4529,9 @@ static Jim_Nvp nvp_config_opts[] = { { .name = "-coreid", .value = TCFG_COREID }, { .name = "-chain-position", .value = TCFG_CHAIN_POSITION }, { .name = "-dbgbase", .value = TCFG_DBGBASE }, + { .name = "-ctibase", .value = TCFG_CTIBASE }, { .name = "-rtos", .value = TCFG_RTOS }, + { .name = "-defer-examine", .value = TCFG_DEFER_EXAMINE }, { .name = NULL, .value = -1 } }; @@ -4566,7 +4796,20 @@ no_params: Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dbgbase)); /* loop for more */ break; - + case TCFG_CTIBASE: + if (goi->isconfigure) { + e = Jim_GetOpt_Wide(goi, &w); + if (e != JIM_OK) + return e; + target->ctibase = (uint32_t)w; + target->ctibase_set = true; + } else { + if (goi->argc != 0) + goto no_params; + } + Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->ctibase)); + /* loop for more */ + break; case TCFG_RTOS: /* RTOS */ { @@ -4576,6 +4819,13 @@ no_params: } /* loop for more */ break; + + case TCFG_DEFER_EXAMINE: + /* DEFER_EXAMINE */ + target->defer_examine = true; + /* loop for more */ + break; + } } /* while (goi->argc) */ @@ -4590,12 +4840,9 @@ static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *a Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); goi.isconfigure = !strcmp(Jim_GetString(argv[0], NULL), "configure"); - int need_args = 1 + goi.isconfigure; - if (goi.argc < need_args) { + if (goi.argc < 1) { Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, - goi.isconfigure - ? "missing: -option VALUE ..." - : "missing: -option ..."); + "missing: -option ..."); return JIM_ERR; } struct target *target = Jim_CmdPrivData(goi.interp); @@ -4708,7 +4955,7 @@ static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv) } int (*fn)(struct target *target, - uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); fn = target_read_memory; int e; @@ -4846,20 +5093,58 @@ static int jim_target_tap_disabled(Jim_Interp *interp) static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - if (argc != 1) { - Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); + bool allow_defer = false; + + Jim_GetOptInfo goi; + Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); + if (goi.argc > 1) { + const char *cmd_name = Jim_GetString(argv[0], NULL); + Jim_SetResultFormatted(goi.interp, + "usage: %s ['allow-defer']", cmd_name); return JIM_ERR; } + if (goi.argc > 0 && + strcmp(Jim_GetString(argv[1], NULL), "allow-defer") == 0) { + /* consume it */ + struct Jim_Obj *obj; + int e = Jim_GetOpt_Obj(&goi, &obj); + if (e != JIM_OK) + return e; + allow_defer = true; + } + struct target *target = Jim_CmdPrivData(interp); if (!target->tap->enabled) return jim_target_tap_disabled(interp); + if (allow_defer && target->defer_examine) { + LOG_INFO("Deferring arp_examine of %s", target_name(target)); + LOG_INFO("Use arp_examine command to examine it manually!"); + return JIM_OK; + } + int e = target->type->examine(target); if (e != ERROR_OK) return JIM_ERR; return JIM_OK; } +static int jim_target_was_examined(Jim_Interp *interp, int argc, Jim_Obj * const *argv) +{ + struct target *target = Jim_CmdPrivData(interp); + + Jim_SetResultBool(interp, target_was_examined(target)); + return JIM_OK; +} + +static int jim_target_examine_deferred(Jim_Interp *interp, int argc, Jim_Obj * const *argv) +{ + struct target *target = Jim_CmdPrivData(interp); + + Jim_SetResultBool(interp, target->defer_examine); + return JIM_OK; +} + static int jim_target_halt_gdb(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 1) { @@ -4927,6 +5212,10 @@ static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) target_name(target)); return JIM_ERR; } + + if (target->defer_examine) + target_reset_examined(target); + /* determine if we should halt or not. */ target->reset_halt = !!a; /* When this happens - all workareas are invalid. */ @@ -5137,6 +5426,21 @@ static const struct command_registration target_instance_command_handlers[] = { .mode = COMMAND_EXEC, .jim_handler = jim_target_examine, .help = "used internally for reset processing", + .usage = "arp_examine ['allow-defer']", + }, + { + .name = "was_examined", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_was_examined, + .help = "used internally for reset processing", + .usage = "was_examined", + }, + { + .name = "examine_deferred", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_examine_deferred, + .help = "used internally for reset processing", + .usage = "examine_deferred", }, { .name = "arp_halt_gdb", @@ -5257,7 +5561,7 @@ static int target_create(Jim_GetOptInfo *goi) target = calloc(1, sizeof(struct target)); /* set target number */ target->target_number = new_target_number(); - cmd_ctx->current_target = target->target_number; + cmd_ctx->current_target = target; /* allocate memory for each unique target type */ target->type = calloc(1, sizeof(struct target_type)); @@ -5288,14 +5592,7 @@ static int target_create(Jim_GetOptInfo *goi) target->halt_issued = false; /* initialize trace information */ - target->trace_info = malloc(sizeof(struct trace)); - target->trace_info->num_trace_points = 0; - target->trace_info->trace_points_size = 0; - target->trace_info->trace_points = NULL; - target->trace_info->trace_history_size = 0; - target->trace_info->trace_history = NULL; - target->trace_info->trace_history_pos = 0; - target->trace_info->trace_history_overflowed = 0; + target->trace_info = calloc(1, sizeof(struct trace)); target->dbgmsg = NULL; target->dbg_msg_enabled = 0; @@ -5530,7 +5827,7 @@ static const struct command_registration target_subcommand_handlers[] = { }; struct FastLoad { - uint32_t address; + target_addr_t address; uint8_t *data; int length; @@ -5557,8 +5854,8 @@ COMMAND_HANDLER(handle_fast_load_image_command) uint8_t *buffer; size_t buf_cnt; uint32_t image_size; - uint32_t min_address = 0; - uint32_t max_address = 0xffffffff; + target_addr_t min_address = 0; + target_addr_t max_address = -1; int i; struct image image; @@ -5664,7 +5961,7 @@ COMMAND_HANDLER(handle_fast_load_command) return ERROR_FAIL; } int i; - int ms = timeval_ms(); + int64_t ms = timeval_ms(); int size = 0; int retval = ERROR_OK; for (i = 0; i < fastload_num; i++) { @@ -5678,7 +5975,7 @@ COMMAND_HANDLER(handle_fast_load_command) size += fastload[i].length; } if (retval == ERROR_OK) { - int after = timeval_ms(); + int64_t after = timeval_ms(); command_print(CMD_CTX, "Loaded image %f kBytes/s", (float)(size/1024.0)/((float)(after-ms)/1000.0)); } return retval; @@ -6028,6 +6325,13 @@ static const struct command_registration target_exec_command_handlers[] = { .help = "step one instruction from current PC or address", .usage = "[address]", }, + { + .name = "mdd", + .handler = handle_md_command, + .mode = COMMAND_EXEC, + .help = "display memory words", + .usage = "['phys'] address [count]", + }, { .name = "mdw", .handler = handle_md_command, @@ -6049,6 +6353,13 @@ static const struct command_registration target_exec_command_handlers[] = { .help = "display memory bytes", .usage = "['phys'] address [count]", }, + { + .name = "mwd", + .handler = handle_mw_command, + .mode = COMMAND_EXEC, + .help = "write memory word", + .usage = "['phys'] address value [count]", + }, { .name = "mww", .handler = handle_mw_command, @@ -6111,6 +6422,12 @@ static const struct command_registration target_exec_command_handlers[] = { .mode = COMMAND_EXEC, .usage = "filename address size", }, + { + .name = "verify_image_checksum", + .handler = handle_verify_image_checksum_command, + .mode = COMMAND_EXEC, + .usage = "filename [offset [type]]", + }, { .name = "verify_image", .handler = handle_verify_image_command,