1 /*
2  * Copyright 2018-2020 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  */
8 
9 #ifndef __FSL_IAP_FFR_H_
10 #define __FSL_IAP_FFR_H_
11 
12 #include "fsl_iap.h"
13 
14 /*!
15  * @addtogroup flash_ifr_driver
16  * @{
17  */
18 
19 /*! @file */
20 
21 /*******************************************************************************
22  * Definitions
23  ******************************************************************************/
24 /*!
25  * @name Flash IFR version
26  * @{
27  */
28 /*! @brief Flash IFR driver version for SDK*/
29 #define FSL_FLASH_IFR_DRIVER_VERSION (MAKE_VERSION(2, 1, 0)) /*!< Version 2.1.0. */
30 /*@}*/
31 
32 /*! @brief Alignment(down) utility. */
33 #if !defined(ALIGN_DOWN)
34 #define ALIGN_DOWN(x, a) ((x) & (uint32_t)(-((int32_t)(a))))
35 #endif
36 
37 /*! @brief Alignment(up) utility. */
38 #if !defined(ALIGN_UP)
39 #define ALIGN_UP(x, a) (-((int32_t)((uint32_t)(-((int32_t)(x))) & (uint32_t)(-((int32_t)(a))))))
40 #endif
41 
42 #define FLASH_FFR_MAX_PAGE_SIZE    (512u)
43 #define FLASH_FFR_HASH_DIGEST_SIZE (32u)
44 #define FLASH_FFR_IV_CODE_SIZE     (52u)
45 
46 /*! @brief flash ffr page offset. */
47 enum _flash_ffr_page_offset
48 {
49     kFfrPageOffset_CFPA         = 0, /*!< Customer In-Field programmed area*/
50     kFfrPageOffset_CFPA_Scratch = 0, /*!< CFPA Scratch page */
51     kFfrPageOffset_CFPA_Cfg     = 1, /*!< CFPA Configuration area (Ping page)*/
52     kFfrPageOffset_CFPA_CfgPong = 2, /*!< Same as CFPA page (Pong page)*/
53 
54     kFfrPageOffset_CMPA     = 3, /*!< Customer Manufacturing programmed area*/
55     kFfrPageOffset_CMPA_Cfg = 3, /*!< CMPA Configuration area (Part of CMPA)*/
56     kFfrPageOffset_CMPA_Key = 4, /*!< Key Store area (Part of CMPA)*/
57 
58     kFfrPageOffset_NMPA        = 7,  /*!< NXP Manufacturing programmed area*/
59     kFfrPageOffset_NMPA_Romcp  = 7,  /*!< ROM patch area (Part of NMPA)*/
60     kFfrPageOffset_NMPA_Repair = 9,  /*!< Repair area (Part of NMPA)*/
61     kFfrPageOffset_NMPA_Cfg    = 15, /*!< NMPA configuration area (Part of NMPA)*/
62     kFfrPageOffset_NMPA_End    = 16, /*!< Reserved (Part of NMPA)*/
63 };
64 
65 /*! @brief flash ffr page number. */
66 enum _flash_ffr_page_num
67 {
68     kFfrPageNum_CFPA = 3,  /*!< Customer In-Field programmed area*/
69     kFfrPageNum_CMPA = 4,  /*!< Customer Manufacturing programmed area*/
70     kFfrPageNum_NMPA = 10, /*!< NXP Manufacturing programmed area*/
71 
72     kFfrPageNum_CMPA_Cfg   = 1,
73     kFfrPageNum_CMPA_Key   = 3,
74     kFfrPageNum_NMPA_Romcp = 2,
75 
76     kFfrPageNum_SpecArea = kFfrPageNum_CFPA + kFfrPageNum_CMPA,
77     kFfrPageNum_Total    = (kFfrPageNum_CFPA + kFfrPageNum_CMPA + kFfrPageNum_NMPA),
78 };
79 
80 enum _flash_ffr_block_size
81 {
82     kFfrBlockSize_Key            = 52u,
83     kFfrBlockSize_ActivationCode = 1192u,
84 };
85 
86 typedef enum _cfpa_cfg_cmpa_prog_process
87 {
88     kFfrCmpaProgProcess_Pre  = 0x0u,
89     kFfrCmpaProgProcess_Post = 0xFFFFFFFFu,
90 } cmpa_prog_process_t;
91 
92 typedef struct _cfpa_cfg_iv_code
93 {
94     uint32_t keycodeHeader;
95     uint8_t reserved[FLASH_FFR_IV_CODE_SIZE];
96 } cfpa_cfg_iv_code_t;
97 
98 typedef struct _cfpa_cfg_info
99 {
100     uint32_t header;                          /*!< [0x000-0x003] */
101     uint32_t version;                         /*!< [0x004-0x007 */
102     uint32_t secureFwVersion;                 /*!< [0x008-0x00b */
103     uint32_t nsFwVersion;                     /*!< [0x00c-0x00f] */
104     uint32_t imageKeyRevoke;                  /*!< [0x010-0x013] */
105     uint8_t reserved0[4];                     /*!< [0x014-0x017] */
106     uint32_t rotkhRevoke;                     /*!< [0x018-0x01b] */
107     uint32_t vendorUsage;                     /*!< [0x01c-0x01f] */
108     uint32_t dcfgNsPin;                       /*!< [0x020-0x013] */
109     uint32_t dcfgNsDflt;                      /*!< [0x024-0x017] */
110     uint32_t enableFaMode;                    /*!< [0x028-0x02b] */
111     uint8_t reserved1[4];                     /*!< [0x02c-0x02f] */
112     cfpa_cfg_iv_code_t ivCodePrinceRegion[3]; /*!< [0x030-0x0d7] */
113     uint8_t reserved2[264];                   /*!< [0x0d8-0x1df] */
114     uint8_t sha256[32];                       /*!< [0x1e0-0x1ff] */
115 } cfpa_cfg_info_t;
116 
117 #define FFR_BOOTCFG_BOOTSPEED_MASK  (0x18U)
118 #define FFR_BOOTCFG_BOOTSPEED_SHIFT (7U)
119 #define FFR_BOOTCFG_BOOTSPEED_48MHZ (0x0U)
120 #define FFR_BOOTCFG_BOOTSPEED_96MHZ (0x1U)
121 
122 #define FFR_USBID_VENDORID_MASK   (0xFFFFU)
123 #define FFR_USBID_VENDORID_SHIFT  (0U)
124 #define FFR_USBID_PRODUCTID_MASK  (0xFFFF0000U)
125 #define FFR_USBID_PRODUCTID_SHIFT (16U)
126 
127 typedef struct _cmpa_cfg_info
128 {
129     uint32_t bootCfg;     /*!< [0x000-0x003] */
130     uint32_t spiFlashCfg; /*!< [0x004-0x007] */
131     struct
132     {
133         uint16_t vid;
134         uint16_t pid;
135     } usbId;                 /*!< [0x008-0x00b] */
136     uint32_t sdioCfg;        /*!< [0x00c-0x00f] */
137     uint32_t dcfgPin;        /*!< [0x010-0x013] */
138     uint32_t dcfgDflt;       /*!< [0x014-0x017] */
139     uint32_t dapVendorUsage; /*!< [0x018-0x01b] */
140     uint32_t secureBootCfg;  /*!< [0x01c-0x01f] */
141     uint32_t princeBaseAddr; /*!< [0x020-0x023] */
142     uint32_t princeSr[3];    /*!< [0x024-0x02f] */
143     uint8_t reserved0[32];   /*!< [0x030-0x04f] */
144     uint32_t rotkh[8];       /*!< [0x050-0x06f] */
145     uint8_t reserved1[368];  /*!< [0x070-0x1df] */
146     uint8_t sha256[32];      /*!< [0x1e0-0x1ff] */
147 } cmpa_cfg_info_t;
148 
149 typedef struct _cmpa_key_store_header
150 {
151     uint32_t header;
152     uint8_t reserved[4];
153 } cmpa_key_store_header_t;
154 
155 #define FFR_SYSTEM_SPEED_CODE_MASK             (0x3U)
156 #define FFR_SYSTEM_SPEED_CODE_SHIFT            (0U)
157 #define FFR_SYSTEM_SPEED_CODE_FRO12MHZ_12MHZ   (0x0U)
158 #define FFR_SYSTEM_SPEED_CODE_FROHF96MHZ_24MHZ (0x1U)
159 #define FFR_SYSTEM_SPEED_CODE_FROHF96MHZ_48MHZ (0x2U)
160 #define FFR_SYSTEM_SPEED_CODE_FROHF96MHZ_96MHZ (0x3U)
161 
162 #define FFR_PERIPHERALCFG_PERI_MASK    (0x7FFFFFFFU)
163 #define FFR_PERIPHERALCFG_PERI_SHIFT   (0U)
164 #define FFR_PERIPHERALCFG_COREEN_MASK  (0x10000000U)
165 #define FFR_PERIPHERALCFG_COREEN_SHIFT (31U)
166 
167 typedef struct _nmpa_cfg_info
168 {
169     uint16_t fro32kCfg;   /*!< [0x000-0x001] */
170     uint8_t reserved0[6]; /*!< [0x002-0x007] */
171     uint8_t sysCfg;       /*!< [0x008-0x008] */
172     uint8_t reserved1[7]; /*!< [0x009-0x00f] */
173     struct
174     {
175         uint32_t data;
176         uint32_t reserved[3];
177     } GpoInitData[3];              /*!< [0x010-0x03f] */
178     uint32_t GpoDataChecksum[4];   /*!< [0x040-0x04f] */
179     uint32_t finalTestBatchId[4];  /*!< [0x050-0x05f] */
180     uint32_t deviceType;           /*!< [0x060-0x063] */
181     uint32_t finalTestProgVersion; /*!< [0x064-0x067] */
182     uint32_t finalTestDate;        /*!< [0x068-0x06b] */
183     uint32_t finalTestTime;        /*!< [0x06c-0x06f] */
184     uint32_t uuid[4];              /*!< [0x070-0x07f] */
185     uint8_t reserved2[32];         /*!< [0x080-0x09f] */
186     uint32_t peripheralCfg;        /*!< [0x0a0-0x0a3] */
187     uint32_t ramSizeCfg;           /*!< [0x0a4-0x0a7] */
188     uint32_t flashSizeCfg;         /*!< [0x0a8-0x0ab] */
189     uint8_t reserved3[36];         /*!< [0x0ac-0x0cf] */
190     uint8_t fro1mCfg;              /*!< [0x0d0-0x0d0] */
191     uint8_t reserved4[15];         /*!< [0x0d1-0x0df] */
192     uint32_t dcdc[4];              /*!< [0x0e0-0x0ef] */
193     uint32_t bod;                  /*!< [0x0f0-0x0f3] */
194     uint8_t reserved5[12];         /*!< [0x0f4-0x0ff] */
195     uint8_t calcHashReserved[192]; /*!< [0x100-0x1bf] */
196     uint8_t sha256[32];            /*!< [0x1c0-0x1df] */
197     uint32_t ecidBackup[4];        /*!< [0x1e0-0x1ef] */
198     uint32_t pageChecksum[4];      /*!< [0x1f0-0x1ff] */
199 } nmpa_cfg_info_t;
200 
201 typedef struct _ffr_key_store
202 {
203     uint8_t reserved[3][FLASH_FFR_MAX_PAGE_SIZE];
204 } ffr_key_store_t;
205 
206 typedef enum _ffr_key_type
207 {
208     kFFR_KeyTypeSbkek         = 0x00U,
209     kFFR_KeyTypeUser          = 0x01U,
210     kFFR_KeyTypeUds           = 0x02U,
211     kFFR_KeyTypePrinceRegion0 = 0x03U,
212     kFFR_KeyTypePrinceRegion1 = 0x04U,
213     kFFR_KeyTypePrinceRegion2 = 0x05U,
214 } ffr_key_type_t;
215 
216 typedef enum _ffr_bank_type
217 {
218     kFFR_BankTypeBank0_NMPA = 0x00U,
219     kFFR_BankTypeBank1_CMPA = 0x01U,
220     kFFR_BankTypeBank2_CFPA = 0x02U
221 } ffr_bank_type_t;
222 
223 /*******************************************************************************
224  * API
225  ******************************************************************************/
226 
227 #if defined(__cplusplus)
228 extern "C" {
229 #endif
230 
231 /*!
232  * @name FFR APIs
233  * @{
234  */
235 
236 /*!
237  * @brief Initializes the global FFR properties structure members.
238  *
239  * @param config A pointer to the storage for the driver runtime state.
240  *
241  * @retval #kStatus_FLASH_Success API was executed successfully.
242  * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
243  */
244 status_t FFR_Init(flash_config_t *config);
245 
246 /*!
247  * @brief Enable firewall for all flash banks.
248  *
249  * CFPA, CMPA, and NMPA flash areas region will be locked, After this function executed;
250  * Unless the board is reset again.
251  *
252  * @param config A pointer to the storage for the driver runtime state.
253  *
254  * @retval #kStatus_FLASH_Success An invalid argument is provided.
255  * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
256  */
257 status_t FFR_Lock_All(flash_config_t *config);
258 
259 /*!
260  * @brief APIs to access CFPA pages
261  *
262  * This routine will erase CFPA and program the CFPA page with passed data.
263  *
264  * @param config A pointer to the storage for the driver runtime state.
265  * @param page_data A pointer to the source buffer of data that is to be programmed
266  *        into the CFPA.
267  * @param valid_len The length, given in bytes, to be programmed.
268  *
269  * @retval #kStatus_FLASH_Success The desire page-data were programed successfully into CFPA.
270  * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
271  * @retval kStatus_FTFx_AddressError Address is out of range.
272  * @retval #kStatus_FLASH_FfrBankIsLocked The CFPA was locked.
273  * @retval #kStatus_FLASH_OutOfDateCfpaPage It is not newest CFPA page.
274  */
275 status_t FFR_InfieldPageWrite(flash_config_t *config, uint8_t *page_data, uint32_t valid_len);
276 
277 /*!
278  * @brief APIs to access CFPA pages
279  *
280  * Generic read function, used by customer to read data stored in 'Customer In-field Page'.
281  *
282  * @param config A pointer to the storage for the driver runtime state.
283  * @param pData A pointer to the dest buffer of data that is to be read from 'Customer In-field Page'.
284  * @param offset An offset from the 'Customer In-field Page' start address.
285  * @param len The length, given in bytes, to be read.
286  *
287  * @retval #kStatus_FLASH_Success Get data from 'Customer In-field Page'.
288  * @retval #kStatus_FLASH_InvalidArgument An invalid argument is provided.
289  * @retval kStatus_FTFx_AddressError Address is out of range.
290  * @retval #kStatus_FLASH_CommandFailure access error.
291  */
292 status_t FFR_GetCustomerInfieldData(flash_config_t *config, uint8_t *pData, uint32_t offset, uint32_t len);
293 
294 /*!
295  * @brief APIs to access CMPA pages
296  *
297  * This routine will erase "customer factory page" and program the page with passed data.
298  * If 'seal_part' parameter is TRUE then the routine will compute SHA256 hash of
299  * the page contents and then programs the pages.
300  * 1.During development customer code uses this API with 'seal_part' set to FALSE.
301  * 2.During manufacturing this parameter should be set to TRUE to seal the part
302  * from further modifications
303  * 3.This routine checks if the page is sealed or not. A page is said to be sealed if
304  * the SHA256 value in the page has non-zero value. On boot ROM locks the firewall for
305  * the region if hash is programmed anyways. So, write/erase commands will fail eventually.
306  *
307  * @param config A pointer to the storage for the driver runtime state.
308  * @param page_data A pointer to the source buffer of data that is to be programmed
309  *        into the "customer factory page".
310  * @param seal_part Set fasle for During development customer code.
311  *
312  * @retval #kStatus_FLASH_Success The desire page-data were programed successfully into CMPA.
313  * @retval #kStatus_FLASH_InvalidArgument Parameter is not aligned with the specified baseline.
314  * @retval kStatus_FTFx_AddressError Address is out of range.
315  * @retval #kStatus_FLASH_CommandFailure access error.
316  */
317 status_t FFR_CustFactoryPageWrite(flash_config_t *config, uint8_t *page_data, bool seal_part);
318 
319 /*!
320  * @brief APIs to access CMPA page
321  *
322  * Read data stored in 'Customer Factory CFG Page'.
323  *
324  * @param config A pointer to the storage for the driver runtime state.
325  * @param pData A pointer to the dest buffer of data that is to be read
326  *            from the Customer Factory CFG Page.
327  * @param offset Address offset relative to the CMPA area.
328  * @param len The length, given in bytes to be read.
329  *
330  * @retval #kStatus_FLASH_Success Get data from 'Customer Factory CFG Page'.
331  * @retval #kStatus_FLASH_InvalidArgument Parameter is not aligned with the specified baseline.
332  * @retval kStatus_FTFx_AddressError Address is out of range.
333  * @retval #kStatus_FLASH_CommandFailure access error.
334  */
335 status_t FFR_GetCustomerData(flash_config_t *config, uint8_t *pData, uint32_t offset, uint32_t len);
336 
337 /*!
338  * @brief APIs to access CMPA page
339  *
340  * 1.SW should use this API routine to get the UUID of the chip.
341  * 2.Calling routine should pass a pointer to buffer which can hold 128-bit value.
342  */
343 status_t FFR_GetUUID(flash_config_t *config, uint8_t *uuid);
344 
345 /*!
346  * @brief This routine writes the 3 pages allocated for Key store data,
347  *
348  * 1.Used during manufacturing. Should write pages when 'customer factory page' is not in sealed state.
349  * 2.Optional routines to set individual data members (activation code, key codes etc) to construct
350  * the key store structure in RAM before committing it to IFR/FFR.
351  *
352  * @param config A pointer to the storage for the driver runtime state.
353  * @param pKeyStore A Pointer to the 3 pages allocated for Key store data.
354  *        that will be written to 'customer factory page'.
355  *
356  * @retval #kStatus_FLASH_Success The key were programed successfully into FFR.
357  * @retval #kStatus_FLASH_InvalidArgument Parameter is not aligned with the specified baseline.
358  * @retval kStatus_FTFx_AddressError Address is out of range.
359  * @retval #kStatus_FLASH_CommandFailure access error.
360  */
361 status_t FFR_KeystoreWrite(flash_config_t *config, ffr_key_store_t *pKeyStore);
362 
363 /*!
364  * @brief Get/Read Key store code routines
365  *
366  * 1. Calling code should pass buffer pointer which can hold activation code 1192 bytes.
367  * 2. Check if flash aperture is small or regular and read the data appropriately.
368  */
369 status_t FFR_KeystoreGetAC(flash_config_t *config, uint8_t *pActivationCode);
370 
371 /*!
372  * @brief Get/Read Key store code routines
373  *
374  * 1. Calling code should pass buffer pointer which can hold key code 52 bytes.
375  * 2. Check if flash aperture is small or regular and read the data appropriately.
376  * 3. keyIndex specifies which key code is read.
377  */
378 status_t FFR_KeystoreGetKC(flash_config_t *config, uint8_t *pKeyCode, ffr_key_type_t keyIndex);
379 
380 /*@}*/
381 
382 #ifdef __cplusplus
383 }
384 #endif
385 
386 /*@}*/
387 
388 #endif /*! __FSL_FLASH_FFR_H_ */
389