target: check memory handlers before use for all types
[fw/openocd] / src / target / target.c
index 4d277c694b85412d0be46d1ee36f920cf0b22609..89fee4aaa5fa7899fed3dfd96ee448bd734ab997 100644 (file)
@@ -55,6 +55,7 @@
 #include "trace.h"
 #include "image.h"
 #include "rtos/rtos.h"
+#include "transport/transport.h"
 
 /* default halt wait timeout (ms) */
 #define DEFAULT_HALT_TIMEOUT 5000
@@ -88,7 +89,7 @@ extern struct target_type feroceon_target;
 extern struct target_type dragonite_target;
 extern struct target_type xscale_target;
 extern struct target_type cortexm_target;
-extern struct target_type cortexa8_target;
+extern struct target_type cortexa_target;
 extern struct target_type cortexr4_target;
 extern struct target_type arm11_target;
 extern struct target_type mips_m4k_target;
@@ -117,7 +118,7 @@ static struct target_type *target_types[] = {
        &dragonite_target,
        &xscale_target,
        &cortexm_target,
-       &cortexa8_target,
+       &cortexa_target,
        &cortexr4_target,
        &arm11_target,
        &mips_m4k_target,
@@ -138,6 +139,7 @@ static struct target_type *target_types[] = {
 struct target *all_targets;
 static struct target_event_callback *target_event_callbacks;
 static struct target_timer_callback *target_timer_callbacks;
+LIST_HEAD(target_reset_callback_list);
 static const int polling_interval = 100;
 
 static const Jim_Nvp nvp_assert[] = {
@@ -215,6 +217,8 @@ static const Jim_Nvp nvp_target_event[] = {
        { .value = TARGET_EVENT_GDB_FLASH_ERASE_START, .name = "gdb-flash-erase-start" },
        { .value = TARGET_EVENT_GDB_FLASH_ERASE_END  , .name = "gdb-flash-erase-end" },
 
+       { .value = TARGET_EVENT_TRACE_CONFIG, .name = "trace-config" },
+
        { .name = NULL, .value = -1 }
 };
 
@@ -279,6 +283,28 @@ const char *target_state_name(struct target *t)
        return cp;
 }
 
+const char *target_event_name(enum target_event event)
+{
+       const char *cp;
+       cp = Jim_Nvp_value2name_simple(nvp_target_event, event)->name;
+       if (!cp) {
+               LOG_ERROR("Invalid target event: %d", (int)(event));
+               cp = "(*BUG*unknown*BUG*)";
+       }
+       return cp;
+}
+
+const char *target_reset_mode_name(enum target_reset_mode reset_mode)
+{
+       const char *cp;
+       cp = Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode)->name;
+       if (!cp) {
+               LOG_ERROR("Invalid target reset mode: %d", (int)(reset_mode));
+               cp = "(*BUG*unknown*BUG*)";
+       }
+       return cp;
+}
+
 /* determine the number of the new target */
 static int new_target_number(void)
 {
@@ -460,7 +486,7 @@ struct target *get_target(const char *id)
 }
 
 /* returns a pointer to the n-th configured target */
-static struct target *get_target_by_num(int num)
+struct target *get_target_by_num(int num)
 {
        struct target *target = all_targets;
 
@@ -600,6 +626,10 @@ static int target_process_reset(struct command_context *cmd_ctx, enum target_res
                return ERROR_FAIL;
        }
 
+       struct target *target;
+       for (target = all_targets; target; target = target->next)
+               target_call_reset_callbacks(target, reset_mode);
+
        /* disable polling during reset to make reset event scripts
         * more predictable, i.e. dr/irscan & pathmove in events will
         * not have JTAG operations injected into the middle of a sequence.
@@ -622,7 +652,6 @@ static int target_process_reset(struct command_context *cmd_ctx, enum target_res
        /* We want any events to be processed before the prompt */
        retval = target_call_timer_callbacks_now();
 
-       struct target *target;
        for (target = all_targets; target; target = target->next) {
                target->type->check_reset(target);
                target->running_alg = false;
@@ -658,7 +687,15 @@ static int default_check_reset(struct target *target)
 
 int target_examine_one(struct target *target)
 {
-       return target->type->examine(target);
+       target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_START);
+
+       int retval = target->type->examine(target);
+       if (retval != ERROR_OK)
+               return retval;
+
+       target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_END);
+
+       return ERROR_OK;
 }
 
 static int jtag_enable_callback(enum jtag_event event, void *priv)
@@ -670,15 +707,7 @@ static int jtag_enable_callback(enum jtag_event event, void *priv)
 
        jtag_unregister_event_callback(jtag_enable_callback, target);
 
-       target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_START);
-
-       int retval = target_examine_one(target);
-       if (retval != ERROR_OK)
-               return retval;
-
-       target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_END);
-
-       return retval;
+       return target_examine_one(target);
 }
 
 /* Targets that correctly implement init + examine, i.e.
@@ -699,13 +728,9 @@ int target_examine(void)
                        continue;
                }
 
-               target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_START);
-
                retval = target_examine_one(target);
                if (retval != ERROR_OK)
                        return retval;
-
-               target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_END);
        }
        return retval;
 }
@@ -862,6 +887,8 @@ int target_run_flash_async_algorithm(struct target *target,
        int retval;
        int timeout = 0;
 
+       const uint8_t *buffer_orig = buffer;
+
        /* Set up working area. First word is write pointer, second word is read pointer,
         * rest is fifo data area. */
        uint32_t wp_addr = buffer_start;
