
/*
   *  Object %name    : SEPDriver.h
   *  State           :  %state%
   *  Creation date   :  Wed Nov 17 17:39:24 2004
   *  Last modified   :  %modify_time%
   */
  /** @file
   *  \brief  Key Management h file (API and structures )
   *
   *  \version 
   *  \author yevgenys
   *  \remarks Copyright (C) 2004 by Discretix Technologies Ltd.
   *           All Rights reserved
   */

#include "DX_VOS_BaseTypes.h"
#include "DX_VOS_Mem.h"
#include "DX_VOS_Memmap.h"
#include "error.h"
#include "gen.h"
#include "Init_CC.h"
#include "SEPDriver.h"
#include "host_op_code.h"
#include "mng_host_op_code.h"
#include "GeneralHwDefs.h"



/*------------------------------
    DEFINES
--------------------------------*/

/* message token to sep */
#define HOST_SEP_MSG_TOKEN_HEAD             0X02558808UL

/* start address of the shared RAM */
#define DX_SHARED_RAM_START_ADDR            0x60000000

/* size of the shared RAM */
#define DX_SHARED_RAM_SIZE                  0x4000

/* resident area address */
#define DX_RESIDENT_START_ADDR              0x80000000

/* cache area address */
#define DX_CACHE_START_ADDR                 0x90000000



/*defaul D-cache size, it is set if the user send 0x0 for D-cache size*/
#define DX_CC_HOST_D_CACHE_SIZE				0x10000
/*defaul D-cache Heap size, it is set if the user send 0x0 for D-cache heap size*/
#define DX_CC_HOST_D_CACHE_HEAP_SIZE		0x8000
/*defaul D-cache Heap size, it is set if the user send 0x0 for D-cache stack size*/
#define DX_CC_HOST_D_CACHE_STACK_SIZE		0x2000
/*defaul D-cache global vars default address */
#define DX_CC_HOST_D_CACHE_GLOBAL_VARS_ADDR 0x2000FC00

/*--------------------------------------
  PROTOTYPES
---------------------------------------*/

/*------------------------------
    GLOBALS
--------------------------------*/

/*------------------------------------------------
    FUNCTIONS
--------------------------------------------------*/

/**
 * @brief      This function checks that the SEP first stage initialization has completed succuesfully 
 * @return     DxError:  
 *                        
 */
