1 /*
2 * Copyright (c) 2017 Nordic Semiconductor ASA
3 * Copyright (c) 2015 Runtime Inc
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <stddef.h>
9
10 #include <fs/fcb.h>
11 #include "fcb_priv.h"
12
13 int
fcb_getnext_in_sector(struct fcb * fcb,struct fcb_entry * loc)14 fcb_getnext_in_sector(struct fcb *fcb, struct fcb_entry *loc)
15 {
16 int rc;
17
18 rc = fcb_elem_info(fcb, loc);
19 if (rc == 0 || rc == -EBADMSG) {
20 do {
21 loc->fe_elem_off = loc->fe_data_off +
22 fcb_len_in_flash(fcb, loc->fe_data_len) +
23 fcb_len_in_flash(fcb, FCB_CRC_SZ);
24 rc = fcb_elem_info(fcb, loc);
25 if (rc != -EBADMSG) {
26 break;
27 }
28 } while (rc == -EBADMSG);
29 }
30 return rc;
31 }
32
33 struct flash_sector *
fcb_getnext_sector(struct fcb * fcb,struct flash_sector * sector)34 fcb_getnext_sector(struct fcb *fcb, struct flash_sector *sector)
35 {
36 sector++;
37 if (sector >= &fcb->f_sectors[fcb->f_sector_cnt]) {
38 sector = &fcb->f_sectors[0];
39 }
40 return sector;
41 }
42
43 int
fcb_getnext_nolock(struct fcb * fcb,struct fcb_entry * loc)44 fcb_getnext_nolock(struct fcb *fcb, struct fcb_entry *loc)
45 {
46 int rc;
47
48 if (loc->fe_sector == NULL) {
49 /*
50 * Find the first one we have in flash.
51 */
52 loc->fe_sector = fcb->f_oldest;
53 }
54 if (loc->fe_elem_off == 0U) {
55 /*
56 * If offset is zero, we serve the first entry from the sector.
57 */
58 loc->fe_elem_off = sizeof(struct fcb_disk_area);
59 rc = fcb_elem_info(fcb, loc);
60 switch (rc) {
61 case 0:
62 return 0;
63 case -EBADMSG:
64 break;
65 default:
66 goto next_sector;
67 }
68 } else {
69 rc = fcb_getnext_in_sector(fcb, loc);
70 if (rc == 0) {
71 return 0;
72 }
73 if (rc == -ENOTSUP) {
74 goto next_sector;
75 }
76 }
77 while (rc == -EBADMSG) {
78 rc = fcb_getnext_in_sector(fcb, loc);
79 if (rc == 0) {
80 return 0;
81 }
82
83 if (rc != -EBADMSG) {
84 /*
85 * Moving to next sector.
86 */
87 next_sector:
88 if (loc->fe_sector == fcb->f_active.fe_sector) {
89 return -ENOTSUP;
90 }
91 loc->fe_sector = fcb_getnext_sector(fcb, loc->fe_sector);
92 loc->fe_elem_off = sizeof(struct fcb_disk_area);
93 rc = fcb_elem_info(fcb, loc);
94 switch (rc) {
95 case 0:
96 return 0;
97 case -EBADMSG:
98 break;
99 default:
100 goto next_sector;
101 }
102 }
103 }
104
105 return 0;
106 }
107
108 int
fcb_getnext(struct fcb * fcb,struct fcb_entry * loc)109 fcb_getnext(struct fcb *fcb, struct fcb_entry *loc)
110 {
111 int rc;
112
113 rc = k_mutex_lock(&fcb->f_mtx, K_FOREVER);
114 if (rc) {
115 return -EINVAL;
116 }
117 rc = fcb_getnext_nolock(fcb, loc);
118 k_mutex_unlock(&fcb->f_mtx);
119
120 return rc;
121 }
122