ARM: memory utils aren't ARM7/ARM9 dependent

The arm7_9_checksum_memory() and arm7_9_blank_check_memory()
routines are not actually specific to the ARM7 and ARM9 core
generations ... they can work for any core which can run
algorithms using basic ARM (not Thumb) instructions.

Rename them; move the declarations to a more generic site;
likewise move the code (and tidy it a bit in the process).

NOTE:  the blank_check() method falsely returned a success
status (0) on one error path, when the algorithm failed.
Fixed this bug.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
This commit is contained in:
David Brownell 2009-11-15 10:35:34 -08:00
parent 9ac7cdec82
commit 269040bbad
15 changed files with 209 additions and 178 deletions

View File

@ -535,8 +535,9 @@ struct target_type arm720t_target =
.virt2phys = arm720_virt2phys,
.bulk_write_memory = arm7_9_bulk_write_memory,
.checksum_memory = arm7_9_checksum_memory,
.blank_check_memory = arm7_9_blank_check_memory,
.checksum_memory = arm_checksum_memory,
.blank_check_memory = arm_blank_check_memory,
.run_algorithm = armv4_5_run_algorithm,

View File

@ -2706,156 +2706,6 @@ int arm7_9_bulk_write_memory(struct target *target, uint32_t address, uint32_t c
return retval;
}
int arm7_9_checksum_memory(struct target *target, uint32_t address, uint32_t count, uint32_t* checksum)
{
struct working_area *crc_algorithm;
struct armv4_5_algorithm armv4_5_info;
struct reg_param reg_params[2];
int retval;
static const uint32_t arm7_9_crc_code[] = {
0xE1A02000, /* mov r2, r0 */
0xE3E00000, /* mov r0, #0xffffffff */
0xE1A03001, /* mov r3, r1 */
0xE3A04000, /* mov r4, #0 */
0xEA00000B, /* b ncomp */
/* nbyte: */
0xE7D21004, /* ldrb r1, [r2, r4] */
0xE59F7030, /* ldr r7, CRC32XOR */
0xE0200C01, /* eor r0, r0, r1, asl 24 */
0xE3A05000, /* mov r5, #0 */
/* loop: */
0xE3500000, /* cmp r0, #0 */
0xE1A06080, /* mov r6, r0, asl #1 */
0xE2855001, /* add r5, r5, #1 */
0xE1A00006, /* mov r0, r6 */
0xB0260007, /* eorlt r0, r6, r7 */
0xE3550008, /* cmp r5, #8 */
0x1AFFFFF8, /* bne loop */
0xE2844001, /* add r4, r4, #1 */
/* ncomp: */
0xE1540003, /* cmp r4, r3 */
0x1AFFFFF1, /* bne nbyte */
/* end: */
0xEAFFFFFE, /* b end */
0x04C11DB7 /* CRC32XOR: .word 0x04C11DB7 */
};
uint32_t i;
if (target_alloc_working_area(target, sizeof(arm7_9_crc_code), &crc_algorithm) != ERROR_OK)
{
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
/* convert flash writing code into a buffer in target endianness */
for (i = 0; i < (sizeof(arm7_9_crc_code)/sizeof(uint32_t)); i++)
{
if ((retval = target_write_u32(target, crc_algorithm->address + i*sizeof(uint32_t), arm7_9_crc_code[i])) != ERROR_OK)
{
return retval;
}
}
armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
armv4_5_info.core_state = ARMV4_5_STATE_ARM;
init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
buf_set_u32(reg_params[0].value, 0, 32, address);
buf_set_u32(reg_params[1].value, 0, 32, count);
/* 20 second timeout/megabyte */
int timeout = 20000 * (1 + (count / (1024*1024)));
if ((retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
crc_algorithm->address, crc_algorithm->address + (sizeof(arm7_9_crc_code) - 8), timeout, &armv4_5_info)) != ERROR_OK)
{
LOG_ERROR("error executing arm7_9 crc algorithm");
destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
target_free_working_area(target, crc_algorithm);
return retval;
}
*checksum = buf_get_u32(reg_params[0].value, 0, 32);
destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
target_free_working_area(target, crc_algorithm);
return ERROR_OK;
}
int arm7_9_blank_check_memory(struct target *target, uint32_t address, uint32_t count, uint32_t* blank)
{
struct working_area *erase_check_algorithm;
struct reg_param reg_params[3];
struct armv4_5_algorithm armv4_5_info;
int retval;
uint32_t i;
static const uint32_t erase_check_code[] =
{
/* loop: */
0xe4d03001, /* ldrb r3, [r0], #1 */
0xe0022003, /* and r2, r2, r3 */
0xe2511001, /* subs r1, r1, #1 */
0x1afffffb, /* bne loop */
/* end: */
0xeafffffe /* b end */
};
/* make sure we have a working area */
if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK)
{
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
/* convert flash writing code into a buffer in target endianness */
for (i = 0; i < (sizeof(erase_check_code)/sizeof(uint32_t)); i++)
if ((retval = target_write_u32(target, erase_check_algorithm->address + i*sizeof(uint32_t), erase_check_code[i])) != ERROR_OK)
{
return retval;
}
armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
armv4_5_info.core_state = ARMV4_5_STATE_ARM;
init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
buf_set_u32(reg_params[0].value, 0, 32, address);
init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
buf_set_u32(reg_params[1].value, 0, 32, count);
init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
buf_set_u32(reg_params[2].value, 0, 32, 0xff);
if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
erase_check_algorithm->address, erase_check_algorithm->address + (sizeof(erase_check_code) - 4), 10000, &armv4_5_info)) != ERROR_OK)
{
destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
destroy_reg_param(&reg_params[2]);
target_free_working_area(target, erase_check_algorithm);
return 0;
}
*blank = buf_get_u32(reg_params[2].value, 0, 32);
destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
destroy_reg_param(&reg_params[2]);
target_free_working_area(target, erase_check_algorithm);
return ERROR_OK;
}
/**
* Perform per-target setup that requires JTAG access.
*/

