+ WARNING("empty section %d", section);
+ section++;
+ section_offset = 0;
+ continue;
+ }
+
+ /* find the corresponding flash bank */
+ if ((c = get_flash_bank_by_addr(target, run_address)) == NULL)
+ {
+ if (failed == NULL)
+ {
+ if (error_str == NULL)
+ return ERROR_FLASH_DST_OUT_OF_BANK; /* abort operation */
+ *error_str = malloc(FLASH_MAX_ERROR_STR);
+ snprintf(*error_str, FLASH_MAX_ERROR_STR, "no flash mapped at requested address");
+ return ERROR_FLASH_DST_OUT_OF_BANK; /* abort operation */
+ }
+ failed[section] = ERROR_FLASH_DST_OUT_OF_BANK; /* mark the section as failed */
+ section++; /* and skip it */
+ section_offset = 0;
+ continue;
+ }
+
+ /* collect consecutive sections which fall into the same bank */
+ section_first = section;
+ section_last = section;
+ while ((run_address + run_size < c->base + c->size)
+ && (section_last + 1 < image->num_sections))
+ {
+ if (image->sections[section_last + 1].base_address < (run_address + run_size))
+ {
+ DEBUG("section %d out of order(very slightly surprising, but supported)", section_last + 1);
+ break;
+ }
+ if (image->sections[section_last + 1].base_address != (run_address + run_size))
+ break;
+ run_size += image->sections[++section_last].size;
+ }
+
+ /* fit the run into bank constraints */
+ if (run_address + run_size > c->base + c->size)
+ run_size = c->base + c->size - run_address;
+
+ /* allocate buffer */
+ buffer = malloc(run_size);
+ buffer_size = 0;
+
+ /* read sections to the buffer */
+ while (buffer_size < run_size)
+ {
+ u32 size_read;
+
+ if (buffer_size - run_size <= image->sections[section].size - section_offset)
+ size_read = buffer_size - run_size;
+ else
+ size_read = image->sections[section].size - section_offset;
+
+ if ((retval = image_read_section(image, section, section_offset,
+ size_read, buffer + buffer_size, &size_read)) != ERROR_OK || size_read == 0)
+ {
+ free(buffer);
+
+ if (error_str == NULL)
+ return ERROR_IMAGE_TEMPORARILY_UNAVAILABLE;
+
+ *error_str = malloc(FLASH_MAX_ERROR_STR);
+
+ /* if image_read_section returned an error there's an error string we can pass on */
+ if (retval != ERROR_OK)
+ snprintf(*error_str, FLASH_MAX_ERROR_STR, "error reading from image: %s", image->error_str);
+ else
+ snprintf(*error_str, FLASH_MAX_ERROR_STR, "error reading from image");
+
+ return ERROR_IMAGE_TEMPORARILY_UNAVAILABLE;
+ }
+
+ buffer_size += size_read;
+ section_offset += size_read;
+
+ if (section_offset >= image->sections[section].size)
+ {
+ section++;
+ section_offset = 0;
+ }
+ }
+
+ retval = ERROR_OK;
+
+ if (erase)
+ {
+ /* calculate and erase sectors */
+ retval = flash_erase( target, run_address, run_size );
+ }
+
+ if (retval == ERROR_OK)
+ {
+ /* write flash sectors */
+ retval = c->driver->write(c, buffer, run_address - c->base, run_size);
+ }
+
+ free(buffer);
+
+ if (retval != ERROR_OK)
+ {
+ if (error_str == NULL)
+ return retval; /* abort operation */
+
+ *error_str = malloc(FLASH_MAX_ERROR_STR);