Skip to content

Commit

Permalink
drivers: flash: stm32: add STM32 option bytes extended ops
Browse files Browse the repository at this point in the history
Add two new flash extended operations for reading and writing STM32
option bytes from the application code.

Signed-off-by: Fabio Baltieri <[email protected]>
  • Loading branch information
fabiobaltieri committed Nov 29, 2024
1 parent 4e66317 commit fe5f9d5
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 17 deletions.
8 changes: 8 additions & 0 deletions drivers/flash/Kconfig.stm32
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ config FLASH_STM32_BLOCK_REGISTERS
registers improves system security, because flash content (or
protection settings) can't be changed even when exploit was found.

config FLASH_STM32_OPTION_BYTES
bool "Extended operation for option bytes access"
select FLASH_HAS_EX_OP
default n
help
Enables flash extended operations that can be used to write and write
STM32 option bytes.

config USE_MICROCHIP_QSPI_FLASH_WITH_STM32
bool "Include patch for Microchip qspi flash when running with stm32"
depends on DT_HAS_ST_STM32_QSPI_NOR_ENABLED
Expand Down
35 changes: 35 additions & 0 deletions drivers/flash/flash_stm32.c
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,41 @@ static int flash_stm32_ex_op(const struct device *dev, uint16_t code,
rv = flash_stm32_control_register_disable(dev);
break;
#endif /* CONFIG_FLASH_STM32_BLOCK_REGISTERS */
#if defined(CONFIG_FLASH_STM32_OPTION_BYTES) && ( \
defined(CONFIG_DT_HAS_ST_STM32F4_FLASH_CONTROLLER_ENABLED) || \
defined(CONFIG_DT_HAS_ST_STM32F7_FLASH_CONTROLLER_ENABLED) || \
defined(CONFIG_DT_HAS_ST_STM32G4_FLASH_CONTROLLER_ENABLED) || \
defined(CONFIG_DT_HAS_ST_STM32L4_FLASH_CONTROLLER_ENABLED))
case FLASH_STM32_EX_OP_OPTB_READ:
if (out == NULL) {
rv = -EINVAL;
break;
}

*(uint32_t *)out = flash_stm32_option_bytes_read(dev);
rv = 0;

break;
case FLASH_STM32_EX_OP_OPTB_WRITE:
int rv2;

rv = flash_stm32_option_bytes_lock(dev, false);
if (rv > 0) {
break;
}

rv2 = flash_stm32_option_bytes_write(dev, UINT32_MAX, (uint32_t)in);
/* returned later, we always re-lock */

rv = flash_stm32_option_bytes_lock(dev, true);
if (rv > 0) {
break;
}

rv = rv2;

break;
#endif
}

flash_stm32_sem_give(dev);
Expand Down
5 changes: 5 additions & 0 deletions drivers/flash/flash_stm32.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,11 @@ int flash_stm32_wait_flash_idle(const struct device *dev);

int flash_stm32_option_bytes_lock(const struct device *dev, bool enable);

uint32_t flash_stm32_option_bytes_read(const struct device *dev);

int flash_stm32_option_bytes_write(const struct device *dev, uint32_t mask,
uint32_t value);

#ifdef CONFIG_SOC_SERIES_STM32WBX
int flash_stm32_check_status(const struct device *dev);
#endif /* CONFIG_SOC_SERIES_STM32WBX */
Expand Down
18 changes: 13 additions & 5 deletions drivers/flash/flash_stm32f4x.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,8 @@ int flash_stm32_write_range(const struct device *dev, unsigned int offset,
return rc;
}

static __unused int write_optb(const struct device *dev, uint32_t mask,
uint32_t value)
int flash_stm32_option_bytes_write(const struct device *dev, uint32_t mask,
uint32_t value)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
int rc;
Expand Down Expand Up @@ -264,6 +264,13 @@ static __unused int write_optb(const struct device *dev, uint32_t mask,
return 0;
}

uint32_t flash_stm32_option_bytes_read(const struct device *dev)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);

return regs->OPTCR;
}

#if defined(CONFIG_FLASH_STM32_WRITE_PROTECT)
int flash_stm32_update_wp_sectors(const struct device *dev,
uint32_t changed_sectors,
Expand All @@ -279,7 +286,8 @@ int flash_stm32_update_wp_sectors(const struct device *dev,
/* Sector is protected when bit == 0. Flip protected_sectors bits */
protected_sectors = ~protected_sectors & changed_sectors;

return write_optb(dev, changed_sectors, protected_sectors);
return flash_stm32_option_bytes_write(dev, changed_sectors,
protected_sectors);
}

int flash_stm32_get_wp_sectors(const struct device *dev,
Expand All @@ -304,8 +312,8 @@ uint8_t flash_stm32_get_rdp_level(const struct device *dev)

void flash_stm32_set_rdp_level(const struct device *dev, uint8_t level)
{
write_optb(dev, FLASH_OPTCR_RDP_Msk,
(uint32_t)level << FLASH_OPTCR_RDP_Pos);
flash_stm32_option_bytes_write(dev, FLASH_OPTCR_RDP_Msk,
(uint32_t)level << FLASH_OPTCR_RDP_Pos);
}
#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */

Expand Down
15 changes: 11 additions & 4 deletions drivers/flash/flash_stm32f7x.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,8 @@ int flash_stm32_write_range(const struct device *dev, unsigned int offset,
return rc;
}

static __unused int write_optb(const struct device *dev, uint32_t mask,
uint32_t value)
int flash_stm32_option_bytes_write(const struct device *dev, uint32_t mask,
uint32_t value)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
int rc;
Expand All @@ -187,6 +187,13 @@ static __unused int write_optb(const struct device *dev, uint32_t mask,
return flash_stm32_wait_flash_idle(dev);
}

uint32_t flash_stm32_option_bytes_read(const struct device *dev)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);

return regs->OPTCR;
}

