From: drath Date: Wed, 30 May 2007 15:47:18 +0000 (+0000) Subject: - reworked image handling to support multiple sections (tested with ihex file contain... X-Git-Tag: v0.1.0~1111 X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=commitdiff_plain;h=f94d66d7c5f3c018ba72593b720746e4c5be1a16;ds=sidebyside - reworked image handling to support multiple sections (tested with ihex file containing gaps) This checkin is still experimental, not recommended for general use git-svn-id: svn://svn.berlios.de/openocd/trunk@159 b42882b7-edfa-0310-969c-e2dbd0fdcd60 --- diff --git a/src/flash/flash.c b/src/flash/flash.c index 6af29825ca..58a467d2b3 100644 --- a/src/flash/flash.c +++ b/src/flash/flash.c @@ -490,9 +490,10 @@ int handle_flash_protect_command(struct command_context_s *cmd_ctx, char *cmd, c int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { u32 offset; - u32 binary_size; u8 *buffer; u32 buf_cnt; + u32 image_size; + int i; image_t image; @@ -531,51 +532,62 @@ int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, cha return ERROR_OK; } - binary_size = image.size; - buffer = malloc(binary_size); - - image_read(&image, binary_size, buffer, &buf_cnt); - - if ((retval = p->driver->write(p, buffer, offset, buf_cnt)) != ERROR_OK) + image_size = 0x0; + for (i = 0; i < image.num_sections; i++) { - command_print(cmd_ctx, "failed writing file %s to flash bank %i at offset 0x%8.8x", - args[1], strtoul(args[0], NULL, 0), strtoul(args[2], NULL, 0)); - switch (retval) + buffer = malloc(image.sections[i].size); + if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK) { - case ERROR_TARGET_NOT_HALTED: - command_print(cmd_ctx, "can't work with this flash while target is running"); - break; - case ERROR_INVALID_ARGUMENTS: - command_print(cmd_ctx, "usage: flash write "); - break; - case ERROR_FLASH_BANK_INVALID: - command_print(cmd_ctx, "no '%s' flash found at 0x%8.8x", p->driver->name, p->base); - break; - case ERROR_FLASH_OPERATION_FAILED: - command_print(cmd_ctx, "flash program error"); - break; - case ERROR_FLASH_DST_BREAKS_ALIGNMENT: - command_print(cmd_ctx, "offset breaks required alignment"); - break; - case ERROR_FLASH_DST_OUT_OF_BANK: - command_print(cmd_ctx, "destination is out of flash bank (offset and/or file too large)"); - break; - case ERROR_FLASH_SECTOR_NOT_ERASED: - command_print(cmd_ctx, "destination sector(s) not erased"); - break; - default: - command_print(cmd_ctx, "unknown error"); + ERROR("image_read_section failed with error code: %i", retval); + command_print(cmd_ctx, "image reading failed, flash write aborted"); + free(buffer); + image_close(&image); + return ERROR_OK; } + + if ((retval = p->driver->write(p, buffer, offset, buf_cnt)) != ERROR_OK) + { + command_print(cmd_ctx, "failed writing file %s to flash bank %i at offset 0x%8.8x", + args[1], strtoul(args[0], NULL, 0), strtoul(args[2], NULL, 0)); + switch (retval) + { + case ERROR_TARGET_NOT_HALTED: + command_print(cmd_ctx, "can't work with this flash while target is running"); + break; + case ERROR_INVALID_ARGUMENTS: + command_print(cmd_ctx, "usage: flash write "); + break; + case ERROR_FLASH_BANK_INVALID: + command_print(cmd_ctx, "no '%s' flash found at 0x%8.8x", p->driver->name, p->base); + break; + case ERROR_FLASH_OPERATION_FAILED: + command_print(cmd_ctx, "flash program error"); + break; + case ERROR_FLASH_DST_BREAKS_ALIGNMENT: + command_print(cmd_ctx, "offset breaks required alignment"); + break; + case ERROR_FLASH_DST_OUT_OF_BANK: + command_print(cmd_ctx, "destination is out of flash bank (offset and/or file too large)"); + break; + case ERROR_FLASH_SECTOR_NOT_ERASED: + command_print(cmd_ctx, "destination sector(s) not erased"); + break; + default: + command_print(cmd_ctx, "unknown error"); + } + } + image_size += buf_cnt; + + free(buffer); } - else - { - duration_stop_measure(&duration, &duration_text); - command_print(cmd_ctx, "wrote file %s to flash bank %i at offset 0x%8.8x in %s", - args[1], strtoul(args[0], NULL, 0), offset, duration_text); - free(duration_text); - } + - free(buffer); + duration_stop_measure(&duration, &duration_text); + command_print(cmd_ctx, "wrote %u byte from file %s to flash bank %i at offset 0x%8.8x in %s (%f kb/s)", + image_size, args[1], strtoul(args[0], NULL, 0), offset, duration_text, + (float)image_size / 1024.0 / ((float)duration.duration.tv_sec + ((float)duration.duration.tv_usec / 1000000.0))); + free(duration_text); + image_close(&image); return ERROR_OK; diff --git a/src/flash/nand.c b/src/flash/nand.c index 38a70749a4..7ff73512d9 100644 --- a/src/flash/nand.c +++ b/src/flash/nand.c @@ -1164,8 +1164,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char u32 buf_cnt; enum oob_formats oob_format = NAND_OOB_NONE; - image_t image; - int image_type_identified = 0; + fileio_t fileio; duration_t duration; char *duration_text; @@ -1187,7 +1186,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char u32 oob_size = 0; duration_start_measure(&duration); - strtoul(args[2], NULL, 0); + offset = strtoul(args[2], NULL, 0); if (argc > 3) { @@ -1200,40 +1199,18 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char oob_format |= NAND_OOB_RAW | NAND_OOB_ONLY; else { - if (identify_image_type(&image.type, args[i]) == ERROR_OK) - { - image_type_identified = 1; - } - else - { - command_print(cmd_ctx, "unknown option: %s", args[i]); - } + command_print(cmd_ctx, "unknown option: %s", args[i]); } } } - /* if no image type option was encountered, set the default */ - if (!image_type_identified) - { - - identify_image_type(&image.type, NULL); - image_type_identified = 1; - } - - image.base_address_set = 1; - image.base_address = strtoul(args[2], NULL, 0); - image.start_address_set = 0; - - if (image_open(&image, args[1], FILEIO_READ) != ERROR_OK) + if (fileio_open(&fileio, args[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK) { - command_print(cmd_ctx, "flash write error: %s", image.error_str); + command_print(cmd_ctx, "file open error: %s", fileio.error_str); return ERROR_OK; } - /* the offset might have been overwritten by the image base address */ - offset = image.base_address; - - buf_cnt = binary_size = image.size; + buf_cnt = binary_size = fileio.size; if (!(oob_format & NAND_OOB_ONLY)) { @@ -1262,7 +1239,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char if (page) { - image_read(&image, page_size, page, &size_read); + fileio_read(&fileio, page_size, page, &size_read); buf_cnt -= size_read; if (size_read < page_size) { @@ -1272,7 +1249,7 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char if (oob) { - image_read(&image, oob_size, oob, &size_read); + fileio_read(&fileio, oob_size, oob, &size_read); buf_cnt -= size_read; if (size_read < oob_size) { @@ -1289,9 +1266,11 @@ int handle_nand_write_command(struct command_context_s *cmd_ctx, char *cmd, char offset += page_size; } + fileio_close(&fileio); + duration_stop_measure(&duration, &duration_text); command_print(cmd_ctx, "wrote file %s to NAND flash %s at offset 0x%8.8x in %s", - args[1], args[0], image.base_address, duration_text); + args[1], args[0], offset, duration_text); free(duration_text); } else diff --git a/src/openocd.c b/src/openocd.c index 10a4cfd28e..9601b9ef1b 100644 --- a/src/openocd.c +++ b/src/openocd.c @@ -18,7 +18,7 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ -#define OPENOCD_VERSION "Open On-Chip Debugger (2007-05-29 13:15 CEST)" +#define OPENOCD_VERSION "Open On-Chip Debugger (2007-05-30 17:45 CEST)" #ifdef HAVE_CONFIG_H #include "config.h" diff --git a/src/target/etm.h b/src/target/etm.h index 595917885a..65fd757c8d 100644 --- a/src/target/etm.h +++ b/src/target/etm.h @@ -23,6 +23,7 @@ #ifndef ETM_H #define ETM_H +#include "image.h" #include "trace.h" #include "target.h" #include "register.h" @@ -142,7 +143,7 @@ typedef struct etm_context_s etm_portmode_t portmode; /* normal, multiplexed or demultiplexed */ etmv1_tracemode_t tracemode; /* type of information the trace contains (data, addres, contextID, ...) */ armv4_5_state_t core_state; /* current core state (ARM, Thumb, Jazelle) */ -// trace_image_provider_t image_provider; /* source for target opcodes */ + image_t image; /* source for target opcodes */ u32 pipe_index; /* current trace cycle */ u32 data_index; /* cycle holding next data packet */ u32 current_pc; /* current program counter */ diff --git a/src/target/image.c b/src/target/image.c index 3cc9cc5b1d..7381440ed6 100644 --- a/src/target/image.c +++ b/src/target/image.c @@ -39,29 +39,38 @@ int image_ihex_buffer_complete(image_t *image) fileio_t *fileio = &ihex->fileio; u32 raw_bytes_read, raw_bytes; int retval; - u32 full_address = image->base_address; - char *buffer = malloc(ihex->raw_size); - u32 cooked_bytes = 0x0; + u32 full_address = 0x0; + char *buffer = malloc(fileio->size); + u32 cooked_bytes; + int i; - ihex->raw_size = fileio->size; - ihex->buffer = malloc(ihex->raw_size >> 1); + /* we can't determine the number of sections that we'll have to create ahead of time, + * so we locally hold them until parsing is finished */ + image_section_t section[IMAGE_MAX_SECTIONS]; + u8 *section_pointer[IMAGE_MAX_SECTIONS]; - if ((retval = fileio_read(fileio, ihex->raw_size, (u8*)buffer, &raw_bytes_read)) != ERROR_OK) + if ((retval = fileio_read(fileio, fileio->size, (u8*)buffer, &raw_bytes_read)) != ERROR_OK) { free(buffer); ERROR("failed buffering IHEX file, read failed"); return ERROR_FILEIO_OPERATION_FAILED; } - if (raw_bytes_read != ihex->raw_size) + if (raw_bytes_read != fileio->size) { free(buffer); ERROR("failed buffering complete IHEX file, only partially read"); return ERROR_FILEIO_OPERATION_FAILED; } - - image->size = 0x0; + + ihex->buffer = malloc(fileio->size >> 1); raw_bytes = 0x0; + cooked_bytes = 0x0; + image->num_sections = 0; + section_pointer[image->num_sections] = &ihex->buffer[cooked_bytes]; + section[image->num_sections].base_address = 0x0; + section[image->num_sections].size = 0x0; + section[image->num_sections].flags = 0; while (raw_bytes < raw_bytes_read) { u32 count; @@ -75,13 +84,24 @@ int image_ihex_buffer_complete(image_t *image) } raw_bytes += 9; - if (record_type == 0) + if (record_type == 0) /* Data Record */ { if ((full_address & 0xffff) != address) { - free(buffer); - ERROR("can't handle non-linear IHEX file"); - return ERROR_IMAGE_FORMAT_ERROR; + /* we encountered a nonconsecutive location, create a new section, + * unless the current section has zero size, in which case this specifies + * the current section's base address + */ + if (section[image->num_sections].size != 0) + { + image->num_sections++; + section[image->num_sections].size = 0x0; + section[image->num_sections].flags = 0; + section_pointer[image->num_sections] = &ihex->buffer[cooked_bytes]; + } + section[image->num_sections].base_address = + (full_address & 0xffff0000) | address; + full_address = (full_address & 0xffff0000) | address; } while (count-- > 0) @@ -89,16 +109,31 @@ int image_ihex_buffer_complete(image_t *image) sscanf(&buffer[raw_bytes], "%2hhx", &ihex->buffer[cooked_bytes]); raw_bytes += 2; cooked_bytes += 1; + section[image->num_sections].size += 1; full_address++; } } - else if (record_type == 1) + else if (record_type == 1) /* End of File Record */ { + /* finish the current section */ + image->num_sections++; + + /* copy section information */ + ihex->section_pointer = malloc(sizeof(u8*) * image->num_sections); + image->sections = malloc(sizeof(image_section_t) * image->num_sections); + for (i = 0; i < image->num_sections; i++) + { + ihex->section_pointer[i] = section_pointer[i]; + image->sections[i].base_address = section[i].base_address + + ((image->base_address_set) ? image->base_address : 0); + image->sections[i].size = section[i].size; + image->sections[i].flags = section[i].flags; + } + free(buffer); - image->size = cooked_bytes; return ERROR_OK; } - else if (record_type == 4) + else if (record_type == 4) /* Extended Linear Address Record */ { u16 upper_address; @@ -107,12 +142,23 @@ int image_ihex_buffer_complete(image_t *image) if ((full_address >> 16) != upper_address) { - free(buffer); - ERROR("can't handle non-linear IHEX file"); - return ERROR_IMAGE_FORMAT_ERROR; + /* we encountered a nonconsecutive location, create a new section, + * unless the current section has zero size, in which case this specifies + * the current section's base address + */ + if (section[image->num_sections].size != 0) + { + image->num_sections++; + section[image->num_sections].size = 0x0; + section[image->num_sections].flags = 0; + section_pointer[image->num_sections] = &ihex->buffer[cooked_bytes]; + } + section[image->num_sections].base_address = + (full_address & 0xffff) | (upper_address << 16); + full_address = (full_address & 0xffff) | (upper_address << 16); } } - else if (record_type == 5) + else if (record_type == 5) /* Start Linear Address Record */ { u32 start_address; @@ -163,10 +209,14 @@ int image_open(image_t *image, void *source, enum fileio_access access) return retval; } - if (access == FILEIO_WRITE) - image->size = 0; - else - image->size = image_binary->fileio.size; + image->num_sections = 1; + image->sections = malloc(sizeof(image_section_t)); + image->sections[0].base_address = 0x0; + image->sections[0].size = image_binary->fileio.size; + image->sections[0].flags = 0; + + if (image->base_address_set == 1) + image->sections[0].base_address = image->base_address; return ERROR_OK; } @@ -192,9 +242,6 @@ int image_open(image_t *image, void *source, enum fileio_access access) return retval; } - image_ihex->position = 0; - image_ihex->raw_size = image_ihex->fileio.size; - if ((retval = image_ihex_buffer_complete(image)) != ERROR_OK) { snprintf(image->error_str, IMAGE_MAX_ERROR_STRING, @@ -217,7 +264,7 @@ int image_open(image_t *image, void *source, enum fileio_access access) return retval; }; -int image_read(image_t *image, u32 size, u8 *buffer, u32 *size_read) +int image_read_section(image_t *image, int section, u32 offset, u32 size, u8 *buffer, u32 *size_read) { int retval; @@ -225,6 +272,21 @@ int image_read(image_t *image, u32 size, u8 *buffer, u32 *size_read) { image_binary_t *image_binary = image->type_private; + /* only one section in a plain binary */ + if (section != 0) + return ERROR_INVALID_ARGUMENTS; + + if ((offset > image->sections[0].size) || (offset + size > image->sections[0].size)) + return ERROR_INVALID_ARGUMENTS; + + /* seek to offset */ + if ((retval = fileio_seek(&image_binary->fileio, offset)) != ERROR_OK) + { + strncpy(image->error_str, image_binary->fileio.error_str, IMAGE_MAX_ERROR_STRING); + return retval; + } + + /* return requested bytes */ if ((retval = fileio_read(&image_binary->fileio, size, buffer, size_read)) != ERROR_OK) { strncpy(image->error_str, image_binary->fileio.error_str, IMAGE_MAX_ERROR_STRING); @@ -234,15 +296,8 @@ int image_read(image_t *image, u32 size, u8 *buffer, u32 *size_read) else if (image->type == IMAGE_IHEX) { image_ihex_t *image_ihex = image->type_private; - - if ((image_ihex->position + size) > image->size) - { - /* don't read past the end of the file */ - size = (image->size - image_ihex->position); - } - - memcpy(buffer, image_ihex->buffer + image_ihex->position, size); - image_ihex->position += size; + + memcpy(buffer, image_ihex->section_pointer[section] + offset, size); *size_read = size; image->error_str[0] = '\0'; @@ -256,37 +311,6 @@ int image_read(image_t *image, u32 size, u8 *buffer, u32 *size_read) return ERROR_OK; } -int image_write(image_t *image, u32 size, u8 *buffer, u32 *size_written) -{ - int retval = ERROR_FILEIO_OPERATION_NOT_SUPPORTED; - - if (image->type == IMAGE_BINARY) - { - image_binary_t *image_binary = image->type_private; - - if ((retval = fileio_write(&image_binary->fileio, size, buffer, size_written)) != ERROR_OK) - { - strncpy(image->error_str, image_binary->fileio.error_str, IMAGE_MAX_ERROR_STRING); - return retval; - } - } - else if (image->type == IMAGE_IHEX) - { - return ERROR_FILEIO_OPERATION_NOT_SUPPORTED; - } - else if (image->type == IMAGE_MEMORY) - { - /* TODO: handle target memory pseudo image */ - } - - if (retval != ERROR_OK) - return retval; - - image->size += size; - - return ERROR_OK; -} - int image_close(image_t *image) { if (image->type == IMAGE_BINARY) @@ -301,6 +325,9 @@ int image_close(image_t *image) fileio_close(&image_ihex->fileio); + if (image_ihex->section_pointer) + free(image_ihex->section_pointer); + if (image_ihex->buffer) free(image_ihex->buffer); } @@ -309,7 +336,11 @@ int image_close(image_t *image) /* do nothing for now */ } - free(image->type_private); + if (image->type_private) + free(image->type_private); + + if (image->sections) + free(image->sections); return ERROR_OK; } diff --git a/src/target/image.h b/src/target/image.h index 3df175a8d6..75288791a6 100644 --- a/src/target/image.h +++ b/src/target/image.h @@ -24,11 +24,12 @@ #include "target.h" #define IMAGE_MAX_ERROR_STRING (128) +#define IMAGE_MAX_SECTIONS (128) typedef enum image_type { IMAGE_BINARY, /* plain binary */ - IMAGE_IHEX, /* intel hex-record format */ + IMAGE_IHEX, /* intel hex-record format */ IMAGE_MEMORY, /* target-memory pseudo-image */ /* * Possible future enhancements: @@ -37,15 +38,23 @@ typedef enum image_type */ } image_type_t; +typedef struct image_section_s +{ + u32 base_address; + u32 size; + int flags; +} image_section_t; + typedef struct image_s { image_type_t type; /* image type (plain, ihex, ...) */ void *type_private; /* type private data */ - int base_address_set; /* whether the image start address has been set */ - u32 base_address; /* base address of image in target memory */ + int num_sections; /* number of sections contained in the image */ + image_section_t *sections; /* array of sections */ + int base_address_set; /* whether the image has a base address set (for relocation purposes) */ + int base_address; /* base address, if one is set */ int start_address_set; /* whether the image has a start address (entry point) associated */ u32 start_address; /* start address, if one is set */ - u32 size; /* image size in byte */ char error_str[IMAGE_MAX_ERROR_STRING]; } image_t; @@ -57,9 +66,8 @@ typedef struct image_binary_s typedef struct image_ihex_s { fileio_t fileio; - u32 position; - u32 raw_size; u8 *buffer; + u8 **section_pointer; } image_ihex_t; typedef struct image_memory_s @@ -68,8 +76,7 @@ typedef struct image_memory_s } image_memory_t; extern int image_open(image_t *image, void *source, enum fileio_access access); -extern int image_read(image_t *image, u32 size, u8 *buffer, u32 *size_written); -extern int image_write(image_t *image, u32 size, u8 *buffer, u32 *size_written); +extern int image_read_section(image_t *image, int section, u32 offset, u32 size, u8 *buffer, u32 *size_read); extern int image_close(image_t *image); extern int identify_image_type(image_type_t *type, char *type_string); diff --git a/src/target/target.c b/src/target/target.c index e980ae4a14..b7f842e7b8 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1658,6 +1658,8 @@ int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char u8 *buffer; u32 buf_cnt; u32 image_size; + int i; + int retval; image_t image; @@ -1678,8 +1680,6 @@ int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char image.base_address = strtoul(args[1], NULL, 0); image.start_address_set = 0; - - buffer = malloc(128 * 1024); duration_start_measure(&duration); @@ -1689,21 +1689,27 @@ int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char return ERROR_OK; } - image_size = image.size; - address = image.base_address; - - while ((image_size > 0) && - (image_read(&image, 128 * 1024, buffer, &buf_cnt) == ERROR_OK)) + image_size = 0x0; + for (i = 0; i < image.num_sections; i++) { - target_write_buffer(target, address, buf_cnt, buffer); - address += buf_cnt; - image_size -= buf_cnt; + 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, download aborted"); + free(buffer); + image_close(&image); + return ERROR_OK; + } + target_write_buffer(target, image.sections[i].base_address, buf_cnt, buffer); + image_size += buf_cnt; + command_print(cmd_ctx, "%u byte written at address 0x%8.8x", buf_cnt, image.sections[i].base_address); + + free(buffer); } - free(buffer); - duration_stop_measure(&duration, &duration_text); - command_print(cmd_ctx, "downloaded %u byte in %s", image.size, duration_text); + command_print(cmd_ctx, "downloaded %u byte in %s", image_size, duration_text); free(duration_text); image_close(&image);