diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 74928c876..175e06740 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -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); diff --git a/src/target/arm720t.c b/src/target/arm720t.c index b5c9752b2..05cc30f4c 100644 --- a/src/target/arm720t.c +++ b/src/target/arm720t.c @@ -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, diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c index 35cbe6e50..e596d0571 100644 --- a/src/target/arm7_9_common.c +++ b/src/target/arm7_9_common.c @@ -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(®_params[0], "r0", 32, PARAM_IN_OUT); + init_reg_param(®_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(®_params[0]); + destroy_reg_param(®_params[1]); + target_free_working_area(target, crc_algorithm); + return retval; + } + + *checksum = buf_get_u32(reg_params[0].value, 0, 32); + + destroy_reg_param(®_params[0]); + destroy_reg_param(®_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; diff --git a/src/target/arm7_9_common.h b/src/target/arm7_9_common.h index 53a0ce9f6..9d11dc2a6 100644 --- a/src/target/arm7_9_common.h +++ b/src/target/arm7_9_common.h @@ -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); diff --git a/src/target/arm7tdmi.c b/src/target/arm7tdmi.c index ae51e3ae4..9a9a24505 100644 --- a/src/target/arm7tdmi.c +++ b/src/target/arm7tdmi.c @@ -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, diff --git a/src/target/arm920t.c b/src/target/arm920t.c index 0dff25062..882fec2fe 100644 --- a/src/target/arm920t.c +++ b/src/target/arm920t.c @@ -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, diff --git a/src/target/arm926ejs.c b/src/target/arm926ejs.c index 7d8f371be..ef225145c 100644 --- a/src/target/arm926ejs.c +++ b/src/target/arm926ejs.c @@ -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, diff --git a/src/target/arm966e.c b/src/target/arm966e.c index 53627a5f5..2885e3dfb 100644 --- a/src/target/arm966e.c +++ b/src/target/arm966e.c @@ -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, diff --git a/src/target/arm9tdmi.c b/src/target/arm9tdmi.c index b9b1f953f..5bb7e3998 100644 --- a/src/target/arm9tdmi.c +++ b/src/target/arm9tdmi.c @@ -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, diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 7010b5c0f..22ffb5e7d 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -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(®_params[0], "r0", 32, PARAM_IN_OUT); + init_reg_param(®_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(®_params[0]); + destroy_reg_param(®_params[1]); + target_free_working_area(target, crc_algorithm); + return retval; + } + + *checksum = buf_get_u32(reg_params[0].value, 0, 32); + + destroy_reg_param(®_params[0]); + destroy_reg_param(®_params[1]); + + target_free_working_area(target, crc_algorithm); + + return ERROR_OK; +} + diff --git a/src/target/armv7m.h b/src/target/armv7m.h index 8d06cc654..64689f0b7 100644 --- a/src/target/armv7m.h +++ b/src/target/armv7m.h @@ -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 */ diff --git a/src/target/cortex_m3.c b/src/target/cortex_m3.c index c47fbbf84..f1513c7a3 100644 --- a/src/target/cortex_m3.c +++ b/src/target/cortex_m3.c @@ -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, diff --git a/src/target/image.c b/src/target/image.c index dbb1c2ab3..d20f9df27 100644 --- a/src/target/image.c +++ b/src/target/image.c @@ -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; +} + diff --git a/src/target/image.h b/src/target/image.h index e8f585bbc..47f0215f6 100644 --- a/src/target/image.h +++ b/src/target/image.h @@ -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) diff --git a/src/target/target.c b/src/target/target.c index f471167b3..f9d957d69 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -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
['bin'|'ihex'|'elf'|'s19']"); register_command(cmd_ctx, NULL, "dump_image", handle_dump_image_command, COMMAND_EXEC, "dump_image
"); + register_command(cmd_ctx, NULL, "verify_image", handle_verify_image_command, COMMAND_EXEC, "verify_image [offset] [type]"); register_command(cmd_ctx, NULL, "load_binary", handle_load_image_command, COMMAND_EXEC, "[DEPRECATED] load_binary
"); register_command(cmd_ctx, NULL, "dump_binary", handle_dump_image_command, COMMAND_EXEC, "[DEPRECATED] dump_binary
"); @@ -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 [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; diff --git a/src/target/target.h b/src/target/target.h index ae5fbc431..1900351eb 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -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); diff --git a/src/target/trace.h b/src/target/trace.h index 0279d51fa..f7d9e5b1a 100644 --- a/src/target/trace.h +++ b/src/target/trace.h @@ -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) diff --git a/src/target/xscale.c b/src/target/xscale.c index b207dbb26..baef5fe90 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -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;