#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <tee_client_api.h>
#include <unistd.h>

static const TEEC_UUID uuid = {
    .timeLow = 0x216be399,
    .timeMid = 0xf2a9,
    .timeHiAndVersion = 0x43d8,
    .clockSeqAndNode = { 0x80, 0xd4, 0xab, 0xb2, 0xc3, 0x17, 0x2b, 0x12 },
};

int main(void)
{
    TEEC_Context context;
    TEEC_Session session;
    TEEC_Operation operation;
    uint32_t returnOrigin;
    size_t size = 1024;

    TEEC_Result res = TEEC_InitializeContext(NULL, &context);
    if (res != TEEC_SUCCESS) {
        fprintf(stderr, "InitializeContext failed: %x\n", res);
        return (res != TEEC_SUCCESS);
    }
    TEECS_SetCryptoClk(&context, ENABLE_CRYPTO_CLK);
    res = TEEC_OpenSession(&context, &session, &uuid, 0, NULL, NULL, &returnOrigin);
    if (res != TEEC_SUCCESS) {
        fprintf(stderr, "TEEC_OpenSession returned %#x from %#x\n", res, returnOrigin);
        goto finalize;
    }
    TEEC_SharedMemory shMem;
    shMem.size = size;
    shMem.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT;
    res = TEEC_AllocateSharedMemory(&context, &shMem);
    if (res != TEEC_SUCCESS) {
        fprintf(stderr, "Error code %#x from TEEC_AllocateSharedMemory().\n", res);
        goto close_session;
    }
    operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_WHOLE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
    operation.params[0].memref.parent = &shMem;
    res = TEEC_InvokeCommand(&session, 0x0, &operation, &returnOrigin);
    if (res != TEEC_SUCCESS) {
        fprintf(stderr, "TEEC_InvokeCommand returned %#x from %#x\n", res, returnOrigin);
        fprintf(stderr, "[Test failed].\n");
        goto release;
    }
    fprintf(stderr, "[Test passed].\n");
release:
    TEEC_ReleaseSharedMemory(&shMem);
close_session:
    TEEC_CloseSession(&session);
finalize:
    TEECS_SetCryptoClk(&context, DISABLE_CRYPTO_CLK);
    TEEC_FinalizeContext(&context);
    return (res != TEEC_SUCCESS);
}
