aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2021-01-28 09:56:51 -0800
committerGitHub <noreply@github.com>2021-01-28 09:56:51 -0800
commita83ac8102208fe43029e31a20ea00eb5f242f5e3 (patch)
tree3cfdf4f7d35c0857b1634e7f769a186256a281ce
parent3070dbb6ab56502e65d952b2c6a7bb057b0b62fe (diff)
downloadriscv-openocd-a83ac8102208fe43029e31a20ea00eb5f242f5e3.zip
riscv-openocd-a83ac8102208fe43029e31a20ea00eb5f242f5e3.tar.gz
riscv-openocd-a83ac8102208fe43029e31a20ea00eb5f242f5e3.tar.bz2
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>
-rw-r--r--doc/openocd.texi10
-rw-r--r--src/target/riscv/riscv-011.c65
-rw-r--r--src/target/riscv/riscv-013.c21
-rw-r--r--src/target/riscv/riscv.c40
-rw-r--r--src/target/riscv/riscv.h4
5 files changed, 118 insertions, 22 deletions
diff --git a/doc/openocd.texi b/doc/openocd.texi
index b7512fe..53fe9bf 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -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
diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c
index 78cd55f..d1774d7 100644
--- a/src/target/riscv/riscv-011.c
+++ b/src/target/riscv/riscv-011.c
@@ -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)
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index b5ede34..ad0423c 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -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;
}
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index fb198cb..c9a4267 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -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",
diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h
index 094851b..5e057e7 100644
--- a/src/target/riscv/riscv.h
+++ b/src/target/riscv/riscv.h
@@ -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);