Add authdata_read/authdata_write support to 0.11. (#575)
AFAIK there is no hardware that implements this, but it should be a close-to-done starting point in case it is ever required. Change-Id: I49e3082e8629b1d70b12e8a847c2848e75b04508 Signed-off-by: Tim Newsome <tim@sifive.com>
This commit is contained in:
parent
3070dbb6ab
commit
a83ac81022
|
@ -10129,12 +10129,14 @@ set challenge [riscv authdata_read]
|
||||||
riscv authdata_write [expr $challenge + 1]
|
riscv authdata_write [expr $challenge + 1]
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
@deffn Command {riscv authdata_read}
|
@deffn Command {riscv authdata_read} [index=0]
|
||||||
Return the 32-bit value read from authdata.
|
Return the 32-bit value read from authdata or authdata0 (index=0), or
|
||||||
|
authdata1 (index=1).
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn Command {riscv authdata_write} value
|
@deffn Command {riscv authdata_write} [index=0] value
|
||||||
Write the 32-bit value to authdata.
|
Write the 32-bit value to authdata or authdata0 (index=0), or authdata1
|
||||||
|
(index=1).
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@subsection RISC-V DMI Commands
|
@subsection RISC-V DMI Commands
|
||||||
|
|
|
@ -154,6 +154,9 @@ typedef enum slot {
|
||||||
#define DMINFO_AUTHTYPE (3<<2)
|
#define DMINFO_AUTHTYPE (3<<2)
|
||||||
#define DMINFO_VERSION 3
|
#define DMINFO_VERSION 3
|
||||||
|
|
||||||
|
#define DMAUTHDATA0 0x12
|
||||||
|
#define DMAUTHDATA1 0x13
|
||||||
|
|
||||||
/*** Info about the core being debugged. ***/
|
/*** Info about the core being debugged. ***/
|
||||||
|
|
||||||
#define DBUS_ADDRESS_UNKNOWN 0xffff
|
#define DBUS_ADDRESS_UNKNOWN 0xffff
|
||||||
|
@ -2293,6 +2296,65 @@ static int arch_state(struct target *target)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
COMMAND_HELPER(riscv011_print_info, struct target *target)
|
||||||
|
{
|
||||||
|
uint32_t dminfo = dbus_read(target, DMINFO);
|
||||||
|
riscv_print_info_line(CMD, "dm", "authenticated", get_field(dminfo, DMINFO_AUTHENTICATED));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wait_for_authbusy(struct target *target)
|
||||||
|
{
|
||||||
|
time_t start = time(NULL);
|
||||||
|
while (1) {
|
||||||
|
uint32_t dminfo = dbus_read(target, DMINFO);
|
||||||
|
if (!get_field(dminfo, DMINFO_AUTHBUSY))
|
||||||
|
break;
|
||||||
|
if (time(NULL) - start > riscv_command_timeout_sec) {
|
||||||
|
LOG_ERROR("Timed out after %ds waiting for authbusy to go low (dminfo=0x%x). "
|
||||||
|
"Increase the timeout with riscv set_command_timeout_sec.",
|
||||||
|
riscv_command_timeout_sec,
|
||||||
|
dminfo);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int riscv011_authdata_read(struct target *target, uint32_t *value, unsigned index)
|
||||||
|
{
|
||||||
|
if (index > 1) {
|
||||||
|
LOG_ERROR("Spec 0.11 only has a two authdata registers.");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wait_for_authbusy(target) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
uint16_t authdata_address = index ? DMAUTHDATA1 : DMAUTHDATA0;
|
||||||
|
*value = dbus_read(target, authdata_address);
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int riscv011_authdata_write(struct target *target, uint32_t value, unsigned index)
|
||||||
|
{
|
||||||
|
if (index > 1) {
|
||||||
|
LOG_ERROR("Spec 0.11 only has a two authdata registers.");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wait_for_authbusy(target) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
uint16_t authdata_address = index ? DMAUTHDATA1 : DMAUTHDATA0;
|
||||||
|
dbus_write(target, authdata_address, value);
|
||||||
|
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static int init_target(struct command_context *cmd_ctx,
|
static int init_target(struct command_context *cmd_ctx,
|
||||||
struct target *target)
|
struct target *target)
|
||||||
{
|
{
|
||||||
|
@ -2301,6 +2363,9 @@ static int init_target(struct command_context *cmd_ctx,
|
||||||
generic_info->get_register = get_register;
|
generic_info->get_register = get_register;
|
||||||
generic_info->set_register = set_register;
|
generic_info->set_register = set_register;
|
||||||
generic_info->read_memory = read_memory;
|
generic_info->read_memory = read_memory;
|
||||||
|
generic_info->authdata_read = &riscv011_authdata_read;
|
||||||
|
generic_info->authdata_write = &riscv011_authdata_write;
|
||||||
|
generic_info->print_info = &riscv011_print_info;
|
||||||
|
|
||||||
generic_info->version_specific = calloc(1, sizeof(riscv011_info_t));
|
generic_info->version_specific = calloc(1, sizeof(riscv011_info_t));
|
||||||
if (!generic_info->version_specific)
|
if (!generic_info->version_specific)
|
||||||
|
|
|
@ -1500,7 +1500,7 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wait_for_authbusy(struct target *target, uint32_t *dmstatus)
|
static int wait_for_authbusy(struct target *target, uint32_t *dmstatus)
|
||||||
{
|
{
|
||||||
time_t start = time(NULL);
|
time_t start = time(NULL);
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -1784,16 +1784,26 @@ static int examine(struct target *target)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int riscv013_authdata_read(struct target *target, uint32_t *value)
|
static int riscv013_authdata_read(struct target *target, uint32_t *value, unsigned index)
|
||||||
{
|
{
|
||||||
|
if (index > 0) {
|
||||||
|
LOG_ERROR("Spec 0.13 only has a single authdata register.");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
if (wait_for_authbusy(target, NULL) != ERROR_OK)
|
if (wait_for_authbusy(target, NULL) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
return dmi_read(target, value, DM_AUTHDATA);
|
return dmi_read(target, value, DM_AUTHDATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
int riscv013_authdata_write(struct target *target, uint32_t value)
|
static int riscv013_authdata_write(struct target *target, uint32_t value, unsigned index)
|
||||||
{
|
{
|
||||||
|
if (index > 0) {
|
||||||
|
LOG_ERROR("Spec 0.13 only has a single authdata register.");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t before, after;
|
uint32_t before, after;
|
||||||
if (wait_for_authbusy(target, &before) != ERROR_OK)
|
if (wait_for_authbusy(target, &before) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
@ -1867,6 +1877,7 @@ static unsigned riscv013_data_bits(struct target *target)
|
||||||
COMMAND_HELPER(riscv013_print_info, struct target *target)
|
COMMAND_HELPER(riscv013_print_info, struct target *target)
|
||||||
{
|
{
|
||||||
RISCV013_INFO(info);
|
RISCV013_INFO(info);
|
||||||
|
|
||||||
riscv_print_info_line(CMD, "dm", "abits", info->abits);
|
riscv_print_info_line(CMD, "dm", "abits", info->abits);
|
||||||
riscv_print_info_line(CMD, "dm", "progbufsize", info->progbufsize);
|
riscv_print_info_line(CMD, "dm", "progbufsize", info->progbufsize);
|
||||||
riscv_print_info_line(CMD, "dm", "sbversion", get_field(info->sbcs, DM_SBCS_SBVERSION));
|
riscv_print_info_line(CMD, "dm", "sbversion", get_field(info->sbcs, DM_SBCS_SBVERSION));
|
||||||
|
@ -1877,6 +1888,10 @@ COMMAND_HELPER(riscv013_print_info, struct target *target)
|
||||||
riscv_print_info_line(CMD, "dm", "sbaccess16", get_field(info->sbcs, DM_SBCS_SBACCESS16));
|
riscv_print_info_line(CMD, "dm", "sbaccess16", get_field(info->sbcs, DM_SBCS_SBACCESS16));
|
||||||
riscv_print_info_line(CMD, "dm", "sbaccess8", get_field(info->sbcs, DM_SBCS_SBACCESS8));
|
riscv_print_info_line(CMD, "dm", "sbaccess8", get_field(info->sbcs, DM_SBCS_SBACCESS8));
|
||||||
|
|
||||||
|
uint32_t dmstatus;
|
||||||
|
if (dmstatus_read(target, &dmstatus, false) == ERROR_OK)
|
||||||
|
riscv_print_info_line(CMD, "dm", "authenticated", get_field(dmstatus, DM_DMSTATUS_AUTHENTICATED));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2552,8 +2552,13 @@ COMMAND_HANDLER(riscv_set_expose_custom)
|
||||||
|
|
||||||
COMMAND_HANDLER(riscv_authdata_read)
|
COMMAND_HANDLER(riscv_authdata_read)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC != 0) {
|
unsigned index = 0;
|
||||||
LOG_ERROR("Command takes no parameters");
|
if (CMD_ARGC == 0) {
|
||||||
|
/* nop */
|
||||||
|
} else if (CMD_ARGC == 1) {
|
||||||
|
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], index);
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("Command takes at most one parameter");
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2571,7 +2576,7 @@ COMMAND_HANDLER(riscv_authdata_read)
|
||||||
|
|
||||||
if (r->authdata_read) {
|
if (r->authdata_read) {
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
if (r->authdata_read(target, &value) != ERROR_OK)
|
if (r->authdata_read(target, &value, index) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
command_print(CMD, "0x%" PRIx32, value);
|
command_print(CMD, "0x%" PRIx32, value);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
|
@ -2583,19 +2588,26 @@ COMMAND_HANDLER(riscv_authdata_read)
|
||||||
|
|
||||||
COMMAND_HANDLER(riscv_authdata_write)
|
COMMAND_HANDLER(riscv_authdata_write)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC != 1) {
|
uint32_t value;
|
||||||
LOG_ERROR("Command takes exactly 1 argument");
|
unsigned index = 0;
|
||||||
|
|
||||||
|
if (CMD_ARGC == 0) {
|
||||||
|
/* nop */
|
||||||
|
} else if (CMD_ARGC == 1) {
|
||||||
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], value);
|
||||||
|
} else if (CMD_ARGC == 2) {
|
||||||
|
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], index);
|
||||||
|
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("Command takes at most 2 arguments");
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct target *target = get_current_target(CMD_CTX);
|
struct target *target = get_current_target(CMD_CTX);
|
||||||
RISCV_INFO(r);
|
RISCV_INFO(r);
|
||||||
|
|
||||||
uint32_t value;
|
|
||||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], value);
|
|
||||||
|
|
||||||
if (r->authdata_write) {
|
if (r->authdata_write) {
|
||||||
return r->authdata_write(target, value);
|
return r->authdata_write(target, value, index);
|
||||||
} else {
|
} else {
|
||||||
LOG_ERROR("authdata_write is not implemented for this target.");
|
LOG_ERROR("authdata_write is not implemented for this target.");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
@ -3103,16 +3115,18 @@ static const struct command_registration riscv_exec_command_handlers[] = {
|
||||||
{
|
{
|
||||||
.name = "authdata_read",
|
.name = "authdata_read",
|
||||||
.handler = riscv_authdata_read,
|
.handler = riscv_authdata_read,
|
||||||
.usage = "",
|
.usage = "[index]",
|
||||||
.mode = COMMAND_ANY,
|
.mode = COMMAND_ANY,
|
||||||
.help = "Return the 32-bit value read from authdata."
|
.help = "Return the 32-bit value read from authdata or authdata0 "
|
||||||
|
"(index=0), or authdata1 (index=1)."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "authdata_write",
|
.name = "authdata_write",
|
||||||
.handler = riscv_authdata_write,
|
.handler = riscv_authdata_write,
|
||||||
.mode = COMMAND_ANY,
|
.mode = COMMAND_ANY,
|
||||||
.usage = "value",
|
.usage = "[index] value",
|
||||||
.help = "Write the 32-bit value to authdata."
|
.help = "Write the 32-bit value to authdata or authdata0 (index=0), "
|
||||||
|
"or authdata1 (index=1)."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "dmi_read",
|
.name = "dmi_read",
|
||||||
|
|
|
@ -171,8 +171,8 @@ typedef struct {
|
||||||
void (*fill_dmi_read_u64)(struct target *target, char *buf, int a);
|
void (*fill_dmi_read_u64)(struct target *target, char *buf, int a);
|
||||||
void (*fill_dmi_nop_u64)(struct target *target, char *buf);
|
void (*fill_dmi_nop_u64)(struct target *target, char *buf);
|
||||||
|
|
||||||
int (*authdata_read)(struct target *target, uint32_t *value);
|
int (*authdata_read)(struct target *target, uint32_t *value, unsigned index);
|
||||||
int (*authdata_write)(struct target *target, uint32_t value);
|
int (*authdata_write)(struct target *target, uint32_t value, unsigned index);
|
||||||
|
|
||||||
int (*dmi_read)(struct target *target, uint32_t *value, uint32_t address);
|
int (*dmi_read)(struct target *target, uint32_t *value, uint32_t address);
|
||||||
int (*dmi_write)(struct target *target, uint32_t address, uint32_t value);
|
int (*dmi_write)(struct target *target, uint32_t address, uint32_t value);
|
||||||
|
|
Loading…
Reference in New Issue