DxError_t DX_CC_StartExt(DX_CC_START_CCResult_t *CCResult_ptr, DxUint32_t * warningVal_ptr )
{
  /* error */
  DxError_t     Error = DX_OK;

#ifndef DX_TST_OS

  /* reg val */
  DxUint32_t    regVal;
  
  /* warning */
  DxUint32_t    warning;

  DX_CC_START_CCResult_t CCRes = DX_CC_START_IllaglResult_t;
  /*-----------------------------
    CODE
  ------------------------------*/
  
  warning = DX_OK;
  
  /* wait in polling for message from SEP */
  do
  {
    DX_GEN_ReadRegister(GEN_HW_HOST_SEP_HOST_GPR3_REG_ADDR , regVal);
  }while(!regVal);
  
  switch(regVal)
  {
  	case 0x1:
	    /* fatal error - read erro status from GPRO */
	    DX_GEN_ReadRegister(GEN_HW_HOST_SEP_HOST_GPR0_REG_ADDR , Error); 
		CCRes = DX_CC_START_fatalError_t;
		break;
  	case 0x2:
	    /* Boot First Phase ended  */
	    DX_GEN_ReadRegister(GEN_HW_HOST_SEP_HOST_GPR0_REG_ADDR , warning); 
		if(!warning)
		{
		    CCRes = DX_CC_START_ColdBootFirstPhaseComplete_t; 
		}
		else
		{
		    CCRes = DX_CC_START_ColdBootFirstPhaseCompleteWithWarning_t; 
		}
		Error = DX_OK;
		break;
  	case 0x4:
	    /* Cold boot ended successfully  */
	    DX_GEN_ReadRegister(GEN_HW_HOST_SEP_HOST_GPR0_REG_ADDR , warning); 
		if(!warning)
		{
		    CCRes = DX_CC_START_ColdBootComplete_t; 
		}
		else
		{
		    CCRes = DX_CC_START_ColdBootCompleteWithWarning_t; 
		}
		Error = DX_OK;
		break;
  	case 0x8:
	    /* Warmboot ended successfully */
	    DX_GEN_ReadRegister(GEN_HW_HOST_SEP_HOST_GPR0_REG_ADDR , warning); 
		if(!warning)
		{
		    CCRes = DX_CC_START_WarmBootComplete_t; 
		}
		else
		{
		    CCRes = DX_CC_START_WarmBootCompleteWithWarning_t; 
		}
		Error = DX_OK;
		break;
  	case 0x10:
	    /* ColdWarm boot ended successfully */
	    DX_GEN_ReadRegister(GEN_HW_HOST_SEP_HOST_GPR0_REG_ADDR , warning); 
		if(!warning)
		{
		    CCRes = DX_CC_START_ColdWarmBootComplete_t; 
		}
		else
		{
		    CCRes = DX_CC_START_ColdWarmBootCompleteWithWarning_t; 
		}
		Error = DX_OK;
		break;
  	case 0x20:
	    /* BM error  */
		CCRes = DX_CC_START_ICacheFailure_t; 
		Error = DX_OK;
		break;
  }

  if(warningVal_ptr != DX_NULL)
  {
  	*warningVal_ptr = warning;
  }

  if(CCResult_ptr != DX_NULL)
  {
  	*CCResult_ptr = CCRes;
  }
  
#endif
  
  return Error;
  
}

/**
 * @brief      This function finilizes the ROM BOOT process - should be called last. It sends to SEP
 *             the data that is needed for the successfull completion of the SEP setup
 * 
 * @param[in] HostMemoryBaseAddr - the start address of the host code
 * @param[in] HostSharedAreaAddress - the start address of the shared aread between Host and SEP (data area that can be directly accessed by SEP
 * @param[in] HostSharedAreaSize - the size of the shared area
 * @param[in] HostResidentBaseAddress - the start address of the resident code of SEP
 * @param[in] HostCacheBaseAddress - the start address of the cache
 *
 * @return     DxError:  
 *                        
 */
DxError_t DX_CC_Init(DxUint32_t    HostMemoryBaseAddr,
                     DxUint32_t    HostSharedAreaAddress,
                     DxUint32_t    HostSharedAreaSize,
                     DxUint32_t    HostResidentBaseAddress,
                     DxUint32_t    HostCacheBaseAddress,
                     DxUint32_t    HostExtCacheBaseAddress,
                     DxUint32_t    HostDCacheBaseAddress,
                     DxUint32_t    HostDCacheAreaSize,
                     DxUint32_t    HostDCacheHeapSize,
                     DxUint32_t    HostDCacheStackSize,
                     DxUint32_t    HostDCacheGlbBaseAddress)
                     
