- add verify_image command

- add support for gdb qCRC packet (compare-sections command)

git-svn-id: svn://svn.berlios.de/openocd/trunk@210 b42882b7-edfa-0310-969c-e2dbd0fdcd60
This commit is contained in:
ntfreak 2007-10-22 08:44:34 +00:00
parent ce8768f463
commit e27696f6b0
18 changed files with 392 additions and 11 deletions

View File

@ -1167,7 +1167,7 @@ int gdb_breakpoint_watchpoint_packet(connection_t *connection, target_t *target,
return ERROR_OK;
}
void gdb_query_packet(connection_t *connection, char *packet, int packet_size)
int gdb_query_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
{
command_context_t *cmd_ctx = connection->cmd_ctx;
@ -1189,10 +1189,52 @@ void gdb_query_packet(connection_t *connection, char *packet, int packet_size)
free(cmd);
}
gdb_put_packet(connection, "OK", 2);
return;
return ERROR_OK;
}
if (strstr(packet, "qCRC:"))
{
if (packet_size > 5)
{
int retval;
u8 gdb_reply[9];
char *separator;
u32 checksum;
u32 addr = 0;
u32 len = 0;
/* skip command character */
packet += 5;
addr = strtoul(packet, &separator, 16);
if (*separator != ',')
{
ERROR("incomplete read memory packet received, dropping connection");
return ERROR_SERVER_REMOTE_CLOSED;
}
len = strtoul(separator+1, NULL, 16);
retval = target_checksum_memory(target, addr, len, &checksum);
if (retval == ERROR_OK)
{
snprintf(gdb_reply, 9, "C%2.2x", checksum);
gdb_put_packet(connection, gdb_reply, 9);
}
else
{
if ((retval = gdb_memory_packet_error(connection, retval)) != ERROR_OK)
return retval;
}
return ERROR_OK;
}
}
gdb_put_packet(connection, "", 0);
return ERROR_OK;
}
int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
@ -1382,7 +1424,7 @@ int gdb_input(connection_t *connection)
gdb_put_packet(connection, NULL, 0);
break;
case 'q':
gdb_query_packet(connection, packet, packet_size);
retval = gdb_query_packet(connection, target, packet, packet_size);
break;
case 'g':
retval = gdb_get_registers_packet(connection, target, packet, packet_size);

View File

@ -70,7 +70,8 @@ target_type_t arm720t_target =
.read_memory = arm720t_read_memory,
.write_memory = arm720t_write_memory,
.bulk_write_memory = arm7_9_bulk_write_memory,
.checksum_memory = arm7_9_checksum_memory,
.run_algorithm = armv4_5_run_algorithm,
.add_breakpoint = arm7_9_add_breakpoint,

View File

@ -2147,6 +2147,82 @@ int arm7_9_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffe
return ERROR_OK;
}
int arm7_9_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum)
{
working_area_t *crc_algorithm;
armv4_5_algorithm_t armv4_5_info;
reg_param_t reg_params[2];
int retval;
u32 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 */
};
int 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(u32)); i++)
target_write_u32(target, crc_algorithm->address + i*sizeof(u32), arm7_9_crc_code[i]);
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);
if ((retval = target->type->run_algorithm(target, 0, NULL, 2, reg_params,
crc_algorithm->address, crc_algorithm->address + (sizeof(arm7_9_crc_code) - 8), 20000, &armv4_5_info)) != ERROR_OK)
{
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_register_commands(struct command_context_s *cmd_ctx)
{
command_t *arm7_9_cmd;

View File

@ -121,6 +121,7 @@ int arm7_9_read_core_reg(struct target_s *target, int num, enum armv4_5_mode mod
int arm7_9_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
int arm7_9_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
int arm7_9_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer);
int arm7_9_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum);
int arm7_9_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_prams, reg_param_t *reg_param, u32 entry_point, void *arch_info);

View File

