From 8ee7cb12cf8838e91329dccb3647a611cf53186a Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Thu, 11 Apr 2019 08:29:15 +0200 Subject: [PATCH] flash: ROM support The only reason to define a read-only region is that gdb needs a complete memory map to choose hard or soft breakpoints properly. Change-Id: I9d05cb6b91f054ad5cc9333af6b14eb433dbdc99 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/5106 Reviewed-by: Antonio Borneo Tested-by: jenkins --- doc/openocd.texi | 10 ++++ src/flash/nor/Makefile.am | 1 + src/flash/nor/core.c | 10 ++-- src/flash/nor/core.h | 2 + src/flash/nor/driver.h | 1 + src/flash/nor/drivers.c | 1 + src/flash/nor/read_only.c | 51 +++++++++++++++++++++ src/server/gdb_server.c | 96 +++++++++++++++++++++------------------ 8 files changed, 122 insertions(+), 50 deletions(-) create mode 100644 src/flash/nor/read_only.c diff --git a/doc/openocd.texi b/doc/openocd.texi index 325235bb7..9b81cf638 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -6178,6 +6178,16 @@ flash bank vbank1 virtual 0x9fc00000 0 0 0 \ @end example @end deffn +@deffn {Flash Driver} read_only +A stub driver without write and erase. +Use to define a ROM region for the gdb memory map. + +@example +flash bank $_CHIPNAME.sysrom read_only 0x1ff00000 0xedc0 0 0 \ + $_TARGETNAME +@end example +@end deffn + @subsection External Flash @deffn {Flash Driver} {cfi} diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am index d95249c2e..5c4737f7a 100644 --- a/src/flash/nor/Makefile.am +++ b/src/flash/nor/Makefile.am @@ -60,6 +60,7 @@ NOR_DRIVERS = \ %D%/psoc5lp.c \ %D%/psoc6.c \ %D%/qn908x.c \ + %D%/read_only.c \ %D%/renesas_rpchf.c \ %D%/rp2xxx.c \ %D%/rsl10.c \ diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c index 9d24548f4..4db8b8af9 100644 --- a/src/flash/nor/core.c +++ b/src/flash/nor/core.c @@ -44,6 +44,11 @@ int flash_driver_protect(struct flash_bank *bank, int set, unsigned int first, int retval; unsigned int num_blocks; + if (!bank->driver->protect) { + LOG_ERROR("Flash protection is not supported"); + return ERROR_FLASH_OPER_UNSUPPORTED; + } + if (bank->num_prot_blocks) num_blocks = bank->num_prot_blocks; else @@ -59,11 +64,6 @@ int flash_driver_protect(struct flash_bank *bank, int set, unsigned int first, /* force "set" to 0/1 */ set = !!set; - if (!bank->driver->protect) { - LOG_ERROR("Flash protection is not supported."); - return ERROR_FLASH_OPER_UNSUPPORTED; - } - /* DANGER! * * We must not use any cached information about protection state!!!! diff --git a/src/flash/nor/core.h b/src/flash/nor/core.h index f8cf5e269..55ea3c7e5 100644 --- a/src/flash/nor/core.h +++ b/src/flash/nor/core.h @@ -84,6 +84,8 @@ struct flash_bank { target_addr_t base; /**< The base address of this bank */ uint32_t size; /**< The size of this chip bank, in bytes */ + bool read_only; /**< a ROM region - mainly to list in gdb memory map */ + unsigned int chip_width; /**< Width of the chip in bytes (1,2,4 bytes) */ unsigned int bus_width; /**< Maximum bus width, in bytes (1,2,4 bytes) */ diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h index 872e450b4..253de9c0a 100644 --- a/src/flash/nor/driver.h +++ b/src/flash/nor/driver.h @@ -292,6 +292,7 @@ extern const struct flash_driver psoc5lp_flash; extern const struct flash_driver psoc5lp_nvl_flash; extern const struct flash_driver psoc6_flash; extern const struct flash_driver qn908x_flash; +extern const struct flash_driver read_only_flash; extern const struct flash_driver renesas_rpchf_flash; extern const struct flash_driver rp2xxx_flash; extern const struct flash_driver rsl10_flash; diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index 19015554b..86d7ce4ba 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -71,6 +71,7 @@ static const struct flash_driver * const flash_drivers[] = { &psoc5lp_nvl_flash, &psoc6_flash, &qn908x_flash, + &read_only_flash, &renesas_rpchf_flash, &rp2xxx_flash, &rsl10_flash, diff --git a/src/flash/nor/read_only.c b/src/flash/nor/read_only.c new file mode 100644 index 000000000..5459d9b3a --- /dev/null +++ b/src/flash/nor/read_only.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +/* + * Copyright (C) 2019 by Tomas Vanek + * + * To declare a read-only region for GDB memory map. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "imp.h" + +FLASH_BANK_COMMAND_HANDLER(rom_bank_command) +{ + bank->read_only = true; + return ERROR_OK; +} + +static int rom_erase(struct flash_bank *bank, unsigned int first, unsigned int last) +{ + LOG_ERROR("Erase of read-only memory refused"); + return ERROR_FAIL; +} + +static int rom_write(struct flash_bank *bank, const uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + LOG_ERROR("Write to read-only memory refused"); + return ERROR_FAIL; +} + +static int rom_probe(struct flash_bank *bank) +{ + return ERROR_OK; +} + +const struct flash_driver read_only_flash = { + .name = "read_only", + .flash_bank_command = rom_bank_command, + .erase = rom_erase, + .write = rom_write, + .read = default_flash_read, + .probe = rom_probe, + .auto_probe = rom_probe, + .erase_check = default_flash_blank_check, + + // ROM driver doesn't set driver_priv, free(NULL) makes no harm + .free_driver_priv = default_flash_free_driver_priv, +}; diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 6866f6e9d..b966e8593 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -2004,52 +2004,58 @@ static int gdb_memory_map(struct connection *connection, "length=\"" TARGET_ADDR_FMT "\"/>\n", ram_start, p->base - ram_start); - /* Report adjacent groups of same-size sectors. So for - * example top boot CFI flash will list an initial region - * with several large sectors (maybe 128KB) and several - * smaller ones at the end (maybe 32KB). STR7 will have - * regions with 8KB, 32KB, and 64KB sectors; etc. - */ - for (unsigned int j = 0; j < p->num_sectors; j++) { - - /* Maybe start a new group of sectors. */ - if (sector_size == 0) { - if (p->sectors[j].offset + p->sectors[j].size > p->size) { - LOG_WARNING("The flash sector at offset 0x%08" PRIx32 - " overflows the end of %s bank.", - p->sectors[j].offset, p->name); - LOG_WARNING("The rest of bank will not show in gdb memory map."); - break; - } - target_addr_t start; - start = p->base + p->sectors[j].offset; - xml_printf(&retval, &xml, &pos, &size, - "sectors[j].size; - group_len = sector_size; - } else { - group_len += sector_size; /* equal to p->sectors[j].size */ - } - - /* Does this finish a group of sectors? - * If not, continue an already-started group. - */ - if (j < p->num_sectors - 1 - && p->sectors[j + 1].size == sector_size - && p->sectors[j + 1].offset == p->sectors[j].offset + sector_size - && p->sectors[j + 1].offset + p->sectors[j + 1].size <= p->size) - continue; - + if (p->read_only) { xml_printf(&retval, &xml, &pos, &size, - "length=\"0x%x\">\n" - "" - "0x%x\n" - "\n", - group_len, - sector_size); - sector_size = 0; + "\n", + p->base, p->size); + } else { + /* Report adjacent groups of same-size sectors. So for + * example top boot CFI flash will list an initial region + * with several large sectors (maybe 128KB) and several + * smaller ones at the end (maybe 32KB). STR7 will have + * regions with 8KB, 32KB, and 64KB sectors; etc. + */ + for (unsigned int j = 0; j < p->num_sectors; j++) { + // Maybe start a new group of sectors + if (sector_size == 0) { + if (p->sectors[j].offset + p->sectors[j].size > p->size) { + LOG_WARNING("The flash sector at offset 0x%08" PRIx32 + " overflows the end of %s bank.", + p->sectors[j].offset, p->name); + LOG_WARNING("The rest of bank will not show in gdb memory map."); + break; + } + target_addr_t start; + start = p->base + p->sectors[j].offset; + xml_printf(&retval, &xml, &pos, &size, + "sectors[j].size; + group_len = sector_size; + } else { + group_len += sector_size; /* equal to p->sectors[j].size */ + } + + /* Does this finish a group of sectors? + * If not, continue an already-started group. + */ + if (j < p->num_sectors - 1 + && p->sectors[j + 1].size == sector_size + && p->sectors[j + 1].offset == p->sectors[j].offset + sector_size + && p->sectors[j + 1].offset + p->sectors[j + 1].size <= p->size) + continue; + + xml_printf(&retval, &xml, &pos, &size, + "length=\"0x%x\">\n" + "" + "0x%x\n" + "\n", + group_len, + sector_size); + sector_size = 0; + } } ram_start = p->base + p->size;