patchram.cpp revision fca15e562a5a4651a489f7ebcba5ba03f952bc36
1/******************************************************************************
2 *
3 *  Copyright (C) 1999-2012 Broadcom Corporation
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#include "OverrideLog.h"
19#include "config.h"
20#include "nfc_hal_int.h"
21#include "userial.h"
22extern "C"
23{
24    #include "nfc_hal_post_reset.h"
25}
26#include <string>
27#include <cutils/properties.h>
28#include "spdhelper.h"
29#include "StartupConfig.h"
30
31#define LOG_TAG "NfcNciHal"
32
33#define FW_PRE_PATCH                        "FW_PRE_PATCH"
34#define FW_PATCH                            "FW_PATCH"
35#define MAX_RF_DATA_CREDITS                 "MAX_RF_DATA_CREDITS"
36
37#define MAX_BUFFER      (512)
38static char sPrePatchFn[MAX_BUFFER+1];
39static char sPatchFn[MAX_BUFFER+1];
40static void * sPrmBuf = NULL;
41static void * sI2cFixPrmBuf = NULL;
42
43#define CONFIG_MAX_LEN 256
44static UINT8 sConfig [CONFIG_MAX_LEN];
45static StartupConfig sStartupConfig;
46static StartupConfig sLptdConfig;
47static StartupConfig sPreDiscoveryConfig;
48extern UINT8 *p_nfc_hal_dm_start_up_cfg; //defined in the HAL
49static UINT8 nfa_dm_start_up_vsc_cfg[CONFIG_MAX_LEN];
50extern UINT8 *p_nfc_hal_dm_start_up_vsc_cfg; //defined in the HAL
51extern UINT8 *p_nfc_hal_dm_lptd_cfg; //defined in the HAL
52extern UINT8 *p_nfc_hal_pre_discover_cfg; //defined in the HAL
53
54extern tSNOOZE_MODE_CONFIG gSnoozeModeCfg;
55extern tNFC_HAL_CFG *p_nfc_hal_cfg;
56static void mayDisableSecureElement (StartupConfig& config);
57
58/* Default patchfile (in NCD format) */
59#ifndef NFA_APP_DEFAULT_PATCHFILE_NAME
60#define NFA_APP_DEFAULT_PATCHFILE_NAME      "\0"
61#endif
62
63/* Default patchfile (in NCD format) */
64#ifndef NFA_APP_DEFAULT_I2C_PATCHFILE_NAME
65#define NFA_APP_DEFAULT_I2C_PATCHFILE_NAME  "\0"
66#endif
67
68#define BRCM_43341B0_ID 0x43341b00
69
70tNFC_POST_RESET_CB nfc_post_reset_cb =
71{
72    /* Default Patch & Pre-Patch */
73    NFA_APP_DEFAULT_PATCHFILE_NAME,
74    NULL,
75    NFA_APP_DEFAULT_I2C_PATCHFILE_NAME,
76    NULL,
77
78    /* Default UART baud rate */
79    NFC_HAL_DEFAULT_BAUD,
80
81    /* Default tNFC_HAL_DEV_INIT_CFG (flags, num_xtal_cfg, {brcm_hw_id, xtal-freq, xtal-index} ) */
82    {
83        1, /* number of valid entries */
84        {
85            {BRCM_43341B0_ID, 37400, NFC_HAL_XTAL_INDEX_37400},
86            {0, 0, 0},
87            {0, 0, 0},
88            {0, 0, 0},
89            {0, 0, 0},
90        }
91    },
92
93    /* Default low power mode settings */
94    NFC_HAL_LP_SNOOZE_MODE_NONE,    /* Snooze Mode          */
95    NFC_HAL_LP_IDLE_THRESHOLD_HOST, /* Idle Threshold Host  */
96    NFC_HAL_LP_IDLE_THRESHOLD_HC,   /* Idle Threshold HC    */
97    NFC_HAL_LP_ACTIVE_LOW,          /* NFC_WAKE Active Mode */
98    NFC_HAL_LP_ACTIVE_HIGH,         /* DH_WAKE Active Mode  */
99
100    NFA_APP_MAX_NUM_REINIT,         /* max retry to get NVM type */
101    0,                              /* current retry count */
102    TRUE,                           /* debug mode for downloading patchram */
103    FALSE                           /* skip downloading patchram after reinit because of patch download failure */
104};
105
106
107/*******************************************************************************
108**
109** Function         getFileLength
110**
111** Description      return the size of a file
112**
113** Returns          file size in number of bytes
114**
115*******************************************************************************/
116static long getFileLength(FILE* fp)
117{
118    long sz;
119    fseek(fp, 0L, SEEK_END);
120    sz = ftell(fp);
121    fseek(fp, 0L, SEEK_SET);
122
123    return sz;
124}
125
126/*******************************************************************************
127**
128** Function         isFileExist
129**
130** Description      Check if file name exists (android does not support fexists)
131**
132** Returns          TRUE if file exists
133**
134*******************************************************************************/
135static BOOLEAN isFileExist(const char *pFilename)
136{
137    FILE *pf;
138
139    if ((pf = fopen(pFilename, "r")) != NULL)
140    {
141        fclose(pf);
142        return TRUE;
143    }
144    return FALSE;
145}
146
147/*******************************************************************************
148**
149** Function         findPatchramFile
150**
151** Description      Find the patchram file name specified in the .conf
152**
153** Returns          pointer to the file name
154**
155*******************************************************************************/
156static const char* findPatchramFile(const char * pConfigName, char * pBuffer, int bufferLen)
157{
158    ALOGD("%s: config=%s", __FUNCTION__, pConfigName);
159
160    if (pConfigName == NULL)
161    {
162        ALOGD("%s No patchfile defined\n", __FUNCTION__);
163        return NULL;
164    }
165
166    if (GetStrValue(pConfigName, &pBuffer[0], bufferLen))
167    {
168        ALOGD("%s found patchfile %s\n", __FUNCTION__, pBuffer);
169        return (pBuffer[0] == '\0') ? NULL : pBuffer;
170    }
171
172    ALOGD("%s Cannot find patchfile '%s'\n", __FUNCTION__, pConfigName);
173    return NULL;
174}
175
176/*******************************************************************************
177**
178** Function:    continueAfterSetSnoozeMode
179**
180** Description: Called after Snooze Mode is enabled.
181**
182** Returns:     none
183**
184*******************************************************************************/
185static void continueAfterSetSnoozeMode(tHAL_NFC_STATUS status)
186{
187    ALOGD("%s: status=%u", __FUNCTION__, status);
188    //let stack download firmware during next initialization
189    nfc_post_reset_cb.spd_skip_on_power_cycle = FALSE;
190    if (status == NCI_STATUS_OK)
191        HAL_NfcPreInitDone (HAL_NFC_STATUS_OK);
192    else
193        HAL_NfcPreInitDone (HAL_NFC_STATUS_FAILED);
194}
195
196/*******************************************************************************
197**
198** Function:    postDownloadPatchram
199**
200** Description: Called after patch download
201**
202** Returns:     none
203**
204*******************************************************************************/
205static void postDownloadPatchram(tHAL_NFC_STATUS status)
206{
207    ALOGD("%s: status=%i", __FUNCTION__, status);
208    GetStrValue (NAME_SNOOZE_MODE_CFG, (char*)&gSnoozeModeCfg, sizeof(gSnoozeModeCfg));
209    if (status != HAL_NFC_STATUS_OK)
210    {
211        ALOGE("%s: Patch download failed", __FUNCTION__);
212        if (status == HAL_NFC_STATUS_REFUSED)
213        {
214            SpdHelper::setPatchAsBad();
215        }
216        else
217            SpdHelper::incErrorCount();
218
219        /* If in SPD Debug mode, fail immediately and obviously */
220        if (SpdHelper::isSpdDebug())
221            HAL_NfcPreInitDone (HAL_NFC_STATUS_FAILED);
222        else
223        {
224            /* otherwise, power cycle the chip and let the stack startup normally */
225            ALOGD("%s: re-init; don't download firmware", __FUNCTION__);
226            //stop stack from downloading firmware during next initialization
227            nfc_post_reset_cb.spd_skip_on_power_cycle = TRUE;
228            USERIAL_PowerupDevice(0);
229            HAL_NfcReInit ();
230        }
231    }
232    /* Set snooze mode here */
233    else if (gSnoozeModeCfg.snooze_mode != NFC_HAL_LP_SNOOZE_MODE_NONE)
234    {
235        status = HAL_NfcSetSnoozeMode(gSnoozeModeCfg.snooze_mode,
236                                       gSnoozeModeCfg.idle_threshold_dh,
237                                       gSnoozeModeCfg.idle_threshold_nfcc,
238                                       gSnoozeModeCfg.nfc_wake_active_mode,
239                                       gSnoozeModeCfg.dh_wake_active_mode,
240                                       continueAfterSetSnoozeMode);
241        if (status != NCI_STATUS_OK)
242        {
243            ALOGE("%s: Setting snooze mode failed, status=%i", __FUNCTION__, status);
244            HAL_NfcPreInitDone(HAL_NFC_STATUS_FAILED);
245        }
246    }
247    else
248    {
249        ALOGD("%s: Not using Snooze Mode", __FUNCTION__);
250        HAL_NfcPreInitDone(HAL_NFC_STATUS_OK);
251    }
252}
253
254
255/*******************************************************************************
256**
257** Function:    prmCallback
258**
259** Description: Patchram callback (for static patchram mode)
260**
261** Returns:     none
262**
263*******************************************************************************/
264void prmCallback(UINT8 event)
265{
266    ALOGD("%s: event=0x%x", __FUNCTION__, event);
267    switch (event)
268    {
269    case NFC_HAL_PRM_CONTINUE_EVT:
270        /* This event does not occur if static patchram buf is used */
271        break;
272
273    case NFC_HAL_PRM_COMPLETE_EVT:
274        postDownloadPatchram(HAL_NFC_STATUS_OK);
275        break;
276
277    case NFC_HAL_PRM_ABORT_EVT:
278        postDownloadPatchram(HAL_NFC_STATUS_FAILED);
279        break;
280
281    case NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT:
282        ALOGD("%s: invalid patch...skipping patch download", __FUNCTION__);
283        postDownloadPatchram(HAL_NFC_STATUS_REFUSED);
284        break;
285
286    case NFC_HAL_PRM_ABORT_BAD_SIGNATURE_EVT:
287        ALOGD("%s: patch authentication failed", __FUNCTION__);
288        postDownloadPatchram(HAL_NFC_STATUS_REFUSED);
289        break;
290
291    case NFC_HAL_PRM_ABORT_NO_NVM_EVT:
292        ALOGD("%s: No NVM detected", __FUNCTION__);
293        HAL_NfcPreInitDone(HAL_NFC_STATUS_FAILED);
294        break;
295
296    default:
297        ALOGD("%s: not handled event=0x%x", __FUNCTION__, event);
298        break;
299    }
300}
301
302
303/*******************************************************************************
304**
305** Function         getNfaValues
306**
307** Description      Get configuration values needed by NFA layer
308**
309** Returns:         None
310**
311*******************************************************************************/
312static void getNfaValues()
313{
314    unsigned long num = 0;
315    int actualLen = 0;
316
317    p_nfc_hal_cfg->nfc_hal_prm_nvm_required = TRUE; //don't download firmware if controller cannot detect EERPOM
318    sStartupConfig.initialize ();
319    sLptdConfig.initialize ();
320    sPreDiscoveryConfig.initialize();
321
322
323    actualLen = GetStrValue (NAME_NFA_DM_START_UP_CFG, (char*)sConfig, sizeof(sConfig));
324    if (actualLen)
325        sStartupConfig.append (sConfig, actualLen);
326
327    // Set antenna tuning configuration if configured.
328    actualLen = GetStrValue(NAME_PREINIT_DSP_CFG, (char*)sConfig, sizeof(sConfig));
329    if (actualLen)
330        sStartupConfig.append (sConfig, actualLen);
331
332    if ( GetStrValue ( NAME_NFA_DM_START_UP_VSC_CFG, (char*)nfa_dm_start_up_vsc_cfg, sizeof (nfa_dm_start_up_vsc_cfg) ) )
333    {
334        p_nfc_hal_dm_start_up_vsc_cfg = &nfa_dm_start_up_vsc_cfg[0];
335        ALOGD ( "START_UP_VSC_CFG[0] = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
336                                                                            nfa_dm_start_up_vsc_cfg[0],
337                                                                            nfa_dm_start_up_vsc_cfg[1],
338                                                                            nfa_dm_start_up_vsc_cfg[2],
339                                                                            nfa_dm_start_up_vsc_cfg[3],
340                                                                            nfa_dm_start_up_vsc_cfg[4],
341                                                                            nfa_dm_start_up_vsc_cfg[5],
342                                                                            nfa_dm_start_up_vsc_cfg[6],
343                                                                            nfa_dm_start_up_vsc_cfg[7] );
344    }
345
346    actualLen = GetStrValue(NAME_LPTD_CFG, (char*)sConfig, sizeof(sConfig));
347    if (actualLen)
348    {
349        sLptdConfig.append (sConfig, actualLen);
350        p_nfc_hal_dm_lptd_cfg = const_cast<UINT8*> (sLptdConfig.getInternalBuffer ());
351    }
352
353    mayDisableSecureElement (sStartupConfig);
354    p_nfc_hal_dm_start_up_cfg = const_cast<UINT8*> (sStartupConfig.getInternalBuffer ());
355
356    actualLen = GetStrValue(NAME_NFA_DM_PRE_DISCOVERY_CFG, (char*)sConfig, sizeof(sConfig));
357    if (actualLen)
358    {
359        sPreDiscoveryConfig.append (sConfig, actualLen);
360        mayDisableSecureElement (sPreDiscoveryConfig);
361        p_nfc_hal_pre_discover_cfg = const_cast<UINT8*> (sPreDiscoveryConfig.getInternalBuffer ());
362    }
363}
364
365/*******************************************************************************
366**
367** Function         StartPatchDownload
368**
369** Description      Reads configuration settings, and begins the download
370**                  process if patch files are configured.
371**
372** Returns:         None
373**
374*******************************************************************************/
375static void StartPatchDownload(UINT32 chipid)
376{
377    ALOGD ("%s: chipid=%lx",__FUNCTION__, chipid);
378
379    char chipID[30];
380    sprintf(chipID, "%lx", chipid);
381    ALOGD ("%s: chidId=%s", __FUNCTION__, chipID);
382
383    readOptionalConfig(chipID);     // Read optional chip specific settings
384    readOptionalConfig("fime");     // Read optional FIME specific settings
385    getNfaValues();                 // Get NFA configuration values into variables
386
387
388    findPatchramFile(FW_PATCH, sPatchFn, sizeof(sPatchFn));
389    findPatchramFile(FW_PRE_PATCH, sPrePatchFn, sizeof(sPatchFn));
390
391    {
392        FILE *fd;
393        /* If an I2C fix patch file was specified, then tell the stack about it */
394        if (sPrePatchFn[0] != '\0')
395        {
396            if ((fd = fopen(sPrePatchFn, "rb")) != NULL)
397            {
398                UINT32 lenPrmBuffer = getFileLength(fd);
399
400                if ((sI2cFixPrmBuf = malloc(lenPrmBuffer)) != NULL)
401                {
402                    fread(sI2cFixPrmBuf, lenPrmBuffer, 1, fd);
403
404                    ALOGD("%s Setting I2C fix to %s (size: %lu)", __FUNCTION__, sPrePatchFn, lenPrmBuffer);
405                    HAL_NfcPrmSetI2cPatch((UINT8*)sI2cFixPrmBuf, (UINT16)lenPrmBuffer, 0);
406                }
407                else
408                {
409                    ALOGE("%s Unable to get buffer to i2c fix (%lu bytes)", __FUNCTION__, lenPrmBuffer);
410                }
411
412                fclose(fd);
413            }
414            else
415            {
416                ALOGE("%s Unable to open i2c fix patchfile %s", __FUNCTION__, sPrePatchFn);
417            }
418        }
419    }
420
421    {
422        FILE *fd;
423
424        /* If a patch file was specified, then download it now */
425        if (sPatchFn[0] != '\0')
426        {
427            UINT32 bDownloadStarted = false;
428
429            /* open patchfile, read it into a buffer */
430            if ((fd = fopen(sPatchFn, "rb")) != NULL)
431            {
432                UINT32 lenPrmBuffer = getFileLength(fd);
433                ALOGD("%s Downloading patchfile %s (size: %lu) format=%u", __FUNCTION__, sPatchFn, lenPrmBuffer, NFC_HAL_PRM_FORMAT_NCD);
434                if ((sPrmBuf = malloc(lenPrmBuffer)) != NULL)
435                {
436                    fread(sPrmBuf, lenPrmBuffer, 1, fd);
437
438                    if (!SpdHelper::isPatchBad((UINT8*)sPrmBuf, lenPrmBuffer))
439                    {
440                        /* Download patch using static memeory mode */
441                        HAL_NfcPrmDownloadStart(NFC_HAL_PRM_FORMAT_NCD, 0, (UINT8*)sPrmBuf, lenPrmBuffer, 0, prmCallback);
442                        bDownloadStarted = true;
443                    }
444                }
445                else
446                    ALOGE("%s Unable to buffer to hold patchram (%lu bytes)", __FUNCTION__, lenPrmBuffer);
447
448                fclose(fd);
449            }
450            else
451                ALOGE("%s Unable to open patchfile %s", __FUNCTION__, sPatchFn);
452
453            /* If the download never got started */
454            if (!bDownloadStarted)
455            {
456                /* If debug mode, fail in an obvious way, otherwise try to start stack */
457                postDownloadPatchram(SpdHelper::isSpdDebug() ? HAL_NFC_STATUS_FAILED :
458                        HAL_NFC_STATUS_OK);
459            }
460        }
461        else
462        {
463            ALOGE("%s: No patchfile specified or disabled. Proceeding to post-download procedure...", __FUNCTION__);
464            postDownloadPatchram(HAL_NFC_STATUS_OK);
465        }
466    }
467
468    ALOGD ("%s: exit", __FUNCTION__);
469}
470
471/*******************************************************************************
472**
473** Function:    nfc_hal_post_reset_init
474**
475** Description: Called by the NFC HAL after controller has been reset.
476**              Begin to download firmware patch files.
477**
478** Returns:     none
479**
480*******************************************************************************/
481void nfc_hal_post_reset_init (UINT32 brcm_hw_id, UINT8 nvm_type)
482{
483    ALOGD("%s: brcm_hw_id=0x%lx, nvm_type=%d", __FUNCTION__, brcm_hw_id, nvm_type);
484    tHAL_NFC_STATUS stat = HAL_NFC_STATUS_FAILED;
485    UINT8 max_credits = 1;
486
487    if (nvm_type == NCI_SPD_NVM_TYPE_NONE)
488    {
489        ALOGD("%s: No NVM detected, FAIL the init stage to force a retry", __FUNCTION__);
490        USERIAL_PowerupDevice (0);
491        stat = HAL_NfcReInit ();
492    }
493    else
494    {
495        /* Start downloading the patch files */
496        StartPatchDownload(brcm_hw_id);
497
498        if (GetNumValue(MAX_RF_DATA_CREDITS, &max_credits, sizeof(max_credits)) && (max_credits > 0))
499        {
500            ALOGD("%s : max_credits=%d", __FUNCTION__, max_credits);
501            HAL_NfcSetMaxRfDataCredits(max_credits);
502        }
503    }
504}
505
506
507/*******************************************************************************
508**
509** Function:        mayDisableSecureElement
510**
511** Description:     Optionally adjust a TLV to disable secure element.  This feature
512**                  is enabled by setting the system property
513**                  nfc.disable_secure_element to a bit mask represented by a hex
514**                  octet: C0 = do not detect any secure element.
515**                         40 = do not detect secure element in slot 0.
516**                         80 = do not detect secure element in slot 1.
517**
518**                  config: a sequence of TLV's.
519**
520*******************************************************************************/
521void mayDisableSecureElement (StartupConfig& config)
522{
523    unsigned int bitmask = 0;
524    char valueStr [PROPERTY_VALUE_MAX] = {0};
525    int len = property_get ("nfc.disable_secure_element", valueStr, "");
526    if (len > 0)
527    {
528        sscanf (valueStr, "%x", &bitmask); //read system property as a hex octet
529        ALOGD ("%s: disable 0x%02X", __FUNCTION__, (UINT8) bitmask);
530        config.disableSecureElement ((UINT8) (bitmask & 0xC0));
531    }
532}
533