View File

@ -143,8 +143,6 @@ int arm7_9_read_core_reg(struct target *target, int num, enum armv4_5_mode mode)
int arm7_9_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
int arm7_9_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
int arm7_9_bulk_write_memory(struct target *target, uint32_t address, uint32_t count, uint8_t *buffer);
int arm7_9_checksum_memory(struct target *target, uint32_t address, uint32_t count, uint32_t* checksum);
int arm7_9_blank_check_memory(struct target *target, uint32_t address, uint32_t count, uint32_t* blank);
int arm7_9_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_prams, struct reg_param *reg_param, uint32_t entry_point, void *arch_info);

View File

@ -737,8 +737,9 @@ struct target_type arm7tdmi_target =
.read_memory = arm7_9_read_memory,
.write_memory = arm7_9_write_memory,
.bulk_write_memory = arm7_9_bulk_write_memory,
.checksum_memory = arm7_9_checksum_memory,
.blank_check_memory = arm7_9_blank_check_memory,
.checksum_memory = arm_checksum_memory,
.blank_check_memory = arm_blank_check_memory,
.run_algorithm = armv4_5_run_algorithm,

View File

@ -1407,8 +1407,9 @@ struct target_type arm920t_target =
.virt2phys = arm920_virt2phys,
.bulk_write_memory = arm7_9_bulk_write_memory,
.checksum_memory = arm7_9_checksum_memory,
.blank_check_memory = arm7_9_blank_check_memory,
.checksum_memory = arm_checksum_memory,
.blank_check_memory = arm_blank_check_memory,
.run_algorithm = armv4_5_run_algorithm,

View File

@ -864,8 +864,9 @@ struct target_type arm926ejs_target =
.read_memory = arm7_9_read_memory,
.write_memory = arm926ejs_write_memory,
.bulk_write_memory = arm7_9_bulk_write_memory,
.checksum_memory = arm7_9_checksum_memory,
.blank_check_memory = arm7_9_blank_check_memory,
.checksum_memory = arm_checksum_memory,
.blank_check_memory = arm_blank_check_memory,
.run_algorithm = armv4_5_run_algorithm,

View File

@ -261,8 +261,9 @@ struct target_type arm966e_target =
.read_memory = arm7_9_read_memory,
.write_memory = arm7_9_write_memory,
.bulk_write_memory = arm7_9_bulk_write_memory,
.checksum_memory = arm7_9_checksum_memory,
.blank_check_memory = arm7_9_blank_check_memory,
.checksum_memory = arm_checksum_memory,
.blank_check_memory = arm_blank_check_memory,
.run_algorithm = armv4_5_run_algorithm,

View File

@ -938,8 +938,9 @@ struct target_type arm9tdmi_target =
.read_memory = arm7_9_read_memory,
.write_memory = arm7_9_write_memory,
.bulk_write_memory = arm7_9_bulk_write_memory,
.checksum_memory = arm7_9_checksum_memory,
.blank_check_memory = arm7_9_blank_check_memory,
.checksum_memory = arm_checksum_memory,
.blank_check_memory = arm_blank_check_memory,
.run_algorithm = armv4_5_run_algorithm,

