/**
 * @file       kernel_access.h
 * @brief      Platform-depended API to work with kernel memory inside driver
 * @author     Viacheslav Vovchenko (v.vovchenko@samsung.com)
 * @version    1.0
 * @date       Created Jun 6, 2016
 * @copyright  In Samsung Ukraine R&D Center (SURC) under a contract between
 * @copyright  LLC "Samsung Electronics Ukraine Company" (Kiev, Ukraine) and
 * @copyright  "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
 * @copyright  Copyright: (c) Samsung Electronics Co, Ltd 2016. All rights reserved.
**/

#ifndef PA_TZ_DRV_SRC_KERNEL_ACCESS_H_
#define PA_TZ_DRV_SRC_KERNEL_ACCESS_H_

#include <stdint.h>

#include "pa_tz_api.h"
#include "memory.h"

enum {
  kMaxMapsCount = 10
};

/**
 * @brief Structure of kernel address space access contains all info about
 * region of addresses
 */
typedef struct {
  struct {
    KernelAddress kernel; //!< Start kernel virtual address
    PhysicalAddress physical; //!< Start physical address
    void *virt; //!< Start range of virtual addresses
    size_t size; //!< Size of kernel virtual address
    uint32_t is_valid; //!< Flag that this map is used
  } maps[kMaxMapsCount];
} KernelAccessInfo;

/**
 * @brief Initialize part of kernel space to read/write
 * @param [out] context Pointer to structure of kernel space access
 * @return ::PA_TZ_SUCCESS in case of success, ::PA_TZ_GENERAL_ERROR
 */
PaTzResult KernelAccessInit(KernelAccessInfo *context);

/**
 * @brief Destroy part of kernel space to read/write
 * @param [in,out] context Pointer to structure of kernel space access
 * @return ::PA_TZ_SUCCESS in case of success, ::PA_TZ_GENERAL_ERROR
 */
PaTzResult KernelAccessDeinit(KernelAccessInfo *context);

/**
 * @brief Get buffer bytes from kernel space access structure
 * @details Read bytes from kernel space by kernel virtual address.
 * If context is not defined, the routine map/unmap needed region for each time.
 * Use context if you want to cache access to kernel memory.
 * @param [in,out] context Pointer to structure of kernel space access, can be NULL
 * @param [in] address Kernel virtual address of data
 * @param [in] size Size of data
 * @param [out] out Pointer of output data
 * @return ::PA_TZ_SUCCESS in case of success, ::PA_TZ_GENERAL_ERROR
 */
PaTzResult KernelAccessGetBytes(KernelAccessInfo *context,
                                KernelAddress address, size_t size, void *out);

/**
 * @brief Get 1 bytes from kernel space access structure
 * @param [in,out] context Pointer to structure of kernel space access
 * @param [in] address Kernel virtual address of data
 * @param [out] out Pointer of output data
 * @return ::PA_TZ_SUCCESS in case of success, ::PA_TZ_GENERAL_ERROR
 */
PaTzResult KernelAccessGetUint8(KernelAccessInfo *context,
                                KernelAddress address, uint8_t *out);

/**
 * @brief Get 4 bytes from kernel space access structure
 * @param [in,out] context Pointer to structure of kernel space access
 * @param [in] address Kernel virtual address of data
 * @param [out] out Pointer of output data
 * @return ::PA_TZ_SUCCESS in case of success, ::PA_TZ_GENERAL_ERROR
 */
PaTzResult KernelAccessGetUint32(KernelAccessInfo *context,
                                 KernelAddress address, uint32_t *out);

/**
 * @brief Get 8 bytes from kernel space access structure
 * @param [in,out] context Pointer to structure of kernel space access
 * @param [in] address Kernel virtual address of data
 * @param [out] out Pointer of output data
 * @return ::PA_TZ_SUCCESS in case of success, ::PA_TZ_GENERAL_ERROR
 */
PaTzResult KernelAccessGetUint64(KernelAccessInfo *context,
                                 KernelAddress address, uint64_t *out);

/**
 * @brief Get sizeof(KernelAddress) buffer bytes from kernel space access structure
 * @param [in,out] context Pointer to structure of kernel space access
 * @param [in] address Kernel virtual address of data
 * @param [out] out Pointer of output data
 * @return ::PA_TZ_SUCCESS in case of success, ::PA_TZ_GENERAL_ERROR
 */
PaTzResult KernelAccessGetPointer(KernelAccessInfo *context,
                                  KernelAddress address, KernelAddress *out);

#endif  // PA_TZ_DRV_SRC_KERNEL_ACCESS_H_
