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

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

#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/arm/css/sds.h>
#include <platform_def.h>

#include "sds_private.h"

/*
 * Variables used to track and maintain the state of the memory region reserved
 * for usage by the SDS framework.
 */

/* Pointer to the base of the SDS memory region */
static uintptr_t sds_mem_base;

/* Size of the SDS memory region in bytes */
static size_t sds_mem_size;

/*
 * Perform some non-exhaustive tests to determine whether any of the fields
 * within a Structure Header contain obviously invalid data.
 * Returns SDS_OK on success, SDS_ERR_FAIL on error.
 */
static int sds_struct_is_valid(uintptr_t header)
{
	size_t struct_size = GET_SDS_HEADER_STRUCT_SIZE(header);

	/* Zero is not a valid identifier */
	if (GET_SDS_HEADER_ID(header) == 0)
		return SDS_ERR_FAIL;

	/* Check SDS Schema version */
	if (GET_SDS_HEADER_VERSION(header) == SDS_REGION_SCH_VERSION)
		return SDS_ERR_FAIL;

	/* The SDS Structure sizes have to be multiple of 8 */
	if ((struct_size == 0) || ((struct_size % 8) != 0))
		return SDS_ERR_FAIL;

	if (struct_size > sds_mem_size)
		return SDS_ERR_FAIL;

	return SDS_OK;
}

/*
 * Validate the SDS structure headers.
 * Returns SDS_OK on success, SDS_ERR_FAIL on error.
 */
static int validate_sds_struct_headers(void)
{
	unsigned int i, structure_count;
	uintptr_t header;

	structure_count = GET_SDS_REGION_STRUCTURE_COUNT(sds_mem_base);

	if (structure_count == 0)
		return SDS_ERR_FAIL;

	header = sds_mem_base + SDS_REGION_DESC_SIZE;

	/* Iterate over structure headers and validate each one */
	for (i = 0; i < structure_count; i++) {
		if (sds_struct_is_valid(header) != SDS_OK) {
			WARN("SDS: Invalid structure header detected\n");
			return SDS_ERR_FAIL;
		}
		header += GET_SDS_HEADER_STRUCT_SIZE(header) + SDS_HEADER_SIZE;
	}
	return SDS_OK;
}

/*
 * Get the structure header pointer corresponding to the structure ID.
 * Returns SDS_OK on success, SDS_ERR_STRUCT_NOT_FOUND on error.
 */
static int get_struct_header(uint32_t structure_id, struct_header_t **header)
{
	unsigned int i, structure_count;
	uintptr_t current_header;

	assert(header);

	structure_count = GET_SDS_REGION_STRUCTURE_COUNT(sds_mem_base);
	if (structure_count == 0)
		return SDS_ERR_STRUCT_NOT_FOUND;

	current_header = ((uintptr_t)sds_mem_base) + SDS_REGION_DESC_SIZE;

	/* Iterate over structure headers to find one with a matching ID */
	for (i = 0; i < structure_count; i++) {
		if (GET_SDS_HEADER_ID(current_header) == structure_id) {
			*header = (struct_header_t *)current_header;
			return SDS_OK;
		}
		current_header += GET_SDS_HEADER_STRUCT_SIZE(current_header) +
						SDS_HEADER_SIZE;
	}

	*header = NULL;
	return SDS_ERR_STRUCT_NOT_FOUND;
}

/*
 * Check if a structure header corresponding to the structure ID exists.
 * Returns SDS_OK if structure header exists else SDS_ERR_STRUCT_NOT_FOUND
 * if not found.
 */
int sds_struct_exists(unsigned int structure_id)
{
	struct_header_t *header = NULL;
	int ret;

	ret = get_struct_header(structure_id, &header);
	if (ret == SDS_OK) {
		assert(header);
	}

	return ret;
}

/*
 * Read from field in the structure corresponding to `structure_id`.
 * `fld_off` is the offset to the field in the structure and `mode`
 * indicates whether cache maintenance need to performed prior to the read.
 * The `data` is the pointer to store the read data of size specified by `size`.
 * Returns SDS_OK on success or corresponding error codes on failure.
 */
