diff --git a/doc/openocd.texi b/doc/openocd.texi index 9b81cf638..4c5df9b88 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -6160,7 +6160,7 @@ Some drivers also activate driver-specific commands. This is a special driver that maps a previously defined bank to another address. All bank settings will be copied from the master physical bank. -The @var{virtual} driver defines one mandatory parameters, +The @var{virtual} driver defines one mandatory parameter, @itemize @item @var{master_bank} The bank that this virtual address refers to. @@ -6178,6 +6178,18 @@ flash bank vbank1 virtual 0x9fc00000 0 0 0 \ @end example @end deffn +@deffn {Flash Driver} ro_alias +Similar as @var{virtual} driver but suppresses write +and erase. Use to build a complete memory map for gdb. +Bank size will be copied from the master physical bank. + +The @var{virtual} driver defines one mandatory parameter, + +@itemize +@item @var{master_bank} The bank that this virtual address refers to. +@end itemize +@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. diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c index 4db8b8af9..48440662e 100644 --- a/src/flash/nor/core.c +++ b/src/flash/nor/core.c @@ -223,15 +223,8 @@ void flash_free_all_banks(void) else LOG_WARNING("Flash driver of %s does not support free_driver_priv()", bank->name); - /* For 'virtual' flash driver bank->sectors and bank->prot_blocks pointers are copied from - * master flash_bank structure. They point to memory locations allocated by master flash driver - * so master driver is responsible for releasing them. - * Avoid UB caused by double-free memory corruption if flash bank is 'virtual'. */ - - if (strcmp(bank->driver->name, "virtual") != 0) { - free(bank->sectors); - free(bank->prot_blocks); - } + free(bank->sectors); + free(bank->prot_blocks); free(bank->name); free(bank); diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h index 253de9c0a..afb73a3fb 100644 --- a/src/flash/nor/driver.h +++ b/src/flash/nor/driver.h @@ -294,6 +294,7 @@ 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 ro_alias_flash; extern const struct flash_driver rp2xxx_flash; extern const struct flash_driver rsl10_flash; extern const struct flash_driver sh_qspi_flash; diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index 86d7ce4ba..094b5a76b 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -72,6 +72,7 @@ static const struct flash_driver * const flash_drivers[] = { &psoc6_flash, &qn908x_flash, &read_only_flash, + &ro_alias_flash, &renesas_rpchf_flash, &rp2xxx_flash, &rsl10_flash, diff --git a/src/flash/nor/virtual.c b/src/flash/nor/virtual.c index 9db9b9216..5b8a3c5b7 100644 --- a/src/flash/nor/virtual.c +++ b/src/flash/nor/virtual.c @@ -1,9 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-or-later -/*************************************************************************** - * Copyright (C) 2010 by Spencer Oliver * - * spen@spen-soft.co.uk * - ***************************************************************************/ +/* + * Copyright (C) 2010 by Spencer Oliver + * + * Copyright (C) 2019 by Tomas Vanek + */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -31,6 +32,9 @@ static void virtual_update_bank_info(struct flash_bank *bank) /* update the info we do not have */ bank->size = master_bank->size; + if (bank->read_only) + return; + bank->chip_width = master_bank->chip_width; bank->bus_width = master_bank->bus_width; bank->erased_value = master_bank->erased_value; @@ -187,6 +191,19 @@ static int virtual_flash_read(struct flash_bank *bank, return master_bank->driver->read(master_bank, buffer, offset, count); } +void virtual_flash_free_driver_priv(struct flash_bank *bank) +{ + free(bank->driver_priv); + bank->driver_priv = NULL; + + /* For 'virtual' flash driver bank->sectors and bank->prot_blocks pointers are copied from + * master flash_bank structure. They point to memory locations allocated by master flash driver + * so master driver is responsible for releasing them. + * Avoid UB caused by double-free memory corruption if flash bank is 'virtual'. */ + bank->sectors = NULL; + bank->prot_blocks = NULL; +} + const struct flash_driver virtual_flash = { .name = "virtual", .flash_bank_command = virtual_flash_bank_command, @@ -199,5 +216,62 @@ const struct flash_driver virtual_flash = { .erase_check = virtual_blank_check, .protect_check = virtual_protect_check, .info = virtual_info, - .free_driver_priv = default_flash_free_driver_priv, + .free_driver_priv = virtual_flash_free_driver_priv, +}; + +FLASH_BANK_COMMAND_HANDLER(ro_alias_bank_command) +{ + if (CMD_ARGC < 7) + return ERROR_COMMAND_SYNTAX_ERROR; + + // get the master flash bank + const char *bank_name = CMD_ARGV[6]; + struct flash_bank *master_bank = get_flash_bank_by_name_noprobe(bank_name); + + if (!master_bank) { + LOG_ERROR("master flash bank '%s' does not exist", bank_name); + return ERROR_FLASH_OPERATION_FAILED; + } + + // save master bank name - use this to get settings later + bank->driver_priv = strdup(bank_name); + + bank->read_only = true; + + return ERROR_OK; +} + +static int ro_alias_erase(struct flash_bank *bank, + unsigned int first, unsigned int last) +{ + char *bank_name = bank->driver_priv; + + LOG_ERROR("Erase of read-only flash alias refused. Use master flash bank '%s'", + bank_name); + + return ERROR_FAIL; +} + +static int ro_alias_write(struct flash_bank *bank, const uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + char *bank_name = bank->driver_priv; + + LOG_ERROR("Write to read-only flash alias refused. Use master flash bank '%s'", + bank_name); + + return ERROR_FAIL; +} + +const struct flash_driver ro_alias_flash = { + .name = "ro_alias", + .flash_bank_command = ro_alias_bank_command, + .erase = ro_alias_erase, + .write = ro_alias_write, + .read = virtual_flash_read, + .probe = virtual_probe, + .auto_probe = virtual_auto_probe, + .erase_check = virtual_blank_check, + .info = virtual_info, + .free_driver_priv = virtual_flash_free_driver_priv, };