1 /******************************************************************************
2  *
3  *  Copyright 2018-2019,2022 NXP
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 #define LOG_TAG "NxpEseHal"
19 #include "phNxpEse_Spm.h"
20 
21 #include <errno.h>
22 #include <ese_logs.h>
23 #include <fcntl.h>
24 #include <log/log.h>
25 #include <phNxpEsePal.h>
26 #include <phNxpEse_Internal.h>
27 #include <sys/ioctl.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <unistd.h>
31 
32 #include "phNxpEseFeatures.h"
33 
34 /*********************** Global Variables *************************************/
35 
36 static void* pEseDeviceHandle = NULL;
37 #define MAX_ESE_ACCESS_TIME_OUT_MS 2000 /*2 seconds*/
38 
39 /**
40  * \addtogroup SPI_Power_Management
41  *
42  * @{ */
43 /******************************************************************************
44 \section Introduction Introduction
45 
46  * This module provide power request to Pn54x nfc-i2c driver, it checks if
47  * wired access is already granted. It should have access to pn54x drive.
48  * Below are the apis provided by the SPM module.
49  ******************************************************************************/
50 /******************************************************************************
51  * Function         phNxpEse_SPM_Init
52  *
53  * Description      This function opens the nfc i2c driver to manage power
54  *                  and synchronization for ese secure element.
55  *
56  * Returns          On Success ESESTATUS_SUCCESS else proper error code
57  *
58  ******************************************************************************/
phNxpEse_SPM_Init(void * pDevHandle)59 ESESTATUS phNxpEse_SPM_Init(void* pDevHandle) {
60   ESESTATUS status = ESESTATUS_SUCCESS;
61   pEseDeviceHandle = pDevHandle;
62   if (NULL == pEseDeviceHandle) {
63     NXP_LOG_ESE_E("%s : failed, device handle is null", __FUNCTION__);
64     status = ESESTATUS_FAILED;
65   }
66   NXP_LOG_ESE_D("%s : exit status = %d", __FUNCTION__, status);
67 
68   return status;
69 }
70 
71 /******************************************************************************
72  * Function         phNxpEse_SPM_DeInit
73  *
74  * Description      This function closes the nfc i2c driver node.
75  *
76  * Returns          Always returns ESESTATUS_SUCCESS
77  *
78  ******************************************************************************/
phNxpEse_SPM_DeInit(void)79 ESESTATUS phNxpEse_SPM_DeInit(void) {
80   pEseDeviceHandle = NULL;
81   return ESESTATUS_SUCCESS;
82 }
83 
84 /******************************************************************************
85  * Function         phNxpEse_SPM_ConfigPwr
86  *
87  * Description      This function request to the nfc i2c driver
88  *                  to enable/disable power to ese. This api should be called
89  *before
90  *                  sending any apdu to ese/once apdu exchange is done.
91  *
92  * Returns          On Success ESESTATUS_SUCCESS else proper error code
93  *
94  ******************************************************************************/
phNxpEse_SPM_ConfigPwr(spm_power_t arg)95 ESESTATUS phNxpEse_SPM_ConfigPwr(spm_power_t arg) {
96   int32_t ret = -1;
97   ESESTATUS wSpmStatus = ESESTATUS_SUCCESS;
98   spm_state_t current_spm_state = SPM_STATE_INVALID;
99   if (GET_CHIP_OS_VERSION() > OS_VERSION_4_0) {
100     /*None of the IOCTLs valid except SPM_RECOVERY_RESET*/
101     if (arg != SPM_RECOVERY_RESET) {
102       return ESESTATUS_SUCCESS;
103     }
104   }
105   ret = phPalEse_ioctl(phPalEse_e_ChipRst, pEseDeviceHandle, arg);
106   switch (arg) {
107     case SPM_POWER_DISABLE: {
108       if (ret < 0) {
109         NXP_LOG_ESE_E("%s : failed errno = 0x%x", __FUNCTION__, errno);
110         wSpmStatus = ESESTATUS_FAILED;
111       } else {
112         if (phNxpEse_SPM_RelAccess() != ESESTATUS_SUCCESS) {
113           NXP_LOG_ESE_E(" %s phNxpEse_SPM_RelAccess : failed \n", __FUNCTION__);
114         }
115       }
116     } break;
117     case SPM_POWER_ENABLE: {
118       if (ret < 0) {
119         NXP_LOG_ESE_E("%s : failed errno = 0x%x", __FUNCTION__, errno);
120         if (errno == -EBUSY) {
121           wSpmStatus = phNxpEse_SPM_GetState(¤t_spm_state);
122           if (wSpmStatus != ESESTATUS_SUCCESS) {
123             NXP_LOG_ESE_E(" %s : phNxpEse_SPM_GetPwrState Failed",
124                           __FUNCTION__);
125             if (phNxpEse_SPM_RelAccess() != ESESTATUS_SUCCESS) {
126               NXP_LOG_ESE_E(" %s phNxpEse_SPM_RelAccess : failed \n",
127                             __FUNCTION__);
128             }
129             return wSpmStatus;
130           } else {
131             if (current_spm_state & SPM_STATE_DWNLD) {
132               wSpmStatus = ESESTATUS_DWNLD_BUSY;
133             } else {
134               wSpmStatus = ESESTATUS_BUSY;
135             }
136           }
137         } else {
138           wSpmStatus = ESESTATUS_FAILED;
139         }
140         if (wSpmStatus != ESESTATUS_SUCCESS) {
141           if (phNxpEse_SPM_RelAccess() != ESESTATUS_SUCCESS) {
142             NXP_LOG_ESE_E(" %s phNxpEse_SPM_RelAccess : failed \n",
143                           __FUNCTION__);
144           }
145         }
146       }
147     } break;
148     case SPM_POWER_RESET: {
149       if (ret < 0) {
150         NXP_LOG_ESE_E("%s : failed errno = 0x%x", __FUNCTION__, errno);
151         if (errno == -EBUSY) {
152           wSpmStatus = phNxpEse_SPM_GetState(¤t_spm_state);
153           if (wSpmStatus != ESESTATUS_SUCCESS) {
154             NXP_LOG_ESE_E(" %s : phNxpEse_SPM_GetPwrState Failed",
155                           __FUNCTION__);
156             return wSpmStatus;
157           } else {
158             if (current_spm_state & SPM_STATE_DWNLD) {
159               wSpmStatus = ESESTATUS_DWNLD_BUSY;
160             } else {
161               wSpmStatus = ESESTATUS_BUSY;
162             }
163           }
164         } else {
165           wSpmStatus = ESESTATUS_FAILED;
166         }
167       }
168     } break;
169     case SPM_POWER_PRIO_ENABLE: {
170       if (ret < 0) {
171         NXP_LOG_ESE_E("%s : failed errno = 0x%x", __FUNCTION__, errno);
172         if (errno == -EBUSY) {
173           wSpmStatus = phNxpEse_SPM_GetState(¤t_spm_state);
174           if (wSpmStatus != ESESTATUS_SUCCESS) {
175             NXP_LOG_ESE_E(" %s : phNxpEse_SPM_GetPwrState Failed",
176                           __FUNCTION__);
177             return wSpmStatus;
178           } else {
179             if (current_spm_state & SPM_STATE_DWNLD) {
180               wSpmStatus = ESESTATUS_DWNLD_BUSY;
181             } else {
182               wSpmStatus = ESESTATUS_BUSY;
183             }
184           }
185 
186         } else {
187           wSpmStatus = ESESTATUS_FAILED;
188         }
189       }
190     } break;
191     case SPM_POWER_PRIO_DISABLE: {
192       if (ret < 0) {
193         NXP_LOG_ESE_E("%s : failed errno = 0x%x", __FUNCTION__, errno);
194         wSpmStatus = ESESTATUS_FAILED;
195       }
196     } break;
197     case SPM_RECOVERY_RESET: {
198     } break;
199   }
200   return wSpmStatus;
201 }
202 
203 /******************************************************************************
204  * Function         phNxpEse_SPM_EnablePwr
205  *
206  * Description      This function request to the nfc i2c driver
207  *                  to enable power to ese. This api should be called before
208  *                  sending any apdu to ese.
209  *
210  * Returns          On Success ESESTATUS_SUCCESS else proper error code
211  *
212  ******************************************************************************/
phNxpEse_SPM_EnablePwr(void)213 ESESTATUS phNxpEse_SPM_EnablePwr(void) {
214   int32_t ret = -1;
215   ESESTATUS wSpmStatus = ESESTATUS_SUCCESS;
216   spm_state_t current_spm_state = SPM_STATE_INVALID;
217   NXP_LOG_ESE_D("%s : phNxpEse_SPM_EnablePwr is set to  = 0x%d", __FUNCTION__,
218                 0);
219   ret = phPalEse_ioctl(phPalEse_e_ChipRst, pEseDeviceHandle, 0);
220   if (ret < 0) {
221     NXP_LOG_ESE_E("%s : failed errno = 0x%x", __FUNCTION__, errno);
222     if (errno == -EBUSY) {
223       wSpmStatus = phNxpEse_SPM_GetState(¤t_spm_state);
224       if (wSpmStatus != ESESTATUS_SUCCESS) {
225         NXP_LOG_ESE_E(" %s : phNxpEse_SPM_GetPwrState Failed", __FUNCTION__);
226         return wSpmStatus;
227       } else {
228         if (current_spm_state == SPM_STATE_DWNLD) {
229           wSpmStatus = ESESTATUS_DWNLD_BUSY;
230         } else {
231           wSpmStatus = ESESTATUS_BUSY;
232         }
233       }
234 
235     } else {
236       wSpmStatus = ESESTATUS_FAILED;
237     }
238   }
239 
240   return wSpmStatus;
241 }
242 
243 /******************************************************************************
244  * Function         phNxpEse_SPM_DisablePwr
245  *
246  * Description      This function request to the nfc i2c driver
247  *                  to disable power to ese. This api should be called
248  *                  once apdu exchange is done.
249  *
250  * Returns          On Success ESESTATUS_SUCCESS else proper error code
251  *
252  ******************************************************************************/
phNxpEse_SPM_DisablePwr(void)253 ESESTATUS phNxpEse_SPM_DisablePwr(void) {
254   int32_t ret = -1;
255   ESESTATUS status = ESESTATUS_SUCCESS;
256   NXP_LOG_ESE_D("%s : phNxpEse_SPM_DisablePwr is set to  = 0x%d", __FUNCTION__,
257                 1);
258   ret = phPalEse_ioctl(phPalEse_e_ChipRst, pEseDeviceHandle, 1);
259   if (ret < 0) {
260     NXP_LOG_ESE_E("%s : failed errno = 0x%x", __FUNCTION__, errno);
261     status = ESESTATUS_FAILED;
262   }
263 
264   return status;
265 }
266 /******************************************************************************
267  * Function         phNxpEse_SPM_SetPwrScheme
268  *
269  * Description      This function request to the nfc i2c driver
270  *                  to set the chip type and power scheme.
271  *
272  * Returns          On Success ESESTATUS_SUCCESS else proper error code
273  *
274  ******************************************************************************/
phNxpEse_SPM_SetPwrScheme(long arg)275 ESESTATUS phNxpEse_SPM_SetPwrScheme(long arg) {
276   int32_t ret = -1;
277   ESESTATUS status = ESESTATUS_SUCCESS;
278 
279   NXP_LOG_ESE_D("%s : Power scheme is set to  = 0x%ld", __FUNCTION__, arg);
280   ret = phPalEse_ioctl(phPalEse_e_SetPowerScheme, pEseDeviceHandle, arg);
281   if (ret < 0) {
282     NXP_LOG_ESE_E("%s : failed errno = 0x%x", __FUNCTION__, errno);
283     status = ESESTATUS_FAILED;
284   }
285 
286   return status;
287 }
288 
289 /******************************************************************************
290  * Function         phNxpEseP61_SPM_EnableDisablePwrCntrl
291  *
292  * Description      This function request to the nfc i2c driver
293  *                  to set the chip type and power scheme.
294  *
295  * Returns          On Success ESESTATUS_SUCCESS else proper error code
296  *
297  ******************************************************************************/
phNxpEse_SPM_DisablePwrControl(unsigned long arg)298 ESESTATUS phNxpEse_SPM_DisablePwrControl(unsigned long arg) {
299   int32_t ret = -1;
300   ESESTATUS status = ESESTATUS_SUCCESS;
301 
302   NXP_LOG_ESE_D("%s : Inhibit power control is set to  = 0x%ld", __FUNCTION__,
303                 arg);
304   ret = phPalEse_ioctl(phPalEse_e_DisablePwrCntrl, pEseDeviceHandle, arg);
305   if (ret < 0) {
306     NXP_LOG_ESE_E("%s : failed errno = 0x%x", __FUNCTION__, errno);
307     status = ESESTATUS_FAILED;
308   }
309 
310   return status;
311 }
312 
313 /******************************************************************************
314  * Function         phNxpEse_SPM_GetState
315  *
316  * Description      This function gets the current power state of ESE
317  *
318  * Returns          On Success ESESTATUS_SUCCESS else proper error code
319  *
320  ******************************************************************************/
phNxpEse_SPM_GetState(spm_state_t * current_state)321 ESESTATUS phNxpEse_SPM_GetState(spm_state_t* current_state) {
322   int32_t ret = -1;
323   ESESTATUS status = ESESTATUS_SUCCESS;
324   spm_state_t ese_current_state = SPM_STATE_INVALID;
325 
326   if (current_state == NULL) {
327     NXP_LOG_ESE_E("%s : failed Invalid argument", __FUNCTION__);
328     return ESESTATUS_FAILED;
329   }
330   ret = phPalEse_ioctl(phPalEse_e_GetSPMStatus, pEseDeviceHandle,
331                        (unsigned long)&ese_current_state);
332   if (ret < 0) {
333     NXP_LOG_ESE_E("%s : failed errno = 0x%x", __FUNCTION__, errno);
334     status = ESESTATUS_FAILED;
335   } else {
336     *current_state = ese_current_state; /* Current ESE state */
337   }
338 
339   return status;
340 }
341 
342 /******************************************************************************
343  * Function         phNxpEse_SPM_SetJcopDwnldState
344  *
345  * Description      This function is used to set the JCOP OS download state
346  *
347  * Returns          On Success ESESTATUS_SUCCESS else proper error code
348  *
349  ******************************************************************************/
phNxpEse_SPM_SetJcopDwnldState(long arg)350 ESESTATUS phNxpEse_SPM_SetJcopDwnldState(long arg) {
351   int ret = -1;
352   ESESTATUS status = ESESTATUS_SUCCESS;
353 
354   NXP_LOG_ESE_D("%s :phNxpEse_SPM_SetJcopDwnldState  = 0x%ld", __FUNCTION__,
355                 arg);
356   ret = phPalEse_ioctl(phPalEse_e_SetJcopDwnldState, pEseDeviceHandle, arg);
357   if (ret < 0) {
358     NXP_LOG_ESE_E("%s : failed errno = 0x%x", __FUNCTION__, errno);
359     status = ESESTATUS_FAILED;
360   }
361 
362   return status;
363 }
364 
365 /******************************************************************************
366  * Function         phNxpEse_SPM_SetEseClientUpdateState
367  *
368  * Description      This function is used to set the ese Update state
369  *
370  * Returns          On Success ESESTATUS_SUCCESS else proper error code
371  *
372  ******************************************************************************/
phNxpEse_SPM_SetEseClientUpdateState(long arg)373 ESESTATUS phNxpEse_SPM_SetEseClientUpdateState(long arg) {
374   int ret = -1;
375   ESESTATUS status = ESESTATUS_SUCCESS;
376 
377   NXP_LOG_ESE_D("%s :phNxpEse_SPM_SetEseClientUpdateState  = 0x%ld",
378                 __FUNCTION__, arg);
379   ret = phPalEse_ioctl(phPalEse_e_SetClientUpdateState, pEseDeviceHandle, arg);
380   if (ret < 0) {
381     NXP_LOG_ESE_E("%s : failed errno = 0x%x", __FUNCTION__, errno);
382     status = ESESTATUS_FAILED;
383   }
384 
385   return status;
386 }
387 
388 /******************************************************************************
389  * Function         phNxpEse_SPM_ResetPwr
390  *
391  * Description      This function request to the nfc i2c driver
392  *                  to reset ese.
393  *
394  * Returns          On Success ESESTATUS_SUCCESS else proper error code
395  *
396  ******************************************************************************/
phNxpEse_SPM_ResetPwr(void)397 ESESTATUS phNxpEse_SPM_ResetPwr(void) {
398   int32_t ret = -1;
399   ESESTATUS wSpmStatus = ESESTATUS_SUCCESS;
400   spm_state_t current_spm_state = SPM_STATE_INVALID;
401 
402   /* reset the ese */
403   ret = phPalEse_ioctl(phPalEse_e_ChipRst, pEseDeviceHandle, 2);
404   if (ret < 0) {
405     NXP_LOG_ESE_E("%s : failed errno = 0x%x", __FUNCTION__, errno);
406     if (errno == -EBUSY || errno == EBUSY) {
407       wSpmStatus = phNxpEse_SPM_GetState(¤t_spm_state);
408       if (wSpmStatus != ESESTATUS_SUCCESS) {
409         NXP_LOG_ESE_E(" %s : phNxpEse_SPM_GetPwrState Failed", __FUNCTION__);
410         return wSpmStatus;
411       } else {
412         if (current_spm_state == SPM_STATE_DWNLD) {
413           wSpmStatus = ESESTATUS_DWNLD_BUSY;
414         } else {
415           wSpmStatus = ESESTATUS_BUSY;
416         }
417       }
418 
419     } else {
420       wSpmStatus = ESESTATUS_FAILED;
421     }
422   }
423 
424   return wSpmStatus;
425 }
426 
427 /*******************************************************************************
428 **
429 ** Function         phTmlEse_get_ese_access
430 **
431 ** Description
432 **
433 ** Parameters       timeout - timeout to wait for ese access
434 **
435 ** Returns          success or failure
436 **
437 *******************************************************************************/
phNxpEse_SPM_GetAccess(long timeout)438 ESESTATUS phNxpEse_SPM_GetAccess(long timeout) {
439   ESESTATUS status = ESESTATUS_SUCCESS;
440   NXP_LOG_ESE_D("phTmlEse_get_ese_access(), timeout  %ld", timeout);
441 #if ((NFC_NXP_ESE_VER == JCOP_VER_3_1) || (NFC_NXP_ESE_VER == JCOP_VER_3_2))
442   int ret = -1;
443 
444   ret = phPalEse_ioctl(phPalEse_e_GetEseAccess, pEseDeviceHandle, timeout);
445   if (ret < 0) {
446     if (ret == -EBUSY)
447       status = ESESTATUS_BUSY;
448     else
449       status = ESESTATUS_FAILED;
450   }
451   NXP_LOG_ESE_D("phTmlEse_get_ese_access(), exit  %d", status);
452 #endif
453   return status;
454 }
455 /*******************************************************************************
456 **
457 ** Function         phNxpEse_SPM_RelAccess
458 **
459 ** Description
460 **
461 ** Parameters       timeout - Releases the ese access
462 **
463 ** Returns          success or failure
464 **
465 *******************************************************************************/
phNxpEse_SPM_RelAccess(void)466 ESESTATUS phNxpEse_SPM_RelAccess(void) {
467   ESESTATUS status = ESESTATUS_SUCCESS;
468 #if ((NFC_NXP_ESE_VER == JCOP_VER_3_1) || (NFC_NXP_ESE_VER == JCOP_VER_3_2))
469   int ret = -1;
470   NXP_LOG_ESE_D("phNxpEse_SPM_RelAccess(): enter");
471 
472   ret = phPalEse_ioctl(phPalEse_e_ChipRst, pEseDeviceHandle, 5);
473   if (ret < 0) {
474     status = ESESTATUS_FAILED;
475   }
476   NXP_LOG_ESE_D("phNxpEse_SPM_RelAccess(): exit  %d", status);
477 #endif
478   return status;
479 }
480 /** @} */
481