Skip to content

Commit

Permalink
drivers: flash: reduce redundancy in RDP implementation on STM32
Browse files Browse the repository at this point in the history
Reduce the redundancy in the readout protection implementation
on STM32 MCUs.

Signed-off-by: Benedikt Schmidt <[email protected]>
  • Loading branch information
benediktibk authored and nashif committed Aug 7, 2024
1 parent 2f088fa commit db2261b
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 282 deletions.
7 changes: 2 additions & 5 deletions drivers/flash/flash_stm32.h
Original file line number Diff line number Diff line change
Expand Up @@ -311,12 +311,9 @@ int flash_stm32_get_wp_sectors(const struct device *dev,
uint32_t *protected_sectors);
#endif
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
uint8_t flash_stm32_get_rdp_level(const struct device *dev);

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

int flash_stm32_get_rdp(const struct device *dev, bool *enabled,
bool *permanent);
void flash_stm32_set_rdp_level(const struct device *dev, uint8_t level);
#endif

/* Flash extended operations */
Expand Down
95 changes: 90 additions & 5 deletions drivers/flash/flash_stm32_ex_op.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <zephyr/device.h>
#include <zephyr/drivers/flash/stm32_flash_api_extensions.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>

#ifdef CONFIG_USERSPACE
#include <zephyr/syscall.h>
Expand All @@ -17,6 +18,8 @@
#include <soc.h>
#include "flash_stm32.h"

LOG_MODULE_REGISTER(flash_stm32_ex_op, CONFIG_FLASH_LOG_LEVEL);

#if defined(CONFIG_FLASH_STM32_WRITE_PROTECT)
int flash_stm32_ex_op_sector_wp(const struct device *dev, const uintptr_t in,
void *out)
Expand Down Expand Up @@ -85,13 +88,79 @@ int flash_stm32_ex_op_sector_wp(const struct device *dev, const uintptr_t in,
#endif /* CONFIG_FLASH_STM32_WRITE_PROTECT */

#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
int flash_stm32_ex_op_update_rdp(const struct device *dev, bool enable,
bool permanent)
{
uint8_t current_level, target_level;

current_level = flash_stm32_get_rdp_level(dev);
target_level = current_level;

/*
* 0xAA = RDP level 0 (no protection)
* 0xCC = RDP level 2 (permanent protection)
* others = RDP level 1 (protection active)
*/
switch (current_level) {
case FLASH_STM32_RDP2:
if (!enable || !permanent) {
LOG_DBG("RDP level 2 is permanent and can't be changed!");
return -ENOTSUP;
}
break;
case FLASH_STM32_RDP0:
if (enable) {
target_level = FLASH_STM32_RDP1;
if (permanent) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW)
target_level = FLASH_STM32_RDP2;
#else
LOG_DBG("Permanent readout protection (RDP "
"level 0 -> 2) not allowed");
return -ENOTSUP;
#endif
}
}
break;
default: /* FLASH_STM32_RDP1 */
if (enable && permanent) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW)
target_level = FLASH_STM32_RDP2;
#else
LOG_DBG("Permanent readout protection (RDP "
"level 1 -> 2) not allowed");
return -ENOTSUP;
#endif
}
if (!enable) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_DISABLE_ALLOW)
target_level = FLASH_STM32_RDP0;
#else
LOG_DBG("Disabling readout protection (RDP "
"level 1 -> 0) not allowed");
return -EACCES;
#endif
}
}

/* Update RDP level if needed */
if (current_level != target_level) {
LOG_INF("RDP changed from 0x%02x to 0x%02x", current_level,
target_level);

flash_stm32_set_rdp_level(dev, target_level);
}
return 0;
}

