blob: 44eebeba650bf634ed4387d465044f3c2136c1c7 [file] [log] [blame]
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*
* Part of flash simulator which interacts with the host OS
*
* 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
/* Note: This is used only for interaction with the host C library, and is therefore exempt of
* coding guidelines rule A.4&5 which applies to the embedded code using embedded libraries
*/
#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 <stdint.h>
#include <string.h>
#include <nsi_tracing.h>
/*
* Initialize the flash buffer.
* And, if the content is to be kept on disk map it to the the buffer to the file.
*
* Returns -1 on failure
* 0 on success
*/
int 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)
{
struct stat f_stat;
int rc;
if (flash_in_ram == true) {
*mock_flash = (uint8_t *)malloc(size);
if (*mock_flash == NULL) {
nsi_print_warning("Could not allocate flash in the process heap %s\n",
strerror(errno));
return -1;
}
} else {
*flash_fd = open(flash_file_path, O_RDWR | O_CREAT, (mode_t)0600);
if (*flash_fd == -1) {
nsi_print_warning("Failed to open flash device file "
"%s: %s\n",
flash_file_path, strerror(errno));
return -1;
}
rc = fstat(*flash_fd, &f_stat);
if (rc) {
nsi_print_warning("Failed to get status of flash device file "
"%s: %s\n",
flash_file_path, strerror(errno));
return -1;
}
if (ftruncate(*flash_fd, size) == -1) {
nsi_print_warning("Failed to resize flash device file "
"%s: %s\n",
flash_file_path, strerror(errno));
return -1;
}
*mock_flash = mmap(NULL, size,
PROT_WRITE | PROT_READ, MAP_SHARED, *flash_fd, 0);
if (*mock_flash == MAP_FAILED) {
nsi_print_warning("Failed to mmap flash device file "
"%s: %s\n",
flash_file_path, strerror(errno));
return -1;
}
}
if ((flash_erase_at_start == true) || (flash_in_ram == true) || (f_stat.st_size == 0)) {
/* Erase the memory unit by pulling all bits to the configured erase value */
(void)memset(*mock_flash, erase_value, size);
}
return 0;
}
/*
* If in RAM: Free the mock buffer
* If in disk: unmap the flash file from RAM, close the file, and if configured to do so,
* delete the file.
*/
void 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)
{
if (flash_in_ram == true) {
if (mock_flash != NULL) {
free(mock_flash);
}
return;
}
if ((mock_flash != MAP_FAILED) && (mock_flash != NULL)) {
munmap(mock_flash, size);
}
if (flash_fd != -1) {
close(flash_fd);
}
if ((flash_rm_at_exit == true) && (flash_file_path != NULL)) {
/* We try to remove the file but do not error out if we can't */
(void) remove(flash_file_path);
}
}