@ -75,7 +75,8 @@ target_type_t 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,
.run_algorithm = armv4_5_run_algorithm,
.add_breakpoint = arm7_9_add_breakpoint,

View File

@ -79,7 +79,8 @@ target_type_t arm920t_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,
.run_algorithm = armv4_5_run_algorithm,
.add_breakpoint = arm7_9_add_breakpoint,

View File

@ -79,7 +79,8 @@ target_type_t 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,
.run_algorithm = armv4_5_run_algorithm,
.add_breakpoint = arm7_9_add_breakpoint,

View File

@ -70,7 +70,8 @@ target_type_t 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,
.run_algorithm = armv4_5_run_algorithm,
.add_breakpoint = arm7_9_add_breakpoint,

View File

@ -73,7 +73,8 @@ target_type_t 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,
.run_algorithm = armv4_5_run_algorithm,
.add_breakpoint = arm7_9_add_breakpoint,

View File

@ -578,3 +578,83 @@ int armv7m_register_commands(struct command_context_s *cmd_ctx)
{
return ERROR_OK;
}
int armv7m_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum)
{
working_area_t *crc_algorithm;
armv7m_algorithm_t armv7m_info;
reg_param_t reg_params[2];
int retval;
u16 cortex_m3_crc_code[] = {
0x4602, /* mov r2, r0 */
0xF04F, 0x30FF, /* mov r0, #0xffffffff */
0x460B, /* mov r3, r1 */
0xF04F, 0x0400, /* mov r4, #0 */
0xE013, /* b ncomp */
/* nbyte: */
0x5D11, /* ldrb r1, [r2, r4] */
0xF8DF, 0x7028, /* ldr r7, CRC32XOR */
0xEA80, 0x6001, /* eor r0, r0, r1, asl #24 */
0xF04F, 0x0500, /* mov r5, #0 */
/* loop: */
0x2800, /* cmp r0, #0 */
0xEA4F, 0x0640, /* mov r6, r0, asl #1 */
0xF105, 0x0501, /* add r5, r5, #1 */
0x4630, /* mov r0, r6 */
0xBFB8, /* it lt */
0xEA86, 0x0007, /* eor r0, r6, r7 */
0x2D08, /* cmp r5, #8 */
0xD1F4, /* bne loop */
0xF104, 0x0401, /* add r4, r4, #1 */
/* ncomp: */
0x429C, /* cmp r4, r3 */
0xD1E9, /* bne nbyte */
/* end: */
0xE7FE, /* b end */
0x1DB7, 0x04C1 /* CRC32XOR: .word 0x04C11DB7 */
};
int i;
if (target_alloc_working_area(target, sizeof(cortex_m3_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(cortex_m3_crc_code)/sizeof(u16)); i++)
target_write_u16(target, crc_algorithm->address + i*sizeof(u16), cortex_m3_crc_code[i]);
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
armv7m_info.core_mode = ARMV7M_MODE_ANY;
armv7m_info.core_state = ARMV7M_STATE_THUMB;
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);
if ((retval = target->type->run_algorithm(target, 0, NULL, 2, reg_params,
crc_algorithm->address, crc_algorithm->address + (sizeof(cortex_m3_crc_code)-6), 20000, &armv7m_info)) != ERROR_OK)
{
ERROR("error executing cortex_m3 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;
}

View File

@ -168,6 +168,8 @@ extern int armv7m_use_context(target_t *target, enum armv7m_runcontext new_ctx);
extern enum armv7m_runcontext armv7m_get_context(target_t *target);
extern int armv7m_restore_context(target_t *target);
extern int armv7m_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum);
/* Thumb mode instructions
*/

View File

@ -74,7 +74,8 @@ target_type_t cortexm3_target =
.read_memory = cortex_m3_read_memory,
.write_memory = cortex_m3_write_memory,
.bulk_write_memory = cortex_m3_bulk_write_memory,
.checksum_memory = armv7m_checksum_memory,
.run_algorithm = armv7m_run_algorithm,
.add_breakpoint = cortex_m3_add_breakpoint,

View File

@ -949,3 +949,34 @@ int image_close(image_t *image)
return ERROR_OK;
}
static u32 crc32_table[256] = {0, 0};
int image_calculate_checksum(u8* buffer, u32 nbytes, u32* checksum)
{
u32 crc = 0xffffffff;
if (!crc32_table[1])
{
/* Initialize the CRC table and the decoding table. */
int i, j;
unsigned int c;
for (i = 0; i < 256; i++)
{
/* as per gdb */
for (c = i << 24, j = 8; j > 0; --j)
c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
crc32_table[i] = c;
}
}
while (nbytes--)
{
/* as per gdb */
crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buffer++) & 255];
}
*checksum = crc;
return ERROR_OK;
}

