target: rewrite function target_configure() as COMMAND_HELPER

The function target_configure() is used by the commands
'target create', 'configure' and 'cget', already rewritten as
COMMAND_HANDLER.

Rewrite the common function as COMMAND_HELPER.
While there:
- fix the check on arguments, even if it should be coded better;
- keep jimtcl code for target_type::target_jim_configure() and for
  rtos_create(); these would be rewritten later on.

Change-Id: I7e5699ca6d124e34d3b2199714e3ce584bfcce80
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/8829
Tested-by: jenkins
This commit is contained in:
Antonio Borneo
2023-12-03 15:41:27 +01:00
parent 1d9b34baa3
commit 61890e3dc3

View File

@@ -214,8 +214,6 @@ static const struct nvp nvp_target_event[] = {
{ .name = NULL, .value = -1 }
};
static const struct jim_nvp *jim_nvp_target_event = (const struct jim_nvp *)nvp_target_event;
static const struct nvp nvp_target_state[] = {
{ .name = "unknown", .value = TARGET_UNKNOWN },
{ .name = "running", .value = TARGET_RUNNING },
@@ -238,7 +236,7 @@ static const struct nvp nvp_target_debug_reason[] = {
{ .name = NULL, .value = -1 },
};
static const struct jim_nvp nvp_target_endian[] = {
static const struct nvp nvp_target_endian[] = {
{ .name = "big", .value = TARGET_BIG_ENDIAN },
{ .name = "little", .value = TARGET_LITTLE_ENDIAN },
{ .name = "be", .value = TARGET_BIG_ENDIAN },
@@ -2844,8 +2842,7 @@ COMMAND_HANDLER(handle_targets_command)
marker,
target_name(target),
target_type_name(target),
jim_nvp_value2name_simple(nvp_target_endian,
target->endianness)->name,
nvp_value2name(nvp_target_endian, target->endianness)->name,
target->tap->dotted_name,
state);
}
@@ -4859,7 +4856,7 @@ enum target_cfg_param {
TCFG_GDB_MAX_CONNECTIONS,
};
static struct jim_nvp nvp_config_opts[] = {
static struct nvp nvp_config_opts[] = {
{ .name = "-type", .value = TCFG_TYPE },
{ .name = "-event", .value = TCFG_EVENT },
{ .name = "-work-area-virt", .value = TCFG_WORK_AREA_VIRT },
@@ -4877,78 +4874,71 @@ static struct jim_nvp nvp_config_opts[] = {
{ .name = NULL, .value = -1 }
};
static int target_configure(struct jim_getopt_info *goi, struct target *target)
static COMMAND_HELPER(target_configure, struct target *target, unsigned int index, bool is_configure)
{
struct jim_nvp *n;
Jim_Obj *o;
jim_wide w;
int e;
const struct nvp *n;
int retval;
/* parse config or cget options ... */
while (goi->argc > 0) {
Jim_SetEmptyResult(goi->interp);
/* jim_getopt_debug(goi); */
while (index < CMD_ARGC) {
if (target->type->target_jim_configure) {
/* target defines a configure function */
/* target gets first dibs on parameters */
e = (*(target->type->target_jim_configure))(target, goi);
struct jim_getopt_info goi;
jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC - index, CMD_JIMTCL_ARGV + index);
goi.is_configure = is_configure;
int e = (*target->type->target_jim_configure)(target, &goi);
index = CMD_ARGC - goi.argc;
if (e == JIM_OK) {
/* more? */
continue;
}
if (e == JIM_ERR) {
/* An error */
return e;
int reslen;
const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen);
if (reslen > 0)
command_print(CMD, "%s", result);
return ERROR_FAIL;
}
/* otherwise we 'continue' below */
}
e = jim_getopt_nvp(goi, nvp_config_opts, &n);
if (e != JIM_OK) {
jim_getopt_nvp_unknown(goi, nvp_config_opts, 0);
return e;
n = nvp_name2value(nvp_config_opts, CMD_ARGV[index]);
if (!n->name) {
nvp_unknown_command_print(CMD, nvp_config_opts, NULL, CMD_ARGV[index]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
index++;
switch (n->value) {
case TCFG_TYPE:
/* not settable */
if (goi->is_configure) {
Jim_SetResultFormatted(goi->interp,
"not settable: %s", n->name);
return JIM_ERR;
} else {
no_params:
if (goi->argc != 0) {
Jim_WrongNumArgs(goi->interp,
goi->argc, goi->argv,
"NO PARAMS");
return JIM_ERR;
}
if (is_configure) {
command_print(CMD, "not settable: %s", n->name);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
Jim_SetResultString(goi->interp,
target_type_name(target), -1);
if (index != CMD_ARGC)
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD, "%s", target_type_name(target));
/* loop for more */
break;
case TCFG_EVENT:
if (goi->argc == 0) {
Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ...");
return JIM_ERR;
if (index == CMD_ARGC) {
command_print(CMD, "missing event-name");
return ERROR_COMMAND_ARGUMENT_INVALID;
}
e = jim_getopt_nvp(goi, jim_nvp_target_event, &n);
if (e != JIM_OK) {
jim_getopt_nvp_unknown(goi, jim_nvp_target_event, 1);
return e;
n = nvp_name2value(nvp_target_event, CMD_ARGV[index]);
if (!n->name) {
nvp_unknown_command_print(CMD, nvp_target_event, CMD_ARGV[index - 1], CMD_ARGV[index]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
index++;
if (goi->is_configure) {
if (goi->argc != 1) {
Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?");
return JIM_ERR;
}
} else {
if (goi->argc != 0) {
Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name?");
return JIM_ERR;
if (is_configure) {
if (index == CMD_ARGC) {
command_print(CMD, "missing event-body");
return ERROR_COMMAND_ARGUMENT_INVALID;
}
}
@@ -4964,20 +4954,20 @@ no_params:
if (&teap->list == &target->events_action)
teap = NULL;
if (goi->is_configure) {
if (is_configure) {
/* START_DEPRECATED_TPIU */
if (n->value == TARGET_EVENT_TRACE_CONFIG)
LOG_INFO("DEPRECATED target event %s; use TPIU events {pre,post}-{enable,disable}", n->name);
/* END_DEPRECATED_TPIU */
jim_getopt_obj(goi, &o);
if (Jim_Length(o) == 0) {
if (strlen(CMD_ARGV[index]) == 0) {
/* empty action, drop existing one */
if (teap) {
list_del(&teap->list);
Jim_DecrRefCount(teap->interp, teap->body);
free(teap);
}
index++;
break;
}
@@ -4988,10 +4978,12 @@ no_params:
replace = false;
}
teap->event = n->value;
teap->interp = goi->interp;
teap->interp = CMD_CTX->interp;
if (teap->body)
Jim_DecrRefCount(teap->interp, teap->body);
teap->body = Jim_DuplicateObj(goi->interp, o);
/* use jim object to keep its reference on tcl file and line */
/* TODO: need duplicate? isn't IncrRefCount enough? */
teap->body = Jim_DuplicateObj(teap->interp, CMD_JIMTCL_ARGV[index++]);
/*
* FIXME:
* Tcl/TK - "tk events" have a nice feature.
@@ -5008,219 +5000,266 @@ no_params:
/* add to head of event list */
list_add(&teap->list, &target->events_action);
}
Jim_SetEmptyResult(goi->interp);
} else {
/* get */
if (!teap)
Jim_SetEmptyResult(goi->interp);
else
Jim_SetResult(goi->interp, Jim_DuplicateObj(goi->interp, teap->body));
/* cget */
if (index != CMD_ARGC)
return ERROR_COMMAND_SYNTAX_ERROR;
if (teap)
command_print(CMD, "%s", Jim_GetString(teap->body, NULL));
}
}
/* loop for more */
break;
case TCFG_WORK_AREA_VIRT:
if (goi->is_configure) {
target_free_all_working_areas(target);
e = jim_getopt_wide(goi, &w);
if (e != JIM_OK)
return e;
target->working_area_virt = w;
if (is_configure) {
if (index == CMD_ARGC) {
command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[index], target->working_area_virt);
index++;
target->working_area_virt_spec = true;
target_free_all_working_areas(target);
} else {
if (goi->argc != 0)
goto no_params;
if (index != CMD_ARGC)
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD, TARGET_ADDR_FMT, target->working_area_virt);
}
Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_virt));
/* loop for more */
break;
case TCFG_WORK_AREA_PHYS:
if (goi->is_configure) {
target_free_all_working_areas(target);
e = jim_getopt_wide(goi, &w);
if (e != JIM_OK)
return e;
target->working_area_phys = w;
if (is_configure) {
if (index == CMD_ARGC) {
command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[index], target->working_area_phys);
index++;
target->working_area_phys_spec = true;
target_free_all_working_areas(target);
} else {
if (goi->argc != 0)
goto no_params;
if (index != CMD_ARGC)
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD, TARGET_ADDR_FMT, target->working_area_phys);
}
Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_phys));
/* loop for more */
break;
case TCFG_WORK_AREA_SIZE:
if (goi->is_configure) {
if (is_configure) {
if (index == CMD_ARGC) {
command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[index], target->working_area_size);
index++;
target_free_all_working_areas(target);
e = jim_getopt_wide(goi, &w);
if (e != JIM_OK)
return e;
target->working_area_size = w;
} else {
if (goi->argc != 0)
goto no_params;
if (index != CMD_ARGC)
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD, "0x%08" PRIx32, target->working_area_size);
}
Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_size));
/* loop for more */
break;
case TCFG_WORK_AREA_BACKUP:
if (goi->is_configure) {
if (is_configure) {
if (index == CMD_ARGC) {
command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
retval = command_parse_bool_arg(CMD_ARGV[index], &target->backup_working_area);
if (retval != ERROR_OK)
return retval;
index++;
target_free_all_working_areas(target);
e = jim_getopt_wide(goi, &w);
if (e != JIM_OK)
return e;
/* make this boolean */
target->backup_working_area = (w != 0);
} else {
if (goi->argc != 0)
goto no_params;
if (index != CMD_ARGC)
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD, target->backup_working_area ? "1" : "0");
}
Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->backup_working_area ? 1 : 0));
/* loop for more e*/
/* loop for more */
break;
case TCFG_ENDIAN:
if (goi->is_configure) {
e = jim_getopt_nvp(goi, nvp_target_endian, &n);
if (e != JIM_OK) {
jim_getopt_nvp_unknown(goi, nvp_target_endian, 1);
return e;
if (is_configure) {
if (index == CMD_ARGC) {
command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
n = nvp_name2value(nvp_target_endian, CMD_ARGV[index]);
if (!n->name) {
nvp_unknown_command_print(CMD, nvp_target_endian, CMD_ARGV[index - 1], CMD_ARGV[index]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
index++;
target->endianness = n->value;
} else {
if (goi->argc != 0)
goto no_params;
if (index != CMD_ARGC)
return ERROR_COMMAND_SYNTAX_ERROR;
n = nvp_value2name(nvp_target_endian, target->endianness);
if (!n->name) {
target->endianness = TARGET_LITTLE_ENDIAN;
n = nvp_value2name(nvp_target_endian, target->endianness);
}
command_print(CMD, "%s", n->name);
}
n = jim_nvp_value2name_simple(nvp_target_endian, target->endianness);
if (!n->name) {
target->endianness = TARGET_LITTLE_ENDIAN;
n = jim_nvp_value2name_simple(nvp_target_endian, target->endianness);
}
Jim_SetResultString(goi->interp, n->name, -1);
/* loop for more */
break;
case TCFG_COREID:
if (goi->is_configure) {
e = jim_getopt_wide(goi, &w);
if (e != JIM_OK)
return e;
target->coreid = (int32_t)w;
if (is_configure) {
if (index == CMD_ARGC) {
command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
COMMAND_PARSE_NUMBER(s32, CMD_ARGV[index], target->coreid);
index++;
} else {
if (goi->argc != 0)
goto no_params;
if (index != CMD_ARGC)
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD, "%" PRIi32, target->coreid);
}
Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->coreid));
/* loop for more */
break;
case TCFG_CHAIN_POSITION:
if (goi->is_configure) {
Jim_Obj *o_t;
struct jtag_tap *tap;
if (is_configure) {
if (target->has_dap) {
Jim_SetResultString(goi->interp,
"target requires -dap parameter instead of -chain-position!", -1);
return JIM_ERR;
command_print(CMD, "target requires -dap parameter instead of -chain-position!");
return ERROR_COMMAND_ARGUMENT_INVALID;
}
e = jim_getopt_obj(goi, &o_t);
if (e != JIM_OK)
return e;
tap = jtag_tap_by_jim_obj(goi->interp, o_t);
if (!tap)
return JIM_ERR;
if (index == CMD_ARGC) {
command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
struct jtag_tap *tap = jtag_tap_by_string(CMD_ARGV[index]);
if (!tap) {
command_print(CMD, "Tap '%s' could not be found", CMD_ARGV[index]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
index++;
target->tap = tap;
target->tap_configured = true;
} else {
if (goi->argc != 0)
goto no_params;
if (index != CMD_ARGC)
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD, "%s", target->tap->dotted_name);
}
Jim_SetResultString(goi->interp, target->tap->dotted_name, -1);
/* loop for more e*/
break;
case TCFG_DBGBASE:
if (goi->is_configure) {
e = jim_getopt_wide(goi, &w);
if (e != JIM_OK)
return e;
target->dbgbase = (uint32_t)w;
target->dbgbase_set = true;
} else {
if (goi->argc != 0)
goto no_params;
}
Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dbgbase));
/* loop for more */
break;
case TCFG_DBGBASE:
if (is_configure) {
if (index == CMD_ARGC) {
command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[index], target->dbgbase);
index++;
target->dbgbase_set = true;
} else {
if (index != CMD_ARGC)
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD, "0x%08" PRIx32, target->dbgbase);
}
/* loop for more */
break;
case TCFG_RTOS:
/* RTOS */
{
int result = rtos_create(goi, target);
if (result != JIM_OK)
return result;
if (is_configure) {
if (index == CMD_ARGC) {
command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
struct jim_getopt_info goi;
jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC - index, CMD_JIMTCL_ARGV + index);
index++;
goi.is_configure = true;
int resval = rtos_create(&goi, target);
int reslen;
const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen);
if (reslen > 0)
command_print(CMD, "%s", result);
if (resval != JIM_OK)
return ERROR_FAIL;
} else {
if (index != CMD_ARGC)
return ERROR_COMMAND_SYNTAX_ERROR;
if (target->rtos)
command_print(CMD, "%s", target->rtos->type->name);
}
/* loop for more */
break;
case TCFG_DEFER_EXAMINE:
/* DEFER_EXAMINE */
target->defer_examine = true;
if (is_configure)
target->defer_examine = true;
else
command_print(CMD, "%s", target->defer_examine ? "true" : "false");
/* loop for more */
break;
case TCFG_GDB_PORT:
if (goi->is_configure) {
struct command_context *cmd_ctx = current_command_context(goi->interp);
if (cmd_ctx->mode != COMMAND_CONFIG) {
Jim_SetResultString(goi->interp, "-gdb-port must be configured before 'init'", -1);
return JIM_ERR;
if (is_configure) {
if (index == CMD_ARGC) {
command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
const char *s;
e = jim_getopt_string(goi, &s, NULL);
if (e != JIM_OK)
return e;
/* TODO: generalize test of COMMAND_CONFIG */
if (CMD_CTX->mode != COMMAND_CONFIG) {
command_print(CMD, "-gdb-port must be configured before 'init'");
return ERROR_COMMAND_ARGUMENT_INVALID;
}
char *s = strdup(CMD_ARGV[index]);
if (!s) {
LOG_ERROR("Out of memory");
return ERROR_FAIL;
}
free(target->gdb_port_override);
target->gdb_port_override = strdup(s);
target->gdb_port_override = s;
index++;
} else {
if (goi->argc != 0)
goto no_params;
if (index != CMD_ARGC)
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD, "%s", target->gdb_port_override ? target->gdb_port_override : "undefined");
}
Jim_SetResultString(goi->interp, target->gdb_port_override ? target->gdb_port_override : "undefined", -1);
/* loop for more */
break;
case TCFG_GDB_MAX_CONNECTIONS:
if (goi->is_configure) {
struct command_context *cmd_ctx = current_command_context(goi->interp);
if (cmd_ctx->mode != COMMAND_CONFIG) {
Jim_SetResultString(goi->interp, "-gdb-max-connections must be configured before 'init'", -1);
return JIM_ERR;
if (is_configure) {
if (index == CMD_ARGC) {
command_print(CMD, "missing argument to %s", CMD_ARGV[index - 1]);
return ERROR_COMMAND_ARGUMENT_INVALID;
}
e = jim_getopt_wide(goi, &w);
if (e != JIM_OK)
return e;
target->gdb_max_connections = (w < 0) ? CONNECTION_LIMIT_UNLIMITED : (int)w;
if (CMD_CTX->mode != COMMAND_CONFIG) {
command_print(CMD, "-gdb-max-connections must be configured before 'init'");
return ERROR_COMMAND_ARGUMENT_INVALID;
}
COMMAND_PARSE_NUMBER(int, CMD_ARGV[index], target->gdb_max_connections);
index++;
if (target->gdb_max_connections < 0)
target->gdb_max_connections = CONNECTION_LIMIT_UNLIMITED;
} else {
if (goi->argc != 0)
goto no_params;
if (index != CMD_ARGC)
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD, "%d", target->gdb_max_connections);
}
Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->gdb_max_connections));
/* loop for more */
break;
}
} /* while (goi->argc) */
}
/* done - we return */
return JIM_OK;
return ERROR_OK;
}
COMMAND_HANDLER(handle_target_configure)
@@ -5228,23 +5267,11 @@ COMMAND_HANDLER(handle_target_configure)
if (!CMD_ARGC)
return ERROR_COMMAND_SYNTAX_ERROR;
struct jim_getopt_info goi;
jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC, CMD_JIMTCL_ARGV);
goi.is_configure = !strcmp(CMD_NAME, "configure");
bool is_configure = !strcmp(CMD_NAME, "configure");
struct target *target = get_current_target(CMD_CTX);
int e = target_configure(&goi, target);
int reslen;
const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen);
if (reslen > 0)
command_print(CMD, "%s", result);
if (e != JIM_OK)
return ERROR_FAIL;
return ERROR_OK;
return CALL_COMMAND_HANDLER(target_configure, target, 0, is_configure);
}
COMMAND_HANDLER(handle_target_examine)
@@ -5803,18 +5830,9 @@ COMMAND_HANDLER(handle_target_create)
}
/* Do the rest as "configure" options */
struct jim_getopt_info goi;
jim_getopt_setup(&goi, CMD_CTX->interp, CMD_ARGC - 2, CMD_JIMTCL_ARGV + 2);
goi.is_configure = 1;
int e = target_configure(&goi, target);
int reslen;
const char *result = Jim_GetString(Jim_GetResult(CMD_CTX->interp), &reslen);
if (reslen > 0)
command_print(CMD, "%s", result);
if (e == JIM_OK) {
bool is_configure = true;
retval = CALL_COMMAND_HANDLER(target_configure, target, 2, is_configure);
if (retval == ERROR_OK) {
if (target->has_dap) {
if (!target->dap_configured) {
command_print(CMD, "-dap ?name? required when creating target");
@@ -5829,8 +5847,6 @@ COMMAND_HANDLER(handle_target_create)
/* tap must be set after target was configured */
if (!target->tap)
retval = ERROR_COMMAND_ARGUMENT_INVALID;
} else {
retval = ERROR_FAIL;
}
if (retval != ERROR_OK) {