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