
/*
 * =====================================================================================
 *
 *       Filename:  hdm_rpmb.c
 *
 *    Description:  HDM RPMB manipulation
 *
 *        Version:  1.0
 *        Created:  09/16/2019 15:26:11 PM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *        Company:  Samsung Electronics
 *        Copyright (c) 2015 by Samsung Electronics, All rights reserved.
 *
 * =====================================================================================
 */

/** Includes */
#include "hdm_rpmb.h"

/**
 * @brief
 * hdm_rpmb_init
 * RPMB initialization
 *
 * @return HDM status code
 */
hdm_return_code_t hdm_rpmb_init(void) {
        HDM_LOG_DEBUG("hdm_rpmb_init()");

#ifndef MEDIATEK
        TEE_Result ret = TEES_RPMBCheckEnable();

        if (TEE_SUCCESS != ret) {
                HDM_LOG("RPMB is unavailable : 0x%x", ret);
                return HDM_RPMB_FAIL;
        }
#endif

        return HDM_STATUS_SUCCESS;
}

/**
 * @brief
 * hdm_rpmb_read
 * Read RPMB data
 *
 * @param[out] *data     - data buffer with RPMB content
 * @param[in]  *data_len - read data length
 *
 * @return HDM status code
 */
hdm_return_code_t hdm_rpmb_read(uint8_t *data, uint32_t data_len) {
        HDM_LOG_DEBUG("hdm_rpmb_read()");
        TEE_Result tee_ret = TEE_SUCCESS;

#ifdef MEDIATEK
        uint32_t session_id;
        int result;

        session_id = TEE_RpmbOpenSession(HDM_ID);
        if (session_id != HDM_ID) {
                HDM_LOG("Failed to open RPMB session, session_id = 0x%x", session_id);
                return HDM_RPMB_FAIL;
        }

        tee_ret = TEE_RpmbReadData(session_id, data, data_len, &result);
        if (tee_ret != TEE_SUCCESS || result != TEE_SUCCESS) {
                HDM_LOG("Failed to read RPMB : 0x%x", tee_ret);
                //In case read fails, result is handled after the session is closed;
        }

        tee_ret = TEE_RpmbCloseSession(session_id);
        if (tee_ret != TEE_SUCCESS) {
                HDM_LOG("Failed to close RPMB session: 0x%x", tee_ret);
                return HDM_RPMB_FAIL;
        }

        if (result != TEE_SUCCESS) {
                HDM_LOG("Failed to read RPMB, returning ERROR");
                HDM_LOG_DEBUG("Failed to read RPMB, result = 0x%x", result);
                return HDM_RPMB_FAIL;
        }
#else
        tee_ret = TEES_RPMBRead(TZ_RPMB_HDM_PARTITION_ID, 0, data, data_len, RPMB_TYPE_BYTE);
        if (tee_ret != TEE_SUCCESS) {
                HDM_LOG("Failed to read RPMB : 0x%x", tee_ret);
                return HDM_RPMB_FAIL;
        }
#endif

        HDM_LOG("Success to read RPMB : 0x%x", tee_ret);
        return HDM_STATUS_SUCCESS;
}

/**
 * @brief
 * hdm_rpmb_write
 * Write data on RPMB
 *
 * @param[out] *data     - data buffer with RPMB content
 * @param[in]  *data_len - read data length
 *
 * @return HDM status code
 */
hdm_return_code_t hdm_rpmb_write(uint8_t *data, uint32_t data_len) {
        HDM_LOG_DEBUG("hdm_rpmb_write() data_len : %d", data_len);
        TEE_Result tee_ret = TEE_SUCCESS;

#ifdef MEDIATEK
        uint32_t session_id;
        int result;

        session_id = TEE_RpmbOpenSession(HDM_ID);
        if (session_id != HDM_ID) {
                HDM_LOG("Failed to open RPMB session, session_id = 0x%x", session_id);
                return HDM_RPMB_FAIL;
        }

        tee_ret = TEE_RpmbWriteData(session_id, data, data_len, &result);
        if (tee_ret != TEE_SUCCESS || result != TEE_SUCCESS) {
                HDM_LOG("Failed to write RPMB : 0x%x", tee_ret);
                //In case write fails, result is handled after the session is closed;
        }

        tee_ret = TEE_RpmbCloseSession(session_id);
        if (tee_ret != TEE_SUCCESS) {
                HDM_LOG("Failed to close RPMB session: 0x%x", tee_ret);
                return HDM_RPMB_FAIL;
        }

        if (result != TEE_SUCCESS) {
                HDM_LOG("Failed to write RPMB, returning ERROR");
                HDM_LOG_DEBUG("Failed to write RPMB, result = 0x%x", result);
                return HDM_RPMB_FAIL;
        }
#else
        tee_ret = TEES_RPMBWrite(TZ_RPMB_HDM_PARTITION_ID, 0, data, data_len, RPMB_TYPE_BYTE);
        if (tee_ret != TEE_SUCCESS) {
                HDM_LOG("Failed to write RPMB : 0x%x", tee_ret);
                return HDM_RPMB_FAIL;
        }
#endif

        HDM_LOG_DEBUG("success to write RPMB : 0x%x", tee_ret);
        return HDM_STATUS_SUCCESS;
}
