Added target_read/write_phys_memory() fn's. mdX/mwX commands updated to support phys flag to specify bypassing of MMU.
This commit is contained in:
parent
818cedaff3
commit
2783cba810
|
@ -4938,23 +4938,27 @@ Please use their TARGET object siblings to avoid making assumptions
|
||||||
about what TAP is the current target, or about MMU configuration.
|
about what TAP is the current target, or about MMU configuration.
|
||||||
@end enumerate
|
@end enumerate
|
||||||
|
|
||||||
@deffn Command mdw addr [count]
|
@deffn Command mdw [phys] addr [count]
|
||||||
@deffnx Command mdh addr [count]
|
@deffnx Command mdh [phys] addr [count]
|
||||||
@deffnx Command mdb addr [count]
|
@deffnx Command mdb [phys] addr [count]
|
||||||
Display contents of address @var{addr}, as
|
Display contents of address @var{addr}, as
|
||||||
32-bit words (@command{mdw}), 16-bit halfwords (@command{mdh}),
|
32-bit words (@command{mdw}), 16-bit halfwords (@command{mdh}),
|
||||||
or 8-bit bytes (@command{mdb}).
|
or 8-bit bytes (@command{mdb}).
|
||||||
If @var{count} is specified, displays that many units.
|
If @var{count} is specified, displays that many units.
|
||||||
|
@var{phys} is an optional flag to indicate to use
|
||||||
|
physical address and bypass MMU
|
||||||
(If you want to manipulate the data instead of displaying it,
|
(If you want to manipulate the data instead of displaying it,
|
||||||
see the @code{mem2array} primitives.)
|
see the @code{mem2array} primitives.)
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn Command mww addr word
|
@deffn Command mww [phys] addr word
|
||||||
@deffnx Command mwh addr halfword
|
@deffnx Command mwh [phys] addr halfword
|
||||||
@deffnx Command mwb addr byte
|
@deffnx Command mwb [phys] addr byte
|
||||||
Writes the specified @var{word} (32 bits),
|
Writes the specified @var{word} (32 bits),
|
||||||
@var{halfword} (16 bits), or @var{byte} (8-bit) pattern,
|
@var{halfword} (16 bits), or @var{byte} (8-bit) pattern,
|
||||||
at the specified address @var{addr}.
|
at the specified address @var{addr}.
|
||||||
|
@var{phys} is an optional flag to indicate to use
|
||||||
|
physical address and bypass MMU
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -601,11 +601,24 @@ int target_read_memory(struct target_s *target,
|
||||||
return target->type->read_memory(target, address, size, count, buffer);
|
return target->type->read_memory(target, address, size, count, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int target_read_phys_memory(struct target_s *target,
|
||||||
|
uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
|
||||||
|
{
|
||||||
|
return target->type->read_phys_memory(target, address, size, count, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
int target_write_memory(struct target_s *target,
|
int target_write_memory(struct target_s *target,
|
||||||
uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
|
uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
|
||||||
{
|
{
|
||||||
return target->type->write_memory(target, address, size, count, buffer);
|
return target->type->write_memory(target, address, size, count, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int target_write_phys_memory(struct target_s *target,
|
||||||
|
uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
|
||||||
|
{
|
||||||
|
return target->type->write_phys_memory(target, address, size, count, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
int target_bulk_write_memory(struct target_s *target,
|
int target_bulk_write_memory(struct target_s *target,
|
||||||
uint32_t address, uint32_t count, uint8_t *buffer)
|
uint32_t address, uint32_t count, uint8_t *buffer)
|
||||||
{
|
{
|
||||||
|
@ -698,6 +711,17 @@ int target_init(struct command_context_s *cmd_ctx)
|
||||||
{
|
{
|
||||||
target->type->virt2phys = default_virt2phys;
|
target->type->virt2phys = default_virt2phys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (target->type->read_phys_memory == NULL)
|
||||||
|
{
|
||||||
|
target->type->read_phys_memory = target->type->read_memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target->type->write_phys_memory == NULL)
|
||||||
|
{
|
||||||
|
target->type->write_phys_memory = target->type->write_memory;
|
||||||
|
}
|
||||||
|
|
||||||
/* a non-invasive way(in terms of patches) to add some code that
|
/* a non-invasive way(in terms of patches) to add some code that
|
||||||
* runs before the type->write/read_memory implementation
|
* runs before the type->write/read_memory implementation
|
||||||
*/
|
*/
|
||||||
|
@ -1531,13 +1555,13 @@ int target_register_user_commands(struct command_context_s *cmd_ctx)
|
||||||
register_command(cmd_ctx, NULL, "reset", handle_reset_command, COMMAND_EXEC, "reset target [run | halt | init] - default is run");
|
register_command(cmd_ctx, NULL, "reset", handle_reset_command, COMMAND_EXEC, "reset target [run | halt | init] - default is run");
|
||||||
register_command(cmd_ctx, NULL, "soft_reset_halt", handle_soft_reset_halt_command, COMMAND_EXEC, "halt the target and do a soft reset");
|
register_command(cmd_ctx, NULL, "soft_reset_halt", handle_soft_reset_halt_command, COMMAND_EXEC, "halt the target and do a soft reset");
|
||||||
|
|
||||||
register_command(cmd_ctx, NULL, "mdw", handle_md_command, COMMAND_EXEC, "display memory words <addr> [count]");
|
register_command(cmd_ctx, NULL, "mdw", handle_md_command, COMMAND_EXEC, "display memory words [phys] <addr> [count]");
|
||||||
register_command(cmd_ctx, NULL, "mdh", handle_md_command, COMMAND_EXEC, "display memory half-words <addr> [count]");
|
register_command(cmd_ctx, NULL, "mdh", handle_md_command, COMMAND_EXEC, "display memory half-words [phys] <addr> [count]");
|
||||||
register_command(cmd_ctx, NULL, "mdb", handle_md_command, COMMAND_EXEC, "display memory bytes <addr> [count]");
|
register_command(cmd_ctx, NULL, "mdb", handle_md_command, COMMAND_EXEC, "display memory bytes [phys] <addr> [count]");
|
||||||
|
|
||||||
register_command(cmd_ctx, NULL, "mww", handle_mw_command, COMMAND_EXEC, "write memory word <addr> <value> [count]");
|
register_command(cmd_ctx, NULL, "mww", handle_mw_command, COMMAND_EXEC, "write memory word [phys] <addr> <value> [count]");
|
||||||
register_command(cmd_ctx, NULL, "mwh", handle_mw_command, COMMAND_EXEC, "write memory half-word <addr> <value> [count]");
|
register_command(cmd_ctx, NULL, "mwh", handle_mw_command, COMMAND_EXEC, "write memory half-word [phys] <addr> <value> [count]");
|
||||||
register_command(cmd_ctx, NULL, "mwb", handle_mw_command, COMMAND_EXEC, "write memory byte <addr> <value> [count]");
|
register_command(cmd_ctx, NULL, "mwb", handle_mw_command, COMMAND_EXEC, "write memory byte [phys] <addr> <value> [count]");
|
||||||
|
|
||||||
register_command(cmd_ctx, NULL, "bp",
|
register_command(cmd_ctx, NULL, "bp",
|
||||||
handle_bp_command, COMMAND_EXEC,
|
handle_bp_command, COMMAND_EXEC,
|
||||||
|
@ -2183,6 +2207,22 @@ static int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char
|
||||||
default: return ERROR_COMMAND_SYNTAX_ERROR;
|
default: return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool physical=strcmp(args[0], "phys")==0;
|
||||||
|
int (*fn)(struct target_s *target,
|
||||||
|
uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
|
||||||
|
if (physical)
|
||||||
|
{
|
||||||
|
argc--;
|
||||||
|
args++;
|
||||||
|
fn=target_read_phys_memory;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
fn=target_read_memory;
|
||||||
|
}
|
||||||
|
if ((argc < 1) || (argc > 2))
|
||||||
|
{
|
||||||
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
}
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
int retval = parse_u32(args[0], &address);
|
int retval = parse_u32(args[0], &address);
|
||||||
if (ERROR_OK != retval)
|
if (ERROR_OK != retval)
|
||||||
|
@ -2199,8 +2239,7 @@ static int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char
|
||||||
uint8_t *buffer = calloc(count, size);
|
uint8_t *buffer = calloc(count, size);
|
||||||
|
|
||||||
target_t *target = get_current_target(cmd_ctx);
|
target_t *target = get_current_target(cmd_ctx);
|
||||||
retval = target_read_memory(target,
|
retval = fn(target, address, size, count, buffer);
|
||||||
address, size, count, buffer);
|
|
||||||
if (ERROR_OK == retval)
|
if (ERROR_OK == retval)
|
||||||
handle_md_output(cmd_ctx, target, address, size, count, buffer);
|
handle_md_output(cmd_ctx, target, address, size, count, buffer);
|
||||||
|
|
||||||
|
@ -2211,7 +2250,23 @@ static int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char
|
||||||
|
|
||||||
static int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
static int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
|
||||||
{
|
{
|
||||||
if ((argc < 2) || (argc > 3))
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
}
|
||||||
|
bool physical=strcmp(args[0], "phys")==0;
|
||||||
|
int (*fn)(struct target_s *target,
|
||||||
|
uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
|
||||||
|
if (physical)
|
||||||
|
{
|
||||||
|
argc--;
|
||||||
|
args++;
|
||||||
|
fn=target_write_phys_memory;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
fn=target_write_memory;
|
||||||
|
}
|
||||||
|
if ((argc < 2) || (argc > 3))
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
uint32_t address;
|
uint32_t address;
|
||||||
|
@ -2254,7 +2309,7 @@ static int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char
|
||||||
}
|
}
|
||||||
for (unsigned i = 0; i < count; i++)
|
for (unsigned i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
retval = target_write_memory(target,
|
retval = fn(target,
|
||||||
address + i * wordsize, wordsize, 1, value_buf);
|
address + i * wordsize, wordsize, 1, value_buf);
|
||||||
if (ERROR_OK != retval)
|
if (ERROR_OK != retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
@ -180,7 +180,26 @@ struct target_type_s
|
||||||
int (*init_target)(struct command_context_s *cmd_ctx, struct target_s *target);
|
int (*init_target)(struct command_context_s *cmd_ctx, struct target_s *target);
|
||||||
int (*quit)(void);
|
int (*quit)(void);
|
||||||
|
|
||||||
|
/* translate from virtual to physical address. Default implementation is successful
|
||||||
|
* no-op(i.e. virtual==physical).
|
||||||
|
*/
|
||||||
int (*virt2phys)(struct target_s *target, uint32_t address, uint32_t *physical);
|
int (*virt2phys)(struct target_s *target, uint32_t address, uint32_t *physical);
|
||||||
|
|
||||||
|
/* read directly from physical memory. caches are bypassed and untouched.
|
||||||
|
*
|
||||||
|
* If the target does not support disabling caches, leaving them untouched,
|
||||||
|
* then minimally the actual physical memory location will be read even
|
||||||
|
* if cache states are unchanged, flushed, etc.
|
||||||
|
*
|
||||||
|
* Default implementation is to call read_memory.
|
||||||
|
*/
|
||||||
|
int (*read_phys_memory)(struct target_s *target, uint32_t phys_address, uint32_t size, uint32_t count, uint8_t *buffer);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* same as read_phys_memory, except that it writes...
|
||||||
|
*/
|
||||||
|
int (*write_phys_memory)(struct target_s *target, uint32_t phys_address, uint32_t size, uint32_t count, uint8_t *buffer);
|
||||||
|
|
||||||
int (*mmu)(struct target_s *target, int *enabled);
|
int (*mmu)(struct target_s *target, int *enabled);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue