/*
 * Copyright 2021 NXP
 *
 * SPDX-License-Identifier: BSD-3-Clause
 *
 */

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include <arch_helpers.h>
#include "caam.h"
#include <common/debug.h>
#include "jobdesc.h"
#include "sec_hw_specific.h"


/* Callback function after Instantiation descriptor is submitted to SEC */
static void rng_done(uint32_t *desc, uint32_t status, void *arg,
		     void *job_ring)
{
	INFO("RNG Desc SUCCESS with status %x\n", status);
}

/* Is the HW RNG instantiated?
 * Return code:
 * 0 - Not in the instantiated state
 * 1 - In the instantiated state
 * state_handle - 0 for SH0, 1 for SH1
 */
static int is_hw_rng_instantiated(uint32_t *state_handle)
{
	int ret_code = 0;
	uint32_t rdsta;

	rdsta = sec_in32(get_caam_addr() + RNG_REG_RDSTA_OFFSET);

	 /*Check if either of the two state handles has been instantiated */
	if (rdsta & RNG_STATE0_HANDLE_INSTANTIATED) {
		*state_handle = 0;
		ret_code = 1;
	} else if (rdsta & RNG_STATE0_HANDLE_INSTANTIATED) {
		*state_handle = 1;
		ret_code = 1;
	}

	return ret_code;
}

/* @brief Kick the TRNG block of the RNG HW Engine
 * @param [in] ent_delay       Entropy delay to be used
 *        By default, the TRNG runs for 200 clocks per sample;
 *        1200 clocks per sample generates better entropy.
 * @retval 0 on success
 * @retval -1 on error
 */
static void kick_trng(int ent_delay)
{
	uint32_t val;

	/* put RNG4 into program mode */
	val = sec_in32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET);
	val = val | RTMCTL_PRGM;
	sec_out32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET, val);

	/* rtsdctl bits 0-15 contain "Entropy Delay, which defines the
	 *  length (in system clocks) of each Entropy sample taken
	 */
	val = sec_in32(get_caam_addr() + RNG_REG_RTSDCTL_OFFSET);
	val = (val & ~RTSDCTL_ENT_DLY_MASK) |
	    (ent_delay << RTSDCTL_ENT_DLY_SHIFT);
	sec_out32(get_caam_addr() + RNG_REG_RTSDCTL_OFFSET, val);
	/* min. freq. count, equal to 1/4 of the entropy sample length */
	sec_out32(get_caam_addr() + RNG_REG_RTFRQMIN_OFFSET, ent_delay >> 2);
	/* disable maximum frequency count */
	sec_out32(get_caam_addr() + RNG_REG_RTFRQMAX_OFFSET, RTFRQMAX_DISABLE);

	/* select raw sampling in both entropy shifter
	 *  and statistical checker
	 */
	val = sec_in32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET);
	val = val | RTMCTL_SAMP_MODE_RAW_ES_SC;
	sec_out32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET, val);

	/* put RNG4 into run mode */
	val = sec_in32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET);
	val = val & ~RTMCTL_PRGM;
	sec_out32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET, val);
}

/* @brief Submit descriptor to instantiate the RNG
 * @retval 0 on success
 * @retval -1 on error
 */
static int instantiate_rng(void)
{
	int ret = 0;
	struct job_descriptor desc __aligned(CACHE_WRITEBACK_GRANULE);
	struct job_descriptor *jobdesc = &desc;

	jobdesc->arg = NULL;
	jobdesc->callback = rng_done;

	/* create the hw_rng descriptor */
	cnstr_rng_instantiate_jobdesc(jobdesc->desc);

	/* Finally, generate the requested random data bytes */
	ret = run_descriptor_jr(jobdesc);
	if (ret != 0) {
		ERROR("Error in running descriptor\n");
		ret = -1;
	}
	return ret;
}

