1 /*
2  * Copyright 2019-2021 NXP
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_otfad.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.otfad"
18 #endif
19 
20 /*******************************************************************************
21  * Prototypes
22  ******************************************************************************/
23 
24 /*******************************************************************************
25  * Variables
26  ******************************************************************************/
27 
28 /*******************************************************************************
29  * Code
30  ******************************************************************************/
31 /*!
32  * brief OTFAD module get default configuration.
33  *
34  * param config configuration.
35  */
OTFAD_GetDefaultConfig(otfad_config_t * config)36 void OTFAD_GetDefaultConfig(otfad_config_t *config)
37 {
38     assert(config != NULL);
39 
40     /* Including OTFAD operate mode, IRQ eable, key blob and restricted register access */
41 #if defined(FSL_FEATURE_OTFAD_HAS_HAS_IRQ_ENABLE) && (FSL_FEATURE_OTFAD_HAS_HAS_IRQ_ENABLE > 0)
42     config->enableIntRequest = false;
43 #endif /* FSL_FEATURE_OTFAD_HAS_HAS_IRQ_ENABLE */
44 #if defined(FSL_FEATURE_OTFAD_HAS_FORCE_ERR) && (FSL_FEATURE_OTFAD_HAS_FORCE_ERR > 0)
45     config->forceError = false;
46 #endif /* FSL_FEATURE_OTFAD_HAS_FORCE_ERR */
47     config->forceSVM = false;
48     config->forceLDM = false;
49 
50     config->restrictedRegAccess = false;
51 
52 #if defined(FSL_FEATURE_OTFAD_HAS_KEYBLOB_PROCESSING) && (FSL_FEATURE_OTFAD_HAS_KEYBLOB_PROCESSING > 0)
53     /* Start key blob processing */
54     config->startKeyBlobProcessing = false;
55     config->keyBlobProcess         = false;
56     config->keyBlobScramble        = false;
57 #endif /* FSL_FEATURE_OTFAD_HAS_KEYBLOB_PROCESSING */
58 
59     /* Global OTFAD enable */
60     config->enableOTFAD = false;
61 }
62 
63 /*!
64  * brief OTFAD module initialization function, this function need to put into ram for keyblob process.
65  *
66  * param base OTFAD base address.
67  */
AT_QUICKACCESS_SECTION_CODE(void OTFAD_Init (OTFAD_Type * base,const otfad_config_t * config))68 AT_QUICKACCESS_SECTION_CODE(void OTFAD_Init(OTFAD_Type *base, const otfad_config_t *config))
69 {
70     assert(config != NULL);
71 
72     /* No independent clock and it is bind with flexspi clock,
73        so it need to enable clock for flexspi firstly with initialization. */
74 
75     uint32_t temp   = 0U;
76     uint32_t status = 0U;
77 
78     /* Set OTFAD operate mode, IRQ eable, key blob and restricted register access */
79     temp = OTFAD_CR_FLDM(config->forceLDM) |
80 #if defined(FSL_FEATURE_OTFAD_HAS_HAS_IRQ_ENABLE) && (FSL_FEATURE_OTFAD_HAS_HAS_IRQ_ENABLE > 0)
81            OTFAD_CR_IRQE(config->enableIntRequest) |
82 #endif /* FSL_FEATURE_OTFAD_HAS_HAS_IRQ_ENABLE */
83 #if defined(FSL_FEATURE_OTFAD_HAS_FORCE_ERR) && (FSL_FEATURE_OTFAD_HAS_FORCE_ERR > 0)
84            OTFAD_CR_FERR(config->forceError) |
85 #endif /* FSL_FEATURE_OTFAD_HAS_FORCE_ERR */
86 #if defined(FSL_FEATURE_OTFAD_HAS_SVM_MODE) && FSL_FEATURE_OTFAD_HAS_SVM_MODE
87            OTFAD_CR_FSVM(config->forceSVM) |
88 #endif /* FSL_FEATURE_OTFAD_HAS_SVM_MODE */
89 #if defined(FSL_FEATURE_OTFAD_HAS_KEYBLOB_PROCESSING) && (FSL_FEATURE_OTFAD_HAS_KEYBLOB_PROCESSING > 0)
90            OTFAD_CR_KBSE(config->keyBlobScramble) | OTFAD_CR_KBPE(config->keyBlobProcess) |
91 #endif /* FSL_FEATURE_OTFAD_HAS_KEYBLOB_PROCESSING */
92            OTFAD_CR_RRAE(config->restrictedRegAccess);
93 
94     /* Enable global OTFAD operation */
95     temp |= OTFAD_CR_GE(config->enableOTFAD);
96 
97     /* Wait for AHB bus idle, otherwise the keyblob process will fail */
98     status = ((FLEXSPI_Type *)config->flexspiBaseAddr)->STS0;
99     while (!(((status & FLEXSPI_STS0_ARBIDLE_MASK) != 0UL) && ((status & FLEXSPI_STS0_SEQIDLE_MASK) != 0UL)))
100     {
101         status = ((FLEXSPI_Type *)config->flexspiBaseAddr)->STS0;
102     }
103 
104 #if defined(FSL_FEATURE_OTFAD_HAS_KEYBLOB_PROCESSING) && (FSL_FEATURE_OTFAD_HAS_KEYBLOB_PROCESSING > 0)
105     /* Start key blob processing, and software set SKBP only once after a hard reset */
106     if (config->startKeyBlobProcessing == true)
107     {
108         temp |= OTFAD_CR_SKBP(config->startKeyBlobProcessing);
109     }
110 #endif /* FSL_FEATURE_OTFAD_HAS_KEYBLOB_PROCESSING */
111 
112     base->CR |= temp;
113 
114 #if defined(FSL_FEATURE_OTFAD_HAS_KEYBLOB_PROCESSING) && (FSL_FEATURE_OTFAD_HAS_KEYBLOB_PROCESSING > 0)
115     /* Check key blob precessing done if enabled */
116     if (config->keyBlobProcess == true)
117     {
118         while (0U == ((base->SR & OTFAD_SR_KBD_MASK) >> OTFAD_SR_KBD_SHIFT))
119         {
120             ; /* Intentional empty */
121         }
122     }
123 #endif /* FSL_FEATURE_OTFAD_HAS_KEYBLOB_PROCESSING */
124 }
125 
126 /*!
127  * brief Deinitializes the OTFAD.
128  *
129  */
AT_QUICKACCESS_SECTION_CODE(void OTFAD_Deinit (OTFAD_Type * base))130 AT_QUICKACCESS_SECTION_CODE(void OTFAD_Deinit(OTFAD_Type *base))
131 {
132     /* Disable global OTFAD operation */
133     base->CR &= ~OTFAD_CR_GE(1U);
134 }
135 
OTFAD_SetEncryptionConfig(OTFAD_Type * base,const otfad_encryption_config_t * config)136 status_t OTFAD_SetEncryptionConfig(OTFAD_Type *base, const otfad_encryption_config_t *config)
137 {
138     assert(config != NULL);
139 
140     status_t status             = kStatus_Success;
141     uint32_t temp               = 0U;
142     uint32_t startAddr          = config->startAddr;
143     uint32_t endAddr            = config->endAddr;
144     const uint32_t *tempKey     = config->key;
145     const uint32_t *tempCounter = config->counter;
146     uint8_t contextIndex        = config->contextIndex;
147     uint8_t regAccessMode       = 0U;
148 
149     /* Get restricted register access mode */
150     regAccessMode = (uint8_t)((base->SR & OTFAD_SR_RRAM_MASK) >> OTFAD_SR_RRAM_SHIFT);
151 
152     if (regAccessMode == 0U)
153     {
154         /* Set context region */
155         if (startAddr <= endAddr)
156         {
157             /* Address is aligned with 1KBytes */
158             startAddr = (startAddr & OTFAD_RGD_W0_SRTADDR_MASK) >> OTFAD_RGD_W0_SRTADDR_SHIFT;
159             endAddr   = (endAddr & OTFAD_RGD_W1_ENDADDR_MASK) >> OTFAD_RGD_W1_ENDADDR_SHIFT;
160 
161             temp |= OTFAD_RGD_W1_ENDADDR(endAddr) | OTFAD_RGD_W1_RO(config->readOnly) |
162                     OTFAD_RGD_W1_ADE(config->AESdecryption) | OTFAD_RGD_W1_VLD(config->valid);
163 
164             /* Set context n start address  */
165             base->CTX[contextIndex].RGD_W0 = OTFAD_RGD_W0_SRTADDR(startAddr);
166             /* Set context n end address and enable context n AES decryption */
167             base->CTX[contextIndex].RGD_W1 = temp;
168         }
169         else
170         {
171             status = kStatus_OTFAD_AddressError;
172         }
173 
174         /* Set encryption key */
175         base->CTX[contextIndex].KEY[0] = tempKey[0];
176         base->CTX[contextIndex].KEY[1] = tempKey[1];
177         base->CTX[contextIndex].KEY[2] = tempKey[2];
178         base->CTX[contextIndex].KEY[3] = tempKey[3];
179 
180         /* Set encryption counter */
181         base->CTX[contextIndex].CTR[0] = tempCounter[0];
182         base->CTX[contextIndex].CTR[1] = tempCounter[1];
183     }
184     else
185     {
186         /* Restricted register mode, access to these registers is treated as read-as-zero, write-ignored */
187         status = kStatus_OTFAD_ResRegAccessMode;
188     }
189 
190     return status;
191 }
192 
OTFAD_GetEncryptionConfig(OTFAD_Type * base,otfad_encryption_config_t * config)193 status_t OTFAD_GetEncryptionConfig(OTFAD_Type *base, otfad_encryption_config_t *config)
194 {
195     assert(config != NULL);
196 
197     status_t status       = kStatus_Success;
198     uint8_t regAccessMode = 0U;
199 
200     /* Get restricted register access mode */
201     regAccessMode = (uint8_t)((base->SR & OTFAD_SR_RRAM_MASK) >> OTFAD_SR_RRAM_SHIFT);
202 
203     if (regAccessMode == 0U)
204     {
205         config->key[0] = base->CTX[config->contextIndex].KEY[0];
206         config->key[1] = base->CTX[config->contextIndex].KEY[1];
207         config->key[2] = base->CTX[config->contextIndex].KEY[2];
208         config->key[3] = base->CTX[config->contextIndex].KEY[3];
209 
210         config->counter[0] = base->CTX[config->contextIndex].CTR[0];
211         config->counter[1] = base->CTX[config->contextIndex].CTR[1];
212 
213         config->startAddr =
214             (base->CTX[config->contextIndex].RGD_W0 & OTFAD_RGD_W0_SRTADDR_MASK) >> OTFAD_RGD_W0_SRTADDR_SHIFT;
215         config->endAddr =
216             (base->CTX[config->contextIndex].RGD_W1 & OTFAD_RGD_W1_ENDADDR_MASK) >> OTFAD_RGD_W1_ENDADDR_SHIFT;
217     }
218     else
219     {
220         /* Restricted register mode, access to these registers is treated as read-as-zero, write-ignored */
221         status = kStatus_OTFAD_ResRegAccessMode;
222     }
223 
224     return status;
225 }
226 
OTFAD_HitDetermination(OTFAD_Type * base,uint32_t address,uint8_t * contextIndex)227 status_t OTFAD_HitDetermination(OTFAD_Type *base, uint32_t address, uint8_t *contextIndex)
228 {
229     status_t status   = kStatus_Success;
230     bool contextValid = false;
231     uint8_t hitNumber = 0U;
232     uint8_t totalHits = 0U;
233     uint8_t index     = 0U;
234     uint8_t i;
235     uint32_t startAddr;
236     uint32_t endAddr;
237     uint32_t tempAddr;
238 
239     /* Address is aligned with 1KBytes */
240     tempAddr = (address & 0xFFFFFC00U) >> 10U;
241 
242     for (i = 0U; i < OTFAD_RGD_W1_COUNT; i++)
243     {
244         startAddr = (base->CTX[index].RGD_W0 & OTFAD_RGD_W0_SRTADDR_MASK) >> OTFAD_RGD_W0_SRTADDR_SHIFT;
245         endAddr   = (base->CTX[index].RGD_W1 & OTFAD_RGD_W1_ENDADDR_MASK) >> OTFAD_RGD_W1_ENDADDR_SHIFT;
246         contextValid =
247             ((base->CTX[index].RGD_W1 & OTFAD_RGD_W1_VLD_MASK) >> OTFAD_RGD_W1_VLD_SHIFT) == 1U ? true : false;
248 
249         /* Check address hits context n or not */
250         if ((tempAddr >= startAddr) && (tempAddr <= endAddr) && contextValid)
251         {
252             totalHits++;
253             hitNumber = i;
254         }
255 
256         index++;
257     }
258 
259     /* Hit in multiple contexts or no contexts */
260     if (totalHits != 1U)
261     {
262         status = kStatus_OTFAD_RegionOverlap;
263     }
264     /* Hit in single context */
265     else
266     {
267         *contextIndex = hitNumber;
268     }
269 
270     return status;
271 }
272