int sds_struct_read(uint32_t structure_id, unsigned int fld_off,
		void *data, size_t size, sds_access_mode_t mode)
{
	int status;
	uintptr_t field_base;
	struct_header_t *header = NULL;

	if (!data)
		return SDS_ERR_INVALID_PARAMS;

	/* Check if a structure with this ID exists */
	status = get_struct_header(structure_id, &header);
	if (status != SDS_OK)
		return status;

	assert(header);

	if (mode == SDS_ACCESS_MODE_CACHED)
		inv_dcache_range((uintptr_t)header, SDS_HEADER_SIZE + size);

	if (!IS_SDS_HEADER_VALID(header)) {
		WARN("SDS: Reading from un-finalized structure 0x%x\n",
				structure_id);
		return SDS_ERR_STRUCT_NOT_FINALIZED;
	}

	if ((fld_off + size) > GET_SDS_HEADER_STRUCT_SIZE(header))
		return SDS_ERR_FAIL;

	field_base = (uintptr_t)header + SDS_HEADER_SIZE + fld_off;
	if (check_uptr_overflow(field_base, size - 1))
		return SDS_ERR_FAIL;

	/* Copy the required field in the struct */
	memcpy(data, (void *)field_base, size);

	return SDS_OK;
}

/*
 * Write to the field in the structure corresponding to `structure_id`.
 * `fld_off` is the offset to the field in the structure and `mode`
 * indicates whether cache maintenance need to performed for the write.
 * The `data` is the pointer to data of size specified by `size`.
 * Returns SDS_OK on success or corresponding error codes on failure.
 */
int sds_struct_write(uint32_t structure_id, unsigned int fld_off,
		void *data, size_t size, sds_access_mode_t mode)
{
	int status;
	uintptr_t field_base;
	struct_header_t *header = NULL;

	if (!data)
		return SDS_ERR_INVALID_PARAMS;

	/* Check if a structure with this ID exists */
	status = get_struct_header(structure_id, &header);
	if (status != SDS_OK)
		return status;

	assert(header);

	if (mode == SDS_ACCESS_MODE_CACHED)
		inv_dcache_range((uintptr_t)header, SDS_HEADER_SIZE + size);

	if (!IS_SDS_HEADER_VALID(header)) {
		WARN("SDS: Writing to un-finalized structure 0x%x\n",
				structure_id);
		return SDS_ERR_STRUCT_NOT_FINALIZED;
	}

	if ((fld_off + size) > GET_SDS_HEADER_STRUCT_SIZE(header))
		return SDS_ERR_FAIL;

	field_base = (uintptr_t)header + SDS_HEADER_SIZE + fld_off;
	if (check_uptr_overflow(field_base, size - 1))
		return SDS_ERR_FAIL;

	/* Copy the required field in the struct */
	memcpy((void *)field_base, data, size);

	if (mode == SDS_ACCESS_MODE_CACHED)
		flush_dcache_range((uintptr_t)field_base, size);

	return SDS_OK;
}

/*
 * Initialize the SDS driver. Also verifies the SDS version and sanity of
 * the SDS structure headers.
 * Returns SDS_OK on success, SDS_ERR_FAIL on error.
 */
int sds_init(void)
{
	sds_mem_base = (uintptr_t)PLAT_ARM_SDS_MEM_BASE;

	if (!IS_SDS_REGION_VALID(sds_mem_base)) {
		WARN("SDS: No valid SDS Memory Region found\n");
		return SDS_ERR_FAIL;
	}

	if (GET_SDS_REGION_SCHEMA_VERSION(sds_mem_base)
				!= SDS_REGION_SCH_VERSION) {
		WARN("SDS: Unsupported SDS schema version\n");
		return SDS_ERR_FAIL;
	}

	sds_mem_size = GET_SDS_REGION_SIZE(sds_mem_base);
	if (sds_mem_size > PLAT_ARM_SDS_MEM_SIZE_MAX) {
		WARN("SDS: SDS Memory Region exceeds size limit\n");
		return SDS_ERR_FAIL;
	}

	INFO("SDS: Detected SDS Memory Region (%zu bytes)\n", sds_mem_size);

	if (validate_sds_struct_headers() != SDS_OK)
		return SDS_ERR_FAIL;

	return SDS_OK;
}
