1 /*
2 * Copyright (c) 2017-2020 Nordic Semiconductor ASA
3 * Copyright (c) 2015 Runtime Inc
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <stdio.h>
9 #include <string.h>
10
11 #include "fcb_test.h"
12 #include <storage/flash_map.h>
13 #include <drivers/flash.h>
14 #include <device.h>
15
16 struct fcb test_fcb;
17 uint8_t fcb_test_erase_value;
18
19 /* Sectors for FCB are defined far from application code
20 * area. This test suite is the non bootable application so 1. image slot is
21 * suitable for it.
22 */
23 struct flash_sector test_fcb_sector[] = {
24 [0] = {
25 .fs_off = 0,
26 .fs_size = 0x4000, /* 16K */
27 },
28 [1] = {
29 .fs_off = 0x4000,
30 .fs_size = 0x4000
31 },
32 [2] = {
33 .fs_off = 0x8000,
34 .fs_size = 0x4000
35 },
36 [3] = {
37 .fs_off = 0xc000,
38 .fs_size = 0x4000
39 }
40 };
41
42
test_fcb_wipe(void)43 void test_fcb_wipe(void)
44 {
45 int i;
46 int rc;
47 const struct flash_area *fap;
48
49 rc = flash_area_open(TEST_FCB_FLASH_AREA_ID, &fap);
50 zassert_true(rc == 0, "flash area open call failure");
51
52 for (i = 0; i < ARRAY_SIZE(test_fcb_sector); i++) {
53 rc = flash_area_erase(fap, test_fcb_sector[i].fs_off,
54 test_fcb_sector[i].fs_size);
55 zassert_true(rc == 0, "erase call failure");
56 }
57 }
58
fcb_test_empty_walk_cb(struct fcb_entry_ctx * entry_ctx,void * arg)59 int fcb_test_empty_walk_cb(struct fcb_entry_ctx *entry_ctx, void *arg)
60 {
61 zassert_unreachable("fcb_test_empty_walk_cb");
62 return 0;
63 }
64
fcb_test_append_data(int msg_len,int off)65 uint8_t fcb_test_append_data(int msg_len, int off)
66 {
67 return (msg_len ^ off);
68 }
69
fcb_test_data_walk_cb(struct fcb_entry_ctx * entry_ctx,void * arg)70 int fcb_test_data_walk_cb(struct fcb_entry_ctx *entry_ctx, void *arg)
71 {
72 uint16_t len;
73 uint8_t test_data[128];
74 int rc;
75 int i;
76 int *var_cnt = (int *)arg;
77
78 len = entry_ctx->loc.fe_data_len;
79
80 zassert_true(len == *var_cnt, "");
81
82 rc = flash_area_read(entry_ctx->fap,
83 FCB_ENTRY_FA_DATA_OFF(entry_ctx->loc),
84 test_data, len);
85 zassert_true(rc == 0, "read call failure");
86
87 for (i = 0; i < len; i++) {
88 zassert_true(test_data[i] == fcb_test_append_data(len, i),
89 "fcb_test_append_data redout misrepresentation");
90 }
91 (*var_cnt)++;
92 return 0;
93 }
94
fcb_test_cnt_elems_cb(struct fcb_entry_ctx * entry_ctx,void * arg)95 int fcb_test_cnt_elems_cb(struct fcb_entry_ctx *entry_ctx, void *arg)
96 {
97 struct append_arg *aa = (struct append_arg *)arg;
98 int idx;
99
100 idx = entry_ctx->loc.fe_sector - &test_fcb_sector[0];
101 aa->elem_cnts[idx]++;
102 return 0;
103 }
104
fcb_tc_pretest(int sectors)105 void fcb_tc_pretest(int sectors)
106 {
107 struct fcb *fcb;
108 int rc = 0;
109
110 test_fcb_wipe();
111 fcb = &test_fcb;
112 (void)memset(fcb, 0, sizeof(*fcb));
113 fcb->f_erase_value = fcb_test_erase_value;
114 fcb->f_sector_cnt = sectors;
115 fcb->f_sectors = test_fcb_sector; /* XXX */
116
117 rc = 0;
118 rc = fcb_init(TEST_FCB_FLASH_AREA_ID, fcb);
119 if (rc != 0) {
120 printf("%s rc == %xm, %d\n", __func__, rc, rc);
121 zassert_true(rc == 0, "fbc initialization failure");
122 }
123 }
124
fcb_pretest_2_sectors(void)125 void fcb_pretest_2_sectors(void)
126 {
127 fcb_tc_pretest(2);
128 }
129
fcb_pretest_4_sectors(void)130 void fcb_pretest_4_sectors(void)
131 {
132 fcb_tc_pretest(4);
133 }
134
teardown_nothing(void)135 void teardown_nothing(void)
136 {
137 }
138
139 /*
140 * This actually is not a test; the function gets erase value from flash
141 * parameters, of the flash device that is used by tests, and stores it in
142 * global fcb_test_erase_value.
143 */
test_get_flash_erase_value(void)144 void test_get_flash_erase_value(void)
145 {
146 const struct flash_area *fa;
147 const struct flash_parameters *fp;
148 const struct device *dev;
149 int rc = 0;
150
151 rc = flash_area_open(TEST_FCB_FLASH_AREA_ID, &fa);
152 zassert_equal(rc, 0, "Failed top open flash area");
153
154 dev = device_get_binding(fa->fa_dev_name);
155 flash_area_close(fa);
156
157 zassert_true(dev != NULL, "Failed to obtain device");
158
159 fp = flash_get_parameters(dev);
160 zassert_true(fp != NULL, "Failed to get flash device parameters");
161
162 fcb_test_erase_value = fp->erase_value;
163 }
164
165 void test_fcb_len(void);
166 void test_fcb_init(void);
167 void test_fcb_empty_walk(void);
168 void test_fcb_append(void);
169 void test_fcb_append_too_big(void);
170 void test_fcb_append_fill(void);
171 void test_fcb_reset(void);
172 void test_fcb_rotate(void);
173 void test_fcb_multi_scratch(void);
174 void test_fcb_last_of_n(void);
175
test_main(void)176 void test_main(void)
177 {
178 ztest_test_suite(test_fcb,
179 ztest_unit_test(test_get_flash_erase_value),
180 ztest_unit_test_setup_teardown(test_fcb_len,
181 fcb_pretest_2_sectors,
182 teardown_nothing),
183 ztest_unit_test(test_fcb_init),
184 ztest_unit_test_setup_teardown(test_fcb_empty_walk,
185 fcb_pretest_2_sectors,
186 teardown_nothing),
187 ztest_unit_test_setup_teardown(test_fcb_append,
188 fcb_pretest_2_sectors,
189 teardown_nothing),
190 ztest_unit_test_setup_teardown(test_fcb_append_too_big,
191 fcb_pretest_2_sectors,
192 teardown_nothing),
193 ztest_unit_test_setup_teardown(test_fcb_append_fill,
194 fcb_pretest_2_sectors,
195 teardown_nothing),
196 ztest_unit_test_setup_teardown(test_fcb_rotate,
197 fcb_pretest_2_sectors,
198 teardown_nothing),
199 ztest_unit_test_setup_teardown(test_fcb_multi_scratch,
200 fcb_pretest_4_sectors,
201 teardown_nothing),
202 ztest_unit_test_setup_teardown(test_fcb_last_of_n,
203 fcb_pretest_4_sectors,
204 teardown_nothing),
205 /* Finally, run one that leaves behind a
206 * flash.bin file without any random content */
207 ztest_unit_test_setup_teardown(test_fcb_reset,
208 fcb_pretest_2_sectors,
209 teardown_nothing)
210 );
211
212 ztest_run_test_suite(test_fcb);
213 }
214