#include <qsee_services.h>
#include "hdm_core.h"
#include "hdm_allowlist.h"
#include "process_cmd_TA.h"
#include "hdmOperations.h"

#include "CHDMKG.h"        // Should be autogenerated
#include "IHDMKG_invoke.h" // Should be autogenerated

/* HDM Service */
// Null pointer global for use to alleviate build warnings seen when
// intentionally using a null pointer. Static assignment and use will result in a compiler warning.
void *null_ptr = NULL;

static inline int32_t
CHDMKG_get_nonce(void *cxt, uint32_t *ret, const void *caller_ta_name,
                      uint32_t caller_ta_name_size, uint32_t operation, uint32_t *value)
{
  HDM_LOG("Starting CHDMKG()");

  char ta_name[32] = {0, };
  strncpy(ta_name, caller_ta_name, caller_ta_name_size);
  *ret = check_ta_cmd_permission(ta_name, caller_ta_name_size);
  if (*ret != HDM_STATUS_SUCCESS) {
    HDM_LOG("HDM: check command permission failed to TA %s on execute command %d, error %d", ta_name, CHDMKG_UID, *ret);
    goto error;
  }

  HDM_LOG_DEBUG("CHDMKG() operation = %d", operation);
  HDM_LOG_DEBUG("CHDMKG() value = 0x%x", *value);

  switch (operation) {
      case KG_UNBLOCK_CMD:
      case KG_BLOCK_CMD:
              *ret = HDM_KG_generateNonce(operation, value);
              break;
      default:
              HDM_LOG("KG_CMD unknown command!");
              HDM_LOG_DEBUG("KG_CMD unknown command: %d", operation);
              /* Unknown command ID */
              *ret = HDM_UNKNOWN_CMD;
}

  HDM_LOG_DEBUG("CHDMKG() value = 0x%x", *value);
  HDM_LOG_DEBUG("CHDMKG() ret = %d", *ret);


error:
  return Object_OK;
}

static inline int32_t
CHDMKG_get_status(void *cxt, uint32_t *ret, const void *caller_ta_name,
                      uint32_t caller_ta_name_size, uint32_t *device_block, uint32_t *compromise_block)
{
        HDM_LOG("Starting %s", __func__);

        *device_block = HDM_TATA_ERROR;
        *compromise_block = HDM_TATA_ERROR;

        char ta_name[32] = {0, };
        strncpy(ta_name, caller_ta_name, caller_ta_name_size);
        *ret = check_ta_cmd_permission(ta_name, caller_ta_name_size);
        if (*ret != HDM_STATUS_SUCCESS) {
                HDM_LOG("HDM: check command permission failed to TA %s on execute command %d, error %d", ta_name, CHDMKG_UID, *ret);
                *ret = HDM_TATA_ERROR;
                goto error;
        }

        *ret = HDM_KG_get_status(device_block, compromise_block);
        switch(*ret) {
                case HDM_STATUS_SUCCESS:
                        HDM_LOG_DEBUG("%s, device_block = 0x%x", __func__, *device_block);
                        HDM_LOG_DEBUG("%s, compromise_block = 0x%x", __func__, *compromise_block);
                        *ret = HDM_TATA_SUCCESS;
                        break;
                case HDM_RPMB_SERVICE_NAME_MISMATCH:
                case HDM_RPMB_MAGIC_FAIL:
                        HDM_LOG("%s, KG not activated = %d", __func__, *ret);
                        *ret = HDM_KG_NOT_ACTIVATED;
                        break;
                default:
                        HDM_LOG("%s, Fail to get KG policy status %d", __func__, *ret);
                        *ret = HDM_TATA_ERROR;
                        break;
        }

error:
        return Object_OK;
}

// This implementation does not require a context record, so `retain` and
// `release` are no-ops.
#define CHDMKG_release(ctx)   Object_OK
#define CHDMKG_retain(ctx)    Object_OK

static IHDMKG_DEFINE_INVOKE(CHDMKG_invoke, CHDMKG_, void*)

int32_t CHDMKG_open(Object cred, Object *objOut)
{
  HDM_LOG("CHDMKG_open() ");

   *objOut = (Object) { CHDMKG_invoke, NULL };
   return Object_OK;
}
