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