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