View File

@ -707,6 +707,176 @@ int armv4_5_run_algorithm(struct target *target, int num_mem_params, struct mem_
return armv4_5_run_algorithm_inner(target, num_mem_params, mem_params, num_reg_params, reg_params, entry_point, exit_point, timeout_ms, arch_info, armv4_5_run_algorithm_completion);
}
/**
* Runs ARM code in the target to calculate a CRC32 checksum.
*
* \todo On ARMv5+, rely on BKPT termination for reduced overhead.
*/
int arm_checksum_memory(struct target *target,
uint32_t address, uint32_t count, uint32_t *checksum)
{
struct working_area *crc_algorithm;
struct armv4_5_algorithm armv4_5_info;
struct reg_param reg_params[2];
int retval;
uint32_t i;
static const uint32_t arm_crc_code[] = {
0xE1A02000, /* mov r2, r0 */
0xE3E00000, /* mov r0, #0xffffffff */
0xE1A03001, /* mov r3, r1 */
0xE3A04000, /* mov r4, #0 */
0xEA00000B, /* b ncomp */
/* nbyte: */
0xE7D21004, /* ldrb r1, [r2, r4] */
0xE59F7030, /* ldr r7, CRC32XOR */
0xE0200C01, /* eor r0, r0, r1, asl 24 */
0xE3A05000, /* mov r5, #0 */
/* loop: */
0xE3500000, /* cmp r0, #0 */
0xE1A06080, /* mov r6, r0, asl #1 */
0xE2855001, /* add r5, r5, #1 */
0xE1A00006, /* mov r0, r6 */
0xB0260007, /* eorlt r0, r6, r7 */
0xE3550008, /* cmp r5, #8 */
0x1AFFFFF8, /* bne loop */
0xE2844001, /* add r4, r4, #1 */
/* ncomp: */
0xE1540003, /* cmp r4, r3 */
0x1AFFFFF1, /* bne nbyte */
/* end: */
0xEAFFFFFE, /* b end */
/* CRC32XOR: */
0x04C11DB7 /* .word 0x04C11DB7 */
};
retval = target_alloc_working_area(target,
sizeof(arm_crc_code), &crc_algorithm);
if (retval != ERROR_OK)
return retval;
/* convert code into a buffer in target endianness */
for (i = 0; i < DIM(arm_crc_code); i++) {
retval = target_write_u32(target,
crc_algorithm->address + i * sizeof(uint32_t),
arm_crc_code[i]);
if (retval != ERROR_OK)
return retval;
}
armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
armv4_5_info.core_state = ARMV4_5_STATE_ARM;
init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
buf_set_u32(reg_params[0].value, 0, 32, address);
buf_set_u32(reg_params[1].value, 0, 32, count);
/* 20 second timeout/megabyte */
int timeout = 20000 * (1 + (count / (1024 * 1024)));
retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
crc_algorithm->address,
crc_algorithm->address + sizeof(arm_crc_code) - 8,
timeout, &armv4_5_info);
if (retval != ERROR_OK) {
LOG_ERROR("error executing ARM crc algorithm");
destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
target_free_working_area(target, crc_algorithm);
return retval;
}
*checksum = buf_get_u32(reg_params[0].value, 0, 32);
destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
target_free_working_area(target, crc_algorithm);
return ERROR_OK;
}
/**
* Runs ARM code in the target to check whether a memory block holds
* all ones. NOR flash which has been erased, and thus may be written,
* holds all ones.
*
* \todo On ARMv5+, rely on BKPT termination for reduced overhead.
*/
int arm_blank_check_memory(struct target *target,
uint32_t address, uint32_t count, uint32_t *blank)
{
struct working_area *check_algorithm;
struct reg_param reg_params[3];
struct armv4_5_algorithm armv4_5_info;
int retval;
uint32_t i;
static const uint32_t check_code[] = {
/* loop: */
0xe4d03001, /* ldrb r3, [r0], #1 */
0xe0022003, /* and r2, r2, r3 */
0xe2511001, /* subs r1, r1, #1 */
0x1afffffb, /* bne loop */
/* end: */
0xeafffffe /* b end */
};
/* make sure we have a working area */
retval = target_alloc_working_area(target,
sizeof(check_code), &check_algorithm);
if (retval != ERROR_OK)
return retval;
/* convert code into a buffer in target endianness */
for (i = 0; i < DIM(check_code); i++) {
retval = target_write_u32(target,
check_algorithm->address
+ i * sizeof(uint32_t),
check_code[i]);
if (retval != ERROR_OK)
return retval;
}
armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
armv4_5_info.core_state = ARMV4_5_STATE_ARM;
init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
buf_set_u32(reg_params[0].value, 0, 32, address);
init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
buf_set_u32(reg_params[1].value, 0, 32, count);
init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
buf_set_u32(reg_params[2].value, 0, 32, 0xff);
retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
check_algorithm->address,
check_algorithm->address + sizeof(check_code) - 4,
10000, &armv4_5_info);
if (retval != ERROR_OK) {
destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
destroy_reg_param(&reg_params[2]);
target_free_working_area(target, check_algorithm);
return retval;
}
*blank = buf_get_u32(reg_params[2].value, 0, 32);
destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
destroy_reg_param(&reg_params[2]);
target_free_working_area(target, check_algorithm);
return ERROR_OK;
}
int armv4_5_init_arch_info(struct target *target, struct arm *armv4_5)
{
target->arch_info = armv4_5;

View File

@ -190,6 +190,12 @@ int armv4_5_run_algorithm(struct target *target,
int armv4_5_invalidate_core_regs(struct target *target);
int arm_checksum_memory(struct target *target,
uint32_t address, uint32_t count, uint32_t *checksum);
int arm_blank_check_memory(struct target *target,
uint32_t address, uint32_t count, uint32_t *blank);
/* ARM mode instructions
*/
@ -369,7 +375,4 @@ static inline uint32_t mrc_opcode(int cpnum, uint32_t op1, uint32_t op2, uint32_
return t;
}
#endif /* ARMV4_5_H */

View File

@ -1590,8 +1590,9 @@ struct target_type cortexa8_target = {
.read_memory = cortex_a8_read_memory,
.write_memory = cortex_a8_write_memory,
.bulk_write_memory = cortex_a8_bulk_write_memory,
.checksum_memory = arm7_9_checksum_memory,
.blank_check_memory = arm7_9_blank_check_memory,
.checksum_memory = arm_checksum_memory,
.blank_check_memory = arm_blank_check_memory,
.run_algorithm = armv4_5_run_algorithm,

View File

@ -32,7 +32,6 @@
#include "register.h"
#include "target.h"
#include "armv7a.h"
#include "arm7_9_common.h"
extern char* cortex_a8_state_strings[];

View File

@ -380,8 +380,9 @@ struct target_type fa526_target =
.read_memory = arm920t_read_memory,
.write_memory = arm920t_write_memory,
.bulk_write_memory = arm7_9_bulk_write_memory,
.checksum_memory = arm7_9_checksum_memory,
.blank_check_memory = arm7_9_blank_check_memory,
.checksum_memory = arm_checksum_memory,
.blank_check_memory = arm_blank_check_memory,
.run_algorithm = armv4_5_run_algorithm,

View File

@ -696,8 +696,9 @@ struct target_type feroceon_target =
.read_memory = arm7_9_read_memory,
.write_memory = arm926ejs_write_memory,
.bulk_write_memory = feroceon_bulk_write_memory,
.checksum_memory = arm7_9_checksum_memory,
.blank_check_memory = arm7_9_blank_check_memory,
.checksum_memory = arm_checksum_memory,
.blank_check_memory = arm_blank_check_memory,
.run_algorithm = armv4_5_run_algorithm,
@ -734,8 +735,9 @@ struct target_type dragonite_target =
.read_memory = arm7_9_read_memory,
.write_memory = arm7_9_write_memory,
.bulk_write_memory = feroceon_bulk_write_memory,
.checksum_memory = arm7_9_checksum_memory,
.blank_check_memory = arm7_9_blank_check_memory,
.checksum_memory = arm_checksum_memory,
.blank_check_memory = arm_blank_check_memory,
.run_algorithm = armv4_5_run_algorithm,

View File

@ -3626,8 +3626,9 @@ struct target_type xscale_target =
.read_memory = xscale_read_memory,
.write_memory = xscale_write_memory,
.bulk_write_memory = xscale_bulk_write_memory,
.checksum_memory = arm7_9_checksum_memory,
.blank_check_memory = arm7_9_blank_check_memory,
.checksum_memory = arm_checksum_memory,
.blank_check_memory = arm_blank_check_memory,
.run_algorithm = armv4_5_run_algorithm,