1 /*
2  * Copyright (c) 2019 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdio.h>
8 #include <string.h>
9 #include <zephyr/ztest.h>
10 
11 #include <zephyr/drivers/flash.h>
12 #include <zephyr/fs/nvs.h>
13 #include <zephyr/stats/stats.h>
14 #include <zephyr/storage/flash_map.h>
15 #include <zephyr/sys/crc.h>
16 #include "nvs_priv.h"
17 
18 #define TEST_NVS_FLASH_AREA		storage_partition
19 #define TEST_NVS_FLASH_AREA_OFFSET	FIXED_PARTITION_OFFSET(TEST_NVS_FLASH_AREA)
20 #define TEST_NVS_FLASH_AREA_ID		FIXED_PARTITION_ID(TEST_NVS_FLASH_AREA)
21 #define TEST_NVS_FLASH_AREA_DEV \
22 	DEVICE_DT_GET(DT_MTD_FROM_FIXED_PARTITION(DT_NODELABEL(TEST_NVS_FLASH_AREA)))
23 #define TEST_DATA_ID			1
24 #define TEST_SECTOR_COUNT		5U
25 
26 static const struct device *const flash_dev = TEST_NVS_FLASH_AREA_DEV;
27 
28 struct nvs_fixture {
29 	struct nvs_fs fs;
30 #ifdef CONFIG_TEST_NVS_SIMULATOR
31 	struct stats_hdr *sim_stats;
32 	struct stats_hdr *sim_thresholds;
33 #endif /* CONFIG_TEST_NVS_SIMULATOR */
34 };
35 
setup(void)36 static void *setup(void)
37 {
38 	int err;
39 	const struct flash_area *fa;
40 	struct flash_pages_info info;
41 	static struct nvs_fixture fixture;
42 
43 	__ASSERT_NO_MSG(device_is_ready(flash_dev));
44 
45 	err = flash_area_open(TEST_NVS_FLASH_AREA_ID, &fa);
46 	zassert_true(err == 0, "flash_area_open() fail: %d", err);
47 
48 	fixture.fs.offset = TEST_NVS_FLASH_AREA_OFFSET;
49 	err = flash_get_page_info_by_offs(flash_area_get_device(fa), fixture.fs.offset,
50 					  &info);
51 	zassert_true(err == 0,  "Unable to get page info: %d", err);
52 
53 	fixture.fs.sector_size = info.size;
54 	fixture.fs.sector_count = TEST_SECTOR_COUNT;
55 	fixture.fs.flash_device = flash_area_get_device(fa);
56 
57 	return &fixture;
58 }
59 
before(void * data)60 static void before(void *data)
61 {
62 #ifdef CONFIG_TEST_NVS_SIMULATOR
63 	struct nvs_fixture *fixture = (struct nvs_fixture *)data;
64 
65 	fixture->sim_stats = stats_group_find("flash_sim_stats");
66 	fixture->sim_thresholds = stats_group_find("flash_sim_thresholds");
67 #endif /* CONFIG_TEST_NVS_SIMULATOR */
68 }
69 
after(void * data)70 static void after(void *data)
71 {
72 	struct nvs_fixture *fixture = (struct nvs_fixture *)data;
73 
74 #ifdef CONFIG_TEST_NVS_SIMULATOR
75 	if (fixture->sim_stats) {
76 		stats_reset(fixture->sim_stats);
77 	}
78 	if (fixture->sim_thresholds) {
79 		stats_reset(fixture->sim_thresholds);
80 	}
81 #endif /* CONFIG_TEST_NVS_SIMULATOR */
82 
83 	/* Clear NVS */
84 	if (fixture->fs.ready) {
85 		int err;
86 
87 		err = nvs_clear(&fixture->fs);
88 		zassert_true(err == 0, "nvs_clear call failure: %d", err);
89 	}
90 
91 	fixture->fs.sector_count = TEST_SECTOR_COUNT;
92 }
93 
94 ZTEST_SUITE(nvs, NULL, setup, before, after, NULL);
95 
ZTEST_F(nvs,test_nvs_mount)96 ZTEST_F(nvs, test_nvs_mount)
97 {
98 	int err;
99 	size_t orig_sector_size = fixture->fs.sector_size;
100 
101 	fixture->fs.sector_size = KB(128);
102 	err = nvs_mount(&fixture->fs);
103 	zassert_true(err == -EINVAL,
104 		     "nvs_mount did not return expected err for invalid sector_size");
105 
106 	fixture->fs.sector_size = orig_sector_size;
107 	err = nvs_mount(&fixture->fs);
108 	zassert_true(err == 0,  "nvs_mount call failure: %d", err);
109 }
110 
execute_long_pattern_write(uint16_t id,struct nvs_fs * fs)111 static void execute_long_pattern_write(uint16_t id, struct nvs_fs *fs)
112 {
113 	char rd_buf[512];
114 	char wr_buf[512];
115 	char pattern[] = {0xDE, 0xAD, 0xBE, 0xEF};
116 	size_t len;
117 
118 	len = nvs_read(fs, id, rd_buf, sizeof(rd_buf));
119 	zassert_true(len == -ENOENT,  "nvs_read unexpected failure: %d", len);
120 
121 	BUILD_ASSERT((sizeof(wr_buf) % sizeof(pattern)) == 0);
122 	for (int i = 0; i < sizeof(wr_buf); i += sizeof(pattern)) {
123 		memcpy(wr_buf + i, pattern, sizeof(pattern));
124 	}
125 
126 	len = nvs_write(fs, id, wr_buf, sizeof(wr_buf));
127 	zassert_true(len == sizeof(wr_buf), "nvs_write failed: %d", len);
128 
129 	len = nvs_read(fs, id, rd_buf, sizeof(rd_buf));
130 	zassert_true(len == sizeof(rd_buf),  "nvs_read unexpected failure: %d",
131 			len);
132 	zassert_mem_equal(wr_buf, rd_buf, sizeof(rd_buf),
133 			"RD buff should be equal to the WR buff");
134 }
135 
ZTEST_F(nvs,test_nvs_write)136 ZTEST_F(nvs, test_nvs_write)
137 {
138 	int err;
139 
140 	err = nvs_mount(&fixture->fs);
141 	zassert_true(err == 0,  "nvs_mount call failure: %d", err);
142 
143 	execute_long_pattern_write(TEST_DATA_ID, &fixture->fs);
144 }
145 
146 #ifdef CONFIG_TEST_NVS_SIMULATOR
flash_sim_write_calls_find(struct stats_hdr * hdr,void * arg,const char * name,uint16_t off)147 static int flash_sim_write_calls_find(struct stats_hdr *hdr, void *arg,
148 				      const char *name, uint16_t off)
149 {
150 	if (!strcmp(name, "flash_write_calls")) {
151 		uint32_t **flash_write_stat = (uint32_t **) arg;
152 		*flash_write_stat = (uint32_t *)((uint8_t *)hdr + off);
153 	}
154 
155 	return 0;
156 }
157 
flash_sim_max_write_calls_find(struct stats_hdr * hdr,void * arg,const char * name,uint16_t off)158 static int flash_sim_max_write_calls_find(struct stats_hdr *hdr, void *arg,
159 					  const char *name, uint16_t off)
160 {
161 	if (!strcmp(name, "max_write_calls")) {
162 		uint32_t **max_write_calls = (uint32_t **) arg;
163 		*max_write_calls = (uint32_t *)((uint8_t *)hdr + off);
164 	}
165 
166 	return 0;
167 }
168 
ZTEST_F(nvs,test_nvs_corrupted_write)169 ZTEST_F(nvs, test_nvs_corrupted_write)
170 {
171 	int err;
172 	size_t len;
173 	char rd_buf[512];
174 	char wr_buf_1[512];
175 	char wr_buf_2[512];
176 	char pattern_1[] = {0xDE, 0xAD, 0xBE, 0xEF};
177 	char pattern_2[] = {0x03, 0xAA, 0x85, 0x6F};
178 	uint32_t *flash_write_stat;
179 	uint32_t *flash_max_write_calls;
180 
181 	err = nvs_mount(&fixture->fs);
182 	zassert_true(err == 0,  "nvs_mount call failure: %d", err);
183 
184 	err = nvs_read(&fixture->fs, TEST_DATA_ID, rd_buf, sizeof(rd_buf));
185 	zassert_true(err == -ENOENT,  "nvs_read unexpected failure: %d", err);
186 
187 	BUILD_ASSERT((sizeof(wr_buf_1) % sizeof(pattern_1)) == 0);
188 	for (int i = 0; i < sizeof(wr_buf_1); i += sizeof(pattern_1)) {
189 		memcpy(wr_buf_1 + i, pattern_1, sizeof(pattern_1));
190 	}
191 
192 	len = nvs_write(&fixture->fs, TEST_DATA_ID, wr_buf_1, sizeof(wr_buf_1));
193 	zassert_true(len == sizeof(wr_buf_1), "nvs_write failed: %d", len);
194 
195 	len = nvs_read(&fixture->fs, TEST_DATA_ID, rd_buf, sizeof(rd_buf));
196 	zassert_true(len == sizeof(rd_buf),  "nvs_read unexpected failure: %d",
197 			len);
198 	zassert_mem_equal(wr_buf_1, rd_buf, sizeof(rd_buf),
199 			"RD buff should be equal to the first WR buff");
200 
201 	BUILD_ASSERT((sizeof(wr_buf_2) % sizeof(pattern_2)) == 0);
202 	for (int i = 0; i < sizeof(wr_buf_2); i += sizeof(pattern_2)) {
203 		memcpy(wr_buf_2 + i, pattern_2, sizeof(pattern_2));
204 	}
205 
206 	/* Set the maximum number of writes that the flash simulator can
207 	 * execute.
208 	 */
209 	stats_walk(fixture->sim_thresholds, flash_sim_max_write_calls_find,
210 		   &flash_max_write_calls);
211 	stats_walk(fixture->sim_stats, flash_sim_write_calls_find, &flash_write_stat);
212 
213 #if defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE)
214 	*flash_max_write_calls = *flash_write_stat - 1;
215 #else
216 	/* When there is no explicit erase, erase is done with write, which means
217 	 * that there are more writes needed. The nvs_write here will cause erase
218 	 * to be called, which in turn calls the flash_fill; flash_fill will
219 	 * overwrite data using buffer of size CONFIG_FLASH_FILL_BUFFER_SIZE,
220 	 * and then two additional real writes are allowed.
221 	 */
222 	*flash_max_write_calls = (fixture->fs.sector_size /
223 				  CONFIG_FLASH_FILL_BUFFER_SIZE) + 2;
224 #endif
225 	*flash_write_stat = 0;
226 
227 	/* Flash simulator will lose part of the data at the end of this write.
228 	 * This should simulate power down during flash write. The written data
229 	 * are corrupted at this point and should be discarded by the NVS.
230 	 */
231 	len = nvs_write(&fixture->fs, TEST_DATA_ID, wr_buf_2, sizeof(wr_buf_2));
232 	zassert_true(len == sizeof(wr_buf_2), "nvs_write failed: %d", len);
233 
234 	/* Reinitialize the NVS. */
235 	memset(&fixture->fs, 0, sizeof(fixture->fs));
236 	(void)setup();
237 	err = nvs_mount(&fixture->fs);
238 	zassert_true(err == 0,  "nvs_mount call failure: %d", err);
239 
240 	len = nvs_read(&fixture->fs, TEST_DATA_ID, rd_buf, sizeof(rd_buf));
241 	zassert_true(len == sizeof(rd_buf),  "nvs_read unexpected failure: %d",
242 			len);
243 	zassert_true(memcmp(wr_buf_2, rd_buf, sizeof(rd_buf)) != 0,
244 			"RD buff should not be equal to the second WR buff because of "
245 			"corrupted write operation");
246 	zassert_mem_equal(wr_buf_1, rd_buf, sizeof(rd_buf),
247 			"RD buff should be equal to the first WR buff because subsequent "
248 			"write operation has failed");
249 }
250 
ZTEST_F(nvs,test_nvs_gc)251 ZTEST_F(nvs, test_nvs_gc)
252 {
253 	int err;
254 	int len;
255 	uint8_t buf[32];
256 	uint8_t rd_buf[32];
257 
258 	const uint16_t max_id = 10;
259 	/* 25th write will trigger GC. */
260 	const uint16_t max_writes = 26;
261 
262 	fixture->fs.sector_count = 2;
263 
264 	err = nvs_mount(&fixture->fs);
265 	zassert_true(err == 0,  "nvs_mount call failure: %d", err);
266 
267 	for (uint16_t i = 0; i < max_writes; i++) {
268 		uint8_t id = (i % max_id);
269 		uint8_t id_data = id + max_id * (i / max_id);
270 
271 		memset(buf, id_data, sizeof(buf));
272 
273 		len = nvs_write(&fixture->fs, id, buf, sizeof(buf));
274 		zassert_true(len == sizeof(buf), "nvs_write failed: %d", len);
275 	}
276 
277 	for (uint16_t id = 0; id < max_id; id++) {
278 		len = nvs_read(&fixture->fs, id, rd_buf, sizeof(buf));
279 		zassert_true(len == sizeof(rd_buf),
280 			     "nvs_read unexpected failure: %d", len);
281 
282 		for (uint16_t i = 0; i < sizeof(rd_buf); i++) {
283 			rd_buf[i] = rd_buf[i] % max_id;
284 			buf[i] = id;
285 		}
286 		zassert_mem_equal(buf, rd_buf, sizeof(rd_buf),
287 				"RD buff should be equal to the WR buff");
288 
289 	}
290 
291 	err = nvs_mount(&fixture->fs);
292 	zassert_true(err == 0,  "nvs_mount call failure: %d", err);
293 
294 	for (uint16_t id = 0; id < max_id; id++) {
295 		len = nvs_read(&fixture->fs, id, rd_buf, sizeof(buf));
296 		zassert_true(len == sizeof(rd_buf),
297 			     "nvs_read unexpected failure: %d", len);
298 
299 		for (uint16_t i = 0; i < sizeof(rd_buf); i++) {
300 			rd_buf[i] = rd_buf[i] % max_id;
301 			buf[i] = id;
302 		}
303 		zassert_mem_equal(buf, rd_buf, sizeof(rd_buf),
304 				"RD buff should be equal to the WR buff");
305 
306 	}
307 }
308 
write_content(uint16_t max_id,uint16_t begin,uint16_t end,struct nvs_fs * fs)309 static void write_content(uint16_t max_id, uint16_t begin, uint16_t end,
310 			     struct nvs_fs *fs)
311 {
312 	uint8_t buf[32];
313 	ssize_t len;
314 
315 	for (uint16_t i = begin; i < end; i++) {
316 		uint8_t id = (i % max_id);
317 		uint8_t id_data = id + max_id * ((i % 256) / max_id);
318 
319 		memset(buf, id_data, sizeof(buf));
320 
321 		len = nvs_write(fs, id, buf, sizeof(buf));
322 		zassert_true(len == sizeof(buf), "nvs_write failed: %d", len);
323 	}
324 }
325 
check_content(uint16_t max_id,struct nvs_fs * fs)326 static void check_content(uint16_t max_id, struct nvs_fs *fs)
327 {
328 	uint8_t rd_buf[32];
329 	uint8_t buf[32];
330 	ssize_t len;
331 
332 	for (uint16_t id = 0; id < max_id; id++) {
333 		len = nvs_read(fs, id, rd_buf, sizeof(buf));
334 		zassert_true(len == sizeof(rd_buf),
335 			     "nvs_read unexpected failure: %d", len);
336 
337 		for (uint16_t i = 0; i < ARRAY_SIZE(rd_buf); i++) {
338 			rd_buf[i] = rd_buf[i] % max_id;
339 			buf[i] = id;
340 		}
341 		zassert_mem_equal(buf, rd_buf, sizeof(rd_buf),
342 				  "RD buff should be equal to the WR buff");
343 
344 	}
345 }
346 
347 /**
348  * Full round of GC over 3 sectors
349  */
ZTEST_F(nvs,test_nvs_gc_3sectors)350 ZTEST_F(nvs, test_nvs_gc_3sectors)
351 {
352 	int err;
353 
354 	const uint16_t max_id = 10;
355 	/* 50th write will trigger 1st GC. */
356 	uint16_t max_writes = 51;
357 	/* 75th write will trigger 2st GC. */
358 	uint16_t max_writes_2 = 51 + 25;
359 	/* 100th write will trigger 3st GC. */
360 	uint16_t max_writes_3 = 51 + 25 + 25;
361 	/* 125th write will trigger 4st GC. */
362 	uint16_t max_writes_4 = 51 + 25 + 25 + 25;
363 
364 	if (fixture->fs.sector_size == KB(64)) {
365 		/* write 1637 will trigger 1st GC. */
366 		/* write 3274 will trigger 2nd GC. */
367 		max_writes = 3275;
368 		/* write 4911 will trigger 3rd GC. */
369 		max_writes_2 = 3275 + 1637;
370 		/* write 6548 will trigger 4th GC. */
371 		max_writes_3 = 3275 + 1637 + 1637;
372 		/* write 8185 will trigger 5th GC. */
373 		max_writes_4 = 3275 + 1637 + 1637 + 1637;
374 	}
375 
376 	fixture->fs.sector_count = 3;
377 
378 	err = nvs_mount(&fixture->fs);
379 	zassert_true(err == 0,  "nvs_mount call failure: %d", err);
380 	zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 0,
381 		     "unexpected write sector");
382 
383 	/* Trigger 1st and 2nd GC */
384 	write_content(max_id, 0, max_writes, &fixture->fs);
385 
386 	/* sector sequence: empty,closed, write */
387 	zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 2,
388 		     "unexpected write sector");
389 	check_content(max_id, &fixture->fs);
390 
391 	err = nvs_mount(&fixture->fs);
392 	zassert_true(err == 0,  "nvs_mount call failure: %d", err);
393 
394 	zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 2,
395 		     "unexpected write sector");
396 	check_content(max_id, &fixture->fs);
397 
398 	/* Trigger 3rd GC */
399 	write_content(max_id, max_writes, max_writes_2, &fixture->fs);
400 
401 	/* sector sequence: write, empty, closed */
402 	zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 0,
403 		     "unexpected write sector");
404 	check_content(max_id, &fixture->fs);
405 
406 	err = nvs_mount(&fixture->fs);
407 	zassert_true(err == 0,  "nvs_mount call failure: %d", err);
408 
409 	zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 0,
410 		     "unexpected write sector");
411 	check_content(max_id, &fixture->fs);
412 
413 	/* Trigger 4th GC */
414 	write_content(max_id, max_writes_2, max_writes_3, &fixture->fs);
415 
416 	/* sector sequence: closed, write, empty */
417 	zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 1,
418 		     "unexpected write sector");
419 	check_content(max_id, &fixture->fs);
420 
421 	err = nvs_mount(&fixture->fs);
422 	zassert_true(err == 0,  "nvs_mount call failure: %d", err);
423 
424 	zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 1,
425 		     "unexpected write sector");
426 	check_content(max_id, &fixture->fs);
427 
428 	/* Trigger 5th GC */
429 	write_content(max_id, max_writes_3, max_writes_4, &fixture->fs);
430 
431 	/* sector sequence: empty,closed, write */
432 	zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 2,
433 		     "unexpected write sector");
434 	check_content(max_id, &fixture->fs);
435 
436 	err = nvs_mount(&fixture->fs);
437 	zassert_true(err == 0,  "nvs_mount call failure: %d", err);
438 
439 	zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 2,
440 		     "unexpected write sector");
441 	check_content(max_id, &fixture->fs);
442 }
443 
flash_sim_erase_calls_find(struct stats_hdr * hdr,void * arg,const char * name,uint16_t off)444 static int flash_sim_erase_calls_find(struct stats_hdr *hdr, void *arg,
445 				      const char *name, uint16_t off)
446 {
447 	if (!strcmp(name, "flash_erase_calls")) {
448 		uint32_t **flash_erase_stat = (uint32_t **) arg;
449 		*flash_erase_stat = (uint32_t *)((uint8_t *)hdr + off);
450 	}
451 
452 	return 0;
453 }
454 
flash_sim_max_erase_calls_find(struct stats_hdr * hdr,void * arg,const char * name,uint16_t off)455 static int flash_sim_max_erase_calls_find(struct stats_hdr *hdr, void *arg,
456 					  const char *name, uint16_t off)
457 {
458 	if (!strcmp(name, "max_erase_calls")) {
459 		uint32_t **max_erase_calls = (uint32_t **) arg;
460 		*max_erase_calls = (uint32_t *)((uint8_t *)hdr + off);
461 	}
462 
463 	return 0;
464 }
465 
flash_sim_max_len_find(struct stats_hdr * hdr,void * arg,const char * name,uint16_t off)466 static int flash_sim_max_len_find(struct stats_hdr *hdr, void *arg,
467 				  const char *name, uint16_t off)
468 {
469 	if (!strcmp(name, "max_len")) {
470 		uint32_t **max_len = (uint32_t **) arg;
471 		*max_len = (uint32_t *)((uint8_t *)hdr + off);
472 	}
473 
474 	return 0;
475 }
476 
ZTEST_F(nvs,test_nvs_corrupted_sector_close_operation)477 ZTEST_F(nvs, test_nvs_corrupted_sector_close_operation)
478 {
479 	int err;
480 	int len;
481 	uint8_t buf[32];
482 	uint32_t *flash_write_stat;
483 	uint32_t *flash_erase_stat;
484 	uint32_t *flash_max_write_calls;
485 	uint32_t *flash_max_erase_calls;
486 	uint32_t *flash_max_len;
487 
488 	const uint16_t max_id = 10;
489 	/* 25th write will trigger GC. */
490 	const uint16_t max_writes = 26;
491 
492 	/* Get the address of simulator parameters. */
493 	stats_walk(fixture->sim_thresholds, flash_sim_max_write_calls_find,
494 		   &flash_max_write_calls);
495 	stats_walk(fixture->sim_thresholds, flash_sim_max_erase_calls_find,
496 		   &flash_max_erase_calls);
497 	stats_walk(fixture->sim_thresholds, flash_sim_max_len_find,
498 		   &flash_max_len);
499 	stats_walk(fixture->sim_stats, flash_sim_write_calls_find, &flash_write_stat);
500 	stats_walk(fixture->sim_stats, flash_sim_erase_calls_find, &flash_erase_stat);
501 
502 	err = nvs_mount(&fixture->fs);
503 	zassert_true(err == 0,  "nvs_mount call failure: %d", err);
504 
505 	for (uint16_t i = 0; i < max_writes; i++) {
506 		uint8_t id = (i % max_id);
507 		uint8_t id_data = id + max_id * (i / max_id);
508 
509 		memset(buf, id_data, sizeof(buf));
510 
511 		if (i == max_writes - 1) {
512 			/* Reset stats. */
513 			*flash_write_stat = 0;
514 			*flash_erase_stat = 0;
515 
516 			/* Block write calls and simulate power down during
517 			 * sector closing operation, so only a part of a NVS
518 			 * closing ate will be written.
519 			 */
520 			*flash_max_write_calls = 1;
521 			*flash_max_erase_calls = 1;
522 			*flash_max_len = 4;
523 		}
524 
525 		len = nvs_write(&fixture->fs, id, buf, sizeof(buf));
526 		zassert_true(len == sizeof(buf), "nvs_write failed: %d", len);
527 	}
528 
529 	/* Make the flash simulator functional again. */
530 	*flash_max_write_calls = 0;
531 	*flash_max_erase_calls = 0;
532 	*flash_max_len = 0;
533 
534 	err = nvs_mount(&fixture->fs);
535 	zassert_true(err == 0,  "nvs_mount call failure: %d", err);
536 
537 	check_content(max_id, &fixture->fs);
538 
539 	/* Ensure that the NVS is able to store new content. */
540 	execute_long_pattern_write(max_id, &fixture->fs);
541 }
542 #endif /* CONFIG_TEST_NVS_SIMULATOR */
543 
544 /**
545  * @brief Test case when storage become full, so only deletion is possible.
546  */
ZTEST_F(nvs,test_nvs_full_sector)547 ZTEST_F(nvs, test_nvs_full_sector)
548 {
549 	int err;
550 	ssize_t len;
551 	uint16_t filling_id = 0;
552 	uint16_t i, data_read;
553 
554 	fixture->fs.sector_count = 3;
555 
556 	err = nvs_mount(&fixture->fs);
557 	zassert_true(err == 0,  "nvs_mount call failure: %d", err);
558 
559 	while (1) {
560 		len = nvs_write(&fixture->fs, filling_id, &filling_id,
561 				sizeof(filling_id));
562 		if (len == -ENOSPC) {
563 			break;
564 		}
565 		zassert_true(len == sizeof(filling_id), "nvs_write failed: %d",
566 			     len);
567 		filling_id++;
568 	}
569 
570 	/* check whether can delete whatever from full storage */
571 	err = nvs_delete(&fixture->fs, 1);
572 	zassert_true(err == 0,  "nvs_delete call failure: %d", err);
573 
574 	/* the last sector is full now, test re-initialization */
575 	err = nvs_mount(&fixture->fs);
576 	zassert_true(err == 0,  "nvs_mount call failure: %d", err);
577 
578 	len = nvs_write(&fixture->fs, filling_id, &filling_id, sizeof(filling_id));
579 	zassert_true(len == sizeof(filling_id), "nvs_write failed: %d", len);
580 
581 	/* coherence check on NVS content */
582 	for (i = 0; i <= filling_id; i++) {
583 		len = nvs_read(&fixture->fs, i, &data_read, sizeof(data_read));
584 		if (i == 1) {
585 			zassert_true(len == -ENOENT,
586 				     "nvs_read shouldn't found the entry: %d",
587 				     len);
588 		} else {
589 			zassert_true(len == sizeof(data_read),
590 				     "nvs_read #%d failed: len is %zd instead of %zu",
591 				     i, len, sizeof(data_read));
592 			zassert_equal(data_read, i,
593 				      "read unexpected data: %d instead of %d",
594 				      data_read, i);
595 		}
596 	}
597 }
598 
ZTEST_F(nvs,test_delete)599 ZTEST_F(nvs, test_delete)
600 {
601 	int err;
602 	ssize_t len;
603 	uint16_t filling_id, data_read;
604 	uint32_t ate_wra, data_wra;
605 
606 	fixture->fs.sector_count = 3;
607 
608 	err = nvs_mount(&fixture->fs);
609 	zassert_true(err == 0,  "nvs_mount call failure: %d", err);
610 
611 	for (filling_id = 0; filling_id < 10; filling_id++) {
612 		len = nvs_write(&fixture->fs, filling_id, &filling_id,
613 				sizeof(filling_id));
614 
615 		zassert_true(len == sizeof(filling_id), "nvs_write failed: %d",
616 			     len);
617 
618 		if (filling_id != 0) {
619 			continue;
620 		}
621 
622 		/* delete the first entry while it is the most recent one */
623 		err = nvs_delete(&fixture->fs, filling_id);
624 		zassert_true(err == 0,  "nvs_delete call failure: %d", err);
625 
626 		len = nvs_read(&fixture->fs, filling_id, &data_read, sizeof(data_read));
627 		zassert_true(len == -ENOENT,
628 			     "nvs_read shouldn't found the entry: %d", len);
629 	}
630 
631 	/* delete existing entry */
632 	err = nvs_delete(&fixture->fs, 1);
633 	zassert_true(err == 0,  "nvs_delete call failure: %d", err);
634 
635 	len = nvs_read(&fixture->fs, 1, &data_read, sizeof(data_read));
636 	zassert_true(len == -ENOENT, "nvs_read shouldn't found the entry: %d",
637 		     len);
638 
639 	ate_wra = fixture->fs.ate_wra;
640 	data_wra = fixture->fs.data_wra;
641 
642 	/* delete already deleted entry */
643 	err = nvs_delete(&fixture->fs, 1);
644 	zassert_true(err == 0,  "nvs_delete call failure: %d", err);
645 	zassert_true(ate_wra == fixture->fs.ate_wra && data_wra == fixture->fs.data_wra,
646 		     "delete already deleted entry should not make"
647 		     " any footprint in the storage");
648 
649 	/* delete nonexisting entry */
650 	err = nvs_delete(&fixture->fs, filling_id);
651 	zassert_true(err == 0,  "nvs_delete call failure: %d", err);
652 	zassert_true(ate_wra == fixture->fs.ate_wra && data_wra == fixture->fs.data_wra,
653 		     "delete nonexistent entry should not make"
654 		     " any footprint in the storage");
655 }
656 
657 #ifdef CONFIG_TEST_NVS_SIMULATOR
658 /*
659  * Test that garbage-collection can recover all ate's even when the last ate,
660  * ie close_ate, is corrupt. In this test the close_ate is set to point to the
661  * last ate at -5. A valid ate is however present at -6. Since the close_ate
662  * has an invalid crc8, the offset should not be used and a recover of the
663  * last ate should be done instead.
664  */
ZTEST_F(nvs,test_nvs_gc_corrupt_close_ate)665 ZTEST_F(nvs, test_nvs_gc_corrupt_close_ate)
666 {
667 	struct nvs_ate ate, close_ate;
668 	uint32_t data;
669 	ssize_t len;
670 	int err;
671 #ifdef CONFIG_NVS_DATA_CRC
672 	uint32_t data_crc;
673 #endif
674 
675 	close_ate.id = 0xffff;
676 	close_ate.offset = fixture->fs.sector_size - sizeof(struct nvs_ate) * 5;
677 	close_ate.len = 0;
678 	close_ate.part = 0xff;
679 	close_ate.crc8 = 0xff; /* Incorrect crc8 */
680 
681 	ate.id = 0x1;
682 	ate.offset = 0;
683 	ate.len = sizeof(data);
684 #ifdef CONFIG_NVS_DATA_CRC
685 	ate.len += sizeof(data_crc);
686 #endif
687 	ate.part = 0xff;
688 	ate.crc8 = crc8_ccitt(0xff, &ate,
689 			      offsetof(struct nvs_ate, crc8));
690 
691 	/* Mark sector 0 as closed */
692 	err = flash_write(fixture->fs.flash_device, fixture->fs.offset + fixture->fs.sector_size -
693 			  sizeof(struct nvs_ate), &close_ate,
694 			  sizeof(close_ate));
695 	zassert_true(err == 0,  "flash_write failed: %d", err);
696 
697 	/* Write valid ate at -6 */
698 	err = flash_write(fixture->fs.flash_device, fixture->fs.offset + fixture->fs.sector_size -
699 			  sizeof(struct nvs_ate) * 6, &ate, sizeof(ate));
700 	zassert_true(err == 0,  "flash_write failed: %d", err);
701 
702 	/* Write data for previous ate */
703 	data = 0xaa55aa55;
704 	err = flash_write(fixture->fs.flash_device, fixture->fs.offset, &data, sizeof(data));
705 	zassert_true(err == 0,  "flash_write failed: %d", err);
706 #ifdef CONFIG_NVS_DATA_CRC
707 	data_crc = crc32_ieee((const uint8_t *) &data, sizeof(data));
708 	err = flash_write(fixture->fs.flash_device, fixture->fs.offset + sizeof(data), &data_crc,
709 			  sizeof(data_crc));
710 	zassert_true(err == 0,  "flash_write for data CRC failed: %d", err);
711 #endif
712 
713 	/* Mark sector 1 as closed */
714 	err = flash_write(fixture->fs.flash_device,
715 			  fixture->fs.offset + (2 * fixture->fs.sector_size) -
716 			  sizeof(struct nvs_ate), &close_ate,
717 			  sizeof(close_ate));
718 	zassert_true(err == 0,  "flash_write failed: %d", err);
719 
720 	fixture->fs.sector_count = 3;
721 
722 	err = nvs_mount(&fixture->fs);
723 	zassert_true(err == 0,  "nvs_mount call failure: %d", err);
724 
725 	data = 0;
726 	len = nvs_read(&fixture->fs, 1, &data, sizeof(data));
727 	zassert_true(len == sizeof(data),
728 		     "nvs_read should have read %d bytes", sizeof(data));
729 	zassert_true(data == 0xaa55aa55, "unexpected value %d", data);
730 }
731 
732 /*
733  * Test that garbage-collection correctly handles corrupt ate's.
734  */
ZTEST_F(nvs,test_nvs_gc_corrupt_ate)735 ZTEST_F(nvs, test_nvs_gc_corrupt_ate)
736 {
737 	struct nvs_ate corrupt_ate, close_ate;
738 	int err;
739 
740 	close_ate.id = 0xffff;
741 	close_ate.offset = fixture->fs.sector_size / 2;
742 	close_ate.len = 0;
743 	close_ate.part = 0xff;
744 	close_ate.crc8 = crc8_ccitt(0xff, &close_ate,
745 				    offsetof(struct nvs_ate, crc8));
746 
747 	corrupt_ate.id = 0xdead;
748 	corrupt_ate.offset = 0;
749 	corrupt_ate.len = 20;
750 	corrupt_ate.part = 0xff;
751 	corrupt_ate.crc8 = 0xff; /* Incorrect crc8 */
752 
753 	/* Mark sector 0 as closed */
754 	err = flash_write(fixture->fs.flash_device, fixture->fs.offset + fixture->fs.sector_size -
755 			  sizeof(struct nvs_ate), &close_ate,
756 			  sizeof(close_ate));
757 	zassert_true(err == 0,  "flash_write failed: %d", err);
758 
759 	/* Write a corrupt ate */
760 	err = flash_write(fixture->fs.flash_device,
761 			  fixture->fs.offset + (fixture->fs.sector_size / 2),
762 			  &corrupt_ate, sizeof(corrupt_ate));
763 	zassert_true(err == 0,  "flash_write failed: %d", err);
764 
765 	/* Mark sector 1 as closed */
766 	err = flash_write(fixture->fs.flash_device,
767 			  fixture->fs.offset + (2 * fixture->fs.sector_size) -
768 			  sizeof(struct nvs_ate), &close_ate,
769 			  sizeof(close_ate));
770 	zassert_true(err == 0,  "flash_write failed: %d", err);
771 
772 	fixture->fs.sector_count = 3;
773 
774 	err = nvs_mount(&fixture->fs);
775 	zassert_true(err == 0,  "nvs_mount call failure: %d", err);
776 }
777 #endif /* CONFIG_TEST_NVS_SIMULATOR */
778 
779 #ifdef CONFIG_NVS_LOOKUP_CACHE
num_matching_cache_entries(uint32_t addr,bool compare_sector_only,struct nvs_fs * fs)780 static size_t num_matching_cache_entries(uint32_t addr, bool compare_sector_only, struct nvs_fs *fs)
781 {
782 	size_t i, num = 0;
783 	uint32_t mask = compare_sector_only ? ADDR_SECT_MASK : UINT32_MAX;
784 
785 	for (i = 0; i < CONFIG_NVS_LOOKUP_CACHE_SIZE; i++) {
786 		if ((fs->lookup_cache[i] & mask) == addr) {
787 			num++;
788 		}
789 	}
790 
791 	return num;
792 }
793 
num_occupied_cache_entries(struct nvs_fs * fs)794 static size_t num_occupied_cache_entries(struct nvs_fs *fs)
795 {
796 	return CONFIG_NVS_LOOKUP_CACHE_SIZE -
797 	       num_matching_cache_entries(NVS_LOOKUP_CACHE_NO_ADDR, false, fs);
798 }
799 #endif
800 
801 /*
802  * Test that NVS lookup cache is properly rebuilt on nvs_mount(), or initialized
803  * to NVS_LOOKUP_CACHE_NO_ADDR if the store is empty.
804  */
ZTEST_F(nvs,test_nvs_cache_init)805 ZTEST_F(nvs, test_nvs_cache_init)
806 {
807 #ifdef CONFIG_NVS_LOOKUP_CACHE
808 	int err;
809 	size_t num;
810 	uint32_t ate_addr;
811 	uint8_t data = 0;
812 
813 	/* Test cache initialization when the store is empty */
814 
815 	fixture->fs.sector_count = 3;
816 	err = nvs_mount(&fixture->fs);
817 	zassert_true(err == 0, "nvs_mount call failure: %d", err);
818 
819 	num = num_occupied_cache_entries(&fixture->fs);
820 	zassert_equal(num, 0, "uninitialized cache");
821 
822 	/* Test cache update after nvs_write() */
823 
824 	ate_addr = fixture->fs.ate_wra;
825 	err = nvs_write(&fixture->fs, 1, &data, sizeof(data));
826 	zassert_equal(err, sizeof(data), "nvs_write call failure: %d", err);
827 
828 	num = num_occupied_cache_entries(&fixture->fs);
829 	zassert_equal(num, 1, "cache not updated after write");
830 
831 	num = num_matching_cache_entries(ate_addr, false, &fixture->fs);
832 	zassert_equal(num, 1, "invalid cache entry after write");
833 
834 	/* Test cache initialization when the store is non-empty */
835 
836 	memset(fixture->fs.lookup_cache, 0xAA, sizeof(fixture->fs.lookup_cache));
837 	err = nvs_mount(&fixture->fs);
838 	zassert_true(err == 0, "nvs_mount call failure: %d", err);
839 
840 	num = num_occupied_cache_entries(&fixture->fs);
841 	zassert_equal(num, 1, "uninitialized cache after restart");
842 
843 	num = num_matching_cache_entries(ate_addr, false, &fixture->fs);
844 	zassert_equal(num, 1, "invalid cache entry after restart");
845 #endif
846 }
847 
848 /*
849  * Test that even after writing more NVS IDs than the number of NVS lookup cache
850  * entries they all can be read correctly.
851  */
ZTEST_F(nvs,test_nvs_cache_collission)852 ZTEST_F(nvs, test_nvs_cache_collission)
853 {
854 #ifdef CONFIG_NVS_LOOKUP_CACHE
855 	int err;
856 	uint16_t id;
857 	uint16_t data;
858 
859 	fixture->fs.sector_count = 3;
860 	err = nvs_mount(&fixture->fs);
861 	zassert_true(err == 0, "nvs_mount call failure: %d", err);
862 
863 	for (id = 0; id < CONFIG_NVS_LOOKUP_CACHE_SIZE + 1; id++) {
864 		data = id;
865 		err = nvs_write(&fixture->fs, id, &data, sizeof(data));
866 		zassert_equal(err, sizeof(data), "nvs_write call failure: %d", err);
867 	}
868 
869 	for (id = 0; id < CONFIG_NVS_LOOKUP_CACHE_SIZE + 1; id++) {
870 		err = nvs_read(&fixture->fs, id, &data, sizeof(data));
871 		zassert_equal(err, sizeof(data), "nvs_read call failure: %d", err);
872 		zassert_equal(data, id, "incorrect data read");
873 	}
874 #endif
875 }
876 
877 /*
878  * Test that NVS lookup cache does not contain any address from gc-ed sector
879  */
ZTEST_F(nvs,test_nvs_cache_gc)880 ZTEST_F(nvs, test_nvs_cache_gc)
881 {
882 #ifdef CONFIG_NVS_LOOKUP_CACHE
883 	int err;
884 	size_t num;
885 	uint16_t data = 0;
886 
887 	fixture->fs.sector_count = 3;
888 	err = nvs_mount(&fixture->fs);
889 	zassert_true(err == 0, "nvs_mount call failure: %d", err);
890 
891 	/* Fill the first sector with writes of ID 1 */
892 
893 	while (fixture->fs.data_wra + sizeof(data) + sizeof(struct nvs_ate)
894 	       <= fixture->fs.ate_wra) {
895 		++data;
896 		err = nvs_write(&fixture->fs, 1, &data, sizeof(data));
897 		zassert_equal(err, sizeof(data), "nvs_write call failure: %d", err);
898 	}
899 
900 	/* Verify that cache contains a single entry for sector 0 */
901 
902 	num = num_matching_cache_entries(0 << ADDR_SECT_SHIFT, true, &fixture->fs);
903 	zassert_equal(num, 1, "invalid cache content after filling sector 0");
904 
905 	/* Fill the second sector with writes of ID 2 */
906 
907 	while ((fixture->fs.ate_wra >> ADDR_SECT_SHIFT) != 2) {
908 		++data;
909 		err = nvs_write(&fixture->fs, 2, &data, sizeof(data));
910 		zassert_equal(err, sizeof(data), "nvs_write call failure: %d", err);
911 	}
912 
913 	/*
914 	 * At this point sector 0 should have been gc-ed. Verify that action is
915 	 * reflected by the cache content.
916 	 */
917 
918 	num = num_matching_cache_entries(0 << ADDR_SECT_SHIFT, true, &fixture->fs);
919 	zassert_equal(num, 0, "not invalidated cache entries aftetr gc");
920 
921 	num = num_matching_cache_entries(2 << ADDR_SECT_SHIFT, true, &fixture->fs);
922 	zassert_equal(num, 2, "invalid cache content after gc");
923 #endif
924 }
925 
926 /*
927  * Test NVS lookup cache hash quality.
928  */
ZTEST_F(nvs,test_nvs_cache_hash_quality)929 ZTEST_F(nvs, test_nvs_cache_hash_quality)
930 {
931 #ifdef CONFIG_NVS_LOOKUP_CACHE
932 	const size_t MIN_CACHE_OCCUPANCY = CONFIG_NVS_LOOKUP_CACHE_SIZE * 6 / 10;
933 	int err;
934 	size_t num;
935 	uint16_t id;
936 	uint16_t data;
937 
938 	err = nvs_mount(&fixture->fs);
939 	zassert_true(err == 0, "nvs_mount call failure: %d", err);
940 
941 	/* Write NVS IDs from 0 to CONFIG_NVS_LOOKUP_CACHE_SIZE - 1 */
942 
943 	for (uint16_t i = 0; i < CONFIG_NVS_LOOKUP_CACHE_SIZE; i++) {
944 		id = i;
945 		data = 0;
946 
947 		err = nvs_write(&fixture->fs, id, &data, sizeof(data));
948 		zassert_equal(err, sizeof(data), "nvs_write call failure: %d", err);
949 	}
950 
951 	/* Verify that at least 60% cache entries are occupied */
952 
953 	num = num_occupied_cache_entries(&fixture->fs);
954 	TC_PRINT("Cache occupancy: %u\n", (unsigned int)num);
955 	zassert_between_inclusive(num, MIN_CACHE_OCCUPANCY, CONFIG_NVS_LOOKUP_CACHE_SIZE,
956 				  "too low cache occupancy - poor hash quality");
957 
958 	err = nvs_clear(&fixture->fs);
959 	zassert_true(err == 0, "nvs_clear call failure: %d", err);
960 
961 	err = nvs_mount(&fixture->fs);
962 	zassert_true(err == 0, "nvs_mount call failure: %d", err);
963 
964 	/* Write CONFIG_NVS_LOOKUP_CACHE_SIZE NVS IDs that form the following series: 0, 4, 8... */
965 
966 	for (uint16_t i = 0; i < CONFIG_NVS_LOOKUP_CACHE_SIZE; i++) {
967 		id = i * 4;
968 		data = 0;
969 
970 		err = nvs_write(&fixture->fs, id, &data, sizeof(data));
971 		zassert_equal(err, sizeof(data), "nvs_write call failure: %d", err);
972 	}
973 
974 	/* Verify that at least 60% cache entries are occupied */
975 
976 	num = num_occupied_cache_entries(&fixture->fs);
977 	TC_PRINT("Cache occupancy: %u\n", (unsigned int)num);
978 	zassert_between_inclusive(num, MIN_CACHE_OCCUPANCY, CONFIG_NVS_LOOKUP_CACHE_SIZE,
979 				  "too low cache occupancy - poor hash quality");
980 
981 #endif
982 }
983 
984 #ifdef CONFIG_TEST_NVS_SIMULATOR
985 /*
986  * Test NVS bad region initialization recovery.
987  */
ZTEST_F(nvs,test_nvs_init_bad_memory_region)988 ZTEST_F(nvs, test_nvs_init_bad_memory_region)
989 {
990 	int err;
991 	uint32_t data;
992 
993 	err = nvs_mount(&fixture->fs);
994 	zassert_true(err == 0, "nvs_mount call failure: %d", err);
995 
996 	/* Write bad ATE to each sector */
997 	for (uint16_t i = 0; i < TEST_SECTOR_COUNT; i++) {
998 		data = 0xdeadbeef;
999 		err = flash_write(fixture->fs.flash_device,
1000 				  fixture->fs.offset + (fixture->fs.sector_size * (i + 1)) -
1001 					  sizeof(struct nvs_ate),
1002 				  &data, sizeof(data));
1003 		zassert_true(err == 0, "flash_write failed: %d", err);
1004 	}
1005 
1006 	/* Reinitialize the NVS. */
1007 	memset(&fixture->fs, 0, sizeof(fixture->fs));
1008 	(void)setup();
1009 
1010 #ifdef CONFIG_NVS_INIT_BAD_MEMORY_REGION
1011 	err = nvs_mount(&fixture->fs);
1012 	zassert_true(err == 0, "nvs_mount call failure: %d", err);
1013 
1014 	/* Ensure that the NVS is able to store new content. */
1015 	execute_long_pattern_write(TEST_DATA_ID, &fixture->fs);
1016 #else
1017 	err = nvs_mount(&fixture->fs);
1018 	zassert_true(err == -EDEADLK, "nvs_mount call ok, expect fail: %d", err);
1019 #endif
1020 }
1021 #endif /* CONFIG_TEST_NVS_SIMULATOR */
1022