summaryrefslogtreecommitdiff
path: root/src/target
diff options
context:
space:
mode:
authordrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>2007-05-30 15:47:18 +0000
committerdrath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>2007-05-30 15:47:18 +0000
commitf94d66d7c5f3c018ba72593b720746e4c5be1a16 (patch)
treed4d7d3e2ac6d3fd940c1026417eb738decd8055f /src/target
parentcf013d2e135373438815315f48ce86e4b558c58b (diff)
downloadopenocd_libswd-f94d66d7c5f3c018ba72593b720746e4c5be1a16.tar.gz
openocd_libswd-f94d66d7c5f3c018ba72593b720746e4c5be1a16.tar.bz2
openocd_libswd-f94d66d7c5f3c018ba72593b720746e4c5be1a16.tar.xz
openocd_libswd-f94d66d7c5f3c018ba72593b720746e4c5be1a16.zip
- 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
Diffstat (limited to 'src/target')
-rw-r--r--src/target/etm.h3
-rw-r--r--src/target/image.c169
-rw-r--r--src/target/image.h23
-rw-r--r--src/target/target.c32
4 files changed, 136 insertions, 91 deletions
diff --git a/src/target/etm.h b/src/target/etm.h
index 59591788..65fd757c 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 3cc9cc5b..7381440e 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 3df175a8..75288791 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 e980ae4a..b7f842e7 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);