/**
 * @file tees_rpmb.h
 * @brief Extention API for accessing RPMB
 * @author Iaroslav Makarchuk (i.makarchuk@samsung.com)
 * @author Andrey Neyvanov (a.neyvanov@samsung.com)
 * @date Created May 19
 * @par In Samsung Ukraine R&D Center (SURC) under a contract between
 * @par LLC "Samsung Electronics Ukraine Company" (Kiev, Ukraine) and
 * @par "Samsung Elecrtronics Co", Ltd (Seoul, Republic of Korea)
 * @par Copyright: (c) Samsung Electronics Co, Ltd 2017. All rights reserved.
 *
 * This software is proprietary of Samsung Electronics.
 * No part of this software, either material or conceptual may be copied
 * or distributed, transmitted, transcribed, stored in a retrieval system
 * or translated into any human or computer language in any form by any means,
 * electronic, mechanical, manual or otherwise, or disclosed to third parties
 * without the express written permission of Samsung Electronics.
 *
 */
#ifndef MB_TEES_RPMB_H_
#define MB_TEES_RPMB_H_

#include <tee_internal_api.h>

#ifdef __cplusplus
extern "C" {
#endif

#define RPMB_MAX_AUTHORITY_NAME_LEN 16

typedef enum {
  TEES_RPMB_DEVICE_DEFAULT,
} TEES_RpmbDeviceType;

typedef struct {
  uint32_t partitionId;
  uint32_t totalSectors;
  uint32_t bytesPerSector;
  TEE_UUID ownerUUID;
  char ownerAuthority[RPMB_MAX_AUTHORITY_NAME_LEN];
} TEES_RpmbPartitionInfo;

typedef struct {
  uint32_t deviceId;
  uint32_t totalSectors;
  uint32_t bytesPerSector;
  uint32_t freeSectors;
} TEES_RpmbDeviceInfo;

typedef struct __TEES_RpmbDeviceHandle* TEES_RpmbDeviceHandle;
typedef struct __TEES_RpmbPartitionHandle* TEES_RpmbPartitionHandle;


/**
 * @brief Initialize RPMB.
 *
 * Function will be used to initialize RPMB device.
 *
 * @param[in]  deviceType RPMB device to be initialized
 * @param[out] device     RPMB device handle of the opened device.
 *
 * @retval TEE_SUCCESS              Device initialized successfully.
 * @retval TEE_ERROR_BAD_PARAMETERS Bad parameters passed to the function.
 * @retval TEE_ERROR_NOT_SUPPORTED  Device type is not supported.
 * @retval TEE_ERROR_GENERIC        Third party API call issues.
 */
TEE_Result TEES_RpmbDeviceInit(TEES_RpmbDeviceType deviceType,
                               TEES_RpmbDeviceHandle *device);


/**
 * @brief Open desired partition of the specified device.
 *
 * Function will be used to open RPMB partition for read/write.
 *
 * @param[in]  device      Device handle of the device to open partition at.
 * @param[in]  partitionId ID of the RPMB partition to be opened.
 * @param[out] partition   Partition handle of the opened partition.
 *
 * @retval TEE_SUCCESS              Partition opened successfully.
 * @retval TEE_ERROR_BAD_PARAMETERS Bad parameters passed to the function.
 * @retval TEE_ERROR_ITEM_NOT_FOUND Partition with specified ID is not present.
 * @retval TEE_ERROR_GENERIC        Partition cannot be opened.
 */
TEE_Result TEES_RpmbOpenPartition(TEES_RpmbDeviceHandle device,
                                  uint32_t partitionId,
                                  TEES_RpmbPartitionHandle *partition);


/**
 * @brief Creates partition with specified ID on the selected device.
 *
 * Function will be used to create partition on the specified device.
 *
 * @param[in]  device        Device handle of the device to create partition at.
 * @param[in]  partitionId   ID of the RPMB partition to be created.
 * @param[in]  partitionSize Partition size to be created.
 * @param[in]  flags         Partition creation flags. Should be 0 as for now.
 *
 * @retval TEE_SUCCESS                Partition created successfully.
 * @retval TEE_ERROR_BAD_PARAMETERS   Bad parameters passed to the function.
 * @retval TEE_ERROR_STORAGE_NO_SPACE Partition cannot be created due to the
 *                                    lack of free space.
 * @retval TEE_ERROR_NOT_SUPPORTED    Partition creation flags are not
 *                                    supported or platform does not support
 *                                    RPMB create partition functionality.
 * @retval TEE_ERROR_GENERIC          Partition cannot be created.
 */
TEE_Result TEES_RpmbCreatePartition(TEES_RpmbDeviceHandle device,
                                    uint32_t partitionId,
                                    uint32_t partitionSize,
                                    uint32_t flags);



/**
 * @brief Removes partition with specified ID on the selected device.
 *
 * Function will be used to remove partition on the specified device.
 *
 * @param[in]  device        Device handle of the device to remove partition at.
 * @param[in]  partitionId   ID of the RPMB partition to be removed.
 * @param[in]  flags         Partition removal flags. Should be 0 as for now.
 *
 * @retval TEE_SUCCESS                Partition removed successfully.
 * @retval TEE_ERROR_BAD_PARAMETERS   Bad parameters passed to the function.
 * @retval TEE_ERROR_NOT_SUPPORTED    Partition removal flags are not
 *                                    supported or platform does not support
 *                                    RPMB remove partition functionality.
 * @retval TEE_ERROR_GENERIC          Partition cannot be removed.
 */
TEE_Result TEES_RpmbRemovePartition(TEES_RpmbDeviceHandle device,
                                    uint32_t partitionId,
                                    uint32_t flags);


/**
 * @brief Closes RPMB partition.
 *
 * Function will be used to close rpmb partition and release all the allocated
 * resources
 *
 * @param[in]  partition Partition to be closed.
 */
void TEES_RpmbClosePartition(TEES_RpmbPartitionHandle partition);


/**
 * @brief Closes PRMB device and releases all the related resources.
 *
 * Function will be used to close rpmb device and release all the related
 * resources.
 *
 * @param[in]  device Device to be closed.
 */
void TEES_RpmbDeviceClose(TEES_RpmbDeviceHandle device);


/**
 * @brief Obtains device information.
 *
 * Obtains device information, such as total sectors number and sectors
 * available for allocating new partitions.
 *
 * @param[in]      device     RPMB device to get information about.
 * @param[in/out]  deviceInfo Pointer to device info structure to be filled
 *                        with actual information.
 *
 * @retval TEE_SUCCESS              Device information provided.
 * @retval TEE_ERROR_BAD_PARAMETERS Invalid parameters passed to the function.
 */
TEE_Result TEES_RpmbGetDeviceInfo(TEES_RpmbDeviceHandle device,
                                  TEES_RpmbDeviceInfo *deviceInfo);


/**
 * @brief Obtains partition information.
 *
 * Obtains partition information, such as total sectors number and bytes per
 * sector.
 *
 * @param[in]      partition     RPMB partition to get information about.
 * @param[in/out]  partitionInfo Pointer to partition info structure to be filled
 *                           with actual information.
 *
 * @retval TEE_SUCCESS                      Partition information provided.
 * @retval TEE_ERROR_BAD_PARAMETERS Invalid parameters passed to the function.
 */
TEE_Result TEES_RpmbGetPartitionInfo(TEES_RpmbPartitionHandle partition,
                                     TEES_RpmbPartitionInfo *partitionInfo);

/**
 * @brief Writes data to RPMB partition.
 *
 * Writes data to the opened RPMB partition.
 *
 * @param[in]  partition      RPMB partition to write data to.
 * @param[in]  dataBuffer     A pointer to data to be written.
 * @param[in]  bufferLen      Length of data to be written in bytes.
 * @param[in]  startSector    First sector to write data to.
 * @param[out] sectors        Number of sectors which were written.
 *
 * @retval TEE_SUCCESS                Data written successfully.
 * @retval TEE_ERROR_BAD_PARAMETERS   Invalid parameters passed to the function.
 * @retval TEE_ERROR_STORAGE_NO_SPACE Not enough space in the partition to write
 *                                    data.
 * @retval TEE_ERROR_GENERIC          Writing data failed due to other reasons.
 */
TEE_Result TEES_RpmbWriteData(TEES_RpmbPartitionHandle partition,
                              uint8_t *dataBuffer,
                              uint32_t bufferLen,
                              uint32_t startSector,
                              uint32_t *sectors);


/**
 * @brief Reads data from RPMB partition.
 *
 * Reads data from the opened RPMB partition. Note, bufferLen must be greater or
 * equal to (sectors * bytes per sector).
 *
 * @param[in]     partition      RPMB partition to read data from.
 * @param[in]     dataBuffer     A pointer to data buffer to store read data.
 * @param[in,out] bufferLen      Length of data buffer. After successful read,
 *                               the actual number of read bytes are stored here
 * @param[in]     startSector    First sector to re data from.
 * @param[in]     sectors        Number of sectors to read.
 *
 * @retval TEE_SUCCESS                Data read successfully.
 * @retval TEE_ERROR_BAD_PARAMETERS   Invalid parameters passed to the function.
 * @retval TEE_ERROR_SHORT_BUFFER     Buffer length is not enough to store the
 *                                    read data.
 * @retval TEE_ERROR_GENERIC          Reading data failed due to other reasons.
 */
TEE_Result TEES_RpmbReadData(TEES_RpmbPartitionHandle partition,
                             uint8_t *dataBuffer,
                             uint32_t *bufferLen,
                             uint32_t startSector,
                             uint32_t sectors);

#ifdef __cplusplus
}
#endif

#endif /* MB_TEES_RPMB_H_ */
