diff options
author | Andreas Fritiofson <andreas.fritiofson@gmail.com> | 2013-10-05 00:19:08 +0200 |
---|---|---|
committer | Spencer Oliver <spen@spen-soft.co.uk> | 2013-10-15 20:41:08 +0000 |
commit | ff5ec942d80a34e20b5a3ca3328f7e6a55fb309b (patch) | |
tree | 1d5682ae57f84d16f136b27ee75a6158790fca3f /src/target/feroceon.c | |
parent | 8e6e7948de11e69fa53e7b7f306d35d6d4904b14 (diff) |
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>
Diffstat (limited to 'src/target/feroceon.c')
-rw-r--r-- | src/target/feroceon.c | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/src/target/feroceon.c b/src/target/feroceon.c index d3037c54..acaa1b3b 100644 --- a/src/target/feroceon.c +++ b/src/target/feroceon.c @@ -493,8 +493,11 @@ static int feroceon_bulk_write_memory(struct target *target, uint32_t dcc_size = sizeof(dcc_code); + 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) { @@ -503,15 +506,16 @@ static int feroceon_bulk_write_memory(struct target *target, /* make sure we have a working area */ if (target_alloc_working_area(target, dcc_size, &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 < dcc_size/4; 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, dcc_size/4, dcc_code_buf); if (retval != ERROR_OK) return retval; @@ -627,6 +631,10 @@ static int feroceon_target_create(struct target *target, Jim_Interp *interp) arm926ejs_init_arch_info(target, arm926ejs, target->tap); feroceon_common_setup(target); + struct arm *arm = target->arch_info; + struct arm7_9_common *arm7_9 = arm->arch_info; + arm7_9->write_memory = arm926ejs_write_memory; + /* the standard ARM926 methods don't always work (don't ask...) */ arm926ejs->read_cp15 = feroceon_read_cp15; arm926ejs->write_cp15 = feroceon_write_cp15; @@ -641,6 +649,10 @@ static int dragonite_target_create(struct target *target, Jim_Interp *interp) arm966e_init_arch_info(target, arm966e, target->tap); feroceon_common_setup(target); + struct arm *arm = target->arch_info; + struct arm7_9_common *arm7_9 = arm->arch_info; + arm7_9->write_memory = arm7_9_write_memory; + return ERROR_OK; } @@ -697,7 +709,7 @@ struct target_type feroceon_target = { .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm7_9_read_memory, - .write_memory = arm926ejs_write_memory_opt, + .write_memory = arm7_9_write_memory_opt, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, |