/*
 * SecBus - This file is part of SecBus
 * Copyright (C) 2012 - Telecom ParisTech
 * 
 * This file must be used under the terms of the CeCILL.
 * This source file is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.  The terms
 * are also available at    
 * http://www.cecill.info/licences/Licence_CeCILL_V1.1-US.txt
 *
 */

#ifndef SECBUSLIB__H_
#define SECBUSLIB__H_

#include "types.h"

//DES function
void DES(uint32_t *in, uint32_t *out, uint32_t *key, bool cipher);

// common functions for addresses

// test if x is a power of 2
bool isPow2(unsigned int x);
//test if a 8-byte block is complete
bool fill_64(int be, addr_t address);
//Count number of zero in "n"
template<typename T>
unsigned int _ctz(T n, unsigned int p);

template<typename T>
unsigned int _clz(T n, unsigned int p);
//Inclusion function
bool inclusion(addr_t address, addr_t low_address, addr_t high_address);
//Inferior function
bool inferior(addr_t address, addr_t up_address);
//Superior function
bool superior(addr_t address, addr_t low_address);
//Return a block_size_in_bytes aligned address of "address"
addr_t aligned(addr_t address, int block_size_in_bytes);
//Return index of "address" in a "block_size_in_bytes" block
unsigned int index(addr_t address, int block_size_in_bytes);

addr_t getPSPEAddressFromPageSize(addr_t address, 
				  size_t size, 
				  addr_t mb_address,
				  addr_t b_address);
addr_t getPSPEBaseAddress(addr_t mb_address, size_t size);
addr_t getSPBaseAddress(addr_t mb_address, size_t size);
addr_t getMMacTBaseAddress(addr_t mb_address, size_t size);
addr_t getSPAddressFromIdx(uint32_t sp_idx, addr_t mb_address, size_t size);
size_t getPageLevel();
size_t getPageSize(size_t level);
// return size of Master Mac Tree based on the protected size
size_t getMMTSize(size_t size);

bool isMasterTree(addr_t address, addr_t mb_address, size_t size);
bool compare(uint32_t *value, uint32_t *reference, size_t size_in_bytes);

addr_t mt_getPageBaseAddress(addr_t address, size_t level);
addr_t mt_getParentLeavesAddress(addr_t leaf_address,
				 addr_t ht_address,
				 size_t level,
				 addr_t mb_address,
				 size_t size);
bool mt_isLastLevel(addr_t address, size_t level, addr_t mb_address, size_t size);
addr_t mt_getParentAddress(addr_t node_address, size_t level, addr_t mb_address, size_t size);
addr_t mt_getSetAddress(addr_t node_address, size_t level, addr_t mb_address, size_t size);
addr_t mt_getBlockIndex(addr_t address, size_t level, addr_t mb_address, size_t size);
addr_t mt_getBrotherAddress(addr_t node_address, size_t level, addr_t mb_address, size_t size);

addr_t ms_getMacAddress(addr_t address, addr_t page_address, size_t level);



//#warning clean up (old API)
/*
//Get the 4K page address containing "address"
addr_t get4kPageAddress(addr_t address);
//Get the 4M page address containing "address"
addr_t get4mPageAddress(addr_t address);
//Get the first level PSPE address
addr_t getFirstLevelAddress(addr_t base_address, addr_t address);
//Get the second level PSPE address
addr_t getSecondLevelAddress(addr_t base_address, addr_t address);

//Get SP address from "SP_index"
addr_t getSPAddress(int SP_index);
*/

//  PSPE


pspe_msadd_t pspe_getMSAdd(pspe_t *pspe);
void pspe_setMSAdd(pspe_t *pspe, pspe_msadd_t msadd);
pspe_msidx_t pspe_getMSIdx(pspe_t *pspe);
void pspe_setMSIdx(pspe_t *pspe, pspe_msidx_t msidx);
pspe_ivadd_t pspe_getIVAdd(pspe_t *pspe);
void pspe_setIVAdd(pspe_t *pspe, pspe_ivadd_t ivadd);
pspe_ividx_t pspe_getIVIdx(pspe_t *pspe);
void pspe_setIVIdx(pspe_t *pspe, pspe_ividx_t ividx);
pspe_spidx_t pspe_getSPIdx(pspe_t *pspe);
void pspe_setSPIdx(pspe_t *pspe, pspe_spidx_t spidx);
pspe_size_t pspe_getSize(pspe_t *pspe);
void pspe_setSize(pspe_t *pspe, pspe_size_t size);
pspe_prot_t pspe_getProt(pspe_t *pspe);
void pspe_setProt(pspe_t *pspe, pspe_prot_t prot);
pspe_valid_t pspe_getValid(pspe_t *pspe);
void pspe_setValid(pspe_t *pspe, pspe_valid_t valid);
void pspe_getMAC(pspe_t *pspe, pspe_mac_t *mac);
void pspe_setMAC(pspe_t *pspe, pspe_mac_t *mac);

