diff --git a/src/target/target.c b/src/target/target.c index 5ac66c40c..7eeb35f59 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -6181,6 +6181,116 @@ nextw: return retval; } +COMMAND_HANDLER(handle_load_bin_command) +{ + struct image image; + target_addr_t addr; + int retval; + int i; + uint8_t *write_buffer; + uint8_t *read_buffer; + size_t buf_cnt; + uint32_t image_size; + + if (CMD_ARGC != 3) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_ADDRESS(CMD_ARGV[1], addr); + + unsigned verify = 1; + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], verify); + + image.base_address = addr; + image.base_address_set = 1; + image.start_address_set = 0; + if (image_open(&image, CMD_ARGV[0], "bin") != ERROR_OK) + return ERROR_FAIL; + + retval = ERROR_OK; + image_size = 0; + + struct target *target = get_current_target(CMD_CTX); + + struct duration bench; + duration_start(&bench); + + for (i = 0; i < image.num_sections; i++) { + write_buffer = malloc(image.sections[i].size); + if (write_buffer == NULL) { + command_print(CMD, + "error allocating write buffer for section (%d bytes)", + (int)(image.sections[i].size)); + retval = ERROR_FAIL; + break; + } + + if (verify) { + read_buffer = malloc(image.sections[i].size); + if (read_buffer == NULL) { + command_print(CMD, + "error allocating read buffer for section (%d bytes)", + (int)(image.sections[i].size)); + retval = ERROR_FAIL; + free(write_buffer); + break; + } + } + + retval = image_read_section(&image, i, 0x0, image.sections[i].size, write_buffer, &buf_cnt); + if (retval != ERROR_OK) { + free(write_buffer); + break; + } + + retval = target_write_buffer(target, image.sections[i].base_address, buf_cnt, write_buffer); + if (retval != ERROR_OK) { + free(write_buffer); + break; + } + + if (verify) { + retval = target_read_buffer(target, image.sections[i].base_address, buf_cnt, read_buffer); + if (retval != ERROR_OK) { + free(write_buffer); + free(read_buffer); + break; + } + + int k; + for (k = 0; k < buf_cnt; k++) { + if (write_buffer[k] != read_buffer[k]) { + command_print(CMD, "write failed at address " TARGET_ADDR_FMT "", + image.sections[i].base_address); + free(write_buffer); + free(read_buffer); + retval = ERROR_FAIL; + goto end; + } + } + } + + image_size += buf_cnt; + command_print(CMD, "%u bytes written at address " TARGET_ADDR_FMT "", + (unsigned int)buf_cnt, + image.sections[i].base_address); + + free(write_buffer); + if (verify) + free(read_buffer); + } + + if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { + command_print(CMD, "downloaded %" PRIu32 " bytes " + "in %fs (%0.3f KiB/s)", image_size, + duration_elapsed(&bench), duration_kbps(&bench, image_size)); + } + +end: + image_close(&image); + + return retval; +} + static const struct command_registration target_exec_command_handlers[] = { { .name = "fast_load_image", @@ -6427,6 +6537,13 @@ static const struct command_registration target_exec_command_handlers[] = { .help = "Test the target's memory access functions", .usage = "size", }, + { + .name = "load_bin", + .handler = handle_load_bin_command, + .mode = COMMAND_EXEC, + .help = "Download bin file into memory and verify it", + .usage = "filename address verify", + }, COMMAND_REGISTRATION_DONE };