/*
 * 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);
	}
}
