/**
  ******************************************************************************
  * @file    se_user_code.c
  * @author  MCD Application Team
  * @brief   Secure Engine User code example module.
  *          This file demonstrates how to call user defined services running
  *          in Secure Engine.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright(c) 2017 STMicroelectronics International N.V.
  * All rights reserved.</center></h2>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted, provided that the following conditions are met:
  *
  * 1. Redistribution of source code must retain the above copyright notice,
  *    this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright notice,
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. Neither the name of STMicroelectronics nor the names of other
  *    contributors to this software may be used to endorse or promote products
  *    derived from this software without specific written permission.
  * 4. This software, including modifications and/or derivative works of this
  *    software, must execute solely and exclusively on microcontroller or
  *    microprocessor devices manufactured by or for STMicroelectronics.
  * 5. Redistribution and use of this software other than as permitted under
  *    this license is void and will automatically terminate your rights under
  *    this license.
  *
  * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
  * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
  * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

#define STEP2

/* Includes ------------------------------------------------------------------*/
#include "se_def.h"
#include "com.h"
#include "common.h"
#include "stm32l4xx_hal.h"
#include "stm32l4xx_nucleo.h"
#include "se_user_code.h"
#include "se_interface_application.h"
#include <string.h> /* needed for memset */


/** @addtogroup USER_APP User App Example
  * @{
  */

/** @addtogroup  SE_USER_CODE Secure Engine User Code Example
  * @brief Example of user defined code running in Secure Engine.
  *        This code provides user defined services to the user application.
  * @{
  */

/** @defgroup  SE_USER_CODE_Private_Variables Private Variables
  * @{
  */
/*+ Step 2 */
uint8_t myNonce[12] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B};
uint8_t myTag[16];
uint8_t myDataOut_UC1[32];
/*- Step 2 */

/**
  * @}
  */

/** @defgroup  SE_USER_CODE_Private_Functions Private Functions
  * @{
  */
static void SE_USER_CODE_PrintWelcome(void);
static HAL_StatusTypeDef SE_USER_CODE_RunGetActiveFwInfo(void);
static HAL_StatusTypeDef SE_USER_CODE_RunUserCode1(void);
static HAL_StatusTypeDef SE_USER_CODE_RunUserCode2(void);

/**
  * @brief  Display the SE_USER_CODE Main Menu choices on HyperTerminal
  * @param  None.
  * @retval None.
  */
static void SE_USER_CODE_PrintWelcome(void)
{
  printf("\r\n================ Call User Defined Code running in Secure Engine =========================\r\n\n");
}

/**
  * @brief  Display the User Code Main Menu choices on HyperTerminal
  * @param  None.
  * @retval None.
  */
static void TEST_UserCode_PrintTestingMenu(void)
{
  printf("\r\n================== User Code  Menu ====================\r\n\n");
  printf("  GetActiveFwInfo ---------------------- 1\r\n\n");
  printf("  Your function 1 ---------------------- 2\r\n\n");
  printf("  Your function 2 ---------------------- 3\r\n\n");
  printf("  Previous Menu ----------------------------------------- x\r\n\n");
}


/**
  * @}
  */

/** @addtogroup  SE_USER_CODE_Exported_Functions
  * @{
  */

/**
  * @brief  Run GetActive FW Info.
  * @param  None
  * @retval HAL Status.
  */
HAL_StatusTypeDef SE_USER_CODE_RunGetActiveFwInfo(void)
{
  HAL_StatusTypeDef ret = HAL_ERROR;
  SE_ErrorStatus se_retCode = SE_ERROR;
  SE_StatusTypeDef se_Status = SE_KO;
  SE_APP_ActiveFwInfo sl_FwInfo;

  memset(&sl_FwInfo, 0xFF, sizeof(SE_APP_ActiveFwInfo));

  /* Get FW info */
  se_retCode = SE_APP_GetActiveFwInfo(&se_Status, &sl_FwInfo);

  if ((SE_SUCCESS == se_retCode) &&
      (SE_OK == se_Status))
  {
    /* Return success */
    ret = HAL_OK;

    /* Print the result */
    printf("Firmware Info:\r\n");
    printf("\tActiveFwVersion: %d\r\n", sl_FwInfo.ActiveFwVersion);
    printf("\tActiveFwSize: %d bytes\r\n", sl_FwInfo.ActiveFwSize);
  }
  else
  {
    /* Failure */
    printf("  -- !!Operation failed!! \r\n\n");
  }

  return ret;
}


/**
  * @brief  Run UserCode1
  * @param  None
  * @retval HAL Status.
  */
