]> begriffs open source - freertos/blob - portable/IAR/ARM_CM33/secure/secure_context.c
Add SPDX-License-Identifier: MIT to MIT licensed files.
[freertos] / portable / IAR / ARM_CM33 / secure / secure_context.c
1 /*\r
2  * FreeRTOS Kernel <DEVELOPMENT BRANCH>\r
3  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
8  * this software and associated documentation files (the "Software"), to deal in\r
9  * the Software without restriction, including without limitation the rights to\r
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
11  * the Software, and to permit persons to whom the Software is furnished to do so,\r
12  * subject to the following conditions:\r
13  *\r
14  * The above copyright notice and this permission notice shall be included in all\r
15  * copies or substantial portions of the Software.\r
16  *\r
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
19  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
20  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
23  *\r
24  * https://www.FreeRTOS.org\r
25  * https://github.com/FreeRTOS\r
26  *\r
27  */\r
28 \r
29 /* Secure context includes. */\r
30 #include "secure_context.h"\r
31 \r
32 /* Secure heap includes. */\r
33 #include "secure_heap.h"\r
34 \r
35 /* Secure port macros. */\r
36 #include "secure_port_macros.h"\r
37 \r
38 /**\r
39  * @brief CONTROL value for privileged tasks.\r
40  *\r
41  * Bit[0] - 0 --> Thread mode is privileged.\r
42  * Bit[1] - 1 --> Thread mode uses PSP.\r
43  */\r
44 #define securecontextCONTROL_VALUE_PRIVILEGED      0x02\r
45 \r
46 /**\r
47  * @brief CONTROL value for un-privileged tasks.\r
48  *\r
49  * Bit[0] - 1 --> Thread mode is un-privileged.\r
50  * Bit[1] - 1 --> Thread mode uses PSP.\r
51  */\r
52 #define securecontextCONTROL_VALUE_UNPRIVILEGED    0x03\r
53 /*-----------------------------------------------------------*/\r
54 \r
55 /**\r
56  * @brief Structure to represent secure context.\r
57  *\r
58  * @note Since stack grows down, pucStackStart is the highest address while\r
59  * pucStackLimit is the first addess of the allocated memory.\r
60  */\r
61 typedef struct SecureContext\r
62 {\r
63     uint8_t * pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */\r
64     uint8_t * pucStackLimit;          /**< Last location of the stack memory (PSPLIM). */\r
65     uint8_t * pucStackStart;          /**< First location of the stack memory. */\r
66 } SecureContext_t;\r
67 /*-----------------------------------------------------------*/\r
68 \r
69 secureportNON_SECURE_CALLABLE void SecureContext_Init( void )\r
70 {\r
71     uint32_t ulIPSR;\r
72 \r
73     /* Read the Interrupt Program Status Register (IPSR) value. */\r
74     secureportREAD_IPSR( ulIPSR );\r
75 \r
76     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero\r
77      * when the processor is running in the Thread Mode. */\r
78     if( ulIPSR != 0 )\r
79     {\r
80         /* No stack for thread mode until a task's context is loaded. */\r
81         secureportSET_PSPLIM( securecontextNO_STACK );\r
82         secureportSET_PSP( securecontextNO_STACK );\r
83 \r
84         #if ( configENABLE_MPU == 1 )\r
85             {\r
86                 /* Configure thread mode to use PSP and to be unprivileged. */\r
87                 secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED );\r
88             }\r
89         #else /* configENABLE_MPU */\r
90             {\r
91                 /* Configure thread mode to use PSP and to be privileged.. */\r
92                 secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );\r
93             }\r
94         #endif /* configENABLE_MPU */\r
95     }\r
96 }\r
97 /*-----------------------------------------------------------*/\r
98 \r
99 #if ( configENABLE_MPU == 1 )\r
100     secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,\r
101                                                                                        uint32_t ulIsTaskPrivileged )\r
102 #else /* configENABLE_MPU */\r
103     secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize )\r
104 #endif /* configENABLE_MPU */\r
105 {\r
106     uint8_t * pucStackMemory = NULL;\r
107     uint32_t ulIPSR;\r
108     SecureContextHandle_t xSecureContextHandle = NULL;\r
109 \r
110     #if ( configENABLE_MPU == 1 )\r
111         uint32_t * pulCurrentStackPointer = NULL;\r
112     #endif /* configENABLE_MPU */\r
113 \r
114     /* Read the Interrupt Program Status Register (IPSR) value. */\r
115     secureportREAD_IPSR( ulIPSR );\r
116 \r
117     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero\r
118      * when the processor is running in the Thread Mode. */\r
119     if( ulIPSR != 0 )\r
120     {\r
121         /* Allocate the context structure. */\r
122         xSecureContextHandle = ( SecureContextHandle_t ) pvPortMalloc( sizeof( SecureContext_t ) );\r
123 \r
124         if( xSecureContextHandle != NULL )\r
125         {\r
126             /* Allocate the stack space. */\r
127             pucStackMemory = pvPortMalloc( ulSecureStackSize );\r
128 \r
129             if( pucStackMemory != NULL )\r
130             {\r
131                 /* Since stack grows down, the starting point will be the last\r
132                  * location. Note that this location is next to the last\r
133                  * allocated byte because the hardware decrements the stack\r
134                  * pointer before writing i.e. if stack pointer is 0x2, a push\r
135                  * operation will decrement the stack pointer to 0x1 and then\r
136                  * write at 0x1. */\r
137                 xSecureContextHandle->pucStackStart = pucStackMemory + ulSecureStackSize;\r
138 \r
139                 /* The stack cannot go beyond this location. This value is\r
140                  * programmed in the PSPLIM register on context switch.*/\r
141                 xSecureContextHandle->pucStackLimit = pucStackMemory;\r
142 \r
143                 #if ( configENABLE_MPU == 1 )\r
144                     {\r
145                         /* Store the correct CONTROL value for the task on the stack.\r
146                          * This value is programmed in the CONTROL register on\r
147                          * context switch. */\r
148                         pulCurrentStackPointer = ( uint32_t * ) xSecureContextHandle->pucStackStart;\r
149                         pulCurrentStackPointer--;\r
150 \r
151                         if( ulIsTaskPrivileged )\r
152                         {\r
153                             *( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;\r
154                         }\r
155                         else\r
156                         {\r
157                             *( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_UNPRIVILEGED;\r
158                         }\r
159 \r
160                         /* Store the current stack pointer. This value is programmed in\r
161                          * the PSP register on context switch. */\r
162                         xSecureContextHandle->pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;\r
163                     }\r
164                 #else /* configENABLE_MPU */\r
165                     {\r
166                         /* Current SP is set to the starting of the stack. This\r
167                          * value programmed in the PSP register on context switch. */\r
168                         xSecureContextHandle->pucCurrentStackPointer = xSecureContextHandle->pucStackStart;\r
169                     }\r
170                 #endif /* configENABLE_MPU */\r
171             }\r
172             else\r
173             {\r
174                 /* Free the context to avoid memory leak and make sure to return\r
175                  * NULL to indicate failure. */\r
176                 vPortFree( xSecureContextHandle );\r
177                 xSecureContextHandle = NULL;\r
178             }\r
179         }\r
180     }\r
181 \r
182     return xSecureContextHandle;\r
183 }\r
184 /*-----------------------------------------------------------*/\r
185 \r
186 secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle )\r
187 {\r
188     uint32_t ulIPSR;\r
189 \r
190     /* Read the Interrupt Program Status Register (IPSR) value. */\r
191     secureportREAD_IPSR( ulIPSR );\r
192 \r
193     /* Do nothing if the processor is running in the Thread Mode. IPSR is zero\r
194      * when the processor is running in the Thread Mode. */\r
195     if( ulIPSR != 0 )\r
196     {\r
197         /* Ensure that valid parameters are passed. */\r
198         secureportASSERT( xSecureContextHandle != NULL );\r
199 \r
200         /* Free the stack space. */\r
201         vPortFree( xSecureContextHandle->pucStackLimit );\r
202 \r
203         /* Free the context itself. */\r
204         vPortFree( xSecureContextHandle );\r
205     }\r
206 }\r
207 /*-----------------------------------------------------------*/\r