{
  DxUint32_t        messageBuffer[14];
  
  /* size of cache */
  DxUint32_t        cacheSize;
  
  /* size of resident */
  DxUint32_t        residentSize;
  
  /* size of extended cache */
  DxUint32_t        extCacheSize;

  /* new cache address */
  DxUint32_t        newCacheAddr;
  
  /* new resident address */
  DxUint32_t        newResidentAddr;
  
  /* new resident address */
  DxUint32_t        newDCacheAddr;
  
  /* new cache address */
  DxUint32_t        newSharedAreaAddr;
  
  /* new cache address */
  DxUint32_t        newBaseAddr;
  
  /* error */
  DxError_t         error;

  /*-------------------
    CODE
  ---------------------*/
  
  error  = DX_OK;
  
  /*Dcache parameter check*/
  /* Dcache size*/
  if(HostDCacheAreaSize == 0x0)
  {
  	HostDCacheAreaSize = DX_CC_HOST_D_CACHE_SIZE;
  }
  
  if(HostDCacheAreaSize < DX_CC_HOST_D_CACHE_SIZE)
  {
  	return DX_INVALID_D_CACHE_PARAM_ERR;	
  }

  /* Dcache Heap sizesize*/
  if(HostDCacheHeapSize == 0x0)
  {
  	HostDCacheHeapSize = DX_CC_HOST_D_CACHE_HEAP_SIZE;
  }
  
  if(HostDCacheHeapSize < DX_CC_HOST_D_CACHE_HEAP_SIZE)
  {
  	return DX_INVALID_D_CACHE_PARAM_ERR;	
  }

  /* Dcache stack size*/
  if(HostDCacheStackSize == 0x0)
  {
  	HostDCacheStackSize = DX_CC_HOST_D_CACHE_STACK_SIZE;
  }
  
  if(HostDCacheStackSize < DX_CC_HOST_D_CACHE_STACK_SIZE)
  {
  	return DX_INVALID_D_CACHE_PARAM_ERR;	
  }

  /* global var address*/
  if(HostDCacheGlbBaseAddress == 0x0)
  {
  	HostDCacheGlbBaseAddress = DX_CC_HOST_D_CACHE_GLOBAL_VARS_ADDR;
  }
  
  if(HostDCacheGlbBaseAddress < DX_CC_HOST_D_CACHE_GLOBAL_VARS_ADDR)
  {
  	return DX_INVALID_D_CACHE_PARAM_ERR;	
  }

  /* init the SEP driver */
  SEPDriver_Init(HostSharedAreaAddress);

#ifdef DX_TST_OS  
  /* lock the access to the SEP, needed mainly in the OS configuration */
  error = SEPDriver_Lock();
  if(error)
  {
    goto end_function;
  }
#endif
  
#ifndef DSM_SIM
  /* check paramaters */
  error = SEPDriver_CheckInitParams(HostSharedAreaSize);
  if(error)
  {
     goto end_function;
  }
#endif

  /* get size of cache , resident and extended cache in bytes */
  cacheSize = (*((DxUint32_t*)HostCacheBaseAddress)) * sizeof(DxUint32_t);
  residentSize = (*((DxUint32_t*)HostResidentBaseAddress)) * sizeof(DxUint32_t);
  
  if(HostExtCacheBaseAddress == 0)
  {
    extCacheSize = 0;
  }
  else
  {
    extCacheSize = (*((DxUint32_t*)HostExtCacheBaseAddress)) * sizeof(DxUint32_t);
  }

  /* rellocate the cache and resident */
  error = SEPDRiver_ReallocCacheResident(HostMemoryBaseAddr,
                                         HostCacheBaseAddress,
                                         cacheSize,
                                         HostResidentBaseAddress,
                                         residentSize,
                                         HostExtCacheBaseAddress,
                                         extCacheSize,
                                         HostDCacheBaseAddress,
                                         HostDCacheAreaSize,
                                         &newCacheAddr,
                                         &newResidentAddr,
                                         &newDCacheAddr,
                                         &newSharedAreaAddr,
                                         &newBaseAddr);
                                         
  if(error != DX_OK)
  {
    goto end_function;
  }

  
  /*prepare message buffer */
  messageBuffer[0] = HOST_SEP_MSG_TOKEN_HEAD;
  messageBuffer[1] = 15; /*length */
  messageBuffer[2] = 0x1; /*CC start op code*/
  messageBuffer[3] = newBaseAddr;
  messageBuffer[4] = newSharedAreaAddr;
  messageBuffer[5] = HostSharedAreaSize; /* shared area size */
  messageBuffer[6] = newResidentAddr;
  messageBuffer[7] = newCacheAddr;
  messageBuffer[8] = newDCacheAddr;
  messageBuffer[9] = HostDCacheAreaSize;
  messageBuffer[10] = HostDCacheHeapSize;
  messageBuffer[11] = HostDCacheStackSize;
  messageBuffer[12] = HostDCacheGlbBaseAddress;
  messageBuffer[13] = 0x0; /*checksum area*/
  messageBuffer[13] = SEPDriver_CheckSumCalc((DxUint8_t*)&messageBuffer[0],sizeof(messageBuffer));
  
  error = SEPDRiver_SendInitMessage((DxUint32_t)&messageBuffer[0] , 14, HW_CC_SRAM_BASE_ADDRESS);

#ifdef DX_TST_OS  
  SEPDriver_Unlock();
#endif

end_function:

  return error; 
}



