arm7_9: Avoid infinite loops in bulk write dispatching
Add a mandatory field in struct arm7_9_common for regular, non-optimized memory writes. Together with the existing bulk_memory_write field, this allows variants to select any combination of implementations for regular and bulk writes, without risking infinite loops from accidentally using bulk writes for implementing bulk writes. ARM 7/9 targets may now select arm7_9_memory_write_opt as their target.write_memory implementation, which will dispatch to arm7_9_common.bulk_write_memory if possible, or fallback to arm7_9_common.write_memory otherwise. To avoid loops, bulk write implementations mustn't call any other functions than arm7_9_write_memory_no_opt() to write memory; it will unconditionally call arm7_9_common.write_memory. If they fail, they should simply return error to allow the caller to fallback to regular writes. Tested on a regular ARM7TDMI only. Change-Id: Iae42a6e093e2df68c4823c927d757ae8f42ef388 Signed-off-by: Andreas Fritiofson <andreas.fritiofson@gmail.com> Reviewed-on: http://openocd.zylin.com/1685 Tested-by: jenkins Reviewed-by: Sergey A. Borshch <sb-sf@users.sourceforge.net> Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
This commit is contained in:
committed by
Spencer Oliver
parent
8e6e7948de
commit
ff5ec942d8
@@ -2476,11 +2476,28 @@ int arm7_9_write_memory_opt(struct target *target,
|
||||
const uint8_t *buffer)
|
||||
{
|
||||
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
||||
int retval;
|
||||
|
||||
if (size == 4 && count > 32 && arm7_9->bulk_write_memory)
|
||||
return arm7_9->bulk_write_memory(target, address, count, buffer);
|
||||
else
|
||||
return arm7_9_write_memory(target, address, size, count, buffer);
|
||||
if (size == 4 && count > 32 && arm7_9->bulk_write_memory) {
|
||||
/* Attempt to do a bulk write */
|
||||
retval = arm7_9->bulk_write_memory(target, address, count, buffer);
|
||||
|
||||
if (retval == ERROR_OK)
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
return arm7_9->write_memory(target, address, size, count, buffer);
|
||||
}
|
||||
|
||||
int arm7_9_write_memory_no_opt(struct target *target,
|
||||
uint32_t address,
|
||||
uint32_t size,
|
||||
uint32_t count,
|
||||
const uint8_t *buffer)
|
||||
{
|
||||
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
||||
|
||||
return arm7_9->write_memory(target, address, size, count, buffer);
|
||||
}
|
||||
|
||||
static int dcc_count;
|
||||
@@ -2561,8 +2578,11 @@ int arm7_9_bulk_write_memory(struct target *target,
|
||||
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
||||
int i;
|
||||
|
||||
if (address % 4 != 0)
|
||||
return ERROR_TARGET_UNALIGNED_ACCESS;
|
||||
|
||||
if (!arm7_9->dcc_downloads)
|
||||
return target_write_memory(target, address, 4, count, buffer);
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
|
||||
/* regrab previously allocated working_area, or allocate a new one */
|
||||
if (!arm7_9->dcc_working_area) {
|
||||
@@ -2571,15 +2591,16 @@ int arm7_9_bulk_write_memory(struct target *target,
|
||||
/* make sure we have a working area */
|
||||
if (target_alloc_working_area(target, 24, &arm7_9->dcc_working_area) != ERROR_OK) {
|
||||
LOG_INFO("no working area available, falling back to memory writes");
|
||||
return target_write_memory(target, address, 4, count, buffer);
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
/* copy target instructions to target endianness */
|
||||
for (i = 0; i < 6; i++)
|
||||
target_buffer_set_u32(target, dcc_code_buf + i*4, dcc_code[i]);
|
||||
|
||||
/* write DCC code to working area */
|
||||
retval = target_write_memory(target,
|
||||
/* write DCC code to working area, using the non-optimized
|
||||
* memory write to avoid ending up here again */
|
||||
retval = arm7_9_write_memory_no_opt(target,
|
||||
arm7_9->dcc_working_area->address, 4, 6, dcc_code_buf);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
Reference in New Issue
Block a user