arm_adi_v5: add option 'root' to 'dap info' command

On ADIv6 the system root ROM table is found by reading the DAP DP
registers BASEPTR0 and BASEPTR1.

Add option 'root' to the commands 'dap info' to let it retrieve
the system root ROM table's AP from DAP DP, then use such AP for
following dump.

Change-Id: I1789457a005faa3870c5d14f763378d2f6a5f095
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6462
Tested-by: jenkins
This commit is contained in:
Antonio Borneo 2021-08-09 15:31:10 +02:00
parent 3f4bc6ce7f
commit 8c1d518232
4 changed files with 66 additions and 8 deletions

View File

@ -4677,11 +4677,12 @@ This command returns a list of all registered DAP objects. It it useful mainly
for TCL scripting.
@end deffn
@deffn {Command} {dap info} [num]
@deffn {Command} {dap info} [@var{num}|@option{root}]
Displays the ROM table for MEM-AP @var{num},
defaulting to the currently selected AP of the currently selected target.
On ADIv5 DAP @var{num} is the numeric index of the AP.
On ADIv6 DAP @var{num} is the base address of the AP.
With ADIv6 only, @option{root} specifies the root ROM table.
@end deffn
@deffn {Command} {dap init}
@ -4692,11 +4693,12 @@ initialization, too.
The following commands exist as subcommands of DAP instances:
@deffn {Command} {$dap_name info} [num]
@deffn {Command} {$dap_name info} [@var{num}|@option{root}]
Displays the ROM table for MEM-AP @var{num},
defaulting to the currently selected AP.
On ADIv5 DAP @var{num} is the numeric index of the AP.
On ADIv6 DAP @var{num} is the base address of the AP.
With ADIv6 only, @option{root} specifies the root ROM table.
@end deffn
@deffn {Command} {$dap_name apid} [num]

View File

@ -1154,6 +1154,32 @@ static int dap_get_debugbase(struct adiv5_ap *ap,
return ERROR_OK;
}
int adiv6_dap_read_baseptr(struct command_invocation *cmd, struct adiv5_dap *dap, uint64_t *baseptr)
{
uint32_t baseptr_lower, baseptr_upper = 0;
int retval;
if (dap->asize > 32) {
retval = dap_queue_dp_read(dap, DP_BASEPTR1, &baseptr_upper);
if (retval != ERROR_OK)
return retval;
}
retval = dap_dp_read_atomic(dap, DP_BASEPTR0, &baseptr_lower);
if (retval != ERROR_OK)
return retval;
if ((baseptr_lower & DP_BASEPTR0_VALID) != DP_BASEPTR0_VALID) {
command_print(cmd, "System root table not present");
return ERROR_FAIL;
}
baseptr_lower &= ~0x0fff;
*baseptr = (((uint64_t)baseptr_upper) << 32) | baseptr_lower;
return ERROR_OK;
}
/** Holds registers and coordinates of a CoreSight component */
struct cs_component_vals {
struct adiv5_ap *ap;
@ -2225,6 +2251,18 @@ COMMAND_HANDLER(handle_dap_info_command)
apsel = dap->apsel;
break;
case 1:
if (!strcmp(CMD_ARGV[0], "root")) {
if (!is_adiv6(dap)) {
command_print(CMD, "Option \"root\" not allowed with ADIv5 DAP");
return ERROR_COMMAND_ARGUMENT_INVALID;
}
int retval = adiv6_dap_read_baseptr(CMD, dap, &apsel);
if (retval != ERROR_OK) {
command_print(CMD, "Failed reading DAP baseptr");
return retval;
}
break;
}
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], apsel);
if (!is_ap_num_valid(dap, apsel)) {
command_print(CMD, "Invalid AP number");
@ -2595,9 +2633,9 @@ const struct command_registration dap_instance_commands[] = {
.name = "info",
.handler = handle_dap_info_command,
.mode = COMMAND_EXEC,
.help = "display ROM table for MEM-AP "
"(default currently selected AP)",
.usage = "[ap_num]",
.help = "display ROM table for specified MEM-AP (default currently selected AP) "
"or the ADIv6 root ROM table",
.usage = "[ap_num | 'root']",
},
{
.name = "apsel",

View File

@ -86,6 +86,9 @@
#define DP_DPIDR1_ASIZE_MASK (0x7F)
#define DP_DPIDR1_ERRMODE BIT(7)
/* Fields of register DP_BASEPTR0 */
#define DP_BASEPTR0_VALID BIT(0)
/* Fields of the DP's CTRL/STAT register */
#define CORUNDETECT (1UL << 0)
#define SSTICKYORUN (1UL << 1)
@ -692,6 +695,9 @@ int mem_ap_init(struct adiv5_ap *ap);
/* Invalidate cached DP select and cached TAR and CSW of all APs */
void dap_invalidate_cache(struct adiv5_dap *dap);
/* read ADIv6 baseptr register */
int adiv6_dap_read_baseptr(struct command_invocation *cmd, struct adiv5_dap *dap, target_addr_t *baseptr);
/* test if ap_num is valid, based on current knowledge of dap */
bool is_ap_num_valid(struct adiv5_dap *dap, uint64_t ap_num);

View File

@ -471,6 +471,18 @@ COMMAND_HANDLER(handle_dap_info_command)
apsel = dap->apsel;
break;
case 1:
if (!strcmp(CMD_ARGV[0], "root")) {
if (!is_adiv6(dap)) {
command_print(CMD, "Option \"root\" not allowed with ADIv5 DAP");
return ERROR_COMMAND_ARGUMENT_INVALID;
}
int retval = adiv6_dap_read_baseptr(CMD, dap, &apsel);
if (retval != ERROR_OK) {
command_print(CMD, "Failed reading DAP baseptr");
return retval;
}
break;
}
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], apsel);
if (!is_ap_num_valid(dap, apsel))
return ERROR_COMMAND_SYNTAX_ERROR;
@ -515,9 +527,9 @@ static const struct command_registration dap_subcommand_handlers[] = {
.name = "info",
.handler = handle_dap_info_command,
.mode = COMMAND_EXEC,
.help = "display ROM table for MEM-AP of current target "
"(default currently selected AP)",
.usage = "[ap_num]",
.help = "display ROM table for specified MEM-AP (default MEM-AP of current target) "
"or the ADIv6 root ROM table of current target's DAP",
.usage = "[ap_num | 'root']",
},
COMMAND_REGISTRATION_DONE
};