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