1 /*
2  * Copyright (c) 2023-2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT zephyr_sim_flash
8 
9 #include <zephyr/device.h>
10 #include <zephyr/devicetree.h>
11 #include <zephyr/linker/devicetree_regions.h>
12 #include <zephyr/drivers/flash.h>
13 #include <zephyr/init.h>
14 #include <zephyr/kernel.h>
15 #include <zephyr/sys/util.h>
16 #include <zephyr/random/random.h>
17 #include <zephyr/stats/stats.h>
18 #include <string.h>
19 
20 #ifdef CONFIG_ARCH_POSIX
21 
22 #include "flash_simulator_native.h"
23 #include "cmdline.h"
24 #include "soc.h"
25 #define DEFAULT_FLASH_FILE_PATH "flash.bin"
26 
27 #endif /* CONFIG_ARCH_POSIX */
28 
29 /* configuration derived from DT */
30 #ifdef CONFIG_ARCH_POSIX
31 #define SOC_NV_FLASH_NODE DT_INST_CHILD(0, flash_0)
32 #else
33 #define SOC_NV_FLASH_NODE DT_INST_CHILD(0, flash_sim_0)
34 #endif /* CONFIG_ARCH_POSIX */
35 
36 #define FLASH_SIMULATOR_BASE_OFFSET DT_REG_ADDR(SOC_NV_FLASH_NODE)
37 #define FLASH_SIMULATOR_ERASE_UNIT DT_PROP(SOC_NV_FLASH_NODE, erase_block_size)
38 #define FLASH_SIMULATOR_PROG_UNIT DT_PROP(SOC_NV_FLASH_NODE, write_block_size)
39 #define FLASH_SIMULATOR_FLASH_SIZE DT_REG_SIZE(SOC_NV_FLASH_NODE)
40 
41 #define FLASH_SIMULATOR_ERASE_VALUE \
42 		DT_PROP(DT_PARENT(SOC_NV_FLASH_NODE), erase_value)
43 
44 #define FLASH_SIMULATOR_PAGE_COUNT (FLASH_SIMULATOR_FLASH_SIZE / \
45 				    FLASH_SIMULATOR_ERASE_UNIT)
46 
47 #if (FLASH_SIMULATOR_ERASE_UNIT % FLASH_SIMULATOR_PROG_UNIT)
48 #error "Erase unit must be a multiple of program unit"
49 #endif
50 
51 #define MOCK_FLASH(offset) (mock_flash + (offset))
52 
53 /* maximum number of pages that can be tracked by the stats module */
54 #define STATS_PAGE_COUNT_THRESHOLD 256
55 
56 #define STATS_SECT_EC(N, _) STATS_SECT_ENTRY32(erase_cycles_unit##N)
57 #define STATS_NAME_EC(N, _) STATS_NAME(flash_sim_stats, erase_cycles_unit##N)
58 
59 #define STATS_SECT_DIRTYR(N, _) STATS_SECT_ENTRY32(dirty_read_unit##N)
60 #define STATS_NAME_DIRTYR(N, _) STATS_NAME(flash_sim_stats, dirty_read_unit##N)
61 
62 #ifdef CONFIG_FLASH_SIMULATOR_STATS
63 /* increment a unit erase cycles counter */
64 #define ERASE_CYCLES_INC(U)						     \
65 	do {								     \
66 		if (U < STATS_PAGE_COUNT_THRESHOLD) {			     \
67 			(*(&flash_sim_stats.erase_cycles_unit0 + (U)) += 1); \
68 		}							     \
69 	} while (false)
70 
71 #if (CONFIG_FLASH_SIMULATOR_STAT_PAGE_COUNT > STATS_PAGE_COUNT_THRESHOLD)
72        /* Limitation above is caused by used LISTIFY                        */
73        /* Using FLASH_SIMULATOR_FLASH_PAGE_COUNT allows to avoid terrible   */
74        /* error logg at the output and work with the stats module partially */
75        #define FLASH_SIMULATOR_FLASH_PAGE_COUNT STATS_PAGE_COUNT_THRESHOLD
76 #else
77 #define FLASH_SIMULATOR_FLASH_PAGE_COUNT CONFIG_FLASH_SIMULATOR_STAT_PAGE_COUNT
78 #endif
79 
80 /* simulator statistics */
81 STATS_SECT_START(flash_sim_stats)
82 STATS_SECT_ENTRY32(bytes_read)		/* total bytes read */
83 STATS_SECT_ENTRY32(bytes_written)       /* total bytes written */
84 STATS_SECT_ENTRY32(double_writes)       /* num. of writes to non-erased units */
85 STATS_SECT_ENTRY32(flash_read_calls)    /* calls to flash_read() */
86 STATS_SECT_ENTRY32(flash_read_time_us)  /* time spent in flash_read() */
87 STATS_SECT_ENTRY32(flash_write_calls)   /* calls to flash_write() */
88 STATS_SECT_ENTRY32(flash_write_time_us) /* time spent in flash_write() */
89 STATS_SECT_ENTRY32(flash_erase_calls)   /* calls to flash_erase() */
90 STATS_SECT_ENTRY32(flash_erase_time_us) /* time spent in flash_erase() */
91 /* -- per-unit statistics -- */
92 /* erase cycle count for unit */
93 LISTIFY(FLASH_SIMULATOR_FLASH_PAGE_COUNT, STATS_SECT_EC, ())
94 /* number of read operations on worn out erase units */
95 LISTIFY(FLASH_SIMULATOR_FLASH_PAGE_COUNT, STATS_SECT_DIRTYR, ())
96 STATS_SECT_END;
97 
98 STATS_SECT_DECL(flash_sim_stats) flash_sim_stats;
99 STATS_NAME_START(flash_sim_stats)
100 STATS_NAME(flash_sim_stats, bytes_read)
101 STATS_NAME(flash_sim_stats, bytes_written)
102 STATS_NAME(flash_sim_stats, double_writes)
103 STATS_NAME(flash_sim_stats, flash_read_calls)
104 STATS_NAME(flash_sim_stats, flash_read_time_us)
105 STATS_NAME(flash_sim_stats, flash_write_calls)
106 STATS_NAME(flash_sim_stats, flash_write_time_us)
107 STATS_NAME(flash_sim_stats, flash_erase_calls)
108 STATS_NAME(flash_sim_stats, flash_erase_time_us)
109 LISTIFY(FLASH_SIMULATOR_FLASH_PAGE_COUNT, STATS_NAME_EC, ())
110 LISTIFY(FLASH_SIMULATOR_FLASH_PAGE_COUNT, STATS_NAME_DIRTYR, ())
111 STATS_NAME_END(flash_sim_stats);
112 
113 /* simulator dynamic thresholds */
114 STATS_SECT_START(flash_sim_thresholds)
115 STATS_SECT_ENTRY32(max_write_calls)
116 STATS_SECT_ENTRY32(max_erase_calls)
117 STATS_SECT_ENTRY32(max_len)
118 STATS_SECT_END;
119 
120 STATS_SECT_DECL(flash_sim_thresholds) flash_sim_thresholds;
121 STATS_NAME_START(flash_sim_thresholds)
122 STATS_NAME(flash_sim_thresholds, max_write_calls)
123 STATS_NAME(flash_sim_thresholds, max_erase_calls)
124 STATS_NAME(flash_sim_thresholds, max_len)
125 STATS_NAME_END(flash_sim_thresholds);
126 
127 #define FLASH_SIM_STATS_INC(group__, var__) STATS_INC(group__, var__)
128 #define FLASH_SIM_STATS_INCN(group__, var__, n__) STATS_INCN(group__, var__, n__)
129 #define FLASH_SIM_STATS_INIT_AND_REG(group__, size__, name__) \
130 	STATS_INIT_AND_REG(group__, size__, name__)
131 
132 
133 #else
134 
135 #define ERASE_CYCLES_INC(U) do {} while (false)
136 #define FLASH_SIM_STATS_INC(group__, var__)
137 #define FLASH_SIM_STATS_INCN(group__, var__, n__)
138 #define FLASH_SIM_STATS_INIT_AND_REG(group__, size__, name__)
139 
140 #endif /* CONFIG_FLASH_SIMULATOR_STATS */
141 
142 
143 #ifdef CONFIG_ARCH_POSIX
144 static uint8_t *mock_flash;
145 static int flash_fd = -1;
146 static const char *flash_file_path;
147 static bool flash_erase_at_start;
148 static bool flash_rm_at_exit;
149 static bool flash_in_ram;
150 #else
151 #if DT_NODE_HAS_PROP(DT_PARENT(SOC_NV_FLASH_NODE), memory_region)
152 #define FLASH_SIMULATOR_MREGION \
153 	LINKER_DT_NODE_REGION_NAME( \
154 	DT_PHANDLE(DT_PARENT(SOC_NV_FLASH_NODE), memory_region))
155 static uint8_t mock_flash[FLASH_SIMULATOR_FLASH_SIZE] Z_GENERIC_SECTION(FLASH_SIMULATOR_MREGION);
156 #else
157 static uint8_t mock_flash[FLASH_SIMULATOR_FLASH_SIZE];
158 #endif
159 #endif /* CONFIG_ARCH_POSIX */
160 
161 static DEVICE_API(flash, flash_sim_api);
162 
163 static const struct flash_parameters flash_sim_parameters = {
164 	.write_block_size = FLASH_SIMULATOR_PROG_UNIT,
165 	.erase_value = FLASH_SIMULATOR_ERASE_VALUE,
166 	.caps = {
167 #if !defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE)
168 		.no_explicit_erase = false,
169 #endif
170 	},
171 };
172 
flash_range_is_valid(const struct device * dev,off_t offset,size_t len)173 static int flash_range_is_valid(const struct device *dev, off_t offset,
174 				size_t len)
175 {
176 	ARG_UNUSED(dev);
177 
178 	if ((offset < 0 || offset >= FLASH_SIMULATOR_FLASH_SIZE ||
179 	     (FLASH_SIMULATOR_FLASH_SIZE - offset) < len)) {
180 		return 0;
181 	}
182 
183 	return 1;
184 }
185 
flash_sim_read(const struct device * dev,const off_t offset,void * data,const size_t len)186 static int flash_sim_read(const struct device *dev, const off_t offset,
187 			  void *data,
188 			  const size_t len)
189 {
190 	ARG_UNUSED(dev);
191 
192 	if (!flash_range_is_valid(dev, offset, len)) {
193 		return -EINVAL;
194 	}
195 
196 	if (!IS_ENABLED(CONFIG_FLASH_SIMULATOR_UNALIGNED_READ)) {
197 		if ((offset % FLASH_SIMULATOR_PROG_UNIT) ||
198 		    (len % FLASH_SIMULATOR_PROG_UNIT)) {
199 			return -EINVAL;
200 		}
201 	}
202 
203 	FLASH_SIM_STATS_INC(flash_sim_stats, flash_read_calls);
204 
205 	memcpy(data, MOCK_FLASH(offset), len);
206 	FLASH_SIM_STATS_INCN(flash_sim_stats, bytes_read, len);
207 
208 #ifdef CONFIG_FLASH_SIMULATOR_SIMULATE_TIMING
209 	k_busy_wait(CONFIG_FLASH_SIMULATOR_MIN_READ_TIME_US);
210 	FLASH_SIM_STATS_INCN(flash_sim_stats, flash_read_time_us,
211 		   CONFIG_FLASH_SIMULATOR_MIN_READ_TIME_US);
212 #endif
213 
214 	return 0;
215 }
216 
flash_sim_write(const struct device * dev,const off_t offset,const void * data,const size_t len)217 static int flash_sim_write(const struct device *dev, const off_t offset,
218 			   const void *data, const size_t len)
219 {
220 	uint8_t buf[FLASH_SIMULATOR_PROG_UNIT];
221 	ARG_UNUSED(dev);
222 
223 	if (!flash_range_is_valid(dev, offset, len)) {
224 		return -EINVAL;
225 	}
226 
227 	if ((offset % FLASH_SIMULATOR_PROG_UNIT) ||
228 	    (len % FLASH_SIMULATOR_PROG_UNIT)) {
229 		return -EINVAL;
230 	}
231 
232 	FLASH_SIM_STATS_INC(flash_sim_stats, flash_write_calls);
233 
234 #if defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE)
235 	/* check if any unit has been already programmed */
236 	memset(buf, FLASH_SIMULATOR_ERASE_VALUE, sizeof(buf));
237 #else
238 	memcpy(buf, MOCK_FLASH(offset), sizeof(buf));
239 #endif
240 	for (uint32_t i = 0; i < len; i += FLASH_SIMULATOR_PROG_UNIT) {
241 		if (memcmp(buf, MOCK_FLASH(offset + i), sizeof(buf))) {
242 			FLASH_SIM_STATS_INC(flash_sim_stats, double_writes);
243 #if !CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES
244 			return -EIO;
245 #endif
246 		}
247 	}
248 
249 #ifdef CONFIG_FLASH_SIMULATOR_STATS
250 	bool data_part_ignored = false;
251 
252 	if (flash_sim_thresholds.max_write_calls != 0) {
253 		if (flash_sim_stats.flash_write_calls >
254 			flash_sim_thresholds.max_write_calls) {
255 			return 0;
256 		} else if (flash_sim_stats.flash_write_calls ==
257 				flash_sim_thresholds.max_write_calls) {
258 			if (flash_sim_thresholds.max_len == 0) {
259 				return 0;
260 			}
261 
262 			data_part_ignored = true;
263 		}
264 	}
265 #endif
266 
267 	for (uint32_t i = 0; i < len; i++) {
268 #ifdef CONFIG_FLASH_SIMULATOR_STATS
269 		if (data_part_ignored) {
270 			if (i >= flash_sim_thresholds.max_len) {
271 				return 0;
272 			}
273 		}
274 #endif /* CONFIG_FLASH_SIMULATOR_STATS */
275 
276 		/* only pull bits to zero */
277 #if defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE)
278 #if FLASH_SIMULATOR_ERASE_VALUE == 0xFF
279 		*(MOCK_FLASH(offset + i)) &= *((uint8_t *)data + i);
280 #else
281 		*(MOCK_FLASH(offset + i)) |= *((uint8_t *)data + i);
282 #endif
283 #else
284 		*(MOCK_FLASH(offset + i)) = *((uint8_t *)data + i);
285 #endif
286 	}
287 
288 	FLASH_SIM_STATS_INCN(flash_sim_stats, bytes_written, len);
289 
290 #ifdef CONFIG_FLASH_SIMULATOR_SIMULATE_TIMING
291 	/* wait before returning */
292 	k_busy_wait(CONFIG_FLASH_SIMULATOR_MIN_WRITE_TIME_US);
293 	FLASH_SIM_STATS_INCN(flash_sim_stats, flash_write_time_us,
294 		   CONFIG_FLASH_SIMULATOR_MIN_WRITE_TIME_US);
295 #endif
296 
297 	return 0;
298 }
299 
unit_erase(const uint32_t unit)300 static void unit_erase(const uint32_t unit)
301 {
302 	const off_t unit_addr = unit * FLASH_SIMULATOR_ERASE_UNIT;
303 
304 	/* erase the memory unit by setting it to erase value */
305 	memset(MOCK_FLASH(unit_addr), FLASH_SIMULATOR_ERASE_VALUE,
306 	       FLASH_SIMULATOR_ERASE_UNIT);
307 }
308 
flash_sim_erase(const struct device * dev,const off_t offset,const size_t len)309 static int flash_sim_erase(const struct device *dev, const off_t offset,
310 			   const size_t len)
311 {
312 	ARG_UNUSED(dev);
313 
314 	if (!flash_range_is_valid(dev, offset, len)) {
315 		return -EINVAL;
316 	}
317 
318 	/* erase operation must be aligned to the erase unit boundary */
319 	if ((offset % FLASH_SIMULATOR_ERASE_UNIT) ||
320 	    (len % FLASH_SIMULATOR_ERASE_UNIT)) {
321 		return -EINVAL;
322 	}
323 
324 	FLASH_SIM_STATS_INC(flash_sim_stats, flash_erase_calls);
325 
326 #ifdef CONFIG_FLASH_SIMULATOR_STATS
327 	if ((flash_sim_thresholds.max_erase_calls != 0) &&
328 	    (flash_sim_stats.flash_erase_calls >=
329 		flash_sim_thresholds.max_erase_calls)){
330 		return 0;
331 	}
332 #endif
333 	/* the first unit to be erased */
334 	uint32_t unit_start = offset / FLASH_SIMULATOR_ERASE_UNIT;
335 
336 	/* erase as many units as necessary and increase their erase counter */
337 	for (uint32_t i = 0; i < len / FLASH_SIMULATOR_ERASE_UNIT; i++) {
338 		ERASE_CYCLES_INC(unit_start + i);
339 		unit_erase(unit_start + i);
340 	}
341 
342 #ifdef CONFIG_FLASH_SIMULATOR_SIMULATE_TIMING
343 	/* wait before returning */
344 	k_busy_wait(CONFIG_FLASH_SIMULATOR_MIN_ERASE_TIME_US);
345 	FLASH_SIM_STATS_INCN(flash_sim_stats, flash_erase_time_us,
346 		   CONFIG_FLASH_SIMULATOR_MIN_ERASE_TIME_US);
347 #endif
348 
349 	return 0;
350 }
351 
352 #ifdef CONFIG_FLASH_PAGE_LAYOUT
353 static const struct flash_pages_layout flash_sim_pages_layout = {
354 	.pages_count = FLASH_SIMULATOR_PAGE_COUNT,
355 	.pages_size = FLASH_SIMULATOR_ERASE_UNIT,
356 };
357 
flash_sim_page_layout(const struct device * dev,const struct flash_pages_layout ** layout,size_t * layout_size)358 static void flash_sim_page_layout(const struct device *dev,
359 				  const struct flash_pages_layout **layout,
360 				  size_t *layout_size)
361 {
362 	*layout = &flash_sim_pages_layout;
363 	*layout_size = 1;
364 }
365 #endif
366 
flash_sim_get_size(const struct device * dev,uint64_t * size)367 static int flash_sim_get_size(const struct device *dev, uint64_t *size)
368 {
369 	ARG_UNUSED(dev);
370 
371 	*size = FLASH_SIMULATOR_FLASH_SIZE;
372 
373 	return 0;
374 }
375 static const struct flash_parameters *
flash_sim_get_parameters(const struct device * dev)376 flash_sim_get_parameters(const struct device *dev)
377 {
378 	ARG_UNUSED(dev);
379 
380 	return &flash_sim_parameters;
381 }
382 
383 static DEVICE_API(flash, flash_sim_api) = {
384 	.read = flash_sim_read,
385 	.write = flash_sim_write,
386 	.erase = flash_sim_erase,
387 	.get_parameters = flash_sim_get_parameters,
388 	.get_size = flash_sim_get_size,
389 #ifdef CONFIG_FLASH_PAGE_LAYOUT
390 	.page_layout = flash_sim_page_layout,
391 #endif
392 };
393 
394 #ifdef CONFIG_ARCH_POSIX
395 
flash_mock_init(const struct device * dev)396 static int flash_mock_init(const struct device *dev)
397 {
398 	int rc;
399 	ARG_UNUSED(dev);
400 
401 	if (flash_in_ram == false && flash_file_path == NULL) {
402 		flash_file_path = DEFAULT_FLASH_FILE_PATH;
403 	}
404 
405 	rc = flash_mock_init_native(flash_in_ram, &mock_flash, FLASH_SIMULATOR_FLASH_SIZE,
406 				    &flash_fd, flash_file_path, FLASH_SIMULATOR_ERASE_VALUE,
407 				    flash_erase_at_start);
408 
409 	if (rc < 0) {
410 		return -EIO;
411 	} else {
412 		return 0;
413 	}
414 }
415 
416 #else
417 #if DT_NODE_HAS_PROP(DT_PARENT(SOC_NV_FLASH_NODE), memory_region)
flash_mock_init(const struct device * dev)418 static int flash_mock_init(const struct device *dev)
419 {
420 	ARG_UNUSED(dev);
421 	return 0;
422 }
423 #else
flash_mock_init(const struct device * dev)424 static int flash_mock_init(const struct device *dev)
425 {
426 	ARG_UNUSED(dev);
427 	memset(mock_flash, FLASH_SIMULATOR_ERASE_VALUE, ARRAY_SIZE(mock_flash));
428 	return 0;
429 }
430 #endif /* DT_NODE_HAS_PROP(DT_PARENT(SOC_NV_FLASH_NODE), memory_region) */
431 #endif /* CONFIG_ARCH_POSIX */
432 
flash_init(const struct device * dev)433 static int flash_init(const struct device *dev)
434 {
435 	FLASH_SIM_STATS_INIT_AND_REG(flash_sim_stats, STATS_SIZE_32, "flash_sim_stats");
436 	FLASH_SIM_STATS_INIT_AND_REG(flash_sim_thresholds, STATS_SIZE_32,
437 			   "flash_sim_thresholds");
438 	return flash_mock_init(dev);
439 }
440 
441 DEVICE_DT_INST_DEFINE(0, flash_init, NULL,
442 		    NULL, NULL, POST_KERNEL, CONFIG_FLASH_INIT_PRIORITY,
443 		    &flash_sim_api);
444 
445 #ifdef CONFIG_ARCH_POSIX
446 
flash_native_cleanup(void)447 static void flash_native_cleanup(void)
448 {
449 	flash_mock_cleanup_native(flash_in_ram, flash_fd, mock_flash,
450 				  FLASH_SIMULATOR_FLASH_SIZE, flash_file_path,
451 				  flash_rm_at_exit);
452 }
453 
flash_native_options(void)454 static void flash_native_options(void)
455 {
456 	static struct args_struct_t flash_options[] = {
457 		{ .option = "flash",
458 		  .name = "path",
459 		  .type = 's',
460 		  .dest = (void *)&flash_file_path,
461 		  .descript = "Path to binary file to be used as flash, by default \""
462 				DEFAULT_FLASH_FILE_PATH "\""},
463 		{ .is_switch = true,
464 		  .option = "flash_erase",
465 		  .type = 'b',
466 		  .dest = (void *)&flash_erase_at_start,
467 		  .descript = "Erase the flash content at startup" },
468 		{ .is_switch = true,
469 		  .option = "flash_rm",
470 		  .type = 'b',
471 		  .dest = (void *)&flash_rm_at_exit,
472 		  .descript = "Remove the flash file when terminating the execution" },
473 		{ .is_switch = true,
474 		  .option = "flash_in_ram",
475 		  .type = 'b',
476 		  .dest = (void *)&flash_in_ram,
477 		  .descript = "Instead of a file, keep the file content just in RAM. If this is "
478 			      "set, flash, flash_erase & flash_rm are ignored. The flash content"
479 			      " is always erased at startup" },
480 		ARG_TABLE_ENDMARKER
481 	};
482 
483 	native_add_command_line_opts(flash_options);
484 }
485 
486 NATIVE_TASK(flash_native_options, PRE_BOOT_1, 1);
487 NATIVE_TASK(flash_native_cleanup, ON_EXIT, 1);
488 
489 #endif /* CONFIG_ARCH_POSIX */
490 
491 /* Extension to generic flash driver API */
z_impl_flash_simulator_get_memory(const struct device * dev,size_t * mock_size)492 void *z_impl_flash_simulator_get_memory(const struct device *dev,
493 					size_t *mock_size)
494 {
495 	ARG_UNUSED(dev);
496 
497 	*mock_size = FLASH_SIMULATOR_FLASH_SIZE;
498 	return mock_flash;
499 }
500 
501 #ifdef CONFIG_USERSPACE
502 
503 #include <zephyr/internal/syscall_handler.h>
504 
z_vrfy_flash_simulator_get_memory(const struct device * dev,size_t * mock_size)505 void *z_vrfy_flash_simulator_get_memory(const struct device *dev,
506 				      size_t *mock_size)
507 {
508 	K_OOPS(K_SYSCALL_SPECIFIC_DRIVER(dev, K_OBJ_DRIVER_FLASH, &flash_sim_api));
509 
510 	return z_impl_flash_simulator_get_memory(dev, mock_size);
511 }
512 
513 #include <zephyr/syscalls/flash_simulator_get_memory_mrsh.c>
514 
515 #endif /* CONFIG_USERSPACE */
516