summaryrefslogtreecommitdiff
path: root/src/flash
diff options
context:
space:
mode:
authorØyvind Harboe <oyvind.harboe@zylin.com>2010-04-29 17:42:47 +0200
committerØyvind Harboe <oyvind.harboe@zylin.com>2010-04-29 18:39:48 +0200
commit5e79f999bcc898d94a2d7751831e9f7aee24fbd5 (patch)
treed76fb4bf92542115bb6ebd6d72479c9998cc8e2e /src/flash
parent78248f1df67d1b4feefd8ac4e459acd7599d6af2 (diff)
downloadopenocd+libswd-5e79f999bcc898d94a2d7751831e9f7aee24fbd5.tar.gz
openocd+libswd-5e79f999bcc898d94a2d7751831e9f7aee24fbd5.tar.bz2
openocd+libswd-5e79f999bcc898d94a2d7751831e9f7aee24fbd5.tar.xz
openocd+libswd-5e79f999bcc898d94a2d7751831e9f7aee24fbd5.zip
flash: write_image would fail for certain images
Fix a bug where write_image would fail if the sections in the image were not in ascending order. This has previously been fixed in gdb load. Solved by sorting the image sections before running flash write_image erase unlock foo.elf. Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
Diffstat (limited to 'src/flash')
-rw-r--r--src/flash/nor/core.c69
1 files changed, 55 insertions, 14 deletions
diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c
index 1ff41937..9a773537 100644
--- a/src/flash/nor/core.c
+++ b/src/flash/nor/core.c
@@ -509,6 +509,25 @@ static int flash_unlock_address_range(struct target *target, uint32_t addr, uint
addr, length, &flash_driver_unprotect);
}
+static int compare_section (const void * a, const void * b)
+{
+ struct imageection *b1, *b2;
+ b1=*((struct imageection **)a);
+ b2=*((struct imageection **)b);
+
+ if (b1->base_address == b2->base_address)
+ {
+ return 0;
+ } else if (b1->base_address > b2->base_address)
+ {
+ return 1;
+ } else
+ {
+ return -1;
+ }
+}
+
+
int flash_write_unlock(struct target *target, struct image *image,
uint32_t *written, int erase, bool unlock)
{
@@ -536,6 +555,19 @@ int flash_write_unlock(struct target *target, struct image *image,
/* allocate padding array */
padding = calloc(image->num_sections, sizeof(*padding));
+ /* This fn requires all sections to be in ascending order of addresses,
+ * whereas an image can have sections out of order. */
+ struct imageection **sections = malloc(sizeof(struct imageection *) *
+ image->num_sections);
+ int i;
+ for (i = 0; i < image->num_sections; i++)
+ {
+ sections[i] = &image->sections[i];
+ }
+
+ qsort(sections, image->num_sections, sizeof(struct imageection *),
+ compare_section);
+
/* loop until we reach end of the image */
while (section < image->num_sections)
{
@@ -543,11 +575,11 @@ int flash_write_unlock(struct target *target, struct image *image,
uint8_t *buffer;
int section_first;
int section_last;
- uint32_t run_address = image->sections[section].base_address + section_offset;
- uint32_t run_size = image->sections[section].size - section_offset;
+ uint32_t run_address = sections[section]->base_address + section_offset;
+ uint32_t run_size = sections[section]->size - section_offset;
int pad_bytes = 0;
- if (image->sections[section].size == 0)
+ if (sections[section]->size == 0)
{
LOG_WARNING("empty section %d", section);
section++;
@@ -570,7 +602,7 @@ int flash_write_unlock(struct target *target, struct image *image,
while ((run_address + run_size - 1 < c->base + c->size - 1)
&& (section_last + 1 < image->num_sections))
{
- if (image->sections[section_last + 1].base_address < (run_address + run_size))
+ if (sections[section_last + 1]->base_address < (run_address + run_size))
{
LOG_DEBUG("section %d out of order "
"(surprising, but supported)",
@@ -598,11 +630,11 @@ int flash_write_unlock(struct target *target, struct image *image,
/* if we have multiple sections within our image,
* flash programming could fail due to alignment issues
* attempt to rebuild a consecutive buffer for the flash loader */
- pad_bytes = (image->sections[section_last + 1].base_address) - (run_address + run_size);
+ pad_bytes = (sections[section_last + 1]->base_address) - (run_address + run_size);
if ((run_address + run_size + pad_bytes) > (c->base + c->size))
break;
padding[section_last] = pad_bytes;
- run_size += image->sections[++section_last].size;
+ run_size += sections[++section_last]->size;
run_size += pad_bytes;
if (pad_bytes > 0)
@@ -651,15 +683,21 @@ int flash_write_unlock(struct target *target, struct image *image,
size_t size_read;
size_read = run_size - buffer_size;
- if (size_read > image->sections[section].size - section_offset)
- size_read = image->sections[section].size - section_offset;
+ if (size_read > sections[section]->size - section_offset)
+ size_read = sections[section]->size - section_offset;
- if ((retval = image_read_section(image, section, section_offset,
+ /* KLUDGE!
+ *
+ * #¤%#"%¤% we have to figure out the section # from the sorted
+ * list of pointers to sections to invoke image_read_section()...
+ */
+ int t_section_num = (sections[section] - image->sections) / sizeof(struct imageection);
+
+ if ((retval = image_read_section(image, t_section_num, section_offset,
size_read, buffer + buffer_size, &size_read)) != ERROR_OK || size_read == 0)
{
free(buffer);
- free(padding);
- return retval;
+ goto done;
}
/* see if we need to pad the section */
@@ -669,7 +707,7 @@ int flash_write_unlock(struct target *target, struct image *image,
buffer_size += size_read;
section_offset += size_read;
- if (section_offset >= image->sections[section].size)
+ if (section_offset >= sections[section]->size)
{
section++;
section_offset = 0;
@@ -702,14 +740,17 @@ int flash_write_unlock(struct target *target, struct image *image,
if (retval != ERROR_OK)
{
- free(padding);
- return retval; /* abort operation */
+ /* abort operation */
+ goto done;
}
if (written != NULL)
*written += run_size; /* add run size to total written counter */
}
+
+done:
+ free(sections);
free(padding);
return retval;