#include "kg_init.h"

uint32_t kg_init() {
    KG_LOG_DBG("Calling kg_init");
    uint32_t ret = KG_SUCCESS;
    kg_secure_data_t *ksd = NULL;
    uint8_t *wrap_data = NULL;
    uint32_t wrap_data_len = KG_SECURE_DATA_LEN;
    kg_rpmb_info_t *info = NULL;

    ksd = TEE_Malloc(sizeof(kg_secure_data_t), 0);
    if (NULL == ksd) {
        KG_LOG("Failed to alloc buffer for kg secure data\n");
        ret = KG_ALLOC_BUFFER_FAIL;
        goto exit;
    }

    wrap_data = TEE_Malloc(wrap_data_len, 0);
    if (NULL == wrap_data) {
        KG_LOG("Failed to alloc buffer for kg secure wrap data\n");
        ret = KG_ALLOC_BUFFER_FAIL;
        goto exit;
    }

    if (KG_SUCCESS != kg_rpmb_init()) {
        KG_LOG("RPMB is not available when initing KG secure data\n");
        ret = KG_RPMB_UNAVAILABLE;
        goto exit;
    }

    if (KG_SUCCESS != (ret = read_info_object(&info)) || NULL == info) {
        KG_LOG("Failed to read info object \n");
        goto exit;
    }

    if (info->magic == KG_MAGIC) {
        KG_LOG("KG init is done\n");
        goto exit;
    }

    info->magic = KG_MAGIC;
    info->version = KG_SECURE_DATA_VERSION;

    if (TZ_API_OK != TZ_wrap_persist_data((uint8_t *)KG_NAME, strlen(KG_NAME), (uint8_t *)ksd, sizeof(*ksd), wrap_data, &wrap_data_len)) {
        KG_LOG("Wraping secure data during kg init failed\n");
        ret = KG_TZ_API_FAIL;
        goto exit;
    }

    if (wrap_data_len > KG_SECURE_DATA_LEN) {
        KG_LOG("Wrap data size overflow\n");
        ret = KG_BUFFER_SIZE_FAIL;
    }

    info->kg_wrap_data_len = wrap_data_len;

    if (KG_SUCCESS != (ret = write_wrap_data(info->kg_wrap_data_len, wrap_data))) {
        KG_LOG("failed to write wrap data\n");
        goto exit;
    }

    KG_LOG_DBG("write magic and version\n");

    if (KG_SUCCESS != (ret = write_info_object(info))) {
        KG_LOG("failed to write info object\n");
        goto exit;
    }

exit:
    if (info != NULL) {
        TEE_MemFill(info, 0, sizeof(*info));
        TEE_Free(info);
        info = NULL;
    }
    if (ksd != NULL) {
        TEE_MemFill(ksd, 0, sizeof(*ksd));
        TEE_Free(ksd);
        ksd = NULL;
    }
    if (wrap_data != NULL) {
        TEE_Free(wrap_data);
        wrap_data = NULL;
    }
    return ret;
}