View File

@ -105,6 +105,8 @@ extern int image_read_section(image_t *image, int section, u32 offset, u32 size,
extern int image_close(image_t *image);
extern int image_add_section(image_t *image, u32 base, u32 size, int flags, u8 *data);
extern int image_calculate_checksum(u8* buffer, u32 nbytes, u32* checksum);
#define ERROR_IMAGE_FORMAT_ERROR (-1400)
#define ERROR_IMAGE_TYPE_UNKNOWN (-1401)
#define ERROR_IMAGE_TEMPORARILY_UNAVAILABLE (-1402)

View File

@ -69,6 +69,7 @@ int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args,
int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
@ -752,6 +753,36 @@ int target_read_buffer(struct target_s *target, u32 address, u32 size, u8 *buffe
return ERROR_OK;
}
int target_checksum_memory(struct target_s *target, u32 address, u32 size, u32* crc)
{
u8 *buffer;
int retval;
int i;
u32 checksum = 0;
if ((retval = target->type->checksum_memory(target, address,
size, &checksum)) == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
{
buffer = malloc(size);
target_read_buffer(target, address, size, buffer);
/* convert to target endianess */
for (i = 0; i < (size/sizeof(u32)); i++)
{
u32 target_data;
target_data = target_buffer_get_u32(target, &buffer[i*sizeof(u32)]);
target_buffer_set_u32(target, &buffer[i*sizeof(u32)], target_data);
}
retval = image_calculate_checksum( buffer, size, &checksum );
free(buffer);
}
*crc = checksum;
return retval;
}
int target_read_u32(struct target_s *target, u32 address, u32 *value)
{
u8 value_buf[4];
@ -881,6 +912,7 @@ int target_register_user_commands(struct command_context_s *cmd_ctx)
register_command(cmd_ctx, NULL, "load_image", handle_load_image_command, COMMAND_EXEC, "load_image <file> <address> ['bin'|'ihex'|'elf'|'s19']");
register_command(cmd_ctx, NULL, "dump_image", handle_dump_image_command, COMMAND_EXEC, "dump_image <file> <address> <size>");
register_command(cmd_ctx, NULL, "verify_image", handle_verify_image_command, COMMAND_EXEC, "verify_image <file> [offset] [type]");
register_command(cmd_ctx, NULL, "load_binary", handle_load_image_command, COMMAND_EXEC, "[DEPRECATED] load_binary <file> <address>");
register_command(cmd_ctx, NULL, "dump_binary", handle_dump_image_command, COMMAND_EXEC, "[DEPRECATED] dump_binary <file> <address> <size>");
@ -1802,6 +1834,101 @@ int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char
}
int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
u8 *buffer;
u32 buf_cnt;
u32 image_size;
int i;
int retval;
u32 checksum = 0;
u32 mem_checksum = 0;
image_t image;
duration_t duration;
char *duration_text;
target_t *target = get_current_target(cmd_ctx);
if (argc < 1)
{
command_print(cmd_ctx, "usage: verify_image <file> [offset] [type]");
return ERROR_OK;
}
if (!target)
{
ERROR("no target selected");
return ERROR_OK;
}
duration_start_measure(&duration);
if (argc >= 2)
{
image.base_address_set = 1;
image.base_address = strtoul(args[1], NULL, 0);
}
else
{
image.base_address_set = 0;
image.base_address = 0x0;
}
image.start_address_set = 0;
if (image_open(&image, args[0], (argc == 3) ? args[2] : NULL) != ERROR_OK)
{
command_print(cmd_ctx, "verify_image error: %s", image.error_str);
return ERROR_OK;
}
image_size = 0x0;
for (i = 0; i < image.num_sections; i++)
{
buffer = malloc(image.sections[i].size);
if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
{
ERROR("image_read_section failed with error code: %i", retval);
command_print(cmd_ctx, "image reading failed, verify aborted");
free(buffer);
image_close(&image);
return ERROR_OK;
}
/* calculate checksum of image */
image_calculate_checksum( buffer, buf_cnt, &checksum );
free(buffer);
retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum);
if( retval != ERROR_OK )
{
command_print(cmd_ctx, "image verify failed, verify aborted");
image_close(&image);
return ERROR_OK;
}
if( checksum != mem_checksum )
{
command_print(cmd_ctx, "image verify failed, verify aborted");
image_close(&image);
return ERROR_OK;
}
image_size += buf_cnt;
}
duration_stop_measure(&duration, &duration_text);
command_print(cmd_ctx, "verified %u bytes in %s", image_size, duration_text);
free(duration_text);
image_close(&image);
return ERROR_OK;
}
int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
int retval;

