/*
 * Copyright (c) 2019 Qualcomm Technologies, Inc.
 * All Rights Reserved.
 * Confidential and Proprietary - Qualcomm Technologies, Inc.
 */

#include <cstddef>
#include <cstdint>
#include <cstdio>

#include "CAppLoader.hpp"
#include "IAppController.hpp"
#include "IAppLoader.hpp"
#include "IClientEnv.hpp"
#include "ISMCIExample.hpp"
#include "TZCom.h"
#include "object.h"

#include "alog.h"
#include "map_trusted_application.h"
#include "smci_skeleton.h"

/* Similar to Android LOG_TAG, define a tag that appears when logging from this
 * application */
static char const LOG_TAG[] = "SMCInvoke_skeleton_CA";

/* This function demonstrates how to open a TA using SMCInvoke APIs. */
int32_t run_smcinvoke_ta_example(ta_image_data *img_data)
{
  int32_t ret = Object_OK;
  IAppLoader iAppLoader;          // IAppLoader object that allows us to load
                                  // the TA in the trusted environment
  IAppController iAppController;  // AppController contains a reference to
                                  // the app itself, after loading
  ISMCIExample iSMCIExample;

  uint32_t val1 = 2;
  uint32_t val2 = 5;
  uint32_t addResult;

  do {
    /* Before we can obtain an AppLoader object, a ClientEnv object is required
     * from the emulated TZ daemon. */
    Object clientEnv = Object_NULL;
    ret = TZCom_getClientEnvObject(&clientEnv);
    if (Object_isERROR(ret)) {
      ALOGE("failed to get clientEnv object with error %d!", ret);
      break;
    }

    IClientEnv iClientEnv(clientEnv);
    clientEnv = Object_NULL;  // reference was consumed by IClientEnv instantiation

    /* Using the clientEnv object we retrieved, obtain an appLoader by
     * specifying its UID */
    ret = iClientEnv.open(CAppLoader_UID, iAppLoader);
    if (Object_isERROR(ret)) {
      ALOGE("Failed to get apploader object with %d!", ret);
      break;
    }

    ALOGV("Succeeded in getting apploader object.");

    ret = iAppLoader.loadFromBuffer(img_data->buffer, img_data->buffer_size, iAppController);
    if (Object_isERROR(ret)) {
      ALOGE("Loading app failed!");
      break;
    }

    ALOGV("Loading the application succeeded.");

    ret = iAppController.getAppObject(iSMCIExample);
    if (Object_isERROR(ret)) {
      ALOGE("Getting the application object failed with %d!", ret);
      break;
    }

    ALOGV("Getting the application object succeeded.");

    ret = iSMCIExample.add(val1, val2, &addResult);
    if (Object_isERROR(ret)) {
      ALOGE("Addition returned error %d!", ret);
    } else {
      ALOGD("Add result: %d", addResult);
    }
  } while (0);

  return ret;
}