@@ -902,7 +929,8 @@ int target_run_flash_async_algorithm(struct target *target,
                        break;
                }
 
-               LOG_DEBUG("count 0x%" PRIx32 " wp 0x%" PRIx32 " rp 0x%" PRIx32, count, wp, rp);
+               LOG_DEBUG("offs 0x%zx count 0x%" PRIx32 " wp 0x%" PRIx32 " rp 0x%" PRIx32,
+                       (size_t) (buffer - buffer_orig), count, wp, rp);
 
                if (rp == 0) {
                        LOG_ERROR("flash write algorithm aborted by target");
@@ -910,7 +938,7 @@ int target_run_flash_async_algorithm(struct target *target,
                        break;
                }
 
-               if ((rp & (block_size - 1)) || rp < fifo_start_addr || rp >= fifo_end_addr) {
+               if (((rp - fifo_start_addr) & (block_size - 1)) || rp < fifo_start_addr || rp >= fifo_end_addr) {
                        LOG_ERROR("corrupted fifo read pointer 0x%" PRIx32, rp);
                        break;
                }
@@ -993,6 +1021,10 @@ int target_read_memory(struct target *target,
                LOG_ERROR("Target not examined yet");
                return ERROR_FAIL;
        }
+       if (!target->type->read_memory) {
+               LOG_ERROR("Target %s doesn't support read_memory", target_name(target));
+               return ERROR_FAIL;
+       }
        return target->type->read_memory(target, address, size, count, buffer);
 }
 
@@ -1003,6 +1035,10 @@ int target_read_phys_memory(struct target *target,
                LOG_ERROR("Target not examined yet");
                return ERROR_FAIL;
        }
+       if (!target->type->read_phys_memory) {
+               LOG_ERROR("Target %s doesn't support read_phys_memory", target_name(target));
+               return ERROR_FAIL;
+       }
        return target->type->read_phys_memory(target, address, size, count, buffer);
 }
 
@@ -1013,6 +1049,10 @@ int target_write_memory(struct target *target,
                LOG_ERROR("Target not examined yet");
                return ERROR_FAIL;
        }
+       if (!target->type->write_memory) {
+               LOG_ERROR("Target %s doesn't support write_memory", target_name(target));
+               return ERROR_FAIL;
+       }
        return target->type->write_memory(target, address, size, count, buffer);
 }
 
