flash: read only alias

Similar as virtual flash but has write/erase suppressed.

'virtual' flash driver name check in flash_free_all_banks()
was replaced by a customized free_driver_priv()

Change-Id: I528760aad0ba55ebc57fc1fabfdfdf07c92cac94
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: https://review.openocd.org/c/openocd/+/5107
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Tested-by: jenkins
This commit is contained in:
Tomas Vanek
2019-04-11 08:39:10 +02:00
committed by Antonio Borneo
parent 8ee7cb12cf
commit 2b986178cf
5 changed files with 96 additions and 15 deletions

View File

@@ -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.

View File

@@ -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->name);
free(bank);

View File

@@ -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;

View File

@@ -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,

View File

@@ -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 <spen@spen-soft.co.uk>
*
* Copyright (C) 2019 by Tomas Vanek <vanekt@fbl.cz>
*/
#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,
};