1 /*
2  * Copyright (c) 2017-2023 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 <zephyr/storage/flash_map.h>
13 #include <zephyr/drivers/flash.h>
14 #include <zephyr/device.h>
15 
16 struct fcb test_fcb = {0};
17 struct fcb test_fcb_crc_disabled = { .f_flags = FCB_FLAGS_CRC_DISABLED };
18 
19 uint8_t fcb_test_erase_value;
20 
21 #if defined(CONFIG_SOC_SERIES_STM32H7X)
22 	#define SECTOR_SIZE 0x20000 /* 128K */
23 #else
24 	#define SECTOR_SIZE 0x4000 /* 16K */
25 #endif
26 
27 /* Sectors for FCB are defined far from application code
28  * area. This test suite is the non bootable application so 1. image slot is
29  * suitable for it.
30  */
31 struct flash_sector test_fcb_sector[] = {
32 	[0] = {
33 		.fs_off = 0,
34 		.fs_size = SECTOR_SIZE
35 	},
36 	[1] = {
37 		.fs_off = SECTOR_SIZE,
38 		.fs_size = SECTOR_SIZE
39 	},
40 	[2] = {
41 		.fs_off = 2 * SECTOR_SIZE,
42 		.fs_size = SECTOR_SIZE
43 	},
44 	[3] = {
45 		.fs_off = 3 * SECTOR_SIZE,
46 		.fs_size = SECTOR_SIZE
47 	}
48 };
49 
50 
test_fcb_wipe(void)51 void test_fcb_wipe(void)
52 {
53 	int i;
54 	int rc;
55 	const struct flash_area *fap;
56 
57 	rc = flash_area_open(TEST_FCB_FLASH_AREA_ID, &fap);
58 	zassert_true(rc == 0, "flash area open call failure");
59 
60 	for (i = 0; i < ARRAY_SIZE(test_fcb_sector); i++) {
61 		rc = flash_area_erase(fap, test_fcb_sector[i].fs_off,
62 				      test_fcb_sector[i].fs_size);
63 		zassert_true(rc == 0, "erase call failure");
64 	}
65 }
66 
fcb_test_empty_walk_cb(struct fcb_entry_ctx * entry_ctx,void * arg)67 int fcb_test_empty_walk_cb(struct fcb_entry_ctx *entry_ctx, void *arg)
68 {
69 	zassert_unreachable("fcb_test_empty_walk_cb");
70 	return 0;
71 }
72 
fcb_test_append_data(int msg_len,int off)73 uint8_t fcb_test_append_data(int msg_len, int off)
74 {
75 	return (msg_len ^ off);
76 }
77 
fcb_test_data_walk_cb(struct fcb_entry_ctx * entry_ctx,void * arg)78 int fcb_test_data_walk_cb(struct fcb_entry_ctx *entry_ctx, void *arg)
79 {
80 	uint16_t len;
81 	uint8_t test_data[128];
82 	int rc;
83 	int i;
84 	int *var_cnt = (int *)arg;
85 
86 	len = entry_ctx->loc.fe_data_len;
87 
88 	zassert_true(len == *var_cnt, "");
89 
90 	rc = flash_area_read(entry_ctx->fap,
91 			     FCB_ENTRY_FA_DATA_OFF(entry_ctx->loc),
92 			     test_data, len);
93 	zassert_true(rc == 0, "read call failure");
94 
95 	for (i = 0; i < len; i++) {
96 		zassert_true(test_data[i] == fcb_test_append_data(len, i),
97 		"fcb_test_append_data redout misrepresentation");
98 	}
99 	(*var_cnt)++;
100 	return 0;
101 }
102 
fcb_test_cnt_elems_cb(struct fcb_entry_ctx * entry_ctx,void * arg)103 int fcb_test_cnt_elems_cb(struct fcb_entry_ctx *entry_ctx, void *arg)
104 {
105 	struct append_arg *aa = (struct append_arg *)arg;
106 	int idx;
107 
108 	idx = entry_ctx->loc.fe_sector - &test_fcb_sector[0];
109 	aa->elem_cnts[idx]++;
110 	return 0;
111 }
112 
fcb_tc_pretest(int sectors,struct fcb * _fcb)113 void fcb_tc_pretest(int sectors, struct fcb *_fcb)
114 {
115 	int rc = 0;
116 
117 	test_fcb_wipe();
118 	_fcb->f_erase_value = fcb_test_erase_value;
119 	_fcb->f_sector_cnt = sectors;
120 	_fcb->f_sectors = test_fcb_sector; /* XXX */
121 
122 	rc = 0;
123 	rc = fcb_init(TEST_FCB_FLASH_AREA_ID, _fcb);
124 	if (rc != 0) {
125 		printf("%s rc == %xm, %d\n", __func__, rc, rc);
126 		zassert_true(rc == 0, "fbc initialization failure");
127 	}
128 }
129 
fcb_pretest_2_sectors(void * data)130 static void fcb_pretest_2_sectors(void *data)
131 {
132 	fcb_tc_pretest(2, &test_fcb);
133 }
134 
fcb_pretest_4_sectors(void * data)135 static void fcb_pretest_4_sectors(void *data)
136 {
137 	fcb_tc_pretest(4, &test_fcb);
138 }
139 
fcb_pretest_crc_disabled(void * data)140 static void fcb_pretest_crc_disabled(void *data)
141 {
142 	fcb_tc_pretest(2, &test_fcb_crc_disabled);
143 }
144 
145 /*
146  * This actually is not a test; the function gets erase value from flash
147  * parameters, of the flash device that is used by tests, and stores it in
148  * global fcb_test_erase_value.
149  */
ZTEST(fcb_test_without_set,test_get_flash_erase_value)150 ZTEST(fcb_test_without_set, test_get_flash_erase_value)
151 {
152 	const struct flash_area *fa;
153 	const struct flash_parameters *fp;
154 	const struct device *dev;
155 	int rc = 0;
156 
157 	rc = flash_area_open(TEST_FCB_FLASH_AREA_ID, &fa);
158 	zassert_equal(rc, 0, "Failed top open flash area");
159 
160 	dev = fa->fa_dev;
161 	flash_area_close(fa);
162 
163 	zassert_true(dev != NULL, "Failed to obtain device");
164 
165 	fp = flash_get_parameters(dev);
166 	zassert_true(fp != NULL, "Failed to get flash device parameters");
167 
168 	fcb_test_erase_value = fp->erase_value;
169 }
170 
171 ZTEST_SUITE(fcb_test_without_set, NULL, NULL, NULL, NULL, NULL);
172 ZTEST_SUITE(fcb_test_with_2sectors_set, NULL, NULL, fcb_pretest_2_sectors, NULL, NULL);
173 ZTEST_SUITE(fcb_test_with_4sectors_set, NULL, NULL, fcb_pretest_4_sectors, NULL, NULL);
174 
175 ZTEST_SUITE(fcb_test_crc_disabled, NULL, NULL, fcb_pretest_crc_disabled, NULL, NULL);
176