/* UUID和CMD需要和TA里的定义保持一致 */
#define UUID_XOR    { 0x13245768, 0xacbd, 0xcedf,   \
                    { 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78 } }

#define CMD_XOR     (0x01234567) 

/* 设置UUID,对应TA,每个TA有唯一的UUID */
static const TEEC_UUID _g_uuid_xor = UUID_XOR;

int main(int argc, char *argv[])
{
    unsigned int     a = 0, b = 1, c = 0;
    TEEC_Context     context;
    TEEC_Session     session;
    TEEC_Operation   operation;
    TEEC_Result      result = TEEC_SUCCESS;

    _DEPRESS_UNUSED_WARNING(argc);
    _DEPRESS_UNUSED_WARNING(argv);

    /* Step1: 初始化Context */
    result = TEEC_InitializeContext(NULL, &context);
    if (result != TEEC_SUCCESS) {
        ERR_LOG("TEEC_InitializeContext", result);
        goto cleanup1;
    }

    /* Step2: 打开对应TA的Session */
    result = TEEC_OpenSession(&context, &session,
            &_g_uuid_xor, TEEC_LOGIN_USER, NULL, NULL, NULL);
    if (result != TEEC_SUCCESS) {
        ERR_LOG("TEEC_OpenSession", result);
        goto cleanup2;
    }

  /* 初始化对应的参数,如下2个为输入,1个为输出 */
    operation.paramTypes = TEEC_PARAM_TYPES(
            TEEC_VALUE_INPUT, TEEC_VALUE_INPUT,
            TEEC_VALUE_OUTPUT, TEEC_NONE);
    operation.params[0].value.a = a;
    operation.params[1].value.a = b;
    operation.params[2].value.a = c;

  /* Step3: 开始具体的命令调用 */
    result = TEEC_InvokeCommand(&session, CMD_XOR, &operation, NULL);
    if (result != TEEC_SUCCESS) {
        ERR_LOG("TEEC_InvokeCommand", result);
        goto cleanup3;
    }

    c = operation.params[2].value.a;

    printf("a = %d; b = %d; c = a ^ b: %d\n", a, b, c);

  cleanup3:
    /* Step4: 关闭Session */
      TEEC_CloseSession(&session);
  cleanup2:
    /* Step5: 释放Context */
      TEEC_FinalizeContext(&context);
  cleanup1:
      return result;
}
/* UUID和CMD需要和CA里的定义保持一致 */
#define UUID_XOR    { 0x13245768, 0xacbd, 0xcedf,   \
                    { 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78 } }

#define CMD_XOR     (0x01234567)

static TEE_UUID xor_uuid = UUID_XOR;

static TEE_Result _TA_CreateEntryPoint(void)
{
    return TEE_SUCCESS;
}

static void _TA_DestroyEntryPoint(void)
{
    return;
}

static TEE_Result _TA_OpenSessionEntryPoint(
        uint32_t paramTypes, TEE_Param params[4], void **sessionContext)
{
  /* CA调用OpenSession函数时的对应操作可加入其中 */
    return TEE_SUCCESS;
}

static void _TA_CloseSessionEntryPoint(void *sessionContext)
{
    return;
}

/* CA调用InvokeCommand函数时的对应操作可加入其中 */
static TEE_Result _TA_InvokeCommandEntryPoint(
        void *sessionContext, uint32_t commandID,
        uint32_t paramTypes, TEE_Param params[4])
{
    if (TEE_PARAM_TYPES(
                TEE_PARAM_TYPE_VALUE_INPUT,
                TEE_PARAM_TYPE_VALUE_INPUT,
                TEE_PARAM_TYPE_VALUE_OUTPUT,
                TEE_PARAM_TYPE_NONE) != paramTypes) {
        return TEE_ERROR_BAD_PARAMETERS;
    }

    if (CMD_XOR != commandID) {
        return TEE_ERROR_BAD_PARAMETERS;
    }

    params[2].value.a = params[0].value.a ^ params[1].value.a;

    TEE_Print("xor result 0x%08x\n", params[2].value.a);

    return TEE_SUCCESS;
}

TEE_SRV_INFO_START(
        _TA_CreateEntryPoint,
        _TA_DestroyEntryPoint,
        _TA_OpenSessionEntryPoint,
        _TA_CloseSessionEntryPoint,
        _TA_InvokeCommandEntryPoint)
TEE_SRV_PROP_UUID("gpd.ta.appID", UUID_XOR)
TEE_SRV_PROP_BOOL("gpd.ta.singleInstance", false)
TEE_SRV_PROP_BOOL("gpd.ta.multiSession", true)
TEE_SRV_PROP_BOOL("gpd.ta.instanceKeepAlive", false)
TEE_SRV_PROP_INT("gpd.ta.dataSize", 0x1000)
TEE_SRV_PROP_INT("gpd.ta.stackSize", 0x800)
TEE_SRV_INFO_END
};