View File

@ -129,6 +129,8 @@ typedef struct target_type_s
/* write target memory in multiples of 4 byte, optimized for writing large quantities of data */
int (*bulk_write_memory)(struct target_s *target, u32 address, u32 count, u8 *buffer);
int (*checksum_memory)(struct target_s *target, u32 address, u32 count, u32* checksum);
/* target break-/watchpoint control
* rw: 0 = write, 1 = read, 2 = access
*/
@ -217,6 +219,7 @@ extern target_t* get_target_by_num(int num);
extern int target_write_buffer(struct target_s *target, u32 address, u32 size, u8 *buffer);
extern int target_read_buffer(struct target_s *target, u32 address, u32 size, u8 *buffer);
extern int target_checksum_memory(struct target_s *target, u32 address, u32 size, u32* crc);
extern int target_alloc_working_area(struct target_s *target, u32 size, working_area_t **area);
extern int target_free_working_area(struct target_s *target, working_area_t *area);

View File

@ -21,6 +21,8 @@
#define TRACE_H
#include "target.h"
#include "command.h"
#include "types.h"
typedef struct trace_point_s
{
@ -49,6 +51,7 @@ typedef enum trace_status
} trace_status_t;
extern int trace_point(struct target_s *target, int number);
extern int trace_register_commands(struct command_context_s *cmd_ctx);
#define ERROR_TRACE_IMAGE_UNAVAILABLE -(1500)
#define ERROR_TRACE_INSTRUCTION_UNAVAILABLE -(1501)

View File

@ -74,6 +74,7 @@ int xscale_write_core_reg(struct target_s *target, int num, enum armv4_5_mode mo
int xscale_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
int xscale_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
int xscale_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer);
int xscale_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum);
int xscale_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
int xscale_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
@ -109,7 +110,8 @@ target_type_t xscale_target =
.read_memory = xscale_read_memory,
.write_memory = xscale_write_memory,
.bulk_write_memory = xscale_bulk_write_memory,
.checksum_memory = xscale_checksum_memory,
.run_algorithm = armv4_5_run_algorithm,
.add_breakpoint = xscale_add_breakpoint,
@ -2035,6 +2037,11 @@ int xscale_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffe
return ERROR_OK;
}
int xscale_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum)
{
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
u32 xscale_get_ttb(target_t *target)
{
armv4_5_common_t *armv4_5 = target->arch_info;