#ifndef __SB_HSM_DRIVER_H
#define __SB_HSM_DRIVER_H

#include "sb_hsm_types.h"

#ifdef __MUTEKH__
# include <hexo/types.h>
#else
# include "types.h"
#endif

/**
   Initialize HSM driver. Must be called first, before sb_hsm_init and any other HSM operation. Parameters:
   @param io_addr Base address of HSM interface registers.
   @return SB_OK
 **/
sb_hsm_err_t sb_hsm_init_drv(uintptr_t io_addr);

/**
   Initialize HSM. Initializes the HSM @tt cfg interface regsiter with the Master Block base address (@tt cfg.mbba), the start address (@tt cfg.padd) and size (@tt cfg.psiz)
   of the protected memory area. Enables all caches (but IV cache), disables IVs, disables interrupts. Initializes the @tt mik register with the master
   integrity secret key and the @tt mck register with the master confidentiality secret key. Parameters:
   @param mb_addr Master Block byte base address (8 MSBs only, Master Block is always aligned on a 16MB boundary)
   @param ram_p_addr Byte start address of protected memory area (8 MSBs onlys, protected area is always aligned on a 16MB boundary)
   @param l4_ram_p_size_16mb Size of protected memory area (log4 of byte size / 16MB, 1 to 4, 1=64MB, 2=256MB, 3=1GB, 4=4GB)
   @param key_c 184-bits DES-X key used for Master Block encryption. k=key_c[1](23..0)||key_c[0], k1=key_c[3]||key_c[2], k2=key_c[5]||key_c[6]. Most significant byte of key_c[1] ignored.
   @param key_i 184-bits DES-X key used for Master Block and RW-pages integrity. k=key_i[1](23..0)||key_i[0], k1=key_i[3]||key_i[2], k2=key_i[5]||key_i[6]. Most significant byte of key_i[1] ignored.
   @return:
   @list
     @item SB_NDRV if driver not initialized, else
     @item SB_OK
   @end list
 */
sb_hsm_err_t sb_hsm_init(paddr_t  mb_addr,
			 paddr_t  ram_p_addr,
			 size_t   l4_ram_p_size_16mb, 
			 uint32_t key_c[6], 
			 uint32_t key_i[6]);

/**
   Enable HSM. Shall be called only after HSM driver initialization and HSM initialization. @return:
   @list
     @item SB_NDRV if driver not initialized, else
     @item SB_NINIT if HSM not initialized, else
     @item SB_ALREADY if HSM already enabled, else
     @item SB_OK (and sets the @tt cfg.en flag).
   @end list
  */
sb_hsm_err_t sb_hsm_enable();

/**
   Disable HSM. Shall be called only after HSM driver initialization and HSM initialization. @return:
   @list
     @item SB_NDRV if driver not initialized, else
     @item SB_NINIT if HSM not initialized, else
     @item SB_ALREADY if HSM already disabled, else
     @item SB_OK (and clears the @tt cfg.en flag).
   @end list
  */
sb_hsm_err_t sb_hsm_disable();

/**
   Enable HSM interrupt. Shall be called only after HSM driver initialization and HSM initialization. @return:
   @list
     @item SB_NDRV if driver not initialized, else
     @item SB_NINIT if HSM not initialized, else
     @item SB_ALREADY if HSM interrupt already enabled, else
     @item SB_OK (and sets the @tt cfg.ie flag).
   @end list
  */
sb_hsm_err_t sb_hsm_enable_int();

/**
   Disable HSM interrupt. Shall be called only after HSM driver initialization and HSM initialization. @return:
   @list
     @item SB_NDRV if driver not initialized, else
     @item SB_NINIT if HSM not initialized, else
     @item SB_ALREADY if HSM interrupt already disabled, else
     @item SB_OK (and clears the @tt cfg.ie flag).
   @end list
  */
sb_hsm_err_t sb_hsm_disable_int();

/**
  Initialize PSPE. Parameters:
  @param pspe_address Byte address of PSPE in external memory
  @param integrity_page Byte address of MAC set or MAC tree page (must be a multiple of 4kB, ignored if no integrity)
  @param integrity_idx Index of MAC set (0 to 3) or MAC tree (0 to 2) in MAC set or MAC tree page
  @param iv_page Byte address of Initialization Vectors (IV) page (must be a multiple of 4kB, ignored if confidentiality mode of associated Security Policy is not CBC or IVs are disabled)
  @param iv_idx Index of IV set in IV page
  @param sp Index of security policy
  @param unprotected Set if confidentiality and integrity modes of associated Security Policy are @tt none and @tt none
  @param level Size indicator of associated memory page @see sb_page_size_e
  @return:
  @list
    @item SB_NDRV if driver not initialized, else
    @item SB_EADDR if invalid PSPE address, else
    @item SB_OK
  @end list
 */
sb_hsm_err_t 
sb_hsm_pspe_init(paddr_t pspe_address,
		 paddr_t integrity_page,
		 size_t integrity_idx,
		 paddr_t iv_page,
		 size_t iv_idx,
		 size_t sp_idx,
		 bool_t unprotected,
		 enum   sb_page_size_e size);

