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