//#warning clean up (old API)
//Get Validity bit from "PSPE"
/*
bool getValidBit(int* PSPE);
//Set Validity bit in "PSPE"
void setValidBit(int* PSPE, bool V);
//Get Type bit from "PSPE"
PSPEtype_e getTypeBit(int* PSPE);
//Set Type bit in "PSPE"
void setTypeBit(int* PSPE, PSPEtype_e T);
//Get Size bit from "PSPE"
PageSize_e getSizeBit(int* PSPE);
//Set Size bit in "PSPE"
void setSizeBit(int* PSPE, PageSize_e PS);
//get SP index from "PSPE"
unsigned int getSPindex(int* PSPE);
//Set SP index in "PSPE"
void setSPindex(int* PSPE, int SP_index);
//Get Root Hash Value from "PSPE"
void getRHV(int* PSPE, int * RHV);
//Set Root Hash Value in "PSPE"
void setRHV(int* PSPE, int *RHV);
//Get base address from "PSPE"
addr_t getBaseAddress(int* PSPE);
//Set base address in "PSPE"
void setBaseAddress(int* PSPE, addr_t base_address);
*/

//  SP


void sp_getKeyC(sp_t *sp, sp_key_c_t *key_c);
void sp_setKeyC(sp_t *sp, sp_key_c_t *key_c);
void sp_getKeyI(sp_t *sp, sp_key_i_t *key_i);
void sp_setKeyI(sp_t *sp, sp_key_i_t *key_i);
sp_mode_c_t sp_getModeC(sp_t *sp);
void sp_setModeC(sp_t *sp, sp_mode_c_t mode_c);
sp_mode_i_t sp_getModeI(sp_t *sp);
void sp_setModeI(sp_t *sp, sp_mode_i_t mode_i);
sp_valid_t sp_getValid(sp_t *sp);
void sp_setValid(sp_t *sp, sp_valid_t valid);

//#warning clean up (old API)
//Get Confidentiality mode from "SP"
/*
confidentiality_mode_e getPM(int* SP);
//Get Integrity mode from "SP"
integrity_mode_e getIM(int* SP);
//Set Confidentiality mode in "SP"
void setPM(int* SP, confidentiality_mode_e PM);
//Set Integrity mode in "SP"
void setIM(int* SP, integrity_mode_e IM);
//Get key from "SP"
void getSK(int* SP, int* Key);
//Set key in "SP"
void setSK(int* SP, int *PSPE, int * Key);
*/
/*****************************
 *             IO            *
 *****************************/


//  config register


/** 
 * io_config_getMBAddr return the masterblock address from config
 * register 
 */
addr_t io_config_getMBAddr(io_reg_32_t *config);
/** 
 * io_config_setMBAddr set the masterblock address to the config
 * register 
 */
void io_config_setMBAddr(io_reg_32_t *config, addr_t mb_addr);
/** 
 * io_config_getEN return the state of SecBus (enable/disable) from
 * config register 
 */
bool io_config_getEN(io_reg_32_t *config);
/** 
 * io_config_setEN set the SecBus state (enable/disable) to the
 * config register 
 */
void io_config_setEN(io_reg_32_t *config, bool enable);
/** 
 * io_config_getInt return the SecBus interrupt state from config register 
 */
bool io_config_getInt(io_reg_32_t *config);
/** 
 * io_config_setInt set the SecBus interrupt state to the config
 * register 
 */
void io_config_setInt(io_reg_32_t *config, bool enable);
/** 
 * io_config_getPC return the SecBus PSPE cache state from config
 * register 
 */
bool io_config_getPC(io_reg_32_t *config);
/** 
 * io_config_setPC set the SecBus PSPE cache state to the config
 * register 
 */
void io_config_setPC(io_reg_32_t *config, bool enable);
/** 
 * io_config_getSPC return the SecBus SP cache state from config
 * register 
 */
bool io_config_getSPC(io_reg_32_t *config);
/** 
 * io_config_setSPC set the SecBus SP cache state to config
 * register 
 */
void io_config_setSPC(io_reg_32_t *config, bool enable);
/** 
 * io_config_getMACC return the SecBus MAC cache state from config
 * register 
 */
