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