/**
 * @brief      This function initiate and load the external cache image. 
 * 
 * @param[in] HostExtCacheBaseAddress - the start address of the cache
 * @param[in] keyType - the index of the Hashed RSA public key
 *
 * @return     DxError:  
 *                        
 */
DxError_t DX_CC_InitExt(DxUint32_t HostExtCacheBaseAddress, DX_CC_INIT_KEY_TYPES keyTypeOffset)
{
  /* offset into SRAM */
  DxUint32_t   		sramOffset;

  DxUint32_t        messageParam[2];
  
  /* new external application address */
  DxUint32_t        newAppBaseAddr;
  
  /* CC Init Ext op code */
  DxUint32_t 		opCode;
  
  /* external cache size */
  DxUint32_t 		cacheSize;
  
  /* error */
  DxError_t         Error;

  /*-------------------
    CODE
  ---------------------*/
  
  
  /* extended cache base address */
  if(HostExtCacheBaseAddress == DX_NULL)
  {
  	return DX_KMNG_INVALID_INPUT_POINTER_ERR;
  }

  /* initializing the Error to O.K */
  Error  = DX_OK;
  
  /* set offset to 0 */
  sramOffset = 0;
  
   /* set the op code*/
  opCode = DX_SEP_HOST_SEP_PROTOCOL_HOST_INIT_EXTAPP_OP_CODE;

  /* initiate and start the message */
  Error = SEPDriver_BuildMsgHeader(&sramOffset, opCode);
  if(Error != DX_OK)
  {
     goto end_function_unlock;
  }
  
  /* get size of cache in bytes */
  cacheSize = *(DxUint32_t*)HostExtCacheBaseAddress * sizeof(DxUint32_t);

  /* rellocate the cache and resident */
  Error = SEPDRiver_ReallocExtCache( HostExtCacheBaseAddress, cacheSize, &newAppBaseAddr );                     
  
  if(Error != DX_OK)
  {
    goto end_function_unlock;
  }
  
  /*prepare message buffer */
  messageParam[0] = newAppBaseAddr;
  messageParam[1] = keyTypeOffset;
  
  /* send message param */
  Error = SEPDriver_WriteParamater((DxUint32_t)messageParam, 
                           sizeof(DxUint32_t) * 2,
                           sizeof(DxUint32_t) * 2,
                           &sramOffset, 
                           DX_FALSE);
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }

  /* end message */
  SEPDriver_EndMessage(sramOffset);
            
  /* wait for the response */
  Error = SEPDriver_POLL_FOR_REPONSE();
  if(Error != DX_OK)
  {
    goto end_function_unlock;
  }
   
   /*-------------------------------------
      start reading message from the SEP 
   --------------------------------------*/
  
  /* check message status from SEP */
  Error = SEPDriver_CheckStatus(&sramOffset, opCode);
   
  if(Error != DX_OK)
  {
      goto end_function_unlock;
  }
  
   
  /* ................. end of function ..................................... */
  /* ----------------------------------------------------------------------- */
 
end_function_unlock:   

   /* lock access to the SEP */
   SEPDriver_Unlock();

   return Error;
}
