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