/* Generate Random Data using HW RNG
 * Parameters:
 * uint8_t* add_input   - user specified optional input byte array
 * uint32_t add_input_len - number of bytes of additional input
 * uint8_t* out                   - user specified output byte array
 * uint32_t out_len       - number of bytes to store in output byte array
 * Return code:
 * 0 - SUCCESS
 * -1 - ERROR
 */
static int
hw_rng_generate(uint32_t *add_input, uint32_t add_input_len,
		uint8_t *out, uint32_t out_len, uint32_t state_handle)
{
	int ret = 0;
	struct job_descriptor desc __aligned(CACHE_WRITEBACK_GRANULE);
	struct job_descriptor *jobdesc = &desc;

	jobdesc->arg = NULL;
	jobdesc->callback = rng_done;

#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
	inv_dcache_range((uintptr_t)out, out_len);
	dmbsy();
#endif

	/* create the hw_rng descriptor */
	ret = cnstr_rng_jobdesc(jobdesc->desc, state_handle,
				add_input, add_input_len, out, out_len);
	if (ret != 0) {
		ERROR("Descriptor construction failed\n");
		ret = -1;
		goto out;
	}
	/* Finally, generate the requested random data bytes */
	ret = run_descriptor_jr(jobdesc);
	if (ret != 0) {
		ERROR("Error in running descriptor\n");
		ret = -1;
	}

out:
	return ret;
}

/* this function instantiates the rng
 *
 * Return code:
 *  0 - All is well
 * <0 - Error occurred somewhere
 */
int hw_rng_instantiate(void)
{
	int ret = 0;
	int ent_delay = RTSDCTL_ENT_DLY_MIN;
	uint32_t state_handle;

	ret = is_hw_rng_instantiated(&state_handle);
	if (ret != 0) {
		NOTICE("RNG already instantiated\n");
		return 0;
	}
	do {
		kick_trng(ent_delay);
		ent_delay += 400;
		/*if instantiate_rng(...) fails, the loop will rerun
		 *and the kick_trng(...) function will modify the
		 *upper and lower limits of the entropy sampling
		 *interval, leading to a successful initialization of
		 */
		ret = instantiate_rng();
	} while ((ret == -1) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
	if (ret != 0) {
		ERROR("RNG: Failed to instantiate RNG\n");
		return ret;
	}

	NOTICE("RNG: INSTANTIATED\n");

	/* Enable RDB bit so that RNG works faster */
	// sec_setbits32(&sec->scfgr, SEC_SCFGR_RDBENABLE);

	return ret;
}

/* Generate random bytes, and stuff them into the bytes buffer
 *
 * If the HW RNG has not already been instantiated,
 *  it will be instantiated before data is generated.
 *
 * Parameters:
 * uint8_t* bytes  - byte buffer large enough to hold the requested random date
 * int byte_len - number of random bytes to generate
 *
 * Return code:
 *  0 - All is well
 *  ~0 - Error occurred somewhere
 */
int get_rand_bytes_hw(uint8_t *bytes, int byte_len)
{
	int ret_code = 0;
	uint32_t state_handle;

	/* If this is the first time this routine is called,
	 *  then the hash_drbg will not already be instantiated.
	 * Therefore, before generating data, instantiate the hash_drbg
	 */
	ret_code = is_hw_rng_instantiated(&state_handle);
	if (ret_code == 0) {
		INFO("Instantiating the HW RNG\n");

		/* Instantiate the hw RNG */
		ret_code = hw_rng_instantiate();
		if (ret_code != 0) {
			ERROR("HW RNG Instantiate failed\n");
			return ret_code;
		}
	}
	/* If  HW RNG is still not instantiated, something must have gone wrong,
	 * it must be in the error state, we will not generate any random data
	 */
	if (is_hw_rng_instantiated(&state_handle) == 0) {
		ERROR("HW RNG is in an Error state, and cannot be used\n");
		return -1;
	}
	/* Generate a random 256-bit value, as 32 bytes */
	ret_code = hw_rng_generate(0, 0, bytes, byte_len, state_handle);
	if (ret_code != 0) {
		ERROR("HW RNG Generate failed\n");
		return ret_code;
	}

	return ret_code;
}