HAL_StatusTypeDef SE_USER_CODE_RunUserCode1(void)
{
  HAL_StatusTypeDef ret = HAL_ERROR;
  SE_ErrorStatus se_retCode = SE_ERROR;
  SE_StatusTypeDef se_Status = SE_KO;
  uint8_t myDataIn[32];
  uint8_t myDataOut[32];
  uint32_t myDataLen=32;
  uint32_t vLoop=0;


  for (vLoop=0; vLoop<32; vLoop++)
  {
	  myDataIn[vLoop] = vLoop;
  }

  /* Print the input */
  printf("DataIn:\r\n");

  for (vLoop=0; vLoop<32; vLoop++)
  {
	  printf("%x ",myDataIn[vLoop]);
  }
  printf("\r\n");

  /* UserCode1 */
#ifdef STEP2
  /* Would be better to use a struct to provide the parameters */
  se_retCode = SE_APP_ProcessMyData1(&se_Status, myDataIn, myDataOut_UC1, myDataLen, myNonce, myTag);
#else
  se_retCode = SE_APP_ProcessMyData1(&se_Status, myDataIn, myDataOut, myDataLen);
#endif /* STEP2 */

  if ((SE_SUCCESS == se_retCode) &&
      (SE_OK == se_Status))
  {
    /* Return success */
    ret = HAL_OK;

    /* Print the result */
    printf("DataOut:\r\n");

    for (vLoop=0; vLoop<32; vLoop++)
    {
#ifdef STEP2
    	  printf("%x ",myDataOut_UC1[vLoop]);
#else
  	  printf("%x ",myDataOut[vLoop]);
#endif /* STEP2 */
    }
    printf("\r\n");
  }
  else
  {
    /* Failure */
    printf("  -- !!Operation failed!! \r\n\n");
  }

  return ret;
}

/**
  * @brief  Run UserCode1
  * @param  None
  * @retval HAL Status.
  */
HAL_StatusTypeDef SE_USER_CODE_RunUserCode2(void)
{
  HAL_StatusTypeDef ret = HAL_ERROR;
  SE_ErrorStatus se_retCode = SE_ERROR;
  SE_StatusTypeDef se_Status = SE_KO;
  uint8_t myDataIn[32];
  uint8_t myDataOut[32];
  uint32_t myDataLen=32;
  uint32_t vLoop=0;


  for (vLoop=0; vLoop<32; vLoop++)
  {
	  myDataIn[vLoop] = vLoop;
  }

  /* Print the input */
  printf("DataIn:\r\n");

  for (vLoop=0; vLoop<32; vLoop++)
  {
#ifdef STEP2
	  printf("%x ",myDataOut_UC1[vLoop]);
#else
	  printf("%x ",myDataIn[vLoop]);
#endif
  }
  printf("\r\n");

  /* UserCode2 */
#ifdef STEP2
  /* Would be better to use a struct to provide the parameters */
  se_retCode = SE_APP_ProcessMyData2(&se_Status, myDataOut_UC1, myDataOut, myDataLen, myNonce, myTag);
#else
  se_retCode = SE_APP_ProcessMyData2(&se_Status, myDataIn, myDataOut, myDataLen);
#endif /* STEP2 */

  if ((SE_SUCCESS == se_retCode) &&
      (SE_OK == se_Status))
  {
    /* Return success */
    ret = HAL_OK;

    /* Print the result */
    printf("DataOut:\r\n");

    for (vLoop=0; vLoop<32; vLoop++)
    {
  	  printf("%x ",myDataOut[vLoop]);
    }
    printf("\r\n");
  }
  else
  {
    /* Failure */
    printf("  -- !!Operation failed!! \r\n\n");
  }

  return ret;
}


void SE_USER_CODE_Run(void)
{
	uint8_t key = 0U, exit = 0U;

	SE_USER_CODE_PrintWelcome();

	/*Print Main Menu message*/
	TEST_UserCode_PrintTestingMenu();

	while (exit == 0U)
	{
		key = 0U;

		/* If the SecureBoot configured the IWDG, UserApp must reload IWDG counter with value defined in the reload register */
		WRITE_REG(IWDG->KR, IWDG_KEY_RELOAD);

		/* Clean the input path */
		COM_Flush();

		/* Receive key */
		if (COM_Receive(&key, 1U, RX_TIMEOUT) == HAL_OK)
		{
			switch (key)
			{
			case '1' :
				SE_USER_CODE_RunGetActiveFwInfo();
				break;
			case '2' :
				SE_USER_CODE_RunUserCode1();
				break;
			case '3' :
				SE_USER_CODE_RunUserCode2();
				break;
			case 'x' :
				exit = 1U;
				break;

			default:
				printf("Invalid Number !\r");
				break;
			}

			/*Print Main Menu message*/
			TEST_UserCode_PrintTestingMenu();
		}
	}
}

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */


/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
