#include <string.h>
//#include "qsee_log.h"
#include "qsee_stor.h"
#include "app_grdm.h"
#include "app_grdm_rpmb.h"
#include "grdm_log.h"


qsee_stor_device_handle_t gDevHandle = 0;
qsee_stor_client_handle_t gClientHandle = 0;
qsee_stor_client_info_t   gClientInfo;

uint32_t grdm_rpmb_init(uint32_t partition_id)
{
	int ret = QSEE_STOR_SUCCESS;
    uint32_t num_sectors = TZ_RPMB_GRDM_NUM_SECTOR_MAX;

    ret = qsee_stor_device_init(QSEE_STOR_EMMC_RPMB, 0, &gDevHandle);
    if (QSEE_STOR_SUCCESS != ret) {
        LOG_E("%s: Failed to init RPMB device : %d(0x%x))\n", __func__, ret, ret);
        if (ret == QSEE_STOR_RPMB_NOT_PROVISIONED_ERROR
          || ret == QSEE_STOR_RPMB_AUTOPROV_DISABLED) {
            LOG_E("%s: RPMB is not provisioned", __func__);
            return GRDM_BL_RPMB_NOT_PROVISIONED;
        }
        else {
	        return GRDM_BL_RPMB_INIT_FAILED;
        }
    }

    ret = qsee_stor_open_partition(&gDevHandle, partition_id, &gClientHandle);
    if (QSEE_STOR_PARTI_NOT_FOUND_ERROR == ret) {
        qsee_stor_device_info_t device_info;

    LOG_E("%s: There is no partition for guardian m, add it.\n", __func__);
    ret = qsee_stor_device_get_info(&gDevHandle, &device_info);
    if (ret != QSEE_STOR_SUCCESS) {
        LOG_E("%s: Failed to get device info(%d)\n", __func__, ret);
        num_sectors = TZ_RPMB_GRDM_NUM_SECTOR_MAX;
    }
    else {
        LOG_E("%s: Total RPMB sectors (%u), Available RPMB sectors (%u)\n", __func__,
                 device_info.total_sectors, device_info.available_sectors);
        num_sectors = (TZ_RPMB_GRDM_NUM_SECTOR_MAX < device_info.available_sectors)
					 ? TZ_RPMB_GRDM_NUM_SECTOR_MAX : device_info.available_sectors;
    }

    ret = qsee_stor_add_partition(&gDevHandle, partition_id, num_sectors);
    if(QSEE_STOR_SUCCESS != ret)
    {
      LOG_E("%s: Failed to make new partition(%d)\n", __func__, ret);
      return ret;
    }

    ret = qsee_stor_open_partition(&gDevHandle, partition_id ,&gClientHandle);
    if ((QSEE_STOR_SUCCESS != ret) || (gClientHandle == 0))
    {
      LOG_E("%s: Fail to open() return=0x%x", __func__, ret);
      return GRDM_BL_RPMB_INIT_FAILED;
    }
    LOG_E("%s: Successfully open  partition", __func__);
  }
  else if (ret != QSEE_STOR_SUCCESS) {
	LOG_E("%s: Failed to open partition(%d)\n", __func__, ret);
	return GRDM_BL_RPMB_INIT_FAILED;

  }

  return GRDM_BL_RPMB_NO_ERROR;
}

uint32_t grdm_rpmb_read(uint32_t sector_pos, grdm_rpmb_data_t *data)
{
    int ret;
    uint8_t buffer[TZ_RPMB_GRDM_BLOCK_SIZE];

    ret = (uint32_t)qsee_stor_read_sectors(&gClientHandle, sector_pos, 1, buffer);
    if (ret != QSEE_STOR_SUCCESS) {
        LOG_E("%s: Failed to read data from rpmb(0x%08x)\n", __func__, ret);
        return GRDM_BL_RPMB_READ_FAILED;
    }

    memcpy(data, buffer, sizeof(grdm_rpmb_data_t));

    return GRDM_BL_RPMB_NO_ERROR;
}

uint32_t grdm_rpmb_write(uint32_t sector_pos, grdm_rpmb_data_t *data)
{
    int ret;
    uint8_t buffer[TZ_RPMB_GRDM_BLOCK_SIZE];

    memset(buffer, 0x0, TZ_RPMB_GRDM_BLOCK_SIZE);
    memcpy(buffer, data, sizeof(grdm_rpmb_data_t));

    ret = qsee_stor_write_sectors(&gClientHandle, sector_pos, 1, buffer);
    if (ret != QSEE_STOR_SUCCESS) {
        LOG_E("%s: Failed to write data to rpmb(%d)\n", __func__, ret);
        return GRDM_BL_RPMB_WRITE_FAILED;
    }

    return GRDM_BL_RPMB_NO_ERROR;
}

uint32_t grdm_check_magic(grdm_rpmb_data_t data)
{
    uint32_t ret = GRDM_BL_RPMB_NO_ERROR;

    if (data.magic != GRDM_RPMB_MAGIC) {
        LOG_E("%s: magic is not matched(0x%08x)\n", __func__, data.magic);
        ret = GRDM_BL_RPMB_NOT_INITIALIZED;
    }

    return ret;

}
