From da0637d93d5935b1f6a398ecb420bd386d85d410 Mon Sep 17 00:00:00 2001 From: edolomb Date: Wed, 10 Jan 2018 16:45:02 +0000 Subject: SECUMOD Driver git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@11248 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/ports/SAMA/SAMA5D2x/sama_secumod.c | 568 ++++++++++++++++++++++++++++++ os/hal/ports/SAMA/SAMA5D2x/sama_secumod.h | 554 +++++++++++++++++++++++++++++ 2 files changed, 1122 insertions(+) create mode 100644 os/hal/ports/SAMA/SAMA5D2x/sama_secumod.c create mode 100644 os/hal/ports/SAMA/SAMA5D2x/sama_secumod.h (limited to 'os') diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_secumod.c b/os/hal/ports/SAMA/SAMA5D2x/sama_secumod.c new file mode 100644 index 000000000..3652e6b65 --- /dev/null +++ b/os/hal/ports/SAMA/SAMA5D2x/sama_secumod.c @@ -0,0 +1,568 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file SAMA5D2x/sama_secumod.c + * @brief SAMA SECUMOD support code. + * + * @addtogroup SAMA5D2x_SECUMOD + * @{ + */ + +#include "hal.h" + +#if HAL_USE_SECUMOD || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ +/** + * @brief SEC driver identifier. + */ +SECDriver SECD0; + +/*===========================================================================*/ +/* Driver local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver constant */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/** + * @brief SECURAM interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(SAMA_SECURAM_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + uint32_t ramaccsr, sr, sysr; + uint32_t rwx; + uint32_t i; + + ramaccsr = SECUMOD->SECUMOD_RAMACCSR; + sr = SECUMOD->SECUMOD_SR; + + for (i = 0; i < SECUMOD_RAM_REGIONS; i++) { + rwx = (ramaccsr >> (2 * i)) & 3; + if (rwx != RAMACCSR_NO_VIOLATION && SECD0.config->securam_callback != NULL) + SECD0.config->securam_callback(&SECD0); + } + + /* process the end of erase signalling */ + do { + sysr = SECUMOD->SECUMOD_SYSR; + } while (sysr & SECUMOD_SYSR_ERASE_ON); + + if (SECUMOD_SYSR_ERASE_DONE == (sysr & SECUMOD_SYSR_ERASE_DONE)) { + /* Clear the flag ERASE_DONE */ + SECUMOD->SECUMOD_SYSR = SECUMOD_SYSR_ERASE_DONE; + if (SECD0.config->erased_callback != NULL) + SECD0.config->erased_callback(&SECD0); + } + + /* wait at least one slow clock */ + chSysPolledDelayX(SAMA_PCK / SAMA_SLOW_CLK); + + /* Clear RAM access violation flags */ + SECUMOD->SECUMOD_RAMACCSR = ramaccsr; + /* Clear corresponding alarm flag bit */ + SECUMOD->SECUMOD_SCR = sr; + + aicAckInt(); + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief SECUMOD interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(SAMA_SECUMOD_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + uint32_t sr, nimpr; + + /* Read alarm status */ + sr = SECUMOD->SECUMOD_SR; + + if ((sr & SECUMOD_SR_SHLDM) && (nimpr & SECUMOD_NIMPR_SHLDM)) { + SECD0.secumod_callback(&SECD0, SEC_EVENT_SHLDM); + } + else if ((sr & SECUMOD_SR_DBLFM) && (nimpr & SECUMOD_NIMPR_DBLFM)) { + SECD0.secumod_callback(&SECD0, SEC_EVENT_DBLFM); + } + else if ((sr & SECUMOD_SR_TST) && (nimpr & SECUMOD_NIMPR_TST)) { + SECD0.secumod_callback(&SECD0, SEC_EVENT_TST); + } + else if ((sr & SECUMOD_SR_JTAG) && (nimpr & SECUMOD_NIMPR_JTAG)) { + SECD0.secumod_callback(&SECD0, SEC_EVENT_JTAG); + } + else if ((sr & SECUMOD_SR_MCKM) && (nimpr & SECUMOD_NIMPR_MCKM)) { + SECD0.secumod_callback(&SECD0, SEC_EVENT_MCKM); + } + else if ((sr & SECUMOD_SR_TPML) && (nimpr & SECUMOD_NIMPR_TPML)) { + SECD0.secumod_callback(&SECD0, SEC_EVENT_TPML); + } + else if ((sr & SECUMOD_SR_TPMH) && (nimpr & SECUMOD_NIMPR_TPMH)) { + SECD0.secumod_callback(&SECD0, SEC_EVENT_TPMH); + } + else if ((sr & SECUMOD_SR_VDDBUL) && (nimpr & SECUMOD_NIMPR_VDDBUL)) { + SECD0.secumod_callback(&SECD0, SEC_EVENT_VDDBUL); + } + else if ((sr & SECUMOD_SR_VDDBUH) && (nimpr & SECUMOD_NIMPR_VDDBUH)) { + SECD0.secumod_callback(&SECD0, SEC_EVENT_VDDBUH); + } + else if ((sr & SECUMOD_SR_VDDCOREL) && (nimpr & SECUMOD_NIMPR_VDDCOREL)) { + SECD0.secumod_callback(&SECD0, SEC_EVENT_VDDCOREL); + } + else if ((sr & SECUMOD_SR_VDDCOREH) && (nimpr & SECUMOD_NIMPR_VDDCOREH)) { + SECD0.secumod_callback(&SECD0, SEC_EVENT_VDDCOREH); + } + else { + SECD0.secumod_callback(&SECD0, SEC_EVENT_PIOBU); + } + + /* wait at least one slow clock */ + chSysPolledDelayX(SAMA_PCK / SAMA_SLOW_CLK); + + /* Clear corresponding alarm flag bit */ + SECUMOD->SECUMOD_SCR = sr; + + aicAckInt(); + OSAL_IRQ_EPILOGUE(); +} + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ +/** + * @brief Configures PIOBU pads according to configuration struct. + * + * @param[in] listp pointer to a PIOBUConfig array + * @param[in] length length of array + * + * @notapi + */ +void piobu_config(PIOBUConfig *listp, size_t length) { + uint8_t i; + uint32_t cfg; + uint32_t index; + PIOBUConfig *piobup; + + for (i = 0; i < length; i++) { + index = listp[i].pinIndex; + piobup = &listp[i]; + + /* AFV and RFV fields must be set to 0 when dynamic intrusion is selected. */ + if (piobup->dynamic) { + cfg = 0; + } else { + cfg = (piobup->afv << SECUMOD_PIOBU_AFV_Pos ) | (piobup->rfv << SECUMOD_PIOBU_RFV_Pos); + } + + if (piobup->mode) { + cfg |= SECUMOD_PIOBU_OUTPUT; + if (piobup->outputLevel) + cfg |= SECUMOD_PIOBU_PIO_SOD; + } + + cfg |= piobup->pullUpState << SECUMOD_PIOBU_PULLUP_Pos; + + if (piobup->scheduled) + cfg |= SECUMOD_PIOBU_SCHEDULE; + + if (piobup->inputDefaultLevel) + cfg |= SECUMOD_PIOBU_SWITCH; + + /* FILTER3_5 and DYNSTAT fields exist only for even PIOBUs */ + if (0 == (index & 0x01)) { + if (piobup->dynamic) + cfg |= SECUMOD_PIOBU_DYNSTAT; + + if (piobup->filter3_5) + cfg |= SECUMOD_PIOBU_FILTER3_5; + } + SECUMOD->SECUMOD_PIOBU[index] = cfg; + } +} + +/** + * @brief Low level SEC driver initialization. + * + * @notapi + */ +void sec_lld_init(void) { + + /* Driver initialization.*/ + secObjectInit(&SECD0); + SECD0.sec = SECUMOD; +} + +/** + * @brief Configures and activates the SEC peripheral. + * + * @param[in] secp pointer to the @p SECDriver object + * + * @notapi + */ +void sec_lld_start(SECDriver *secp) { + + uint8_t i; + + if (secp->state == SEC_STOP) { + /* Clock activation. */ + pmcEnableSEC(); + + /* Register Reset */ + secp->sec->SECUMOD_NIDPR = SECUMOD_NIDPR_ALL; + secumodSetNormalModeProtections(~SECUMOD_NMPR_ALL); + + /* + * Configure interrupts + */ + aicSetSourcePriority(ID_SECUMOD, SAMA_SECUMOD_IRQ_PRIORITY); + aicSetSourceHandler(ID_SECUMOD, SAMA_SECUMOD_HANDLER); + + aicSetSourcePriority(ID_SECURAM, SAMA_SECURAM_IRQ_PRIORITY); + aicSetSourceHandler(ID_SECURAM, SAMA_SECURAM_HANDLER); + + /* Enabling interrupt. */ + aicEnableInt(ID_SECUMOD); + aicEnableInt(ID_SECURAM); + } + + uint32_t ramacc_cfg = 0; + + /* Select mode normal or backup*/ + secp->sec->SECUMOD_CR = secp->config->cr; + + /* Configure JTAGCR */ + secp->sec->SECUMOD_JTAGCR = secp->config->jtagcr; + + /* Configure region rights. */ + for (i = 0; i < SECUMOD_RAM_REGIONS; i++) { + ramacc_cfg |= (secp->config->region[i].mode & 0x3u) << (i * 2); + } + secp->sec->SECUMOD_RAMACC = ramacc_cfg; + + /* Configure PIOBU pads. */ + piobu_config(secp->config->list, secp->config->length); +} + +/** + * @brief Deactivates the SEC peripheral. + * + * @param[in] secp pointer to the @p SECDriver object + * + * @notapi + */ +void sec_lld_stop(SECDriver *secp) { + + secp->sec->SECUMOD_NMPR &= ~(0xFF << 16); + secp->sec->SECUMOD_NIDPR |= (0xFF << 16); + + aicDisableInt(ID_SECURAM); + aicDisableInt(ID_SECUMOD); + + pmcDisableSEC(); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ +/** + * @brief SEC Driver initialization. + * + * @init + */ +void secInit(void) { + + sec_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p SECDriver structure. + * + * @param[out] secp pointer to a @p SECDriver object + * + * @init + */ +void secObjectInit(SECDriver *secp) { + + secp->state = SEC_STOP; + secp->config = NULL; +} + +/** + * @brief Configures and activates the SEC peripheral. + * + * @param[in] secp pointer to a @p SECDriver object + * @param[in] config pointer to a @p SECConfig object + * + * @api + */ +void secStart(SECDriver *secp, const SECConfig *config) { + + osalDbgCheck((secp != NULL) && (config != NULL)); + + osalSysLock(); + osalDbgAssert((secp->state == SEC_STOP), "invalid state"); + secp->config = config; + sec_lld_start(secp); + secp->state = SEC_ACTIVE; + osalSysUnlock(); +} + +/** + * @brief Deactivates the SEC peripheral. + * + * @param[in] secp pointer to a @p SECDriver object + * + * @api + */ +void secStop(SECDriver *secp) { + + osalDbgCheck(secp != NULL); + + osalSysLock(); + + osalDbgAssert((secp->state == SEC_STOP) || (secp->state == SEC_ACTIVE), + "invalid state"); + + sec_lld_stop(secp); + secp->config = NULL; + secp->state = SEC_STOP; + + osalSysUnlock(); +} + +/** + * @brief Enables or disables SECUMOD callbacks. + * @details This function enables or disables callbacks, use a @p NULL pointer + * in order to disable a callback. + * @note The function can be called from any context. + * + * @param[in] secp pointer to SECUMOD driver structure + * @param[in] sources Bitwise OR of protections. + * @param[in] callback callback function pointer or @p NULL + * + * @api + */ +void secSetCallback(SECDriver *secp, uint32_t sources, secumod_callback_t callback) { + + osalDbgCheck(secp != NULL); + + syssts_t sts; + + /* Entering a reentrant critical zone.*/ + sts = osalSysGetStatusAndLockX(); + + if (callback != NULL) { + + /* IRQ sources enabled only after setting up the callback.*/ + secp->secumod_callback = callback; + secp->sec->SECUMOD_NIEPR = sources; + if (SECUMOD->SECUMOD_NMPR != sources) { + secumodToggleProtectionReg(); + secp->sec->SECUMOD_NIEPR = sources; + } + } + else { + secp->sec->SECUMOD_NIDPR = sources; + + /* Callback set to NULL only after disabling the IRQ sources.*/ + secp->secumod_callback = NULL; + } + + /* Leaving a reentrant critical zone.*/ + osalSysRestoreStatusX(sts); +} + +/** + * @brief Set JTAG protection options of SECUMOD. + * + * @param[in] reset Whether preventing debug state and BSD (Boundary Scan Diagnostics) to work. + * @param[in] permissions Debug permissions. + * @param[in] ack Whether monitor the DBGACK signal. + * + * @api + */ +void secumodSetJtagProtection(bool reset, uint8_t permissions, + bool ack) { + + uint32_t jtagcr; + jtagcr = permissions << SECUMOD_JTAGCR_CA5_DEBUG_MODE_Pos; + + if (reset) + jtagcr |= SECUMOD_JTAGCR_FNTRST; + + if (ack) + jtagcr |= SECUMOD_JTAGCR_CA5_DEBUG_MON; + + SECUMOD->SECUMOD_JTAGCR = jtagcr; +} + +/** + * @brief Tuning dynamic signatures by period and threshold. + * + * @param[in] period Signature Clock Period. + * @param[in] detection_thr Error Detection Threshold. + * @param[in] reset_thr Error Counter Reset Threshold. + * + * @api + */ +void secumodDynamicSignaturesTuning(uint16_t period, + uint8_t detectionThr, uint8_t resetThr) { + + uint32_t dystune; + + dystune = SECUMOD->SECUMOD_DYSTUNE & SECUMOD_DYSTUNE_NOPA; + dystune |= SECUMOD_DYSTUNE_PERIOD(period); + dystune |= SECUMOD_DYSTUNE_RX_ERROR_THRESHOLD(detectionThr); + dystune |= SECUMOD_DYSTUNE_RX_OK_CORREL_NUMBER(resetThr); + SECUMOD->SECUMOD_DYSTUNE = dystune; +} + +/** + * @brief Enable/Disable alarm regenerated periodically while intrusion is maintained. + * + * @param[in] enable periodic alarm while intrusion is maintained, + * true: disable, false: enable. + * @api + */ +void secumodPeriodicAlarm(bool enable) { + + uint32_t tmp; + + tmp = SECUMOD->SECUMOD_DYSTUNE & ~SECUMOD_DYSTUNE_NOPA; + if (!enable) + tmp |= SECUMOD_DYSTUNE_NOPA; + SECUMOD->SECUMOD_DYSTUNE = tmp; +} + +/** + * @brief Set access rights for secure RAM in SECUMOD. + * + * @param[in] region RAM region N, + * for N = 0 ~ 5: RAM range (N)Kbyte ~ (N+1)Kbyte; + * for N = 5: register bank 256bit. + * @param rights 0: No access allowed; + * 1: Only write access allowed; + * 2: Only read access allowed; + * 3: Read and write access allowed. + * @api + */ +void secumodSetRamAccessRights(uint32_t region, uint8_t rights) { + + uint32_t tmp; + + tmp = SECUMOD->SECUMOD_RAMACC & ~SECUMOD_RAMACC_RWx_Msk(region); + SECUMOD->SECUMOD_RAMACC = tmp | (rights << SECUMOD_RAMACC_RWx_Pos(region)); +} + +/** + * @brief Read the SECUMOD internal memory from the specified address + * + * @param[in] data Point to where the data read is stored + * @param[in] addr memory address + * @param[in] size The number of bytes to be read + * + * @return Bytes read + * + * @api + */ +uint32_t secumodReadInternalMemory(uint8_t *data, uint32_t addr, uint32_t size) { + + uint32_t i; + uint32_t region; + uint32_t count; + + if (addr >= ((uint32_t)SECURAM)) + addr -= ((uint32_t)SECURAM); + + for (i = 0; i < size; i += count) { + region = (addr + i) >> 10; + if ((SECUMOD_RAMACC_RWx_NO_ACCESS(region) == + (SECUMOD->SECUMOD_RAMACC & SECUMOD_RAMACC_RWx_Msk(region))) || + (SECUMOD_RAMACC_RWx_WR_ACCESS(region) == + (SECUMOD->SECUMOD_RAMACC & SECUMOD_RAMACC_RWx_Msk(region)))) { + break; + } + count = size; + if (((region + 1) << 10 ) <= (addr + i + size)) { + size = ((region + 1) << 10) - (addr + i); + } + memcpy(data + i, (uint8_t *)(((uint32_t)SECURAM) + addr + i), count); + } + return i; +} + +/** + * @brief Write data to the SECUMOD internal memory from the specified address + * + * @param[in] data Pointer to the data to be written + * @param[in] addr memory address + * @param[in] size The number of bytes to be be written + * + * @return Bytes written + * + * @api + */ +uint32_t secumodWriteInternalMemory(uint8_t *data, uint32_t addr, uint32_t size) { + + uint32_t i; + uint32_t region; + uint32_t count; + + if (addr >= ((uint32_t)SECURAM)) + addr -= ((uint32_t)SECURAM); + + for (i = 0; i < size; i += count) { + region = (addr + i) >> 10; + if ((SECUMOD_RAMACC_RWx_NO_ACCESS(region) == + (SECUMOD->SECUMOD_RAMACC & SECUMOD_RAMACC_RWx_Msk(region))) || + (SECUMOD_RAMACC_RWx_RD_ACCESS(region) == + (SECUMOD->SECUMOD_RAMACC & SECUMOD_RAMACC_RWx_Msk(region)))) { + break; + } + count = size; + if (((region + 1) << 10 ) <= (addr + i + size)) { + size = ((region + 1) << 10) - (addr + i); + } + memcpy((uint8_t *)(((uint32_t)SECURAM) + addr + i), data + i, count); + } + return i; +} + +#endif /* HAL_USE_SECUMOD */ + +/** @} */ diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_secumod.h b/os/hal/ports/SAMA/SAMA5D2x/sama_secumod.h new file mode 100644 index 000000000..54c7a3207 --- /dev/null +++ b/os/hal/ports/SAMA/SAMA5D2x/sama_secumod.h @@ -0,0 +1,554 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file SAMA5D2x/sama_secumod.h + * @brief SAMA SECUMOD support macros and structures. + * + * @addtogroup SAMA5D2x_SECUMOD + * @{ + */ + +#ifndef SAMA_SECUMOD_LLD_H +#define SAMA_SECUMOD_LLD_H + +#if HAL_USE_SECUMOD || defined(__DOXYGEN__) + +#include +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ +/** + * @name RAM ACCESS mode macros + * @{ + */ +/** + * @brief No access allowed. + */ +#define RAMACC_NO_ACCESS 0x0U + +/** + * @brief Only write access allowed. + */ +#define RAMACC_WR_ACCESS 0x1U + +/** + * @brief Only read access allowed. + */ +#define RAMACC_RD_ACCESS 0x2U + +/** + * @brief Read and Write access allowed. + */ +#define RAMACC_WR_RD_ACCESS 0x3U +/** @} */ + +/** + * @name SOURCE INTERRUPT macros + * @{ + */ +/* + * @brief Shield Monitor Protection Interrupt Source. + */ +#define SECUMOD_SHLDM (0x1u << 0) + +/* + * @brief Double Frequency Monitor Protection Interrupt Source. + */ +#define SECUMOD_DBLFM (0x1u << 1) + +/* + * @brief Test Pin Protection Interrupt Source. + */ +#define SECUMOD_TST (0x1u << 2) + +/* + * @brief JTAG Pins Protection Interrupt Source. + */ +#define SECUMOD_JTAG (0x1u << 3) + +/* + * @brief Master Clock Monitor Protection Interrupt Source. + */ +#define SECUMOD_MCKM (0x1u << 5) + +/* + * @brief Low Temperature Monitor Protection Interrupt Source. + */ +#define SECUMOD_TPML (0x1u << 6) + +/* + * @brief High Temperature Monitor Protection Interrupt Source. + */ +#define SECUMOD_TPMH (0x1u << 7) + +/* + * @brief Low VDDBU Voltage Monitor Protection Interrupt Source. + */ +#define SECUMOD_VDDBUL (0x1u << 10) + +/* + * @brief High VDDBU Voltage Monitor Protection Interrupt Source. + */ +#define SECUMOD_VDDBUH (0x1u << 11) + +/* + * @brief Low VDDCORE Voltage Monitor Protection Interrupt Source. + */ +#define SECUMOD_VDDCOREL (0x1u << 12) + +/* + * @brief High VDDCORE Voltage Monitor Protection Interrupt Source. + */ +#define SECUMOD_VDDCOREH (0x1u << 13) + +/* + * @brief PIOBUx Intrusion Detector Protection Interrupt Source. + */ +#define SECUMOD_DET0 (0x1u << 16) +#define SECUMOD_DET1 (0x1u << 17) +#define SECUMOD_DET2 (0x1u << 18) +#define SECUMOD_DET3 (0x1u << 19) +#define SECUMOD_DET4 (0x1u << 20) +#define SECUMOD_DET5 (0x1u << 21) +#define SECUMOD_DET6 (0x1u << 22) +#define SECUMOD_DET7 (0x1u << 23) +/** @} */ + +/** + * @name RAM STATUS mode macros + * @{ + */ +/** + * @brief No access violation occurred. + */ +#define RAMACCSR_NO_VIOLATION 0x0U + +/** + * @brief Write access violation occurred. + */ +#define RAMACCSR_WR_VIOLATION 0x1U + +/** + * @brief Read access violation occurred. + */ +#define RAMACCSR_RD_VIOLATION 0x2U + +/** + * @brief Read and Write access violation occurred. + */ +#define RAMACCSR_WR_RD_VIOLATION 0x3U +/** @} */ + +/** + * @name SCRAMB mode macros + * @{ + */ +/** + * @brief SCRAMB ENABLE. + */ +#define SCRAMB_ENABLE 0x1U + +/** + * @brief SCRAMB DISABLE. + */ +#define SCRAMB_DISABLE 0x2U +/** @} */ + +/* + * @brief RAM regions of SECUMOD + */ +#define SECUMOD_RAM_REGIONS 6 + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ +/** + * @name Configuration options + * @{ + */ +/** + * @brief SECUMOD interrupt priority level setting. + */ +#if !defined(SAMA_SECUMOD_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define SAMA_SECUMOD_IRQ_PRIORITY 7 +#endif + +/** + * @brief SECURAM interrupt priority level setting. + */ +#if !defined(SAMA_SECURAM_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define SAMA_SECURAM_IRQ_PRIORITY 7 +#endif + +/** @} */ +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ +/** + * @brief Driver state machine possible states. + */ +typedef enum { + SEC_UNINIT = 0, /**< Not initialized. */ + SEC_STOP = 1, /**< Stopped. */ + SEC_ACTIVE = 2 /**< Active. */ +} secstate_t; + +/** + * @brief Type of an SECUMOD event. + */ +typedef enum { + SEC_EVENT_SHLDM = 0, /* Triggered on Shield Monitor. */ + SEC_EVENT_DBLFM = 1, /* Triggered on Double Frequency Monitor. */ + SEC_EVENT_TST = 2, /* Triggered on Test Pin Monitor. */ + SEC_EVENT_JTAG = 3, /* Triggered on JTAG Pins Monitor. */ + SEC_EVENT_MCKM = 4, /* Triggered on Master Clock Monitor. */ + SEC_EVENT_TPML = 5, /* Triggered on Low Temperature Monitor. */ + SEC_EVENT_TPMH = 6, /* Triggered on High Temperature Monitor. */ + SEC_EVENT_VDDBUL = 7, /* Triggered on Low VDDBU Voltage Monitor. */ + SEC_EVENT_VDDBUH = 8, /* Triggered on High VDDBU Voltage Monitor. */ + SEC_EVENT_VDDCOREL = 9, /* Triggered on Low VDDCORE Voltage Monitor. */ + SEC_EVENT_VDDCOREH = 10, /* Triggered on High VDDCORE Voltage Monitor. */ + SEC_EVENT_PIOBU = 11 /* Triggered on PIOBU intrusion. */ +} secevent_t; + +/** + * @brief Type of a structure representing an SEC driver. + */ +typedef struct SECDriver SECDriver; + +/** + * @brief SECURAM notification callback type. + * + * @param[in] secp pointer to a @p SECDriver object + */ +typedef void (*securam_callback_t)(SECDriver *secp); + +/** + * @brief SECUMOD notification callback type. + * + * @param[in] secp pointer to a @p SECDriver object + */ +typedef void (*secumod_callback_t)(SECDriver *secp, secevent_t event); + +/** + * @brief SECUMOD erase callback type. + * + * @param[in] secp pointer to a @p SECDriver object + */ +typedef void (*erased_callback_t)(SECDriver *secp); + +/** + * @brief Type of RAM access mode. + */ +typedef uint32_t ram_access_mode_t; + +/** + * @brief PIOBU configuration structure. + */ +typedef struct { + /* + * @brief PIOBU pin's index + */ + uint32_t pinIndex:3; + /* + * @brief alarm filter value + */ + uint32_t afv:4; + /* + * @brief reset filter value + */ + uint32_t rfv:4; + /* + * @brief I/O line mode + * @note 0: pure input, 1: enabled in output + */ + uint32_t mode:1; + /* + * @brief Configure the I/O line in output mode + * @note 0: clear, 1: set + */ + uint32_t outputLevel:1; + /* + * @brief programmable pull-up state + * @note 0: none, 1: pull-up; 2: pull-down; 3: reserved + */ + uint32_t pullUpState:2; + /* + * @brief Pull-up/Down Scheduled: + * @note 0: no; 1: yes + */ + uint32_t scheduled:1; + /* + * @brief switch input default state + */ + uint32_t inputDefaultLevel:1; + /* + * @brief Mode of detection intrusion. + * @note 0: static, 1: dynamic + */ + uint32_t dynamic:1; + /* + * @brief filter for dynamic signatures input + * @note 0: 3 stages majority vote, 1: 5 stages + */ + uint32_t filter3_5:1; +} PIOBUConfig; + +typedef struct { + /** + * @brief RAM Access Right + */ + ram_access_mode_t mode; + /* End of the mandatory fields.*/ +} RAMAccessConfig; + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + /** + * @brief Callback for memory violation + */ + securam_callback_t securam_callback; + /** + * @brief Callback after memory erasing + */ + erased_callback_t erased_callback; + /** + * @brief lenght of PIOBUConfig array + * @note Number of pads to configure + */ + size_t length; + /** + * @brief pointer to PIOBUConfig array + */ + PIOBUConfig *list; + /** + * @brief RAM Access Rights + */ + RAMAccessConfig region[SECUMOD_RAM_REGIONS]; + /** + * @brief SECUMOD CR register initialization data. + */ + uint32_t cr; + /** + * @brief SECUMOD JTAGCR register initialization data. + */ + uint32_t jtagcr; +} SECConfig; + +/** + * @brief Structure representing a SEC driver. + */ +struct SECDriver { + /** + * @brief Driver state. + */ + secstate_t state; + /** + * @brief Current configuration data. + */ + const SECConfig *config; + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the SECUMOD registers block. + */ + Secumod *sec; + /** + * @brief Callback pointer. + */ + secumod_callback_t secumod_callback; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ +/** + * @brief Switch to Backup Mode. + * + * @api + */ +#define secumodSwitch2BackupMode() { \ + SECUMOD->SECUMOD_CR = SECUMOD_CR_BACKUP; \ +} + +/** + * @brief Switch to Normal Mode. + * + * @api + */ +#define secumodSwitch2NormalMode() { \ + SECUMOD->SECUMOD_CR = SECUMOD_CR_NORMAL; \ +} + +/** + * @brief Start clear content of SECUMOD internal RAM 4Kbyte and 256bits. + * + * @api + */ +#define secumodSoftwareProtection() { \ + SECUMOD->SECUMOD_CR = SECUMOD_CR_SWPROT; \ +} + +/** + * @brief Enable/Disable Auto-Backup. + * + * @param[in] enable Enable auto-backup if true, disable otherwise. + * + * @api + */ +#define secumodSetAutoBackup(enable) { \ + if (enable) { \ + SECUMOD->SECUMOD_CR = SECUMOD_CR_AUTOBKP_AUTO_SWITCH; \ + } \ + else { \ + SECUMOD->SECUMOD_CR = SECUMOD_CR_AUTOBKP_SW_SWITCH; \ + } \ +} + +/** + * @brief Enable/Disable Memory Scrambling. + * + * @param[in] enable Enable memory scrambling if true, disable otherwise. + * + * @api + */ +#define secumodSetScrambling(enable) { \ + if (enable) { \ + SECUMOD->SECUMOD_CR = SECUMOD_CR_SCRAMB_ENABLE; \ + } \ + else { \ + SECUMOD->SECUMOD_CR = SECUMOD_CR_SCRAMB_DISABLE; \ + } \ +} + +/** + * @brief Toggle normal or backup protection registers appear and disappear. + * + * @api + */ +#define secumodToggleProtectionReg() { \ + SECUMOD->SECUMOD_CR = SECUMOD_CR_KEY_TOGGLE; \ +} + +/** + * @brief Set scrambling key for secure RAM in SECUMOD. + * + * @param[in] key Scrambling key. + * + * @api + */ +#define secumodSetScramblingKey(key) { \ + SECUMOD->SECUMOD_SCRKEY = key; \ +} + +/** + * @brief Get scrambling key for secure RAM in SECUMOD. + * + * @return Scrambling key. + * + * @api + */ +#define secumodGetScramblingKey() { \ + SECUMOD->SECUMOD_SCRKEY; \ +} + +/** + * @brief Set protections enabled in backup mode. + * + * @note Make sure registers appears before call this function, to toggle the + * appearance of the registers using secumodToggleProtectionReg(). + * + * @param[in] sources Bitwise OR of protections. + * + * @api + */ +#define secumodSetBackupModeProtections(sources) { \ + SECUMOD->SECUMOD_BMPR = sources; \ +} + +/** + * @brief Set protections enabled in normal mode. + * + * @note Make sure registers appears before call this function, to toggle the + * appearance of the registers using secumodToggleProtectionReg(). + * + * @param[in] sources Bitwise OR of protections. + * + * @api + */ +#define secumodSetNormalModeProtections(sources) { \ + SECUMOD->SECUMOD_NMPR = sources; \ + if (SECUMOD->SECUMOD_NMPR != sources) { \ + secumodToggleProtectionReg(); \ + SECUMOD->SECUMOD_NMPR = sources; \ + } \ +} + +/** + * @brief Set protection sources which can cause wake up signal generated. + * + * @param[in] sources Bitwise OR of protection sources. + * + * @api + */ +#define secumodSetWakeupProtections(sources) { \ + SECUMOD->SECUMOD_WKPR = sources; \ +} + +/** + * @brief Wait availability status of memory. + * + * @api + */ +#define secumodMemReady() { \ + while (!(SECUMOD->SECUMOD_RAMRDY & SECUMOD_RAMRDY_READY)); \ +} + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ +extern SECDriver SECD0; + +#ifdef __cplusplus +extern "C" { +#endif + void secInit(void); + void secObjectInit(SECDriver *secp); + void secStart(SECDriver *secp, const SECConfig *config); + void secStop(SECDriver *secp); + void secSetCallback(SECDriver *secp, uint32_t sources, secumod_callback_t callback); + void secumodSetJtagProtection(bool reset, uint8_t permissions, bool ack); + void secumodDynamicSignaturesTuning(uint16_t period, uint8_t detectionThr, uint8_t resetThr); + void secumodPeriodicAlarm(bool enable); + void secumodSetRamAccessRights(uint32_t region, uint8_t rights); + uint32_t secumodReadInternalMemory(uint8_t *data, uint32_t addr, uint32_t size); + uint32_t secumodWriteInternalMemory(uint8_t *data, uint32_t addr, uint32_t size); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SECUMOD */ + +#endif /* SAMA_SECUMOD_LLD_H */ + +/** @} */ -- cgit v1.2.3