/**
  Invalidate PSPE. Resets all PSPE fields, marks PSPE invalid. Parameters:
  @param pspe_address Byte address of PSPE in external memory
  @return:
  @list
    @item SB_NDRV if driver not initialized, else
    @item SB_EADDR if invalid PSPE address, else
    @item SB_OK
  @end list
 */
sb_hsm_err_t sb_hsm_pspe_delete(paddr_t pspe_address);

/**
  Initialize SP. Parameters:
  @param sp_addr Byte address of SP in external memory
  @param c Confidentiality mode @see sb_confidentiality_mode_e
  @param i Integrity mode @see sb_integrity_mode_e
  @param key_c 184-bits DES-X key used for Master Block encryption. k=key_c[1](23..0)||key_c[0], k1=key_c[3]||key_c[2], k2=key_c[5]||key_c[6]. Most significant byte of key_c[1] ignored.
  @param key_i 184-bits DES-X key used for Master Block and RW-pages integrity. k=key_i[1](23..0)||key_i[0], k1=key_i[3]||key_i[2], k2=key_i[5]||key_i[6]. Most significant byte of key_i[1] ignored.
  @return:
  @list
    @item SB_NDRV if driver not initialized, else
    @item SB_OK
  @end list
 */
sb_hsm_err_t sb_hsm_sp_init(paddr_t sp_addr,
			    enum sb_confidentiality_mode_e c,
			    enum sb_integrity_mode_e i,
			    uint32_t key_c[6],
			    uint32_t key_i[6]);

/**
  Invalidate SP. Resets all SP fields, mark SP invalid. Parameters:
  @param sp_addr Byte address of SP in external memory
  @return:
  @list
    @item SB_NDRV if driver not initialized, else
    @item SB_OK
  @end list
 */
sb_hsm_err_t sb_hsm_sp_delete(paddr_t sp_addr);

/**
  Initialize MAC tree. Creates a new MAC tree protecting a memory page. Computes all tree nodes from data in memory page up to topmost tree level. Also computes
  root of all trees in MAC tree page and updates slave PSPE accordingly. Two cases:
  @list
    @item first tree in MAC tree page: no check of topmost level of other trees, else
    @item check topmost level of other trees before root computation.
  @end list
  Parameters:
  @param address_page Byte address of memory page protected by new tree.
  @param new If set first tree in MAC tree page.

  Also used to initialize Master MAC Tree in Master Block. In this case parameter is base address of Master Block, root node is computed on MMT only and stored in dedicated HSM internal register.
  @return:
  @list
    @item SB_NDRV if driver not initialized, else
    @item SB_OK
  @end list
 */
sb_hsm_err_t sb_hsm_init_page_integrity(paddr_t address_page, bool_t new);

/**
   Atomic 256 bits group write. Performs an atomic write of a 256 bits group in external memory (chains a call to sb_hsm_prewriteGroup and sb_hsm_completedwriteGroup).
   Equivalent to a memcopy with fixed size (256 bits), atomicity and on-the-fly security.
   @param dest Destination byte address of atomic write.
   @param src Byte address of group to write.
   @return:
   @list
     @item SB_NDRV if driver not initialized, else
     @item SB_OK
   @end list
 */
sb_hsm_err_t sb_hsm_writeGroup(paddr_t dest, uintptr_t src);

/**
   First step of 256 bits atomic group write. Loads HSM @tt agrwdata interface register with 256 bits group at byte address @tt src.
   @param src Byte address of group to write.
   @return:
   @list
     @item SB_NDRV if driver not initialized, else
     @item SB_OK
   @end list
*/
sb_hsm_err_t sb_hsm_prewriteGroup(uintptr_t src);

/**
   Second step of 256 bits atomic group write. Loads HSM @tt agrwadd interface register with destination address of atomic write, launches the atomic write by loading the @tt agrwcmd interface register with write command.
   @param dest Destination byte address of atomic write.
   @return:
   @list
     @item SB_NDRV if driver not initialized, else
     @item SB_OK
   @end list
*/
sb_hsm_err_t sb_hsm_completedwriteGroup(paddr_t dest);

/**
   First step of 256 bits atomic group read. Loads HSM @tt agrwadd interface register with source address of atomic read, launches the atomic read by loading the @tt agrwcmd interface register with read command.
   @param src Byte address of group to read.
   @return:
   @list
     @item SB_NDRV if driver not initialized, else
     @item SB_OK
   @end list
 */
sb_hsm_err_t sb_hsm_prereadGroup(paddr_t src);

/**
   Second step of 256 bits atomic group read. Stores the 256 bits content of the HSM @tt agrwdata interface register at destination byte address.
   @param dest Destination byte address.
   @return:
   @list
     @item SB_NDRV if driver not initialized, else
     @item SB_OK
   @end list
*/
sb_hsm_err_t sb_hsm_completedreadGroup(uintptr_t dest);

/**
   Get HSM status register. @return the content of HSM @tt status interface register.
*/
reg_t sb_hsm_getstatus();

#endif
