1 /******************************************************************************
2  *
3  *  Copyright (C) 2018 ST Microelectronics S.A.
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  ******************************************************************************/
19 #define LOG_TAG "NfcHalFd"
20 #include "hal_fd.h"
21 #include <cutils/properties.h>
22 #include <errno.h>
23 #include <hardware/nfc.h>
24 #include <string.h>
25 #include "android_logmsg.h"
26 #include "halcore.h"
27 /* Initialize fw info structure pointer used to access fw info structure */
28 FWInfo *mFWInfo = NULL;
29 FILE *mFwFileBin;
30 FILE *mCustomFileBin;
31 fpos_t mPos;
32 fpos_t mPosInit;
33 uint8_t mBinData[260];
34 bool mRetry = true;
35 bool mCustomParamFailed = false;
36 bool mCustomParamDone = false;
37 uint8_t *pCmd;
38 int mFWRecovCount = 0;
39 const char *FwType = "generic";
40 char mApduAuthent[24];
41 
42 static const uint8_t propNfcModeSetCmdOn[] = {0x2f, 0x02, 0x02, 0x02, 0x01};
43 static const uint8_t coreInitCmd[] = {0x20, 0x01, 0x02, 0x00, 0x00};
44 static const uint8_t NciPropNfcFwUpdate[] = {0x2F, 0x02, 0x05, 0x06,
45                                              0x00, 0x01, 0x02, 0x03};
46 
47 static uint8_t ApduEraseNfcKeepAppliAndNdef[] = {
48     0x2F, 0x04, 0x16, 0x80, 0x0C, 0x00, 0x00, 0x11, 0x05,
49     0x00, 0x23, 0xDF, 0x00, 0x00, 0x23, 0xDF, 0xFF, 0x00,
50     0x23, 0xE0, 0x00, 0x00, 0x23, 0xFF, 0xFF};
51 
52 static const uint8_t ApduExitLoadMode[] = {0x2F, 0x04, 0x06, 0x80, 0xA0,
53                                            0x00, 0x00, 0x01, 0x01};
54 
55 hal_fd_state_e mHalFDState = HAL_FD_STATE_AUTHENTICATE;
56 void SendExitLoadMode(HALHANDLE mmHalHandle);
57 extern void hal_wrapper_update_complete();
58 
59 /**
60  * Send a HW reset and decode NCI_CORE_RESET_NTF information
61  * @param pHwVersion is used to return HW version, part of NCI_CORE_RESET_NTF
62  * @param pFwVersion is used to return FW version, part of NCI_CORE_RESET_NTF
63  * @param pLoaderVersion is used to return Loader version, part of
64  * NCI_CORE_RESET_NTF
65  * @param pCustVersion si used to return Customer field value, part of
66  * NCI_CORE_RESET_NTF when in router mode
67  *
68  * @return mode: FT_CLF_MODE_ROUTER if router mode
69  *               FT_CLF_MODE_LOADER if loader mode
70  *               FT_CLF_MODE_ERROR if Error
71  */
72 
hal_fd_init()73 int hal_fd_init() {
74   uint8_t result = 0;
75   char FwPath[256];
76   char ConfPath[256];
77   char fwBinName[256];
78   char fwConfName[256];
79 
80   STLOG_HAL_D("  %s - enter", __func__);
81 
82   if (!GetStrValue(NAME_STNFC_FW_PATH_STORAGE, (char *)FwPath,
83                    sizeof(FwPath))) {
84     STLOG_HAL_D(
85         "%s - FW path not found in conf. use default location /vendor/firmware "
86         "\n", __func__);
87     strcpy(FwPath, "/vendor/firmware");
88   }
89 
90   if (!GetStrValue(NAME_STNFC_FW_BIN_NAME, (char *)fwBinName,
91                    sizeof(fwBinName))) {
92     STLOG_HAL_D(
93         "%s - FW binary file name not found in conf. use default name "
94         "/st21nfc_fw.bin \n", __func__);
95     strcpy(fwBinName, "/st21nfc_fw.bin");
96   }
97 
98   if (!GetStrValue(NAME_STNFC_FW_CONF_NAME, (char *)fwConfName,
99                    sizeof(fwConfName))) {
100     STLOG_HAL_D(
101         "%s - FW config file name not found in conf. use default name "
102         "/st21nfc_conf.bin \n", __func__);
103     strcpy(fwConfName, "/st21nfc_conf.bin");
104   }
105 
106   // Getting information about FW patch, if any
107   strcpy(ConfPath, FwPath);
108   strncat(FwPath, fwBinName, sizeof(FwPath) - strlen(FwPath) - 1);
109   strncat(ConfPath, fwConfName, sizeof(ConfPath) - strlen(ConfPath) - 1);
110   STLOG_HAL_D("%s - FW update binary file = %s", __func__, FwPath);
111   STLOG_HAL_D("%s - FW config binary file = %s", __func__, ConfPath);
112 
113   // Initializing structure holding FW patch details
114   mFWInfo = (FWInfo *)malloc(sizeof(FWInfo));
115 
116   if (mFWInfo == NULL) {
117     result = 0;
118   }
119 
120   memset(mFWInfo, 0, sizeof(FWInfo));
121 
122   mFwFileBin = NULL;
123   mCustomFileBin = NULL;
124 
125   // Check if FW patch binary file is present
126   // If not, get recovery FW patch file
127   if ((mFwFileBin = fopen((char *)FwPath, "r")) == NULL) {
128     STLOG_HAL_D("%s - %s not detected", __func__, fwBinName);
129   } else {
130     STLOG_HAL_D("%s - %s file detected\n", __func__, fwBinName);
131 
132     result |= FW_PATCH_AVAILABLE;
133     fread(mBinData, sizeof(uint8_t), 4, mFwFileBin);
134     mFWInfo->patchVersion =
135         mBinData[0] << 24 | mBinData[1] << 16 | mBinData[2] << 8 | mBinData[3];
136 
137     fread(mApduAuthent, sizeof(uint8_t), 24, mFwFileBin);
138 
139     fgetpos(mFwFileBin, &mPosInit);
140 
141     STLOG_HAL_D(
142         "%s --> st21nfc_fw integrates patch NFC FW version 0x%08X (%s)\n",
143         __func__, mFWInfo->patchVersion, FwType);
144   }
145 
146   if ((mCustomFileBin = fopen((char *)ConfPath, "r")) == NULL) {
147     STLOG_HAL_D("%s - st21nfc custom configuration not detected\n", __func__);
148   } else {
149     STLOG_HAL_D("%s - %s file detected\n", __func__, ConfPath);
150     fread(mBinData, sizeof(uint8_t), 2, mCustomFileBin);
151     mFWInfo->confVersion = mBinData[0] << 8 | mBinData[1];
152     STLOG_HAL_D("%s --> st21nfc_custom configuration version 0x%04X \n",
153                 __func__, mFWInfo->confVersion);
154     result |= FW_CUSTOM_PARAM_AVAILABLE;
155   }
156 
157   return result;
158 }
159 
hal_fd_close()160 void hal_fd_close() {
161   STLOG_HAL_D("  %s -enter", __func__);
162   mCustomParamFailed = false;
163   if (mFWInfo != NULL) {
164     free(mFWInfo);
165     mFWInfo = NULL;
166   }
167   if (mFwFileBin != NULL) {
168     fclose(mFwFileBin);
169     mFwFileBin = NULL;
170   }
171   if (mCustomFileBin != NULL) {
172     fclose(mCustomFileBin);
173     mCustomFileBin = NULL;
174   }
175 }
176 
177 /**
178  * Send a HW reset and decode NCI_CORE_RESET_NTF information
179  * @param pHwVersion is used to return HW version, part of NCI_CORE_RESET_NTF
180  * @param pFwVersion is used to return FW version, part of NCI_CORE_RESET_NTF
181  * @param pLoaderVersion is used to return Loader version, part of
182  * NCI_CORE_RESET_NTF
183  * @param pCustVersion si used to return Customer field value, part of
184  * NCI_CORE_RESET_NTF when in router mode
185  *
186  * @return mode: FT_CLF_MODE_ROUTER if router mode
187  *               FT_CLF_MODE_LOADER if loader mode
188  *               FT_CLF_MODE_ERROR if Error
189  */
190 
ft_cmd_HwReset(uint8_t * pdata,uint8_t * clf_mode)191 uint8_t ft_cmd_HwReset(uint8_t *pdata, uint8_t *clf_mode) {
192   uint8_t result = 0;
193 
194   STLOG_HAL_D("  %s - execution", __func__);
195 
196   if ((pdata[1] == 0x0) && (pdata[3] == 0x1)) {
197     STLOG_HAL_D("-> Router Mode NCI_CORE_RESET_NTF received after HW Reset");
198 
199     /* retrieve HW Version from NCI_CORE_RESET_NTF */
200     mFWInfo->hwVersion = pdata[8];
201     STLOG_HAL_D("   HwVersion = 0x%02X", mFWInfo->hwVersion);
202 
203     /* retrieve FW Version from NCI_CORE_RESET_NTF */
204     mFWInfo->fwVersion =
205         (pdata[10] << 24) | (pdata[11] << 16) | (pdata[12] << 8) | pdata[13];
206     STLOG_HAL_D("   FwVersion = 0x%08X", mFWInfo->fwVersion);
207 
208     /* retrieve Loader Version from NCI_CORE_RESET_NTF */
209     mFWInfo->loaderVersion = (pdata[14] << 16) | (pdata[15] << 8) | pdata[16];
210     STLOG_HAL_D("   LoaderVersion = 0x%06X", mFWInfo->loaderVersion);
211 
212     /* retrieve Customer Version from NCI_CORE_RESET_NTF */
213     mFWInfo->custVersion = (pdata[31] << 8) | pdata[32];
214     STLOG_HAL_D("   CustomerVersion = 0x%04X", mFWInfo->custVersion);
215 
216     *clf_mode = FT_CLF_MODE_ROUTER;
217   } else if ((pdata[2] == 0x39) && (pdata[3] == 0xA1)) {
218     STLOG_HAL_D("-> Loader Mode NCI_CORE_RESET_NTF received after HW Reset");
219 
220     /* deduce HW Version from Factory Loader version */
221     if (pdata[16] == 0x01) {
222       mFWInfo->hwVersion = 0x05;  // ST54J
223     } else if (pdata[16] == 0x02) {
224       mFWInfo->hwVersion = 0x04;  // ST21NFCD
225     } else {
226       mFWInfo->hwVersion = 0x03;  // ST21NFCD
227     }
228     STLOG_HAL_D("   HwVersion = 0x%02X", mFWInfo->hwVersion);
229 
230     /* Identify the Active loader. Normally only one should be detected*/
231     if (pdata[11] == 0xA0) {
232       mFWInfo->loaderVersion = (pdata[8] << 16) | (pdata[9] << 8) | pdata[10];
233       STLOG_HAL_D("         - Most recent loader activated, revision 0x%06X",
234                   mFWInfo->loaderVersion);
235     }
236     if (pdata[15] == 0xA0) {
237       mFWInfo->loaderVersion = (pdata[12] << 16) | (pdata[13] << 8) | pdata[14];
238       STLOG_HAL_D("         - Least recent loader activated, revision 0x%06X",
239                   mFWInfo->loaderVersion);
240     }
241     if (pdata[19] == 0xA0) {
242       mFWInfo->loaderVersion = (pdata[16] << 16) | (pdata[17] << 8) | pdata[18];
243       STLOG_HAL_D("         - Factory loader activated, revision 0x%06X",
244                   mFWInfo->loaderVersion);
245     }
246 
247     *clf_mode = FT_CLF_MODE_LOADER;
248   } else {
249     STLOG_HAL_E(
250         "%s --> ERROR: wrong NCI_CORE_RESET_NTF received after HW Reset",
251         __func__);
252     *clf_mode = FT_CLF_MODE_ERROR;
253   }
254 
255   // Allow update only for ST54J
256   if (mFWInfo->hwVersion == 0x05) {
257     if ((mFwFileBin != NULL) && (mFWInfo->patchVersion != mFWInfo->fwVersion)) {
258       STLOG_HAL_D("---> Firmware update needed\n");
259       result |= FW_UPDATE_NEEDED;
260     } else {
261       STLOG_HAL_D("---> No Firmware update needed\n");
262     }
263 
264     if ((mFWInfo->confVersion != 0) &&
265         (mFWInfo->custVersion != mFWInfo->confVersion)) {
266       STLOG_HAL_D(
267           "%s - Need to apply new st21nfc custom configuration settings\n",
268           __func__);
269       if (!mCustomParamFailed) result |= CONF_UPDATE_NEEDED;
270     } else {
271       STLOG_HAL_D("%s - No need to apply custom configuration settings\n",
272                   __func__);
273     }
274   }
275 
276   return result;
277 } /* ft_cmd_HwReset */
278 
ExitHibernateHandler(HALHANDLE mHalHandle,uint16_t data_len,uint8_t * p_data)279 void ExitHibernateHandler(HALHANDLE mHalHandle, uint16_t data_len,
280                           uint8_t *p_data) {
281   STLOG_HAL_D("%s - Enter", __func__);
282   if (data_len < 3) {
283     STLOG_HAL_E("%s - Error, too short data (%d)", __func__, data_len);
284     return;
285   }
286   switch (p_data[0]) {
287     case 0x40:  //
288       STLOG_HAL_D("%s - hibernate_exited = %d ", __func__,
289                   mFWInfo->hibernate_exited);
290 
291       // CORE_INIT_RSP
292       if ((p_data[1] == 0x1) && (p_data[3] == 0x0) &&
293           (mFWInfo->hibernate_exited == 0)) {
294         // Send PROP_NFC_MODE_SET_CMD(ON)
295         if (!HalSendDownstream(mHalHandle, propNfcModeSetCmdOn,
296                                sizeof(propNfcModeSetCmdOn))) {
297           STLOG_HAL_E("%s - SendDownstream failed", __func__);
298         }
299       } else if ((p_data[1] == 0x1) && (p_data[3] == 0x0) &&
300                  (mFWInfo->hibernate_exited == 1)) {
301         STLOG_HAL_D(
302             "%s - send NCI_PROP_NFC_FW_UPDATE_CMD and use 100 ms timer for "
303             "each cmd from here",
304             __func__);
305 
306         if (!HalSendDownstreamTimer(mHalHandle, NciPropNfcFwUpdate,
307                                     sizeof(NciPropNfcFwUpdate),
308                                     FW_TIMER_DURATION)) {
309           STLOG_HAL_E("%s  SendDownstream failed", __func__);
310         }
311       } else if (p_data[3] != 0x00) {
312         STLOG_HAL_D("%s - Wrong response. Retry HW reset", __func__);
313         I2cResetPulse();
314         hal_wrapper_set_state(HAL_WRAPPER_STATE_OPEN);
315       }
316       break;
317 
318     case 0x4f:  //
319       if ((p_data[1] == 0x02) && (p_data[3] == 0x00) &&
320           (mFWInfo->hibernate_exited == 1)) {
321         STLOG_HAL_D("%s - NCI_PROP_NFC_FW_RSP : loader mode", __func__);
322         I2cResetPulse();
323         hal_wrapper_set_state(HAL_WRAPPER_STATE_OPEN);
324       } else if (p_data[3] != 0x00) {
325         STLOG_HAL_D("%s - Wrong response. Retry HW reset", __func__);
326         I2cResetPulse();
327         hal_wrapper_set_state(HAL_WRAPPER_STATE_OPEN);
328       }
329       break;
330     case 0x60:  //
331       if (p_data[3] == 0x2) {
332         STLOG_HAL_D("%s - CORE_RESET_NTF : after core_reset_cmd", __func__);
333 
334         if (!HalSendDownstream(mHalHandle, coreInitCmd, sizeof(coreInitCmd))) {
335           STLOG_HAL_E("%s - SendDownstream failed", __func__);
336         }
337       } else if (p_data[3] == 0xa0) {
338         mFWInfo->hibernate_exited = 1;
339         STLOG_HAL_D("%s - hibernate_exited = %d ", __func__,
340                     mFWInfo->hibernate_exited);
341 
342         if (!HalSendDownstream(mHalHandle, coreInitCmd, sizeof(coreInitCmd))) {
343           STLOG_HAL_E("%s - SendDownstream failed", __func__);
344         }
345       }
346       break;
347   }
348 }
349 
resetHandlerState()350 void resetHandlerState() {
351   STLOG_HAL_D("%s", __func__);
352   mHalFDState = HAL_FD_STATE_AUTHENTICATE;
353 }
354 
UpdateHandler(HALHANDLE mHalHandle,uint16_t data_len,uint8_t * p_data)355 void UpdateHandler(HALHANDLE mHalHandle, uint16_t data_len, uint8_t *p_data) {
356   HalSendDownstreamStopTimer(mHalHandle);
357 
358   switch (mHalFDState) {
359     case HAL_FD_STATE_AUTHENTICATE:
360       STLOG_HAL_D("%s - mHalFDState = HAL_FD_STATE_AUTHENTICATE", __func__);
361 
362       if ((p_data[data_len - 2] == 0x90) && (p_data[data_len - 1] == 0x00)) {
363         STLOG_HAL_D("%s - send APDU_AUTHENTICATION_CMD", __func__);
364         if (!HalSendDownstreamTimer(mHalHandle, (uint8_t *)mApduAuthent,
365                                     sizeof(mApduAuthent), FW_TIMER_DURATION)) {
366           STLOG_HAL_E("%s - SendDownstream failed", __func__);
367         }
368         mHalFDState = HAL_FD_STATE_ERASE_FLASH;
369       } else {
370         STLOG_HAL_D("%s - FW flash not succeeded", __func__);
371         SendExitLoadMode(mHalHandle);
372       }
373       break;
374 
375     case HAL_FD_STATE_ERASE_FLASH:  // 1
376       STLOG_HAL_D("%s - mHalFDState = HAL_FD_STATE_ERASE_FLASH", __func__);
377 
378       if ((p_data[0] == 0x4f) && (p_data[1] == 0x04)) {
379         if ((p_data[data_len - 2] == 0x90) && (p_data[data_len - 1] == 0x00)) {
380           STLOG_HAL_D(
381               " %s - send APDU_ERASE_FLASH_CMD (keep appli and NDEF areas)",
382               __func__);
383 
384           if (!HalSendDownstreamTimer(mHalHandle, ApduEraseNfcKeepAppliAndNdef,
385                                       sizeof(ApduEraseNfcKeepAppliAndNdef),
386                                       FW_TIMER_DURATION)) {
387             STLOG_HAL_E("%s - SendDownstream failed", __func__);
388           }
389 
390           fsetpos(mFwFileBin, &mPosInit);  // reset pos in stream
391 
392           mHalFDState = HAL_FD_STATE_SEND_RAW_APDU;
393 
394         } else {
395           STLOG_HAL_D("%s - FW flash not succeeded", __func__);
396           SendExitLoadMode(mHalHandle);
397         }
398       }
399       break;
400 
401     case HAL_FD_STATE_SEND_RAW_APDU:  // 3
402       STLOG_HAL_D("%s - mHalFDState = HAL_FD_STATE_SEND_RAW_APDU", __func__);
403       if ((p_data[0] == 0x4f) && (p_data[1] == 0x04)) {
404         if ((p_data[data_len - 2] == 0x90) && (p_data[data_len - 1] == 0x00)) {
405           mRetry = true;
406 
407           fgetpos(mFwFileBin, &mPos);  // save current position in stream
408           if ((fread(mBinData, sizeof(uint8_t), 3, mFwFileBin) == 3) &&
409               (fread(mBinData + 3, sizeof(uint8_t), mBinData[2], mFwFileBin) ==
410                mBinData[2])) {
411             if (!HalSendDownstreamTimer(mHalHandle, mBinData, mBinData[2] + 3,
412                                         FW_TIMER_DURATION)) {
413               STLOG_HAL_E("%s - SendDownstream failed", __func__);
414             }
415           } else {
416             STLOG_HAL_D("%s - EOF of FW binary", __func__);
417             SendExitLoadMode(mHalHandle);
418           }
419         } else if (mRetry == true) {
420           STLOG_HAL_D("%s - Last Tx was NOK. Retry", __func__);
421           mRetry = false;
422           fsetpos(mFwFileBin, &mPos);
423           if ((fread(mBinData, sizeof(uint8_t), 3, mFwFileBin) == 3) &&
424               (fread(mBinData + 3, sizeof(uint8_t), mBinData[2], mFwFileBin) ==
425                mBinData[2])) {
426             if (!HalSendDownstreamTimer(mHalHandle, mBinData, mBinData[2] + 3,
427                                         FW_TIMER_DURATION)) {
428               STLOG_HAL_E("%s - SendDownstream failed", __func__);
429             }
430             fgetpos(mFwFileBin, &mPos);  // save current position in stream
431           } else {
432             STLOG_HAL_D("%s - EOF of FW binary", __func__);
433             SendExitLoadMode(mHalHandle);
434           }
435         } else {
436           STLOG_HAL_D("%s - FW flash not succeeded.", __func__);
437           I2cResetPulse();
438           SendExitLoadMode(mHalHandle);
439         }
440       }
441       break;
442 
443     case HAL_FD_STATE_EXIT_APDU:  // 2
444       STLOG_HAL_D("%s - mHalFDState = HAL_FD_STATE_EXIT_APDU", __func__);
445       if ((p_data[data_len - 2] != 0x90) || (p_data[data_len - 1] != 0x00)) {
446         STLOG_HAL_D(
447             "%s - Error exiting loader mode, i.e. a problem occured during FW "
448             "update", __func__);
449       }
450 
451       I2cResetPulse();
452       hal_wrapper_set_state(HAL_WRAPPER_STATE_OPEN);
453       mHalFDState = HAL_FD_STATE_AUTHENTICATE;
454       break;
455 
456     default:
457       STLOG_HAL_D("%s - mHalFDState = unknown", __func__);
458       STLOG_HAL_D("%s - FW flash not succeeded", __func__);
459       SendExitLoadMode(mHalHandle);
460       break;
461   }
462 }
463 
ApplyCustomParamHandler(HALHANDLE mHalHandle,uint16_t data_len,uint8_t * p_data)464 void ApplyCustomParamHandler(HALHANDLE mHalHandle, uint16_t data_len,
465                              uint8_t *p_data) {
466   STLOG_HAL_D("%s - Enter ", __func__);
467   if (data_len < 3) {
468     STLOG_HAL_E("%s : Error, too short data (%d)", __func__, data_len);
469     return;
470   }
471 
472   switch (p_data[0]) {
473     case 0x40:  //
474       // CORE_RESET_RSP
475       if ((p_data[1] == 0x0) && (p_data[3] == 0x0)) {
476         // do nothing
477       } else if ((p_data[1] == 0x1) && (p_data[3] == 0x0)) {
478         if (mFWInfo->hibernate_exited == 0) {
479           // Send a NFC mode on .
480           if (!HalSendDownstream(mHalHandle, propNfcModeSetCmdOn,
481                                  sizeof(propNfcModeSetCmdOn))) {
482             STLOG_HAL_E("%s - SendDownstream failed", __func__);
483           }
484           // CORE_INIT_RSP
485         } else if (mFWInfo->hibernate_exited == 1) {
486           if ((fread(mBinData, sizeof(uint8_t), 3, mCustomFileBin)) &&
487               (fread(mBinData + 3, sizeof(uint8_t), mBinData[2],
488                      mCustomFileBin))) {
489             if (!HalSendDownstream(mHalHandle, mBinData, mBinData[2] + 3)) {
490               STLOG_HAL_E("%s - SendDownstream failed", __func__);
491             }
492           }
493         }
494 
495       } else {
496         STLOG_HAL_D("%s - Error in custom param application", __func__);
497         mCustomParamFailed = true;
498         I2cResetPulse();
499         hal_wrapper_set_state(HAL_WRAPPER_STATE_OPEN);
500       }
501       break;
502 
503     case 0x4f:
504       if (mFWInfo->hibernate_exited == 1) {
505         if ((fread(mBinData, sizeof(uint8_t), 3, mCustomFileBin) == 3) &&
506             (fread(mBinData + 3, sizeof(uint8_t), mBinData[2],
507                    mCustomFileBin) == mBinData[2])) {
508           if (!HalSendDownstream(mHalHandle, mBinData, mBinData[2] + 3)) {
509             STLOG_HAL_E("%s - SendDownstream failed", __func__);
510           }
511         } else {
512           STLOG_HAL_D("%s - EOF of custom file", __func__);
513           mCustomParamDone = true;
514           I2cResetPulse();
515         }
516 
517         // Check if an error has occured for PROP_SET_CONFIG_CMD
518         // Only log a warning, do not exit code
519         if (p_data[3] != 0x00) {
520           STLOG_HAL_D("%s - Error in custom file, continue anyway", __func__);
521         }
522       }
523       break;
524 
525     case 0x60:  //
526       if (p_data[1] == 0x0) {
527         if (p_data[3] == 0xa0) {
528           mFWInfo->hibernate_exited = 1;
529         }
530         if (!HalSendDownstream(mHalHandle, coreInitCmd, sizeof(coreInitCmd))) {
531           STLOG_HAL_E("%s - SendDownstream failed", __func__);
532         }
533 
534       } else if ((p_data[1] == 0x6) && mCustomParamDone) {
535         mCustomParamDone = false;
536         hal_wrapper_update_complete();
537       }
538       break;
539   }
540 }
541 
SendExitLoadMode(HALHANDLE mmHalHandle)542 void SendExitLoadMode(HALHANDLE mmHalHandle) {
543   STLOG_HAL_D("%s - Send APDU_EXIT_LOAD_MODE_CMD", __func__);
544 
545   if (!HalSendDownstreamTimer(mmHalHandle, ApduExitLoadMode,
546                               sizeof(ApduExitLoadMode), FW_TIMER_DURATION)) {
547     STLOG_HAL_E("%s - SendDownstream failed", __func__);
548   }
549   mHalFDState = HAL_FD_STATE_EXIT_APDU;
550 }
551