bool io_config_getMACC(io_reg_32_t *config);
/** 
 * io_config_setMACC set the SecBus MAC cache state to config
 * register 
 */
void io_config_setMACC(io_reg_32_t *config, bool enable);
/** 
 * io_config_getHMACC return the SecBus MACTree cache state from
 * config register 
 */
bool io_config_getHMACC(io_reg_32_t *config);
/** 
 * io_config_setHMACC set the SecBus MACTree cache state to config
 * register 
 */
void io_config_setHMACC(io_reg_32_t *config, bool enable);
/** 
 * io_config_getBRAM return the beggining of the protected RAM
 * area 
 */
addr_t io_config_getBRAM(io_reg_32_t *config);
/** 
 * io_config_setBRAM set the protected RAM area 
 */
void io_config_setBRAM(io_reg_32_t *config, addr_t b_ram_addr);
/** 
 * io_config_getSRAM return the size of the protected RAM area 
 */
size_t io_config_getSRAM(io_reg_32_t *config);
/** 
 * io_config_setSRAM set the size of the protected RAM area 
 */
void io_config_setSRAM(io_reg_32_t *config, size_t s_ram);


//  status register


/** 
 * io_status_setBusy set the SecBus busy flag of the status
 * register 
 */
void io_status_setBusy(io_reg_32_t *status, bool busy);
/** 
 * io_status_getBusy return the SecBus busy flag from the status
 * register 
 */
bool io_status_getBusy(io_reg_32_t *status);
/** 
 * io_status_setErrT set the SecBus error type of the status
 * register, @see enum io_status_errt_e 
 */
void io_status_setErrT(io_reg_32_t *status, io_status_errt_t errt);
/** 
 * io_status_getErrT return the SecBus error type from the status
 * register, @see enum io_status_errt_e 
 */
io_status_errt_t io_status_getErrT(io_reg_32_t *status);
/** 
 * io_status_setErrT set the SecBus R/W error of the status register,
 * @see enum io_status_errc_e 
 */
void io_status_setErrC(io_reg_32_t *status, io_status_errc_t errc);
/** 
 * io_status_getErrC return the SecBus R/W error from the status
 * register, @see enum io_status_errc_e 
 */
io_status_errc_t io_status_getErrC(io_reg_32_t *status);
/** 
 * io_status_setErrA set the SecBus address error of the status
 * register 
 */
void io_status_setErrA(io_reg_32_t *status, addr_t erra); 
/** 
 * io_status_getErrA return the SecBus address error from the status
 * register 
 */
addr_t io_status_getErrA(io_reg_32_t *status);


// command register


/** 
 * io_cmd_setCmd set the command to be executed by SecBus in the
 * command register, @see enum io_cmd_cmd_e 
 */
void io_cmd_setCmd(io_reg_32_t *cmd, io_cmd_cmd_t cmd_val);
/** 
 * io_cmd_getCmd return the command to be executed by SecBus from
 * the command register, @see enum io_cmd_cmd_e
 */
io_cmd_cmd_t io_cmd_getCmd(io_reg_32_t *cmd);

//#warning is it still useful ?
void io_cmd_setSize(io_reg_32_t *cmd, size_t size);
size_t io_cmd_getSize(io_reg_32_t *cmd);


// used for MAC-Set Tree & MAC-Set

/*
//Return base address of page containing address
addr_t getPageBaseAddress(addr_t address, PageSize_e page_size);
//Return parent address from a node address
addr_t getParentAddress(addr_t node_address, PageSize_e ht_page_size);
//Return parent address from a leaf address
addr_t getParentLeavesAddress(addr_t leaf_address, addr_t  ht_start_address, PageSize_e ht_page_size);
//Return address of the hash set containing  node address
addr_t getSetAddress(addr_t node_address, PageSize_e ht_page_size);
//Return the index of a hash block in a hash set
unsigned int getBlockIndex(addr_t address, PageSize_e ht_page_size);

//Test if address belongs to last level of tree
bool isLastLevel(addr_t address, PageSize_e ht_page_size);

//Get address of parent MAC block
addr_t getMacAddress(addr_t address, addr_t page_address, PageSize_e page_size);

//Test if address belongs to Master tree
bool isMasterTree(addr_t address);

//Get brother address of a node
addr_t getBrotherAddress(addr_t node_address, PageSize_e ht_page_size);
*/
//Compare computed value and reference value
bool compare(int *value, int *reference, int size_in_bytes);

//Test if address belongs to Master Block 
bool isMasterBlock(addr_t address);

// debug functions
void printCacheParam(cache_param_s &cache);
void printWithUnit(uint32_t number);

#endif

