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]
@end example
@deffn Command {riscv authdata_read}
Return the 32-bit value read from authdata.
@deffn Command {riscv authdata_read} [index=0]
Return the 32-bit value read from authdata or authdata0 (index=0), or
authdata1 (index=1).
@end deffn
@deffn Command {riscv authdata_write} value
Write the 32-bit value to authdata.
@deffn Command {riscv authdata_write} [index=0] value
Write the 32-bit value to authdata or authdata0 (index=0), or authdata1
(index=1).
@end deffn
@subsection RISC-V DMI Commands

View File

@ -154,6 +154,9 @@ typedef enum slot {
#define DMINFO_AUTHTYPE (3<<2)
#define DMINFO_VERSION 3
#define DMAUTHDATA0 0x12
#define DMAUTHDATA1 0x13
/*** Info about the core being debugged. ***/
#define DBUS_ADDRESS_UNKNOWN 0xffff
@ -2293,6 +2296,65 @@ static int arch_state(struct target *target)
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,
struct target *target)
{
@ -2301,6 +2363,9 @@ static int init_target(struct command_context *cmd_ctx,
generic_info->get_register = get_register;
generic_info->set_register = set_register;
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));
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;
}
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);
while (1) {
@ -1784,16 +1784,26 @@ static int examine(struct target *target)
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)
return ERROR_FAIL;
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;
if (wait_for_authbusy(target, &before) != ERROR_OK)
return ERROR_FAIL;
@ -1867,6 +1877,7 @@ static unsigned riscv013_data_bits(struct target *target)
COMMAND_HELPER(riscv013_print_info, struct target *target)
{
RISCV013_INFO(info);
riscv_print_info_line(CMD, "dm", "abits", info->abits);
riscv_print_info_line(CMD, "dm", "progbufsize", info->progbufsize);
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", "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;
}

View File

@ -2552,8 +2552,13 @@ COMMAND_HANDLER(riscv_set_expose_custom)
COMMAND_HANDLER(riscv_authdata_read)
{
if (CMD_ARGC != 0) {
LOG_ERROR("Command takes no parameters");
unsigned index = 0;
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;
}
@ -2571,7 +2576,7 @@ COMMAND_HANDLER(riscv_authdata_read)
if (r->authdata_read) {
uint32_t value;
if (r->authdata_read(target, &value) != ERROR_OK)
if (r->authdata_read(target, &value, index) != ERROR_OK)
return ERROR_FAIL;
command_print(CMD, "0x%" PRIx32, value);
return ERROR_OK;
@ -2583,19 +2588,26 @@ COMMAND_HANDLER(riscv_authdata_read)
COMMAND_HANDLER(riscv_authdata_write)
{
if (CMD_ARGC != 1) {
LOG_ERROR("Command takes exactly 1 argument");
uint32_t value;
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;
}
struct target *target = get_current_target(CMD_CTX);
RISCV_INFO(r);
uint32_t value;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], value);
if (r->authdata_write) {
return r->authdata_write(target, value);
return r->authdata_write(target, value, index);
} else {
LOG_ERROR("authdata_write is not implemented for this target.");
return ERROR_FAIL;
@ -3103,16 +3115,18 @@ static const struct command_registration riscv_exec_command_handlers[] = {
{
.name = "authdata_read",
.handler = riscv_authdata_read,
.usage = "",
.usage = "[index]",
.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",
.handler = riscv_authdata_write,
.mode = COMMAND_ANY,
.usage = "value",
.help = "Write the 32-bit value to authdata."
.usage = "[index] value",
.help = "Write the 32-bit value to authdata or authdata0 (index=0), "
"or authdata1 (index=1)."
},
{
.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_nop_u64)(struct target *target, char *buf);
int (*authdata_read)(struct target *target, uint32_t *value);
int (*authdata_write)(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, unsigned index);
int (*dmi_read)(struct target *target, uint32_t *value, uint32_t address);
int (*dmi_write)(struct target *target, uint32_t address, uint32_t value);