int flash_stm32_ex_op_rdp(const struct device *dev, const uintptr_t in,
void *out)
{
const struct flash_stm32_ex_op_rdp *request =
(const struct flash_stm32_ex_op_rdp *)in;
struct flash_stm32_ex_op_rdp *result =
(struct flash_stm32_ex_op_rdp *)out;
uint8_t current_level;

#ifdef CONFIG_USERSPACE
struct flash_stm32_ex_op_rdp copy;
Expand All @@ -108,7 +177,7 @@ int flash_stm32_ex_op_rdp(const struct device *dev, const uintptr_t in,
#endif
rc = flash_stm32_option_bytes_lock(dev, false);
if (rc == 0) {
rc = flash_stm32_update_rdp(dev, request->enable,
rc = flash_stm32_ex_op_update_rdp(dev, request->enable,
request->permanent);
}

Expand All @@ -124,10 +193,26 @@ int flash_stm32_ex_op_rdp(const struct device *dev, const uintptr_t in,
result = &copy;
}
#endif
rc2 = flash_stm32_get_rdp(dev, &result->enable,
&result->permanent);
if (!rc) {
rc = rc2;

current_level = flash_stm32_get_rdp_level(dev);

/*
* 0xAA = RDP level 0 (no protection)
* 0xCC = RDP level 2 (permanent protection)
* others = RDP level 1 (protection active)
*/
switch (current_level) {
case FLASH_STM32_RDP2:
result->enable = true;
result->permanent = true;
break;
case FLASH_STM32_RDP0:
result->enable = false;
result->permanent = false;
break;
default: /* FLASH_STM32_RDP1 */
result->enable = true;
result->permanent = false;
}

#ifdef CONFIG_USERSPACE
Expand Down
95 changes: 5 additions & 90 deletions drivers/flash/flash_stm32f4x.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,102 +295,17 @@ int flash_stm32_get_wp_sectors(const struct device *dev,
#endif /* CONFIG_FLASH_STM32_WRITE_PROTECT */

#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
int flash_stm32_update_rdp(const struct device *dev, bool enable,
bool permanent)
uint8_t flash_stm32_get_rdp_level(const struct device *dev)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
uint8_t current_level, target_level;

current_level =
(regs->OPTCR & FLASH_OPTCR_RDP_Msk) >> FLASH_OPTCR_RDP_Pos;
target_level = current_level;

/*
* 0xAA = RDP level 0 (no protection)
* 0xCC = RDP level 2 (permanent protection)
* others = RDP level 1 (protection active)
*/
switch (current_level) {
case FLASH_STM32_RDP2:
if (!enable || !permanent) {
LOG_ERR("RDP level 2 is permanent and can't be changed!");
return -ENOTSUP;
}
break;
case FLASH_STM32_RDP0:
if (enable) {
target_level = FLASH_STM32_RDP1;
if (permanent) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW)
target_level = FLASH_STM32_RDP2;
#else
LOG_ERR("Permanent readout protection (RDP "
"level 0 -> 2) not allowed");
return -ENOTSUP;
#endif
}
}
break;
default: /* FLASH_STM32_RDP1 */
if (enable && permanent) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW)
target_level = FLASH_STM32_RDP2;
#else
LOG_ERR("Permanent readout protection (RDP "
"level 1 -> 2) not allowed");
return -ENOTSUP;
#endif
}
if (!enable) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_DISABLE_ALLOW)
target_level = FLASH_STM32_RDP0;
#else
LOG_ERR("Disabling readout protection (RDP "
"level 1 -> 0) not allowed");
return -EACCES;
#endif
}
}

/* Update RDP level if needed */
if (current_level != target_level) {
LOG_INF("RDP changed from 0x%02x to 0x%02x", current_level,
target_level);

write_optb(dev, FLASH_OPTCR_RDP_Msk,
(uint32_t)target_level << FLASH_OPTCR_RDP_Pos);
}
return 0;
return (regs->OPTCR & FLASH_OPTCR_RDP_Msk) >> FLASH_OPTCR_RDP_Pos;
}

int flash_stm32_get_rdp(const struct device *dev, bool *enabled,
bool *permanent)
void flash_stm32_set_rdp_level(const struct device *dev, uint8_t level)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
uint8_t current_level;

current_level =
(regs->OPTCR & FLASH_OPTCR_RDP_Msk) >> FLASH_OPTCR_RDP_Pos;

