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