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