@@ -1023,6 +1063,10 @@ int target_write_phys_memory(struct target *target,
                LOG_ERROR("Target not examined yet");
                return ERROR_FAIL;
        }
+       if (!target->type->write_phys_memory) {
+               LOG_ERROR("Target %s doesn't support write_phys_memory", target_name(target));
+               return ERROR_FAIL;
+       }
        return target->type->write_phys_memory(target, address, size, count, buffer);
 }
 
@@ -1144,20 +1188,6 @@ static void target_reset_examined(struct target *target)
        target->examined = false;
 }
 
-static int err_read_phys_memory(struct target *target, uint32_t address,
-               uint32_t size, uint32_t count, uint8_t *buffer)
-{
-       LOG_ERROR("Not implemented: %s", __func__);
-       return ERROR_FAIL;
-}
-
-static int err_write_phys_memory(struct target *target, uint32_t address,
-               uint32_t size, uint32_t count, const uint8_t *buffer)
-{
-       LOG_ERROR("Not implemented: %s", __func__);
-       return ERROR_FAIL;
-}
-
 static int handle_target(void *priv);
 
 static int target_init_one(struct command_context *cmd_ctx,
@@ -1184,16 +1214,6 @@ static int target_init_one(struct command_context *cmd_ctx,
         * implement it in stages, but warn if we need to do so.
         */
        if (type->mmu) {
-               if (type->write_phys_memory == NULL) {
-                       LOG_ERROR("type '%s' is missing write_phys_memory",
-                                       type->name);
-                       type->write_phys_memory = err_write_phys_memory;
-               }
-               if (type->read_phys_memory == NULL) {
-                       LOG_ERROR("type '%s' is missing read_phys_memory",
-                                       type->name);
-                       type->read_phys_memory = err_read_phys_memory;
-               }
                if (type->virt2phys == NULL) {
                        LOG_ERROR("type '%s' is missing virt2phys", type->name);
                        type->virt2phys = identity_virt2phys;
@@ -1308,6 +1328,28 @@ int target_register_event_callback(int (*callback)(struct target *target,
        return ERROR_OK;
 }
 
+int target_register_reset_callback(int (*callback)(struct target *target,
+               enum target_reset_mode reset_mode, void *priv), void *priv)
+{
+       struct target_reset_callback *entry;
+
+       if (callback == NULL)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       entry = malloc(sizeof(struct target_reset_callback));
+       if (entry == NULL) {
+               LOG_ERROR("error allocating buffer for reset callback entry");
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       entry->callback = callback;
+       entry->priv = priv;
+       list_add(&entry->list, &target_reset_callback_list);
+
+
+       return ERROR_OK;
+}
+
 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;
@@ -1326,6 +1368,7 @@ int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int
        (*callbacks_p)->callback = callback;
        (*callbacks_p)->periodic = periodic;
        (*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;
@@ -1365,26 +1408,39 @@ int target_unregister_event_callback(int (*callback)(struct target *target,
        return ERROR_OK;
 }
 
-int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
+int target_unregister_reset_callback(int (*callback)(struct target *target,
+               enum target_reset_mode reset_mode, void *priv), void *priv)
 {
-       struct target_timer_callback **p = &target_timer_callbacks;
-       struct target_timer_callback *c = target_timer_callbacks;
+       struct target_reset_callback *entry;
 
        if (callback == NULL)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       while (c) {
-               struct target_timer_callback *next = c->next;
+       list_for_each_entry(entry, &target_reset_callback_list, list) {
+               if (entry->callback == callback && entry->priv == priv) {
+                       list_del(&entry->list);
+                       free(entry);
+                       break;
+               }
+       }
+
+       return ERROR_OK;
+}
+
+int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
+{
+       if (callback == NULL)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       for (struct target_timer_callback *c = target_timer_callbacks;
+            c; c = c->next) {
                if ((c->callback == callback) && (c->priv == priv)) {
-                       *p = next;
-                       free(c);
+                       c->removed = true;
                        return ERROR_OK;
-               } else
-                       p = &(c->next);
-               c = next;
+               }
        }
 
-       return ERROR_OK;
+       return ERROR_FAIL;
 }
 
 int target_call_event_callbacks(struct target *target, enum target_event event)
@@ -1411,6 +1467,19 @@ int target_call_event_callbacks(struct target *target, enum target_event event)
        return ERROR_OK;
 }
 
+int target_call_reset_callbacks(struct target *target, enum target_reset_mode reset_mode)
+{
+       struct target_reset_callback *callback;
+
+       LOG_DEBUG("target reset %i (%s)", reset_mode,
+                       Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode)->name);
+
+       list_for_each_entry(callback, &target_reset_callback_list, list)
+               callback->callback(target, reset_mode, callback->priv);
+
+       return ERROR_OK;
+}
+
 static int target_timer_callback_periodic_restart(
                struct target_timer_callback *cb, struct timeval *now)
 {
@@ -1438,31 +1507,44 @@ static int target_call_timer_callback(struct target_timer_callback *cb,
 
 static int target_call_timer_callbacks_check_time(int checktime)
 {
+       static bool callback_processing;
+
+       /* Do not allow nesting */
+       if (callback_processing)
+               return ERROR_OK;
+
+       callback_processing = true;
+
        keep_alive();
 
        struct timeval now;
        gettimeofday(&now, NULL);
 
-       struct target_timer_callback *callback = target_timer_callbacks;
-       while (callback) {
-               /* cleaning up may unregister and free this callback */
-               struct target_timer_callback *next_callback = callback->next;
+       /* Store an address of the place containing a pointer to the
+        * next item; initially, that's a standalone "root of the
+        * list" variable. */
+       struct target_timer_callback **callback = &target_timer_callbacks;
+       while (*callback) {
+               if ((*callback)->removed) {
+                       struct target_timer_callback *p = *callback;
+                       *callback = (*callback)->next;
+                       free(p);
+                       continue;
+               }
 
-               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));
+               bool call_it = (*callback)->callback &&
+                       ((!checktime && (*callback)->periodic) ||
+                        now.tv_sec > (*callback)->when.tv_sec ||
+                        (now.tv_sec == (*callback)->when.tv_sec &&
+                         now.tv_usec >= (*callback)->when.tv_usec));
 
-               if (call_it) {
-                       int retval = target_call_timer_callback(callback, &now);
-                       if (retval != ERROR_OK)
-                               return retval;
-               }
+               if (call_it)
+                       target_call_timer_callback(*callback, &now);
 
-               callback = next_callback;
+               callback = &(*callback)->next;
        }
 
+       callback_processing = false;
        return ERROR_OK;
 }
 
@@ -1712,6 +1794,31 @@ int target_free_working_area(struct target *target, struct working_area *area)
        return target_free_working_area_restore(target, area, 1);
 }
 
+void target_quit(void)
+{
+       struct target_event_callback *pe = target_event_callbacks;
+       while (pe) {
+               struct target_event_callback *t = pe->next;
+               free(pe);
+               pe = t;
+       }
+       target_event_callbacks = NULL;
+
+       struct target_timer_callback *pt = target_timer_callbacks;
+       while (pt) {
+               struct target_timer_callback *t = pt->next;
+               free(pt);
+               pt = t;
+       }
+       target_timer_callbacks = NULL;
+
+       for (struct target *target = all_targets;
+            target; target = target->next) {
+               if (target->type->deinit_target)
+                       target->type->deinit_target(target);
+       }
+}
+
 /* free resources and restore memory, if restoring memory fails,
  * free up resources anyway
  */
@@ -1815,7 +1922,7 @@ static int target_profiling_default(struct target *target, uint32_t *samples,
        for (;;) {
                target_poll(target);
                if (target->state == TARGET_HALTED) {
-                       uint32_t t = *((uint32_t *)reg->value);
+                       uint32_t t = buf_get_u32(reg->value, 0, 32);
                        samples[sample_count++] = t;
                        /* current pc, addr = 0, do not handle breakpoints, not debugging */
                        retval = target_resume(target, 1, 0, 0, 0);
@@ -2407,23 +2514,27 @@ static int handle_target(void *priv)
                                        target->backoff.times *= 2;
                                        target->backoff.times++;
                                }
-                               LOG_USER("Polling target %s failed, GDB will be halted. Polling again in %dms",
-                                               target_name(target),
-                                               target->backoff.times * polling_interval);
 
                                /* Tell GDB to halt the debugger. This allows the user to
                                 * run monitor commands to handle the situation.
                                 */
                                target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
-                               return retval;
                        }
-                       /* Since we succeeded, we reset backoff count */
                        if (target->backoff.times > 0) {
-                               LOG_USER("Polling target %s succeeded again, trying to reexamine", target_name(target));
+                               LOG_USER("Polling target %s failed, trying to reexamine", target_name(target));
                                target_reset_examined(target);
-                               target_examine_one(target);
+                               retval = target_examine_one(target);
+                               /* Target examination could have failed due to unstable connection,
+                                * but we set the examined flag anyway to repoll it later */
+                               if (retval != ERROR_OK) {
+                                       target->examined = true;
+                                       LOG_USER("Examination failed, GDB will be halted. Polling again in %dms",
+                                                target->backoff.times * polling_interval);
+                                       return retval;
+                               }
                        }
 
+                       /* Since we succeeded, we reset backoff count */
                        target->backoff.times = 0;
                }
        }
@@ -3300,9 +3411,10 @@ static int handle_bp_command_set(struct command_context *cmd_ctx,
                uint32_t addr, uint32_t asid, uint32_t length, int hw)
 {
        struct target *target = get_current_target(cmd_ctx);
+       int retval;
 
        if (asid == 0) {
-               int retval = breakpoint_add(target, addr, length, hw);
+               retval = breakpoint_add(target, addr, length, hw);
                if (ERROR_OK == retval)
                        command_print(cmd_ctx, "breakpoint set at 0x%8.8" PRIx32 "", addr);
                else {
@@ -3310,7 +3422,11 @@ static int handle_bp_command_set(struct command_context *cmd_ctx,
                        return retval;
                }
        } else if (addr == 0) {
-               int retval = context_breakpoint_add(target, asid, length, hw);
+               if (target->type->add_context_breakpoint == NULL) {
+                       LOG_WARNING("Context breakpoint not available");
+                       return ERROR_OK;
+               }
+               retval = context_breakpoint_add(target, asid, length, hw);
                if (ERROR_OK == retval)
                        command_print(cmd_ctx, "Context breakpoint set at 0x%8.8" PRIx32 "", asid);
                else {
@@ -3318,7 +3434,11 @@ static int handle_bp_command_set(struct command_context *cmd_ctx,
                        return retval;
                }
        } else {
-               int retval = hybrid_breakpoint_add(target, addr, asid, length, hw);
+               if (target->type->add_hybrid_breakpoint == NULL) {
+                       LOG_WARNING("Hybrid breakpoint not available");
+                       return ERROR_OK;
+               }
+               retval = hybrid_breakpoint_add(target, addr, asid, length, hw);
                if (ERROR_OK == retval)
                        command_print(cmd_ctx, "Hybrid breakpoint set at 0x%8.8" PRIx32 "", asid);
                else {
@@ -3501,14 +3621,12 @@ static void writeData(FILE *f, const void *data, size_t len)
                LOG_ERROR("failed to write %zu bytes: %s", len, strerror(errno));
 }
 
-static void writeLong(FILE *f, int l)
+static void writeLong(FILE *f, int l, struct target *target)
 {
-       int i;
-       for (i = 0; i < 4; i++) {
-               char c = (l >> (i*8))&0xff;
-               writeData(f, &c, 1);
-       }
+       uint8_t val[4];
 
+       target_buffer_set_u32(target, val, l);
+       writeData(f, val, 4);
 }
 
 static void writeString(FILE *f, char *s)
@@ -3519,18 +3637,18 @@ static void writeString(FILE *f, char *s)
 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)
+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 i;
        FILE *f = fopen(filename, "w");
        if (f == NULL)
                return;
        writeString(f, "gmon");
-       writeLong(f, 0x00000001); /* Version */
-       writeLong(f, 0); /* padding */
-       writeLong(f, 0); /* padding */
-       writeLong(f, 0); /* padding */
+       writeLong(f, 0x00000001, target); /* Version */
+       writeLong(f, 0, target); /* padding */
+       writeLong(f, 0, target); /* padding */
+       writeLong(f, 0, target); /* padding */
 
        uint8_t zero = 0;  /* GMON_TAG_TIME_HIST */
        writeData(f, &zero, 1);
@@ -3585,10 +3703,10 @@ static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filena
        }
 
        /* append binary memory gmon.out &profile_hist_hdr ((char*)&profile_hist_hdr + sizeof(struct gmon_hist_hdr)) */
-       writeLong(f, min);                      /* low_pc */
-       writeLong(f, max);                      /* high_pc */
-       writeLong(f, numBuckets);       /* # of buckets */
-       writeLong(f, 100);                      /* KLUDGE! We lie, ca. 100Hz best case. */
+       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. */
        writeString(f, "seconds");
        for (i = 0; i < (15-strlen("seconds")); i++)
                writeData(f, &zero, 1);
@@ -3680,7 +3798,7 @@ COMMAND_HANDLER(handle_profile_command)
        }
 
        write_gmon(samples, num_of_samples, CMD_ARGV[1],
-                       with_range, start_address, end_address);
+                  with_range, start_address, end_address, target);
        command_print(CMD_CTX, "Wrote %s", CMD_ARGV[1]);
 
        free(samples);
@@ -4111,7 +4229,6 @@ enum target_cfg_param {
        TCFG_WORK_AREA_SIZE,
        TCFG_WORK_AREA_BACKUP,
        TCFG_ENDIAN,
-       TCFG_VARIANT,
        TCFG_COREID,
        TCFG_CHAIN_POSITION,
        TCFG_DBGBASE,
@@ -4126,7 +4243,6 @@ static Jim_Nvp nvp_config_opts[] = {
        { .name = "-work-area-size",   .value = TCFG_WORK_AREA_SIZE },
        { .name = "-work-area-backup", .value = TCFG_WORK_AREA_BACKUP },
        { .name = "-endian" ,          .value = TCFG_ENDIAN },
-       { .name = "-variant",          .value = TCFG_VARIANT },
        { .name = "-coreid",           .value = TCFG_COREID },
        { .name = "-chain-position",   .value = TCFG_CHAIN_POSITION },
        { .name = "-dbgbase",          .value = TCFG_DBGBASE },
@@ -4139,7 +4255,6 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
        Jim_Nvp *n;
        Jim_Obj *o;
        jim_wide w;
-       char *cp;
        int e;
 
        /* parse config or cget options ... */
@@ -4348,27 +4463,6 @@ no_params:
                        /* loop for more */
                        break;
 
-               case TCFG_VARIANT:
-                       if (goi->isconfigure) {
-                               if (goi->argc < 1) {
-                                       Jim_SetResultFormatted(goi->interp,
-                                                                                  "%s ?STRING?",
-                                                                                  n->name);
-                                       return JIM_ERR;
-                               }
-                               e = Jim_GetOpt_String(goi, &cp, NULL);
-                               if (e != JIM_OK)
-                                       return e;
-                               free(target->variant);
-                               target->variant = strdup(cp);
-                       } else {
-                               if (goi->argc != 0)
-                                       goto no_params;
-                       }
-                       Jim_SetResultString(goi->interp, target->variant, -1);
-                       /* loop for more */
-                       break;
-
                case TCFG_COREID:
                        if (goi->isconfigure) {
                                e = Jim_GetOpt_Wide(goi, &w);
@@ -5066,6 +5160,15 @@ static int target_create(Jim_GetOptInfo *goi)
        if (e != JIM_OK)
                return e;
        cp = cp2;
+       struct transport *tr = get_current_transport();
+       if (tr->override_target) {
+               e = tr->override_target(&cp);
+               if (e != ERROR_OK) {
+                       LOG_ERROR("The selected transport doesn't support this target");
+                       return JIM_ERR;
+               }
+               LOG_INFO("The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD");
+       }
        /* now does target type exist */
        for (x = 0 ; target_types[x] ; x++) {
                if (0 == strcmp(cp, target_types[x]->name)) {
@@ -5104,6 +5207,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;
 
        /* allocate memory for each unique target type */
        target->type = calloc(1, sizeof(struct target_type));
@@ -5171,10 +5275,6 @@ static int target_create(Jim_GetOptInfo *goi)
                target->endianness = TARGET_LITTLE_ENDIAN;
        }
 
-       /* incase variant is not set */
-       if (!target->variant)
-               target->variant = strdup("");
-
        cp = Jim_GetString(new_cmd, NULL);
        target->cmd_name = strdup(cp);
 
@@ -5334,55 +5434,6 @@ static int jim_target_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        return target_create(&goi);
 }
 
-static int jim_target_number(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
-       Jim_GetOptInfo goi;
-       Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
-
-       /* It's OK to remove this mechanism sometime after August 2010 or so */
-       LOG_WARNING("don't use numbers as target identifiers; use names");
-       if (goi.argc != 1) {
-               Jim_SetResultFormatted(goi.interp, "usage: target number <number>");
-               return JIM_ERR;
-       }
-       jim_wide w;
-       int e = Jim_GetOpt_Wide(&goi, &w);
-       if (e != JIM_OK)
-               return JIM_ERR;
-
-       struct target *target;
-       for (target = all_targets; NULL != target; target = target->next) {
-               if (target->target_number != w)
-                       continue;
-
-               Jim_SetResultString(goi.interp, target_name(target), -1);
-               return JIM_OK;
-       }
-       {
-               Jim_Obj *wObj = Jim_NewIntObj(goi.interp, w);
-               Jim_SetResultFormatted(goi.interp,
-                       "Target: number %#s does not exist", wObj);
-               Jim_FreeNewObj(interp, wObj);
-       }
-       return JIM_ERR;
-}
-
-static int jim_target_count(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
-       if (argc != 1) {
-               Jim_WrongNumArgs(interp, 1, argv, "<no parameters>");
-               return JIM_ERR;
-       }
-       unsigned count = 0;
-       struct target *target = all_targets;
-       while (NULL != target) {
-               target = target->next;
-               count++;
-       }
-       Jim_SetResult(interp, Jim_NewIntObj(interp, count));
-       return JIM_OK;
-}
-
 static const struct command_registration target_subcommand_handlers[] = {
        {
                .name = "init",
@@ -5417,21 +5468,6 @@ static const struct command_registration target_subcommand_handlers[] = {
                .jim_handler = jim_target_names,
                .help = "Returns the names of all targets as a list of strings",
        },
-       {
-               .name = "number",
-               .mode = COMMAND_ANY,
-               .jim_handler = jim_target_number,
-               .usage = "number",
-               .help = "Returns the name of the numbered target "
-                       "(DEPRECATED)",
-       },
-       {
-               .name = "count",
-               .mode = COMMAND_ANY,
-               .jim_handler = jim_target_count,
-               .help = "Returns the number of targets as an integer "
-                       "(DEPRECATED)",
-       },
        {
                .name = "smp",
                .mode = COMMAND_ANY,