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:
Tim Newsome 2021-01-28 09:56:51 -08:00 committed by GitHub
parent 3070dbb6ab
commit a83ac81022
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 118 additions and 22 deletions

View File

@ -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

View File

@ -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)

View File

@ -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;
} }

View File

@ -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",

View File

@ -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);