|  | /* | 
|  | * Copyright (c) 2024 Nordic Semiconductor ASA | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | * | 
|  | * Part of EEPROM simulator which interacts with the host OS / Linux | 
|  | * | 
|  | * When building for the native simulator, this file is built in the | 
|  | * native simulator runner/host context, and not in Zephyr/embedded context. | 
|  | */ | 
|  |  | 
|  | #undef _POSIX_C_SOURCE | 
|  | #define _POSIX_C_SOURCE 200809L | 
|  |  | 
|  | #include <unistd.h> | 
|  | #include <sys/types.h> | 
|  | #include <sys/stat.h> | 
|  | #include <sys/mman.h> | 
|  | #include <fcntl.h> | 
|  | #include <errno.h> | 
|  | #include <stdio.h> | 
|  | #include <stdlib.h> | 
|  | #include <stdbool.h> | 
|  | #include <string.h> | 
|  | #include <nsi_tracing.h> | 
|  |  | 
|  | /* | 
|  | * Initialize the EEPROM buffer. | 
|  | * And, if the content is to be kept on disk map it to the buffer to the file. | 
|  | * | 
|  | * Returns -1 on failure | 
|  | *	    0 on success | 
|  | */ | 
|  | int eeprom_mock_init_native(bool eeprom_in_ram, char **mock_eeprom, unsigned int size, | 
|  | int *eeprom_fd, const char *eeprom_file_path, unsigned int erase_value, | 
|  | bool eeprom_erase_at_start) | 
|  | { | 
|  | struct stat f_stat; | 
|  | int rc; | 
|  |  | 
|  | if (eeprom_in_ram == true) { | 
|  | *mock_eeprom = (char *)malloc(size); | 
|  | if (*mock_eeprom == NULL) { | 
|  | nsi_print_warning("Could not allocate EEPROM in the process heap %s\n", | 
|  | strerror(errno)); | 
|  | return -1; | 
|  | } | 
|  | } else { | 
|  | *eeprom_fd = open(eeprom_file_path, O_RDWR | O_CREAT | O_CLOEXEC, (mode_t)0600); | 
|  | if (*eeprom_fd == -1) { | 
|  | nsi_print_warning("Failed to open EEPROM device file %s: %s\n", | 
|  | eeprom_file_path, strerror(errno)); | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | rc = fstat(*eeprom_fd, &f_stat); | 
|  | if (rc) { | 
|  | nsi_print_warning("Failed to get status of EEPROM device file %s: %s\n", | 
|  | eeprom_file_path, strerror(errno)); | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | if (ftruncate(*eeprom_fd, size) == -1) { | 
|  | nsi_print_warning("Failed to resize EEPROM device file %s: %s\n", | 
|  | eeprom_file_path, strerror(errno)); | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | *mock_eeprom = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, *eeprom_fd, 0); | 
|  | if (*mock_eeprom == MAP_FAILED) { | 
|  | nsi_print_warning("Failed to mmap EEPROM device file %s: %s\n", | 
|  | eeprom_file_path, strerror(errno)); | 
|  | return -1; | 
|  | } | 
|  | } | 
|  |  | 
|  | if ((eeprom_erase_at_start == true) || (eeprom_in_ram == true) || (f_stat.st_size == 0)) { | 
|  | /* Erase the EEPROM by setting all bits to the configured erase value */ | 
|  | (void)memset(*mock_eeprom, erase_value, size); | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * If in RAM: Free the mock buffer | 
|  | * If in disk: unmap the eeprom file from RAM, close the file, and if configured to do so, | 
|  | * delete the file. | 
|  | */ | 
|  | void eeprom_mock_cleanup_native(bool eeprom_in_ram, int eeprom_fd, char *mock_eeprom, | 
|  | unsigned int size, const char *eeprom_file_path, | 
|  | bool eeprom_rm_at_exit) | 
|  | { | 
|  |  | 
|  | if (eeprom_in_ram == true) { | 
|  | if (mock_eeprom != NULL) { | 
|  | free(mock_eeprom); | 
|  | } | 
|  | return; | 
|  | } | 
|  |  | 
|  | if ((mock_eeprom != MAP_FAILED) && (mock_eeprom != NULL)) { | 
|  | munmap(mock_eeprom, size); | 
|  | } | 
|  |  | 
|  | if (eeprom_fd != -1) { | 
|  | close(eeprom_fd); | 
|  | } | 
|  |  | 
|  | if ((eeprom_rm_at_exit == true) && (eeprom_file_path != NULL)) { | 
|  | /* We try to remove the file but do not error out if we can't */ | 
|  | (void)remove(eeprom_file_path); | 
|  | } | 
|  | } |