2017-12-13 22:53:20 +08:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2017 Nordic Semiconductor ASA
|
|
|
|
* Copyright (c) 2015 Runtime Inc
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
|
|
|
#include "fcb.h"
|
|
|
|
#include "fcb_priv.h"
|
|
|
|
|
|
|
|
int
|
2018-01-27 06:07:10 +08:00
|
|
|
fcb_getnext_in_sector(struct fcb *fcb, struct fcb_entry *loc)
|
2017-12-13 22:53:20 +08:00
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = fcb_elem_info(fcb, loc);
|
|
|
|
if (rc == 0 || rc == FCB_ERR_CRC) {
|
|
|
|
do {
|
|
|
|
loc->fe_elem_off = loc->fe_data_off +
|
|
|
|
fcb_len_in_flash(fcb, loc->fe_data_len) +
|
|
|
|
fcb_len_in_flash(fcb, FCB_CRC_SZ);
|
|
|
|
rc = fcb_elem_info(fcb, loc);
|
|
|
|
if (rc != FCB_ERR_CRC) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (rc == FCB_ERR_CRC);
|
|
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2018-01-27 06:07:10 +08:00
|
|
|
struct flash_sector *
|
|
|
|
fcb_getnext_sector(struct fcb *fcb, struct flash_sector *sector)
|
2017-12-13 22:53:20 +08:00
|
|
|
{
|
2018-01-27 06:07:10 +08:00
|
|
|
sector++;
|
|
|
|
if (sector >= &fcb->f_sectors[fcb->f_sector_cnt]) {
|
|
|
|
sector = &fcb->f_sectors[0];
|
2017-12-13 22:53:20 +08:00
|
|
|
}
|
2018-01-27 06:07:10 +08:00
|
|
|
return sector;
|
2017-12-13 22:53:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
fcb_getnext_nolock(struct fcb *fcb, struct fcb_entry *loc)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
2018-01-27 06:07:10 +08:00
|
|
|
if (loc->fe_sector == NULL) {
|
2017-12-13 22:53:20 +08:00
|
|
|
/*
|
|
|
|
* Find the first one we have in flash.
|
|
|
|
*/
|
2018-01-27 06:07:10 +08:00
|
|
|
loc->fe_sector = fcb->f_oldest;
|
2017-12-13 22:53:20 +08:00
|
|
|
}
|
2019-03-27 09:57:45 +08:00
|
|
|
if (loc->fe_elem_off == 0U) {
|
2017-12-13 22:53:20 +08:00
|
|
|
/*
|
2018-01-27 06:07:10 +08:00
|
|
|
* If offset is zero, we serve the first entry from the sector.
|
2017-12-13 22:53:20 +08:00
|
|
|
*/
|
|
|
|
loc->fe_elem_off = sizeof(struct fcb_disk_area);
|
|
|
|
rc = fcb_elem_info(fcb, loc);
|
|
|
|
switch (rc) {
|
|
|
|
case 0:
|
|
|
|
return 0;
|
|
|
|
case FCB_ERR_CRC:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
goto next_sector;
|
|
|
|
}
|
|
|
|
} else {
|
2018-01-27 06:07:10 +08:00
|
|
|
rc = fcb_getnext_in_sector(fcb, loc);
|
2017-12-13 22:53:20 +08:00
|
|
|
if (rc == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (rc == FCB_ERR_NOVAR) {
|
|
|
|
goto next_sector;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (rc == FCB_ERR_CRC) {
|
2018-01-27 06:07:10 +08:00
|
|
|
rc = fcb_getnext_in_sector(fcb, loc);
|
2017-12-13 22:53:20 +08:00
|
|
|
if (rc == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rc != FCB_ERR_CRC) {
|
|
|
|
/*
|
|
|
|
* Moving to next sector.
|
|
|
|
*/
|
|
|
|
next_sector:
|
2018-01-27 06:07:10 +08:00
|
|
|
if (loc->fe_sector == fcb->f_active.fe_sector) {
|
2017-12-13 22:53:20 +08:00
|
|
|
return FCB_ERR_NOVAR;
|
|
|
|
}
|
2018-01-27 06:07:10 +08:00
|
|
|
loc->fe_sector = fcb_getnext_sector(fcb, loc->fe_sector);
|
2017-12-13 22:53:20 +08:00
|
|
|
loc->fe_elem_off = sizeof(struct fcb_disk_area);
|
|
|
|
rc = fcb_elem_info(fcb, loc);
|
|
|
|
switch (rc) {
|
|
|
|
case 0:
|
|
|
|
return 0;
|
|
|
|
case FCB_ERR_CRC:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
goto next_sector;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
fcb_getnext(struct fcb *fcb, struct fcb_entry *loc)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = k_mutex_lock(&fcb->f_mtx, K_FOREVER);
|
|
|
|
if (rc) {
|
|
|
|
return FCB_ERR_ARGS;
|
|
|
|
}
|
|
|
|
rc = fcb_getnext_nolock(fcb, loc);
|
|
|
|
k_mutex_unlock(&fcb->f_mtx);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|