1 /*
2 * Copyright (c) 2023 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Part of flash simulator which interacts with the host OS
7 *
8 * When building for the native simulator, this file is built in the
9 * native simulator runner/host context, and not in Zephyr/embedded context.
10 */
11
12 #undef _POSIX_C_SOURCE
13 /* Note: This is used only for interaction with the host C library, and is therefore exempt of
14 * coding guidelines rule A.4&5 which applies to the embedded code using embedded libraries
15 */
16 #define _POSIX_C_SOURCE 200809L
17
18 #include <unistd.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <sys/mman.h>
22 #include <fcntl.h>
23 #include <errno.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdbool.h>
27 #include <stdint.h>
28 #include <string.h>
29 #include <nsi_tracing.h>
30
31 /*
32 * Initialize the flash buffer.
33 * And, if the content is to be kept on disk map it to the buffer to the file.
34 *
35 * Returns -1 on failure
36 * 0 on success
37 */
flash_mock_init_native(bool flash_in_ram,uint8_t ** mock_flash,unsigned int size,int * flash_fd,const char * flash_file_path,unsigned int erase_value,bool flash_erase_at_start)38 int flash_mock_init_native(bool flash_in_ram, uint8_t **mock_flash, unsigned int size,
39 int *flash_fd, const char *flash_file_path,
40 unsigned int erase_value, bool flash_erase_at_start)
41 {
42 struct stat f_stat;
43 int rc;
44
45 if (flash_in_ram == true) {
46 *mock_flash = (uint8_t *)malloc(size);
47 if (*mock_flash == NULL) {
48 nsi_print_warning("Could not allocate flash in the process heap %s\n",
49 strerror(errno));
50 return -1;
51 }
52 } else {
53 *flash_fd = open(flash_file_path, O_RDWR | O_CREAT, (mode_t)0600);
54 if (*flash_fd == -1) {
55 nsi_print_warning("Failed to open flash device file "
56 "%s: %s\n",
57 flash_file_path, strerror(errno));
58 return -1;
59 }
60
61 rc = fstat(*flash_fd, &f_stat);
62 if (rc) {
63 nsi_print_warning("Failed to get status of flash device file "
64 "%s: %s\n",
65 flash_file_path, strerror(errno));
66 return -1;
67 }
68
69 if (ftruncate(*flash_fd, size) == -1) {
70 nsi_print_warning("Failed to resize flash device file "
71 "%s: %s\n",
72 flash_file_path, strerror(errno));
73 return -1;
74 }
75
76 *mock_flash = mmap(NULL, size,
77 PROT_WRITE | PROT_READ, MAP_SHARED, *flash_fd, 0);
78 if (*mock_flash == MAP_FAILED) {
79 nsi_print_warning("Failed to mmap flash device file "
80 "%s: %s\n",
81 flash_file_path, strerror(errno));
82 return -1;
83 }
84 }
85
86 if ((flash_erase_at_start == true) || (flash_in_ram == true) || (f_stat.st_size == 0)) {
87 /* Erase the memory unit by pulling all bits to the configured erase value */
88 (void)memset(*mock_flash, erase_value, size);
89 }
90
91 return 0;
92 }
93
94 /*
95 * If in RAM: Free the mock buffer
96 * If in disk: unmap the flash file from RAM, close the file, and if configured to do so,
97 * delete the file.
98 */
flash_mock_cleanup_native(bool flash_in_ram,int flash_fd,uint8_t * mock_flash,unsigned int size,const char * flash_file_path,bool flash_rm_at_exit)99 void flash_mock_cleanup_native(bool flash_in_ram, int flash_fd, uint8_t *mock_flash,
100 unsigned int size, const char *flash_file_path,
101 bool flash_rm_at_exit)
102 {
103
104 if (flash_in_ram == true) {
105 if (mock_flash != NULL) {
106 free(mock_flash);
107 }
108 return;
109 }
110
111 if ((mock_flash != MAP_FAILED) && (mock_flash != NULL)) {
112 munmap(mock_flash, size);
113 }
114
115 if (flash_fd != -1) {
116 close(flash_fd);
117 }
118
119 if ((flash_rm_at_exit == true) && (flash_file_path != NULL)) {
120 /* We try to remove the file but do not error out if we can't */
121 (void) remove(flash_file_path);
122 }
123 }
124