* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
/* cycle through bank list */
for (c = flash_banks; c; c = c->next) {
+ if (c->target != target)
+ continue;
+
int retval;
retval = c->driver->auto_probe(c);
return retval;
}
/* check whether address belongs to this flash bank */
- if ((addr >= c->base) && (addr <= c->base + (c->size - 1)) && target == c->target) {
+ if ((addr >= c->base) && (addr <= c->base + (c->size - 1))) {
*result_bank = c;
return ERROR_OK;
}
* and address. Maps an address range to a set of sectors, and issues
* the callback() on that set ... e.g. to erase or unprotect its members.
*
- * (Note a current bad assumption: that protection operates on the same
- * size sectors as erase operations use.)
+ * Parameter iterate_protect_blocks switches iteration of protect block
+ * instead of erase sectors. If there is no protect blocks array, sectors
+ * are used in iteration, so compatibility for old flash drivers is retained.
*
* The "pad_reason" parameter is a kind of boolean: when it's NULL, the
* range must fit those sectors exactly. This is clearly safe; it can't
*/
static int flash_iterate_address_range_inner(struct target *target,
char *pad_reason, uint32_t addr, uint32_t length,
+ bool iterate_protect_blocks,
int (*callback)(struct flash_bank *bank, int first, int last))
{
struct flash_bank *c;
+ struct flash_sector *block_array;
uint32_t last_addr = addr + length; /* first address AFTER end */
int first = -1;
int last = -1;
int i;
+ int num_blocks;
int retval = get_flash_bank_by_addr(target, addr, true, &c);
if (retval != ERROR_OK)
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}
- /** @todo: handle erasures that cross into adjacent banks */
-
addr -= c->base;
last_addr -= c->base;
- for (i = 0; i < c->num_sectors; i++) {
- struct flash_sector *f = c->sectors + i;
+ if (iterate_protect_blocks && c->prot_blocks && c->num_prot_blocks) {
+ block_array = c->prot_blocks;
+ num_blocks = c->num_prot_blocks;
+ } else {
+ block_array = c->sectors;
+ num_blocks = c->num_sectors;
+ iterate_protect_blocks = false;
+ }
+
+
+ for (i = 0; i < num_blocks; i++) {
+ struct flash_sector *f = &block_array[i];
uint32_t end = f->offset + f->size;
/* start only on a sector boundary */
*/
static int flash_iterate_address_range(struct target *target,
char *pad_reason, uint32_t addr, uint32_t length,
+ bool iterate_protect_blocks,
int (*callback)(struct flash_bank *bank, int first, int last))
{
struct flash_bank *c;
}
retval = flash_iterate_address_range_inner(target,
pad_reason, addr, cur_length,
+ iterate_protect_blocks,
callback);
if (retval != ERROR_OK)
break;
bool pad, uint32_t addr, uint32_t length)
{
return flash_iterate_address_range(target, pad ? "erase" : NULL,
- addr, length, &flash_driver_erase);
+ addr, length, false, &flash_driver_erase);
}
static int flash_driver_unprotect(struct flash_bank *bank, int first, int last)
* and doesn't restore it.
*/
return flash_iterate_address_range(target, "unprotect",
- addr, length, &flash_driver_unprotect);
+ addr, length, true, &flash_driver_unprotect);
}
static int compare_section(const void *a, const void *b)
if (retval != ERROR_OK)
goto done;
if (c == NULL) {
- LOG_WARNING("no flash bank found for address %x", run_address);
+ LOG_WARNING("no flash bank found for address %" PRIx32, run_address);
section++; /* and skip it */
section_offset = 0;
continue;
{
return flash_write_unlock(target, image, written, erase, false);
}
+
+struct flash_sector *alloc_block_array(uint32_t offset, uint32_t size, int num_blocks)
+{
+ int i;
+
+ struct flash_sector *array = calloc(num_blocks, sizeof(struct flash_sector));
+ if (array == NULL)
+ return NULL;
+
+ for (i = 0; i < num_blocks; i++) {
+ array[i].offset = offset;
+ array[i].size = size;
+ array[i].is_erased = -1;
+ array[i].is_protected = -1;
+ offset += size;
+ }
+
+ return array;
+}