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