drivers: flash: simulator: fix address resolution

The flash simulator assumes that flash is being addressed with absolute
addresses by clients. But this is not the case. Given addresses are
relative to the flash base address.

The existing code only worked because the base address was always zero.
Testing with non-zero base addresses caused a mem fault/page fault.

(Reproducible e.g. when using the NVS settings subsystem on QEMU x86
with a non-zero base address in the soc-nv-flash node.)

Fixes #79082

Signed-off-by: Florian Grandel <fgrandel@code-for-humans.de>
This commit is contained in:
Florian Grandel 2024-09-25 11:25:46 +02:00 committed by Alberto Escolar
parent ca26820ac1
commit 117a0098f3
1 changed files with 6 additions and 8 deletions

View File

@ -48,7 +48,7 @@
#error "Erase unit must be a multiple of program unit" #error "Erase unit must be a multiple of program unit"
#endif #endif
#define MOCK_FLASH(addr) (mock_flash + (addr) - FLASH_SIMULATOR_BASE_OFFSET) #define MOCK_FLASH(offset) (mock_flash + (offset))
/* maximum number of pages that can be tracked by the stats module */ /* maximum number of pages that can be tracked by the stats module */
#define STATS_PAGE_COUNT_THRESHOLD 256 #define STATS_PAGE_COUNT_THRESHOLD 256
@ -174,9 +174,9 @@ static int flash_range_is_valid(const struct device *dev, off_t offset,
size_t len) size_t len)
{ {
ARG_UNUSED(dev); ARG_UNUSED(dev);
if ((offset + len > FLASH_SIMULATOR_FLASH_SIZE +
FLASH_SIMULATOR_BASE_OFFSET) || if ((offset < 0 || offset >= FLASH_SIMULATOR_FLASH_SIZE ||
(offset < FLASH_SIMULATOR_BASE_OFFSET)) { (FLASH_SIMULATOR_FLASH_SIZE - offset) < len)) {
return 0; return 0;
} }
@ -299,8 +299,7 @@ static int flash_sim_write(const struct device *dev, const off_t offset,
static void unit_erase(const uint32_t unit) static void unit_erase(const uint32_t unit)
{ {
const off_t unit_addr = FLASH_SIMULATOR_BASE_OFFSET + const off_t unit_addr = unit * FLASH_SIMULATOR_ERASE_UNIT;
(unit * FLASH_SIMULATOR_ERASE_UNIT);
/* erase the memory unit by setting it to erase value */ /* erase the memory unit by setting it to erase value */
memset(MOCK_FLASH(unit_addr), FLASH_SIMULATOR_ERASE_VALUE, memset(MOCK_FLASH(unit_addr), FLASH_SIMULATOR_ERASE_VALUE,
@ -332,8 +331,7 @@ static int flash_sim_erase(const struct device *dev, const off_t offset,
} }
#endif #endif
/* the first unit to be erased */ /* the first unit to be erased */
uint32_t unit_start = (offset - FLASH_SIMULATOR_BASE_OFFSET) / uint32_t unit_start = offset / FLASH_SIMULATOR_ERASE_UNIT;
FLASH_SIMULATOR_ERASE_UNIT;
/* erase as many units as necessary and increase their erase counter */ /* erase as many units as necessary and increase their erase counter */
for (uint32_t i = 0; i < len / FLASH_SIMULATOR_ERASE_UNIT; i++) { for (uint32_t i = 0; i < len / FLASH_SIMULATOR_ERASE_UNIT; i++) {