drivers: flashdisk: check partition constraints
Fail with error if any of flashdisk partition assumptions are not met: * uniform page size through the whole partition * flashdisk starts at page boundary * flashdisk ends at page boundary Read-only flashdisks are not subject to above conditions because the cache buffer is not used for read-only flashdisks. The checks can be disabled via Kconfig option to save code space. Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
This commit is contained in:
parent
8981015335
commit
c011646081
2 changed files with 70 additions and 28 deletions
|
@ -9,6 +9,14 @@ config DISK_DRIVER_FLASH
|
||||||
Flash device is used for the file system.
|
Flash device is used for the file system.
|
||||||
|
|
||||||
if DISK_DRIVER_FLASH
|
if DISK_DRIVER_FLASH
|
||||||
|
|
||||||
|
config FLASHDISK_VERIFY_PAGE_LAYOUT
|
||||||
|
bool "Verify flashdisk partition layout"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Enable runtime zephyr,flash-disk partition page layout constraints
|
||||||
|
verification. Disable to reduce code size.
|
||||||
|
|
||||||
module = FLASHDISK
|
module = FLASHDISK
|
||||||
module-str = flashdisk
|
module-str = flashdisk
|
||||||
source "subsys/logging/Kconfig.template.log_config"
|
source "subsys/logging/Kconfig.template.log_config"
|
||||||
|
|
|
@ -47,12 +47,72 @@ static int disk_flash_access_status(struct disk_info *disk)
|
||||||
return DISK_STATUS_OK;
|
return DISK_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int flashdisk_init_runtime(struct flashdisk_data *ctx,
|
||||||
|
const struct flash_area *fap)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
struct flash_pages_info page;
|
||||||
|
off_t offset;
|
||||||
|
|
||||||
|
rc = flash_get_page_info_by_offs(ctx->info.dev, ctx->offset, &page);
|
||||||
|
if (rc < 0) {
|
||||||
|
LOG_ERR("Error %d while getting page info", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->page_size = page.size;
|
||||||
|
LOG_INF("Initialize device %s", ctx->info.name);
|
||||||
|
LOG_INF("offset %lx, sector size %zu, page size %zu, volume size %zu",
|
||||||
|
(long)ctx->offset, ctx->sector_size, ctx->page_size, ctx->size);
|
||||||
|
|
||||||
|
if (ctx->cache_size == 0) {
|
||||||
|
/* Read-only flashdisk, no flash partition constraints */
|
||||||
|
LOG_INF("%s is read-only", ctx->info.name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_FLASHDISK_VERIFY_PAGE_LAYOUT)) {
|
||||||
|
if (ctx->offset != page.start_offset) {
|
||||||
|
LOG_ERR("Disk %s does not start at page boundary",
|
||||||
|
ctx->info.name);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = ctx->offset + page.size;
|
||||||
|
while (offset < ctx->offset + ctx->size) {
|
||||||
|
rc = flash_get_page_info_by_offs(ctx->info.dev, offset, &page);
|
||||||
|
if (rc < 0) {
|
||||||
|
LOG_ERR("Error %d while getting page info", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
if (page.size != ctx->page_size) {
|
||||||
|
LOG_ERR("Non-uniform page size is not supported");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
offset += page.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset != ctx->offset + ctx->size) {
|
||||||
|
LOG_ERR("Last page crossess disk %s boundary",
|
||||||
|
ctx->info.name);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->page_size > ctx->cache_size) {
|
||||||
|
LOG_ERR("Cache too small (%zu needs %zu)",
|
||||||
|
ctx->cache_size, ctx->page_size);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int disk_flash_access_init(struct disk_info *disk)
|
static int disk_flash_access_init(struct disk_info *disk)
|
||||||
{
|
{
|
||||||
struct flashdisk_data *ctx;
|
struct flashdisk_data *ctx;
|
||||||
const struct flash_area *fap;
|
const struct flash_area *fap;
|
||||||
int rc;
|
int rc;
|
||||||
struct flash_pages_info page;
|
|
||||||
|
|
||||||
ctx = CONTAINER_OF(disk, struct flashdisk_data, info);
|
ctx = CONTAINER_OF(disk, struct flashdisk_data, info);
|
||||||
|
|
||||||
|
@ -66,33 +126,7 @@ static int disk_flash_access_init(struct disk_info *disk)
|
||||||
|
|
||||||
disk->dev = flash_area_get_device(fap);
|
disk->dev = flash_area_get_device(fap);
|
||||||
|
|
||||||
rc = flash_get_page_info_by_offs(disk->dev, ctx->offset, &page);
|
rc = flashdisk_init_runtime(ctx, fap);
|
||||||
if (rc < 0) {
|
|
||||||
LOG_ERR("Error %d while getting page info", rc);
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->page_size = page.size;
|
|
||||||
LOG_INF("Initialize device %s", disk->name);
|
|
||||||
LOG_INF("offset %lx, sector size %zu, page size %zu, volume size %zu",
|
|
||||||
(long)ctx->offset, ctx->sector_size, ctx->page_size, ctx->size);
|
|
||||||
|
|
||||||
if (ctx->cache_size == 0) {
|
|
||||||
LOG_INF("%s is read-only", disk->name);
|
|
||||||
} else if (ctx->page_size > ctx->cache_size) {
|
|
||||||
LOG_ERR("Cache too small (%zu needs %zu)",
|
|
||||||
ctx->cache_size, ctx->page_size);
|
|
||||||
rc = -ENOMEM;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx->cache_valid && ctx->cache_dirty) {
|
|
||||||
LOG_ERR("Discarding %s dirty cache", disk->name);
|
|
||||||
ctx->cache_valid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = 0;
|
|
||||||
end:
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
flash_area_close(fap);
|
flash_area_close(fap);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue