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