1 /**
2   ******************************************************************************
3   * @file    stm32l4xx_hal_firewall.c
4   * @author  MCD Application Team
5   * @brief   FIREWALL HAL module driver.
6   *          This file provides firmware functions to manage the Firewall
7   *          Peripheral initialization and enabling.
8   *
9   ******************************************************************************
10   * @attention
11   *
12   * Copyright (c) 2017 STMicroelectronics.
13   * All rights reserved.
14   *
15   * This software is licensed under terms that can be found in the LICENSE file
16   * in the root directory of this software component.
17   * If no LICENSE file comes with this software, it is provided AS-IS.
18   *
19   ******************************************************************************
20   @verbatim
21  ===============================================================================
22                         ##### How to use this driver #####
23  ===============================================================================
24   [..]
25     The FIREWALL HAL driver can be used as follows:
26 
27     (#) Declare a FIREWALL_InitTypeDef initialization structure.
28 
29     (#) Resort to HAL_FIREWALL_Config() API to initialize the Firewall
30 
31     (#) Enable the FIREWALL in calling HAL_FIREWALL_EnableFirewall() API
32 
33     (#) To ensure that any code executed outside the protected segment closes the
34         FIREWALL, the user must set the flag FIREWALL_PRE_ARM_SET in calling
35         __HAL_FIREWALL_PREARM_ENABLE() macro if called within a protected code segment
36         or
37         HAL_FIREWALL_EnablePreArmFlag() API if called outside of protected code segment
38         after HAL_FIREWALL_Config() call.
39 
40 
41   @endverbatim
42   ******************************************************************************
43   */
44 
45 /* Includes ------------------------------------------------------------------*/
46 #include "stm32l4xx_hal.h"
47 
48 /** @addtogroup STM32L4xx_HAL_Driver
49   * @{
50   */
51 
52 /** @defgroup FIREWALL FIREWALL
53   * @brief HAL FIREWALL module driver
54   * @{
55   */
56 #ifdef HAL_FIREWALL_MODULE_ENABLED
57 
58 /* Private typedef -----------------------------------------------------------*/
59 /* Private define ------------------------------------------------------------*/
60 /* Private macro -------------------------------------------------------------*/
61 /* Private variables ---------------------------------------------------------*/
62 /* Private function prototypes -----------------------------------------------*/
63 /* Private functions ---------------------------------------------------------*/
64 
65 
66 /** @defgroup FIREWALL_Exported_Functions FIREWALL Exported Functions
67   * @{
68   */
69 
70 /** @defgroup FIREWALL_Exported_Functions_Group1 Initialization Functions
71   * @brief    Initialization and Configuration Functions
72   *
73 @verbatim
74 ===============================================================================
75             ##### Initialization and Configuration functions #####
76  ===============================================================================
77     [..]
78     This subsection provides the functions allowing to initialize the Firewall.
79     Initialization is done by HAL_FIREWALL_Config():
80 
81       (+) Enable the Firewall clock through __HAL_RCC_FIREWALL_CLK_ENABLE() macro.
82 
83       (+) Set the protected code segment address start and length.
84 
85       (+) Set the protected non-volatile and/or volatile data segments
86           address starts and lengths if applicable.
87 
88       (+) Set the volatile data segment execution and sharing status.
89 
90       (+) Length must be set to 0 for an unprotected segment.
91 
92 @endverbatim
93   * @{
94   */
95 
96 /**
97   * @brief Initialize the Firewall according to the FIREWALL_InitTypeDef structure parameters.
98   * @param fw_init: Firewall initialization structure
99   * @note  The API returns HAL_ERROR if the Firewall is already enabled.
100   * @retval HAL status
101   */
HAL_FIREWALL_Config(FIREWALL_InitTypeDef * fw_init)102 HAL_StatusTypeDef HAL_FIREWALL_Config(FIREWALL_InitTypeDef * fw_init)
103 {
104   /* Check the Firewall initialization structure allocation */
105   if(fw_init == NULL)
106   {
107     return HAL_ERROR;
108   }
109 
110   /* Enable Firewall clock */
111   __HAL_RCC_FIREWALL_CLK_ENABLE();
112 
113   /* Make sure that Firewall is not enabled already */
114   if (__HAL_FIREWALL_IS_ENABLED() != RESET)
115   {
116     return HAL_ERROR;
117   }
118 
119   /* Check Firewall configuration addresses and lengths when segment is protected */
120   /* Code segment */
121   if (fw_init->CodeSegmentLength != 0U)
122   {
123     assert_param(IS_FIREWALL_CODE_SEGMENT_ADDRESS(fw_init->CodeSegmentStartAddress));
124     assert_param(IS_FIREWALL_CODE_SEGMENT_LENGTH(fw_init->CodeSegmentStartAddress, fw_init->CodeSegmentLength));
125     /* Make sure that NonVDataSegmentLength is properly set to prevent code segment access */
126     if (fw_init->NonVDataSegmentLength < 0x100U)
127     {
128       return HAL_ERROR;
129     }
130   }
131   /* Non volatile data segment */
132   if (fw_init->NonVDataSegmentLength != 0U)
133   {
134     assert_param(IS_FIREWALL_NONVOLATILEDATA_SEGMENT_ADDRESS(fw_init->NonVDataSegmentStartAddress));
135     assert_param(IS_FIREWALL_NONVOLATILEDATA_SEGMENT_LENGTH(fw_init->NonVDataSegmentStartAddress, fw_init->NonVDataSegmentLength));
136   }
137   /* Volatile data segment */
138   if (fw_init->VDataSegmentLength != 0U)
139   {
140     assert_param(IS_FIREWALL_VOLATILEDATA_SEGMENT_ADDRESS(fw_init->VDataSegmentStartAddress));
141     assert_param(IS_FIREWALL_VOLATILEDATA_SEGMENT_LENGTH(fw_init->VDataSegmentStartAddress, fw_init->VDataSegmentLength));
142   }
143 
144   /* Check Firewall Configuration Register parameters */
145   assert_param(IS_FIREWALL_VOLATILEDATA_EXECUTE(fw_init->VolatileDataExecution));
146   assert_param(IS_FIREWALL_VOLATILEDATA_SHARE(fw_init->VolatileDataShared));
147 
148 
149    /* Configuration */
150 
151   /* Protected code segment start address configuration */
152   WRITE_REG(FIREWALL->CSSA, (FW_CSSA_ADD & fw_init->CodeSegmentStartAddress));
153 	/* Protected code segment length configuration */
154   WRITE_REG(FIREWALL->CSL, (FW_CSL_LENG & fw_init->CodeSegmentLength));
155 
156   /* Protected non volatile data segment start address configuration */
157   WRITE_REG(FIREWALL->NVDSSA, (FW_NVDSSA_ADD & fw_init->NonVDataSegmentStartAddress));
158 	/* Protected non volatile data segment length configuration */
159   WRITE_REG(FIREWALL->NVDSL, (FW_NVDSL_LENG & fw_init->NonVDataSegmentLength));
160 
161   /* Protected volatile data segment start address configuration */
162   WRITE_REG(FIREWALL->VDSSA, (FW_VDSSA_ADD & fw_init->VDataSegmentStartAddress));
163 	/* Protected volatile data segment length configuration */
164   WRITE_REG(FIREWALL->VDSL, (FW_VDSL_LENG & fw_init->VDataSegmentLength));
165 
166   /* Set Firewall Configuration Register VDE and VDS bits
167      (volatile data execution and shared configuration) */
168   MODIFY_REG(FIREWALL->CR, FW_CR_VDS|FW_CR_VDE, fw_init->VolatileDataExecution|fw_init->VolatileDataShared);
169 
170   return HAL_OK;
171 }
172 
173 /**
174   * @brief Retrieve the Firewall configuration.
175   * @param fw_config: Firewall configuration, type is same as initialization structure
176   * @note This API can't be executed inside a code area protected by the Firewall
177   *       when the Firewall is enabled
178   * @note If NVDSL register is different from 0, that is, if the non volatile data segment
179   *       is defined, this API can't be executed when the Firewall is enabled.
180   * @note User should resort to __HAL_FIREWALL_GET_PREARM() macro to retrieve FPA bit status
181   * @retval None
182   */
HAL_FIREWALL_GetConfig(FIREWALL_InitTypeDef * fw_config)183 void HAL_FIREWALL_GetConfig(FIREWALL_InitTypeDef * fw_config)
184 {
185 
186   /* Enable Firewall clock, in case no Firewall configuration has been carried
187      out up to this point */
188   __HAL_RCC_FIREWALL_CLK_ENABLE();
189 
190   /* Retrieve code segment protection setting */
191   fw_config->CodeSegmentStartAddress = (READ_REG(FIREWALL->CSSA) & FW_CSSA_ADD);
192   fw_config->CodeSegmentLength = (READ_REG(FIREWALL->CSL) & FW_CSL_LENG);
193 
194   /* Retrieve non volatile data segment protection setting */
195   fw_config->NonVDataSegmentStartAddress = (READ_REG(FIREWALL->NVDSSA) & FW_NVDSSA_ADD);
196   fw_config->NonVDataSegmentLength = (READ_REG(FIREWALL->NVDSL) & FW_NVDSL_LENG);
197 
198   /* Retrieve volatile data segment protection setting */
199   fw_config->VDataSegmentStartAddress = (READ_REG(FIREWALL->VDSSA) & FW_VDSSA_ADD);
200   fw_config->VDataSegmentLength = (READ_REG(FIREWALL->VDSL) & FW_VDSL_LENG);
201 
202   /* Retrieve volatile data execution setting */
203   fw_config->VolatileDataExecution = (READ_REG(FIREWALL->CR) & FW_CR_VDE);
204 
205   /* Retrieve volatile data shared setting */
206   fw_config->VolatileDataShared = (READ_REG(FIREWALL->CR) & FW_CR_VDS);
207 
208   return;
209 }
210 
211 
212 
213 /**
214   * @brief Enable FIREWALL.
215   * @note Firewall is enabled in clearing FWDIS bit of SYSCFG CFGR1 register.
216   *       Once enabled, the Firewall cannot be disabled by software. Only a
217   *       system reset can set again FWDIS bit.
218   * @retval None
219   */
HAL_FIREWALL_EnableFirewall(void)220 void HAL_FIREWALL_EnableFirewall(void)
221 {
222   /* Clears FWDIS bit of SYSCFG CFGR1 register */
223   CLEAR_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FWDIS);
224 
225 }
226 
227 /**
228   * @brief Enable FIREWALL pre arm.
229   * @note When FPA bit is set, any code executed outside the protected segment
230   *       will close the Firewall.
231   * @note This API provides the same service as __HAL_FIREWALL_PREARM_ENABLE() macro
232   *       but can't be executed inside a code area protected by the Firewall.
233   * @note When the Firewall is disabled, user can resort to HAL_FIREWALL_EnablePreArmFlag() API any time.
234   * @note When the Firewall is enabled and NVDSL register is equal to 0 (that is,
235   *       when the non volatile data segment is not defined),
236   *        **  this API can be executed when the Firewall is closed
237   *        **  when the Firewall is opened, user should resort to
238   *            __HAL_FIREWALL_PREARM_ENABLE() macro instead
239   * @note When the Firewall is enabled and  NVDSL register is different from 0
240   *       (that is, when the non volatile data segment is defined)
241   *       **  FW_CR register can be accessed only when the Firewall is opened:
242   *           user should resort to  __HAL_FIREWALL_PREARM_ENABLE() macro instead.
243   * @retval None
244   */
HAL_FIREWALL_EnablePreArmFlag(void)245 void HAL_FIREWALL_EnablePreArmFlag(void)
246 {
247   /* Set FPA bit */
248   SET_BIT(FIREWALL->CR, FW_CR_FPA);
249 }
250 
251 
252 /**
253   * @brief Disable FIREWALL pre arm.
254   * @note When FPA bit is reset, any code executed outside the protected segment
255   *       when the Firewall is opened will generate a system reset.
256   * @note This API provides the same service as __HAL_FIREWALL_PREARM_DISABLE() macro
257   *       but can't be executed inside a code area protected by the Firewall.
258   * @note When the Firewall is disabled, user can resort to HAL_FIREWALL_EnablePreArmFlag() API any time.
259   * @note When the Firewall is enabled and NVDSL register is equal to 0 (that is,
260   *       when the non volatile data segment is not defined),
261   *        **  this API can be executed when the Firewall is closed
262   *        **  when the Firewall is opened, user should resort to
263   *            __HAL_FIREWALL_PREARM_DISABLE() macro instead
264   * @note When the Firewall is enabled and  NVDSL register is different from 0
265   *       (that is, when the non volatile data segment is defined)
266   *       **  FW_CR register can be accessed only when the Firewall is opened:
267   *           user should resort to  __HAL_FIREWALL_PREARM_DISABLE() macro instead.
268 
269   * @retval None
270   */
HAL_FIREWALL_DisablePreArmFlag(void)271 void HAL_FIREWALL_DisablePreArmFlag(void)
272 {
273   /* Clear FPA bit */
274   CLEAR_BIT(FIREWALL->CR, FW_CR_FPA);
275 }
276 
277 /**
278   * @}
279   */
280 
281 /**
282   * @}
283   */
284 
285 #endif /* HAL_FIREWALL_MODULE_ENABLED */
286 /**
287   * @}
288   */
289 
290 /**
291   * @}
292   */
293