retval = bank->driver->erase(bank, first, last);
if (retval != ERROR_OK)
{
- LOG_ERROR("failed erasing sectors %d to %d (%d)", first, last, retval);
+ LOG_ERROR("failed erasing sectors %d to %d", first, last);
}
return retval;
retval = bank->driver->protect(bank, set, first, last);
if (retval != ERROR_OK)
{
- LOG_ERROR("failed setting protection for areas %d to %d (%d)", first, last, retval);
+ LOG_ERROR("failed setting protection for areas %d to %d", first, last);
}
return retval;
retval = bank->driver->write(bank, buffer, offset, count);
if (retval != ERROR_OK)
{
- LOG_ERROR("error writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32 " (%d)",
- bank->base, offset, retval);
+ LOG_ERROR("error writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32,
+ bank->base, offset);
}
return retval;
retval = bank->driver->read(bank, buffer, offset, count);
if (retval != ERROR_OK)
{
- LOG_ERROR("error reading to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32 " (%d)",
- bank->base, offset, retval);
+ LOG_ERROR("error reading to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32,
+ bank->base, offset);
}
return retval;
if (retval != ERROR_OK)
{
- LOG_ERROR("auto_probe failed %d\n", retval);
+ LOG_ERROR("auto_probe failed");
return retval;
}
}
if (retval != ERROR_OK)
{
- LOG_ERROR("auto_probe failed %d\n", retval);
+ LOG_ERROR("auto_probe failed");
return retval;
}
*bank = p;
if (retval != ERROR_OK)
{
- LOG_ERROR("auto_probe failed %d\n", retval);
+ LOG_ERROR("auto_probe failed");
return retval;
}
/* check whether address belongs to this flash bank */
*result_bank = NULL;
if (check)
{
- LOG_ERROR("No flash at address 0x%08" PRIx32 "\n", addr);
+ LOG_ERROR("No flash at address 0x%08" PRIx32, addr);
return ERROR_FAIL;
}
return ERROR_OK;
* sectors will be added to the range, and that reason string is used when
* warning about those additions.
*/
-static int flash_iterate_address_range(struct target *target,
+static int flash_iterate_address_range_inner(struct target *target,
char *pad_reason, uint32_t addr, uint32_t length,
int (*callback)(struct flash_bank *bank, int first, int last))
{
return callback(c, first, last);
}
+/* The inner fn only handles a single bank, we could be spanning
+ * multiple chips.
+ */
+static int flash_iterate_address_range(struct target *target,
+ char *pad_reason, uint32_t addr, uint32_t length,
+ int (*callback)(struct flash_bank *bank, int first, int last))
+{
+ struct flash_bank *c;
+ int retval = ERROR_OK;
+
+ /* Danger! zero-length iterations means entire bank! */
+ do
+ {
+ retval = get_flash_bank_by_addr(target, addr, true, &c);
+ if (retval != ERROR_OK)
+ return retval;
+
+ uint32_t cur_length = length;
+ /* check whether it all fits in this bank */
+ if (addr + length - 1 > c->base + c->size - 1)
+ {
+ LOG_DEBUG("iterating over more than one flash bank.");
+ cur_length = c->base + c->size - addr;
+ }
+ retval = flash_iterate_address_range_inner(target,
+ pad_reason, addr, cur_length,
+ callback);
+ if (retval != ERROR_OK)
+ break;
+
+ length -= cur_length;
+ addr += cur_length;
+ } while (length > 0);
+
+ return retval;
+}
+
int flash_erase_address_range(struct target *target,
bool pad, uint32_t addr, uint32_t length)
{
static int compare_section (const void * a, const void * b)
{
- struct imageection *b1, *b2;
- b1=*((struct imageection **)a);
- b2=*((struct imageection **)b);
+ struct imagesection *b1, *b2;
+ b1=*((struct imagesection **)a);
+ b2=*((struct imagesection **)b);
if (b1->base_address == b2->base_address)
{
/* 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 *) *
+ struct imagesection **sections = malloc(sizeof(struct imagesection *) *
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 *),
+ qsort(sections, image->num_sections, sizeof(struct imagesection *),
compare_section);
/* loop until we reach end of the image */
{
uint32_t buffer_size;
uint8_t *buffer;
- int section_first;
int section_last;
uint32_t run_address = sections[section]->base_address + section_offset;
uint32_t run_size = sections[section]->size - section_offset;
}
/* find the corresponding flash bank */
- int retval;
retval = get_flash_bank_by_addr(target, run_address, false, &c);
if (retval != ERROR_OK)
- return retval;
+ {
+ goto done;
+ }
if (c == NULL)
{
section++; /* and skip it */
}
/* collect consecutive sections which fall into the same bank */
- section_first = section;
section_last = section;
padding[section] = 0;
while ((run_address + run_size - 1 < c->base + c->size - 1)
if (run_address + run_size - 1 > c->base + c->size - 1)
{
- LOG_ERROR("The image is too big for the flash");
- return ERROR_FAIL;
+ /* If we have more than one flash chip back to back, then we limit
+ * the current write operation to the current chip.
+ */
+ LOG_DEBUG("Truncate flash run size to the current flash chip.");
+
+ run_size = c->base + c->size - run_address;
+ assert(run_size > 0);
}
/* If we're applying any sector automagic, then pad this
/* allocate buffer */
buffer = malloc(run_size);
+ if (buffer == NULL)
+ {
+ LOG_ERROR("Out of memory for flash bank buffer");
+ retval = ERROR_FAIL;
+ goto done;
+ }
buffer_size = 0;
/* read sections to the buffer */
* list of pointers to sections to invoke image_read_section()...
*/
intptr_t diff = (intptr_t)sections[section] - (intptr_t)image->sections;
- int t_section_num = diff / sizeof(struct imageection);
+ int t_section_num = diff / sizeof(struct imagesection);
LOG_DEBUG("image_read_section: section = %d, t_section_num = %d, section_offset = %d, buffer_size = %d, size_read = %d",
(int)section,