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