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 #include <unistd.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <sys/mman.h>
16 #include <fcntl.h>
17 #include <errno.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <stdbool.h>
21 #include <stdint.h>
22 #include <string.h>
23 #include <nsi_tracing.h>
24
25 /*
26 * Initialize the flash buffer.
27 * And, if the content is to be kept on disk map it to the the buffer to the file.
28 *
29 * Returns -1 on failure
30 * 0 on success
31 */
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)32 int flash_mock_init_native(bool flash_in_ram, uint8_t **mock_flash, unsigned int size,
33 int *flash_fd, const char *flash_file_path,
34 unsigned int erase_value, bool flash_erase_at_start)
35 {
36 struct stat f_stat;
37 int rc;
38
39 if (flash_in_ram == true) {
40 *mock_flash = (uint8_t *)malloc(size);
41 if (*mock_flash == NULL) {
42 nsi_print_warning("Could not allocate flash in the process heap %s\n",
43 strerror(errno));
44 return -1;
45 }
46 } else {
47 *flash_fd = open(flash_file_path, O_RDWR | O_CREAT, (mode_t)0600);
48 if (*flash_fd == -1) {
49 nsi_print_warning("Failed to open flash device file "
50 "%s: %s\n",
51 flash_file_path, strerror(errno));
52 return -1;
53 }
54
55 rc = fstat(*flash_fd, &f_stat);
56 if (rc) {
57 nsi_print_warning("Failed to get status of flash device file "
58 "%s: %s\n",
59 flash_file_path, strerror(errno));
60 return -1;
61 }
62
63 if (ftruncate(*flash_fd, size) == -1) {
64 nsi_print_warning("Failed to resize flash device file "
65 "%s: %s\n",
66 flash_file_path, strerror(errno));
67 return -1;
68 }
69
70 *mock_flash = mmap(NULL, size,
71 PROT_WRITE | PROT_READ, MAP_SHARED, *flash_fd, 0);
72 if (*mock_flash == MAP_FAILED) {
73 nsi_print_warning("Failed to mmap flash device file "
74 "%s: %s\n",
75 flash_file_path, strerror(errno));
76 return -1;
77 }
78 }
79
80 if ((flash_erase_at_start == true) || (flash_in_ram == true) || (f_stat.st_size == 0)) {
81 /* Erase the memory unit by pulling all bits to the configured erase value */
82 (void)memset(*mock_flash, erase_value, size);
83 }
84
85 return 0;
86 }
87
88 /*
89 * If in RAM: Free the mock buffer
90 * If in disk: unmap the flash file from RAM, close the file, and if configured to do so,
91 * delete the file.
92 */
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)93 void flash_mock_cleanup_native(bool flash_in_ram, int flash_fd, uint8_t *mock_flash,
94 unsigned int size, const char *flash_file_path,
95 bool flash_rm_at_exit)
96 {
97
98 if (flash_in_ram == true) {
99 if (mock_flash != NULL) {
100 free(mock_flash);
101 }
102 return;
103 }
104
105 if ((mock_flash != MAP_FAILED) && (mock_flash != NULL)) {
106 munmap(mock_flash, size);
107 }
108
109 if (flash_fd != -1) {
110 close(flash_fd);
111 }
112
113 if ((flash_rm_at_exit == true) && (flash_file_path != NULL)) {
114 /* We try to remove the file but do not error out if we can't */
115 (void) remove(flash_file_path);
116 }
117 }
118