/*
* 0xAA = RDP level 0 (no protection)
* 0xCC = RDP level 2 (permanent protection)
* others = RDP level 1 (protection active)
*/
switch (current_level) {
case FLASH_STM32_RDP2:
*enabled = true;
*permanent = true;
break;
case FLASH_STM32_RDP0:
*enabled = false;
*permanent = false;
break;
default: /* FLASH_STM32_RDP1 */
*enabled = true;
*permanent = false;
}
return 0;
write_optb(dev, FLASH_OPTCR_RDP_Msk,
(uint32_t)level << FLASH_OPTCR_RDP_Pos);
}
#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */

Expand Down
95 changes: 5 additions & 90 deletions drivers/flash/flash_stm32g4x.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,102 +305,17 @@ static __unused int write_optb(const struct device *dev, uint32_t mask,
#endif /* CONFIG_FLASH_STM32_WRITE_PROTECT */

#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
int flash_stm32_update_rdp(const struct device *dev, bool enable,
bool permanent)
uint8_t flash_stm32_get_rdp_level(const struct device *dev)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
uint8_t current_level, target_level;

current_level =
(regs->OPTR & FLASH_OPTR_RDP_Msk) >> FLASH_OPTR_RDP_Pos;
target_level = current_level;

/*
* 0xAA = RDP level 0 (no protection)
* 0xCC = RDP level 2 (permanent protection)
* others = RDP level 1 (protection active)
*/
switch (current_level) {
case FLASH_STM32_RDP2:
if (!enable || !permanent) {
LOG_ERR("RDP level 2 is permanent and can't be changed!");
return -ENOTSUP;
}
break;
case FLASH_STM32_RDP0:
if (enable) {
target_level = FLASH_STM32_RDP1;
if (permanent) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW)
target_level = FLASH_STM32_RDP2;
#else
LOG_ERR("Permanent readout protection (RDP "
"level 0 -> 2) not allowed");
return -ENOTSUP;
#endif
}
}
break;
default: /* FLASH_STM32_RDP1 */
if (enable && permanent) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW)
target_level = FLASH_STM32_RDP2;
#else
LOG_ERR("Permanent readout protection (RDP "
"level 1 -> 2) not allowed");
return -ENOTSUP;
#endif
}
if (!enable) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_DISABLE_ALLOW)
target_level = FLASH_STM32_RDP0;
#else
LOG_ERR("Disabling readout protection (RDP "
"level 1 -> 0) not allowed");
return -EACCES;
#endif
}
}

/* Update RDP level if needed */
if (current_level != target_level) {
LOG_INF("RDP changed from 0x%02x to 0x%02x", current_level,
target_level);

write_optb(dev, FLASH_OPTR_RDP_Msk,
(uint32_t)target_level << FLASH_OPTR_RDP_Pos);
}
return 0;
return (regs->OPTR & FLASH_OPTR_RDP_Msk) >> FLASH_OPTR_RDP_Pos;
}

int flash_stm32_get_rdp(const struct device *dev, bool *enabled,
bool *permanent)
void flash_stm32_set_rdp_level(const struct device *dev, uint8_t level)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
uint8_t current_level;

current_level =
(regs->OPTR & FLASH_OPTR_RDP_Msk) >> FLASH_OPTR_RDP_Pos;

/*
* 0xAA = RDP level 0 (no protection)
* 0xCC = RDP level 2 (permanent protection)
* others = RDP level 1 (protection active)
*/
switch (current_level) {
case FLASH_STM32_RDP2:
*enabled = true;
*permanent = true;
break;
case FLASH_STM32_RDP0:
*enabled = false;
*permanent = false;
break;
default: /* FLASH_STM32_RDP1 */
*enabled = true;
*permanent = false;
}
return 0;
write_optb(dev, FLASH_OPTR_RDP_Msk,
(uint32_t)level << FLASH_OPTR_RDP_Pos);
}
#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */

Expand Down
Loading

0 comments on commit db2261b

Please sign in to comment.