/*
 * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>
#include <string.h>

#include <platform_def.h>

#include <common/debug.h>
#include <drivers/io/io_driver.h>
#include <drivers/io/io_memmap.h>
#include <drivers/io/io_storage.h>
#include <lib/utils.h>

/* As we need to be able to keep state for seek, only one file can be open
 * at a time. Make this a structure and point to the entity->info. When we
 * can malloc memory we can change this to support more open files.
 */
typedef struct {
	/* Use the 'in_use' flag as any value for base and file_pos could be
	 * valid.
	 */
	int			in_use;
	uintptr_t		base;
	unsigned long long	file_pos;
	unsigned long long	size;
} memmap_file_state_t;

static memmap_file_state_t current_memmap_file = {0};

/* Identify the device type as memmap */
static io_type_t device_type_memmap(void)
{
	return IO_TYPE_MEMMAP;
}

/* Memmap device functions */
static int memmap_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
static int memmap_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
			     io_entity_t *entity);
static int memmap_block_seek(io_entity_t *entity, int mode,
			     signed long long offset);
static int memmap_block_len(io_entity_t *entity, size_t *length);
static int memmap_block_read(io_entity_t *entity, uintptr_t buffer,
			     size_t length, size_t *length_read);
static int memmap_block_write(io_entity_t *entity, const uintptr_t buffer,
			      size_t length, size_t *length_written);
static int memmap_block_close(io_entity_t *entity);
static int memmap_dev_close(io_dev_info_t *dev_info);


static const io_dev_connector_t memmap_dev_connector = {
	.dev_open = memmap_dev_open
};


static const io_dev_funcs_t memmap_dev_funcs = {
	.type = device_type_memmap,
	.open = memmap_block_open,
	.seek = memmap_block_seek,
	.size = memmap_block_len,
	.read = memmap_block_read,
	.write = memmap_block_write,
	.close = memmap_block_close,
	.dev_init = NULL,
	.dev_close = memmap_dev_close,
};


/* No state associated with this device so structure can be const */
static io_dev_info_t memmap_dev_info = {
	.funcs = &memmap_dev_funcs,
	.info = (uintptr_t)NULL
};


/* Open a connection to the memmap device */
static int memmap_dev_open(const uintptr_t dev_spec __unused,
			   io_dev_info_t **dev_info)
{
	assert(dev_info != NULL);
	*dev_info = &memmap_dev_info;
	return 0;
}



/* Close a connection to the memmap device */
static int memmap_dev_close(io_dev_info_t *dev_info)
{
	/* NOP */
	/* TODO: Consider tracking open files and cleaning them up here */
	return 0;
}


/* Open a file on the memmap device */
static int memmap_block_open(io_dev_info_t *dev_info, const uintptr_t spec,
			     io_entity_t *entity)
{
	int result = -ENOMEM;
	const io_block_spec_t *block_spec = (io_block_spec_t *)spec;

	/* Since we need to track open state for seek() we only allow one open
	 * spec at a time. When we have dynamic memory we can malloc and set
	 * entity->info.
	 */
	if (current_memmap_file.in_use == 0) {
		assert(block_spec != NULL);
		assert(entity != NULL);

		current_memmap_file.in_use = 1;
		current_memmap_file.base = block_spec->offset;
		/* File cursor offset for seek and incremental reads etc. */
		current_memmap_file.file_pos = 0;
		current_memmap_file.size = block_spec->length;
		entity->info = (uintptr_t)&current_memmap_file;
		result = 0;
	} else {
		WARN("A Memmap device is already active. Close first.\n");
	}

	return result;
}


/* Seek to a particular file offset on the memmap device */
static int memmap_block_seek(io_entity_t *entity, int mode,
			     signed long long offset)
{
	int result = -ENOENT;
	memmap_file_state_t *fp;

	/* We only support IO_SEEK_SET for the moment. */
	if (mode == IO_SEEK_SET) {
		assert(entity != NULL);

		fp = (memmap_file_state_t *) entity->info;

		/* Assert that new file position is valid */
		assert((offset >= 0) &&
		       ((unsigned long long)offset < fp->size));

		/* Reset file position */
		fp->file_pos = (unsigned long long)offset;
		result = 0;
	}

	return result;
}


/* Return the size of a file on the memmap device */
static int memmap_block_len(io_entity_t *entity, size_t *length)
{
	assert(entity != NULL);
	assert(length != NULL);

	*length = (size_t)((memmap_file_state_t *)entity->info)->size;

	return 0;
}


/* Read data from a file on the memmap device */
static int memmap_block_read(io_entity_t *entity, uintptr_t buffer,
			     size_t length, size_t *length_read)
{
	memmap_file_state_t *fp;
	unsigned long long pos_after;

	assert(entity != NULL);
	assert(length_read != NULL);

	fp = (memmap_file_state_t *) entity->info;

	/* Assert that file position is valid for this read operation */
	pos_after = fp->file_pos + length;
	assert((pos_after >= fp->file_pos) && (pos_after <= fp->size));

	memcpy((void *)buffer,
	       (void *)((uintptr_t)(fp->base + fp->file_pos)), length);

	*length_read = length;

	/* Set file position after read */
	fp->file_pos = pos_after;

	return 0;
}


/* Write data to a file on the memmap device */
static int memmap_block_write(io_entity_t *entity, const uintptr_t buffer,
			      size_t length, size_t *length_written)
{
	memmap_file_state_t *fp;
	unsigned long long pos_after;

	assert(entity != NULL);
	assert(length_written != NULL);

	fp = (memmap_file_state_t *) entity->info;

	/* Assert that file position is valid for this write operation */
	pos_after = fp->file_pos + length;
	assert((pos_after >= fp->file_pos) && (pos_after <= fp->size));

	memcpy((void *)((uintptr_t)(fp->base + fp->file_pos)),
	       (void *)buffer, length);

	*length_written = length;

	/* Set file position after write */
	fp->file_pos = pos_after;

	return 0;
}


/* Close a file on the memmap device */
static int memmap_block_close(io_entity_t *entity)
{
	assert(entity != NULL);

	entity->info = 0;

	/* This would be a mem free() if we had malloc.*/
	zeromem((void *)&current_memmap_file, sizeof(current_memmap_file));

	return 0;
}


/* Exported functions */

/* Register the memmap driver with the IO abstraction */
int register_io_dev_memmap(const io_dev_connector_t **dev_con)
{
	int result;
	assert(dev_con != NULL);

	result = io_register_device(&memmap_dev_info);
	if (result == 0)
		*dev_con = &memmap_dev_connector;

	return result;
}