#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
uint8_t flash_stm32_get_rdp_level(const struct device *dev)
{
Expand All @@ -197,8 +204,8 @@ uint8_t flash_stm32_get_rdp_level(const struct device *dev)

void flash_stm32_set_rdp_level(const struct device *dev, uint8_t level)
{
write_optb(dev, FLASH_OPTCR_RDP_Msk,
(uint32_t)level << FLASH_OPTCR_RDP_Pos);
flash_stm32_option_bytes_write(dev, FLASH_OPTCR_RDP_Msk,
(uint32_t)level << FLASH_OPTCR_RDP_Pos);
}
#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */

Expand Down
15 changes: 11 additions & 4 deletions drivers/flash/flash_stm32g4x.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,8 @@ int flash_stm32_write_range(const struct device *dev, unsigned int offset,
return rc;
}

static __unused int write_optb(const struct device *dev, uint32_t mask,
uint32_t value)
int flash_stm32_option_bytes_write(const struct device *dev, uint32_t mask,
uint32_t value)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
int rc;
Expand Down Expand Up @@ -288,6 +288,13 @@ static __unused int write_optb(const struct device *dev, uint32_t mask,
return 0;
}

uint32_t flash_stm32_option_bytes_read(const struct device *dev)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);

return regs->OPTR;
}

#if defined(CONFIG_FLASH_STM32_WRITE_PROTECT)

/*
Expand All @@ -314,8 +321,8 @@ uint8_t flash_stm32_get_rdp_level(const struct device *dev)

void flash_stm32_set_rdp_level(const struct device *dev, uint8_t level)
{
write_optb(dev, FLASH_OPTR_RDP_Msk,
(uint32_t)level << FLASH_OPTR_RDP_Pos);
flash_stm32_option_bytes_write(dev, FLASH_OPTR_RDP_Msk,
(uint32_t)level << FLASH_OPTR_RDP_Pos);
}
#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */

Expand Down
15 changes: 11 additions & 4 deletions drivers/flash/flash_stm32l4x.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,8 @@ int flash_stm32_write_range(const struct device *dev, unsigned int offset,
return rc;
}

static __unused int write_optb(const struct device *dev, uint32_t mask,
uint32_t value)
int flash_stm32_option_bytes_write(const struct device *dev, uint32_t mask,
uint32_t value)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
int rc;
Expand Down Expand Up @@ -279,6 +279,13 @@ static __unused int write_optb(const struct device *dev, uint32_t mask,
return 0;
}

uint32_t flash_stm32_option_bytes_read(const struct device *dev)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);

return regs->OPTR;
}

#if defined(CONFIG_FLASH_STM32_WRITE_PROTECT)

/*
Expand All @@ -305,8 +312,8 @@ uint8_t flash_stm32_get_rdp_level(const struct device *dev)

void flash_stm32_set_rdp_level(const struct device *dev, uint8_t level)
{
write_optb(dev, FLASH_OPTR_RDP_Msk,
(uint32_t)level << FLASH_OPTR_RDP_Pos);
flash_stm32_option_bytes_write(dev, FLASH_OPTR_RDP_Msk,
(uint32_t)level << FLASH_OPTR_RDP_Pos);
}
#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */

Expand Down
14 changes: 14 additions & 0 deletions include/zephyr/drivers/flash/stm32_flash_api_extensions.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,20 @@ enum stm32_ex_ops {
* erasing or writing.
*/
FLASH_STM32_EX_OP_BLOCK_CONTROL_REG,
/*
* STM32 option bytes read.
*
* Read the option bytes content, out takes a *uint32_t, in is unused.
*/
FLASH_STM32_EX_OP_OPTB_READ,
/*
* STM32 option bytes write.
*
* Write the option bytes content, in takes the new value, out is
* unused. Note that the new value only takes effect after the device
* is restarted.
*/
FLASH_STM32_EX_OP_OPTB_WRITE,
};

#if defined(CONFIG_FLASH_STM32_WRITE_PROTECT)
Expand Down

0 comments on commit fe5f9d5

Please sign in to comment.