| /* |
| * Copyright (C) 2010 NXP Semiconductors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /*! |
| * =========================================================================== * |
| * * |
| * * |
| * \file phDnldNfc.c * |
| * \brief Download Mgmt Interface Source for the Firmware Download. * |
| * * |
| * * |
| * Project: NFC-FRI-1.1 * |
| * * |
| * $Date: Tue Jun 28 14:25:44 2011 $ * |
| * $Author: ing04880 $ * |
| * $Revision: 1.33 $ * |
| * $Aliases: $ |
| * * |
| * =========================================================================== * |
| */ |
| |
| |
| /* |
| ################################################################################ |
| ***************************** Header File Inclusion **************************** |
| ################################################################################ |
| */ |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <phNfcConfig.h> |
| #include <phNfcCompId.h> |
| #include <phNfcIoctlCode.h> |
| #include <phDnldNfc.h> |
| #include <phOsalNfc.h> |
| #include <phOsalNfc_Timer.h> |
| #include <phDal4Nfc.h> |
| #include <utils/Log.h> |
| /* |
| ################################################################################ |
| ****************************** Macro Definitions ******************************* |
| ################################################################################ |
| */ |
| |
| #ifndef STATIC |
| #define STATIC static |
| #endif |
| |
| #if defined (DNLD_SUMMARY) && !defined (DNLD_TRACE) |
| #define DNLD_TRACE |
| #endif |
| |
| /* #if defined(PHDBG_INFO) && defined (PHDBG_CRITICAL_ERROR) */ |
| #if defined(DNLD_TRACE) |
| extern char phOsalNfc_DbgTraceBuffer[]; |
| |
| #define MAX_TRACE_BUFFER 0x0410 |
| #define Trace_buffer phOsalNfc_DbgTraceBuffer |
| /* #define DNLD_PRINT( str ) phOsalNfc_DbgTrace(str) */ |
| #define DNLD_PRINT( str ) phOsalNfc_DbgString(str) |
| #define DNLD_DEBUG(str, arg) \ |
| { \ |
| snprintf(Trace_buffer,MAX_TRACE_BUFFER,str,arg); \ |
| phOsalNfc_DbgString(Trace_buffer); \ |
| } |
| #define DNLD_PRINT_BUFFER(msg,buf,len) \ |
| { \ |
| snprintf(Trace_buffer,MAX_TRACE_BUFFER,"\n\t %s:",msg); \ |
| phOsalNfc_DbgString(Trace_buffer); \ |
| phOsalNfc_DbgTrace(buf,len); \ |
| phOsalNfc_DbgString("\r"); \ |
| } |
| #else |
| #define DNLD_PRINT( str ) |
| #define DNLD_DEBUG(str, arg) |
| #define DNLD_PRINT_BUFFER(msg,buf,len) |
| #endif |
| |
| #define DO_DELAY(period) usleep(period) |
| |
| /* delay after SW reset cmd in ms, required on uart for XTAL stability */ |
| #define PHDNLD_DNLD_DELAY 5000 |
| //#define PHDNLD_MAX_PACKET 0x0200U /* Max Total Packet Size is 512 */ |
| #define PHDNLD_MAX_PACKET 32U /* Max Total Packet Size is 512 */ |
| #define PHDNLD_DATA_SIZE ((PHDNLD_MAX_PACKET)- 8U) /* 0x01F8U */ |
| /* Max Data Size is 504 */ |
| #define PHDNLD_MIN_PACKET 0x03U /* Minimum Packet Size is 3*/ |
| |
| #define DNLD_DEFAULT_RESPONSE_TIMEOUT 0x4000U |
| |
| #define NXP_FW_MIN_TX_RX_LEN 0x0AU |
| |
| |
| #if defined( NXP_FW_MAX_TX_RX_LEN ) && \ |
| ( NXP_FW_MAX_TX_RX_LEN > NXP_FW_MIN_TX_RX_LEN ) |
| |
| #define PHDNLD_FW_TX_RX_LEN NXP_FW_MAX_TX_RX_LEN |
| |
| #elif !defined( NXP_FW_MAX_TX_RX_LEN ) |
| |
| /* To specify the Maximum TX/RX Len */ |
| #define NXP_FW_MAX_TX_RX_LEN 0x200 |
| #define PHDNLD_FW_TX_RX_LEN NXP_FW_MAX_TX_RX_LEN |
| |
| #else |
| |
| #define PHDNLD_FW_TX_RX_LEN NXP_FW_MIN_TX_RX_LEN |
| |
| #endif |
| |
| #define PHDNLD_FRAME_LEN_SIZE 0x02U |
| #define PHDNLD_ADDR_SIZE 0x03U |
| #define PHDNLD_DATA_LEN_SIZE 0x02U |
| #define PHDNLD_FRAME_DATA_OFFSET 0x03U |
| |
| #define DNLD_SM_UNLOCK_MASK 0x01U |
| #define DNLD_TRIM_MASK 0x02U |
| #define DNLD_RESET_MASK 0x04U |
| #define DNLD_VERIFY_MASK 0x08U |
| #define DNLD_CRITICAL_MASK 0x10U |
| |
| |
| #define NXP_NFC_IMAG_FW_MAX 0x05U |
| |
| #define PHDNLD_FW_PATCH_SEC 0x5FU |
| |
| #define PHDNLD_PAGE_SIZE 0x80U /* Page Size Configured for 64 Bytes */ |
| |
| #define FW_MAX_SECTION 0x15U /* Max Number of Sections */ |
| |
| #define DNLD_CRC16_SIZE 0x02U |
| |
| #define DNLD_CRC32_SIZE 0x04U |
| |
| #define DNLD_CFG_PG_ADDR 0x00008000U |
| #define DNLD_FW_CODE_ADDR 0x00800000U |
| #define DNLD_PATCH_CODE_ADDR 0x00018800U |
| #define DNLD_PATCH_TABLE_ADDR 0x00008200U |
| |
| |
| /* Raw Command to pass the Data in Download Mode */ |
| #define PHDNLD_CMD_RAW 0x00U |
| /* Command to Reset the Device in Download Mode */ |
| #define PHDNLD_CMD_RESET 0x01U |
| /* Command to Read from the Address specified in Download Mode */ |
| #define PHDNLD_CMD_READ 0x07U |
| #define PHDNLD_CMD_READ_LEN 0x0005U |
| /* Command to write to the Address specified in Download Mode */ |
| #define PHDNLD_CMD_WRITE 0x08U |
| #define PHDNLD_CMD_SEC_WRITE 0x0CU |
| #define PHDNLD_CMD_WRITE_MIN_LEN 0x0005U |
| #define PHDNLD_CMD_WRITE_MAX_LEN PHDNLD_DATA_SIZE |
| /* Command to verify the data written */ |
| #define PHDNLD_CMD_CHECK 0x06U |
| #define PHDNLD_CMD_CHECK_LEN 0x0007U |
| |
| /* Command to Lock the */ |
| #define PHDNLD_CMD_LOCK 0x40U |
| #define PHDNLD_CMD_LOCK_LEN 0x0002U |
| |
| |
| /* Command to set the Host Interface properties */ |
| #define PHDNLD_CMD_SET_HIF 0x09U |
| |
| /* Command to Activate the Patches Updated */ |
| #define PHDNLD_CMD_ACTIVATE_PATCH 0x0AU |
| |
| /* Command to verify the Integrity of the data written */ |
| #define PHDNLD_CMD_CHECK_INTEGRITY 0x0BU |
| |
| /* Command to verify the Integrity of the data written */ |
| #define PHDNLD_CMD_ENCAPSULATE 0x0DU |
| |
| #define CHECK_INTEGRITY_RESP_CRC16_LEN 0x03U |
| #define CHECK_INTEGRITY_RESP_CRC32_LEN 0x05U |
| #define CHECK_INTEGRITY_RESP_COMP_LEN 0x10U |
| |
| |
| /* Success Response to a Command Sent in the Download Mode */ |
| #define PHDNLD_RESP_SUCCESS 0x00U |
| /* Timeout Response to a Command Sent in the Download Mode */ |
| #define PHDNLD_RESP_TIMEOUT 0x01U |
| /* CRC Error Response to a Command Sent in the Download Mode */ |
| #define PHDNLD_RESP_CRC_ERROR 0x02U |
| /* Access Denied Response to a Command Sent in the Download Mode */ |
| #define PHDNLD_RESP_ACCESS_DENIED 0x08U |
| /* PROTOCOL Error Response to a Command Sent in the Download Mode */ |
| #define PHDNLD_RESP_PROTOCOL_ERROR 0x0BU |
| /* Invalid parameter Response to a Command Sent in the Download Mode */ |
| #define PHDNLD_RESP_INVALID_PARAMETER 0x11U |
| /* Command Not Supported Response to a Command Sent in the Download Mode */ |
| #define PHDNLD_RESP_CMD_NOT_SUPPORTED 0x13U |
| /* Length parameter error Response to a Command Sent in the Download Mode */ |
| #define PHDNLD_RESP_INVALID_LENGTH 0x18U |
| /* Checksum Error Response to a Command Sent in the Download Mode */ |
| #define PHDNLD_RESP_CHKSUM_ERROR 0x19U |
| /* Version already uptodate Response to a Command Sent in the Download Mode */ |
| #define PHDNLD_RESP_VERSION_UPTODATE 0x1DU |
| /* Memory operation error during the processing of |
| the Command Frame in the Download Mode */ |
| #define PHDNLD_RESP_MEMORY_UPDATE_ERROR 0x20U |
| /* The Chaining of the Command Frame was Successful in the Download Mode */ |
| #define PHDNLD_RESP_CHAINING_SUCCESS 0x21U |
| /* The Command is not allowed anymore in the Download Mode */ |
| #define PHDNLD_RESP_CMD_NOT_ALLOWED 0xE0U |
| /* The Error during the Chaining the Command Frame in the Download Mode */ |
| #define PHDNLD_RESP_CHAINING_ERROR 0xE6U |
| /* Write Error Response to a Command Sent in the Download Mode */ |
| #define PHDNLD_RESP_WRITE_ERROR 0x74U |
| |
| #define PNDNLD_WORD_LEN 0x04U |
| |
| #define NXP_MAX_DNLD_RETRY 0x02U |
| |
| #define NXP_MAX_SECTION_WRITE 0x05U |
| |
| #define NXP_PATCH_VER_INDEX 0x05U |
| |
| |
| /* |
| ################################################################################ |
| ******************** Enumeration and Structure Definition ********************** |
| ################################################################################ |
| */ |
| |
| typedef enum phDnldNfc_eSeqType{ |
| DNLD_SEQ_RESET = 0x00U, |
| DNLD_SEQ_INIT, |
| DNLD_SEQ_RAW, |
| DNLD_SEQ_LOCK, |
| DNLD_SEQ_UNLOCK, |
| DNLD_SEQ_UPDATE, |
| DNLD_SEQ_ROLLBACK, |
| DNLD_SEQ_COMPLETE |
| } phDnldNfc_eSeqType_t; |
| |
| typedef enum phDnldNfc_eState |
| { |
| phDnld_Reset_State = 0x00, |
| phDnld_Unlock_State, |
| phDnld_Upgrade_State, |
| phDnld_Verify_State, |
| phDnld_Complete_State, |
| phDnld_Invalid_State |
| }phDnldNfc_eState_t; |
| |
| |
| typedef enum phDnldNfc_eSeq |
| { |
| phDnld_Reset_Seq = 0x00, |
| phDnld_Activate_Patch, |
| phDnld_Deactivate_Patch, |
| phDnld_Update_Patch, |
| phDnld_Update_Patchtable, |
| phDnld_Lock_System, |
| phDnld_Unlock_System, |
| phDnld_Upgrade_Section, |
| phDnld_Verify_Integrity, |
| phDnld_Verify_Section, |
| phDnld_Complete_Seq, |
| phDnld_Raw_Upgrade, |
| phDnld_Invalid_Seq |
| }phDnldNfc_eSeq_t; |
| |
| typedef enum phDnldNfc_eChkCrc{ |
| CHK_INTEGRITY_CONFIG_PAGE_CRC = 0x00U, |
| CHK_INTEGRITY_PATCH_TABLE_CRC = 0x01U, |
| CHK_INTEGRITY_FLASH_CODE_CRC = 0x02U, |
| CHK_INTEGRITY_PATCH_CODE_CRC = 0x03U, |
| CHK_INTEGRITY_COMPLETE_CRC = 0xFFU |
| } phDnldNfc_eChkCrc_t; |
| |
| |
| |
| typedef struct hw_comp_tbl |
| { |
| uint8_t hw_version[3]; |
| uint8_t compatibility; |
| }hw_comp_tbl_t; |
| |
| |
| typedef struct img_data_hdr |
| { |
| /* Image Identification */ |
| uint32_t img_id; |
| /* Offset of the Data from the header */ |
| uint8_t img_data_offset; |
| /* Number of fimware images available in the img_data */ |
| uint8_t no_of_fw_img; |
| /* Fimware image Padding in the img_data */ |
| uint8_t fw_img_pad[2]; |
| /* HW Compatiblity table for the set of the Hardwares */ |
| hw_comp_tbl_t comp_tbl; |
| /* This data consists of the firmware images required to download */ |
| }img_data_hdr_t; |
| |
| |
| typedef struct fw_data_hdr |
| { |
| /* The data offset from the firmware header. |
| * Just in case if in future we require to |
| * add some more information. |
| */ |
| uint8_t fw_hdr_len; |
| /* Total size of all the sections which needs to be updated */ |
| uint8_t no_of_sections; |
| uint8_t hw_comp_no; |
| uint8_t fw_patch; |
| uint32_t fw_version; |
| }fw_data_hdr_t; |
| |
| |
| |
| /* This data consists all the sections that needs to be downloaded */ |
| typedef struct section_hdr |
| { |
| uint8_t section_hdr_len; |
| uint8_t section_mem_type; |
| uint8_t section_checksum; |
| uint8_t section_conf; |
| uint32_t section_address; |
| uint32_t section_length; |
| }section_hdr_t; |
| |
| typedef struct section_info |
| { |
| section_hdr_t *p_sec_hdr; |
| uint8_t *p_trim_data; |
| /* The section data consist of the Firmware binary required |
| * to be loaded to the particular address. |
| */ |
| uint8_t *p_sec_data; |
| /* The Section checksum to verify the integrity of the section |
| * data. |
| */ |
| uint8_t *p_sec_chksum; |
| /** \internal Index used to refer and process the |
| * Firmware Section Data */ |
| volatile uint32_t section_offset; |
| |
| /** \internal Section Read Sequence */ |
| volatile uint8_t section_read; |
| |
| /** \internal Section Write Sequence */ |
| volatile uint8_t section_write; |
| |
| /** \internal TRIM Write Sequence */ |
| volatile uint8_t trim_write; |
| |
| volatile uint8_t sec_verify_retry; |
| |
| }section_info_t; |
| |
| |
| typedef struct phDnldNfc_sParam |
| { |
| uint8_t data_addr[PHDNLD_ADDR_SIZE]; |
| uint8_t data_len[PHDNLD_DATA_LEN_SIZE]; |
| uint8_t data_packet[PHDNLD_DATA_SIZE]; |
| }phDnldNfc_sParam_t; |
| |
| typedef struct phDnldNfc_sDataHdr |
| { |
| uint8_t frame_type; |
| uint8_t frame_length[PHDNLD_FRAME_LEN_SIZE]; |
| }phDnldNfc_sData_Hdr_t; |
| |
| typedef struct phDnldNfc_sRawHdr |
| { |
| uint8_t frame_type; |
| uint8_t frame_length[PHDNLD_FRAME_LEN_SIZE]; |
| }phDnldNfc_sRawHdr_t; |
| |
| typedef struct phDnldNfc_sRawDataHdr |
| { |
| uint8_t data_addr[PHDNLD_ADDR_SIZE]; |
| uint8_t data_len[PHDNLD_DATA_LEN_SIZE]; |
| }phDnldNfc_sRawDataHdr_t; |
| |
| typedef struct phDnldNfc_sChkCrc16_Resp |
| { |
| uint8_t Chk_status; |
| uint8_t Chk_Crc16[2]; |
| |
| }phDnldNfc_sChkCrc16_Resp_t; |
| |
| typedef struct phDnldNfc_sChkCrc32_Resp |
| { |
| uint8_t Chk_status; |
| uint8_t Chk_Crc32[4]; |
| |
| }phDnldNfc_sChkCrc32_Resp_t; |
| |
| |
| typedef struct phDnldNfc_sChkCrcComplete |
| { |
| phDnldNfc_sChkCrc16_Resp_t config_page; |
| phDnldNfc_sChkCrc16_Resp_t patch_table; |
| phDnldNfc_sChkCrc32_Resp_t flash_code; |
| phDnldNfc_sChkCrc32_Resp_t patch_code; |
| }phDnldNfc_sChkCrcComplete_t; |
| |
| typedef struct phDnldNfc_sData |
| { |
| uint8_t frame_type; |
| uint8_t frame_length[PHDNLD_FRAME_LEN_SIZE]; |
| union param |
| { |
| phDnldNfc_sParam_t data_param; |
| uint8_t response_data[PHDNLD_MAX_PACKET]; |
| uint8_t cmd_param; |
| }param_info; |
| }phDnldNfc_sData_t; |
| |
| #ifdef NXP_NFC_MULTIPLE_FW |
| |
| typedef struct phDnldNfc_sFwImageInfo |
| { |
| /** \internal Data Pointer to the Firmware header section of the Firmware */ |
| fw_data_hdr_t *p_fw_hdr; |
| /** \internal Buffer pointer to store the Firmware Section Data */ |
| section_info_t *p_fw_sec; |
| /** \internal Buffer pointer to store the Firmware Raw Data */ |
| uint8_t *p_fw_raw; |
| }phDnldNfc_sFwImageInfo_t; |
| |
| #endif /* #ifdef NXP_NFC_MULTIPLE_FW */ |
| |
| |
| typedef struct phDnldNfc_TxInfo |
| { |
| uint8_t *transmit_frame; |
| |
| uint16_t tx_offset; |
| |
| /** \internal Remaining amount of data to be sent */ |
| uint16_t tx_len; |
| |
| uint16_t tx_total; |
| |
| /** \internal Chain information for the data to be sent */ |
| uint8_t tx_chain; |
| |
| }phDnldNfc_TxInfo_t; |
| |
| |
| typedef struct phDnldNfc_RxInfo |
| { |
| /** \internal Total length of the received buffer */ |
| uint16_t rx_total; |
| /** \internal Chain information of the received buffer */ |
| uint16_t rx_chain; |
| /** \internal Remaining Data information to be read to complete the |
| * Data Information. |
| */ |
| uint16_t rx_remain; |
| |
| /** \internal Buffer to Send the Raw Data Frame */ |
| uint8_t raw_buffer_data[PHDNLD_MAX_PACKET |
| + PHDNLD_PAGE_SIZE]; |
| }phDnldNfc_RxInfo_t; |
| |
| |
| typedef struct phDnldNfc_sContext |
| { |
| /** \internal Structure to store the lower interface operations */ |
| phNfc_sLowerIF_t lower_interface; |
| |
| phNfc_sData_t *p_fw_version; |
| |
| /** \internal Pointer to the Hardware Reference Sturcture */ |
| phHal_sHwReference_t *p_hw_ref; |
| |
| /** \internal Pointer to the upper layer notification callback function */ |
| pphNfcIF_Notification_CB_t p_upper_notify; |
| /** \internal Pointer to the upper layer context */ |
| void *p_upper_context; |
| |
| /** \internal Timer ID for the Download Abort */ |
| uint32_t timer_id; |
| /** \internal Internal Download for the Download Abort */ |
| uint32_t dnld_timeout; |
| /** \internal Data Pointer to the Image header section of the Firmware */ |
| img_data_hdr_t *p_img_hdr; |
| |
| #ifdef NXP_NFC_MULTIPLE_FW |
| /** \internal Data Pointer to the Firmware Image Information */ |
| phDnldNfc_sFwImageInfo_t *p_img_info; |
| #endif /* #ifdef NXP_NFC_MULTIPLE_FW */ |
| |
| /** \internal Data Pointer to the Firmware header section of the Firmware */ |
| fw_data_hdr_t *p_fw_hdr; |
| /** \internal Buffer pointer to store the Firmware Data */ |
| section_info_t *p_fw_sec; |
| /** \internal Buffer pointer to store the Firmware Raw Data */ |
| uint8_t *p_fw_raw; |
| |
| /** \internal Previous Download Size */ |
| uint32_t prev_dnld_size; |
| |
| /** \internal Single Data Block to download the Firmware */ |
| uint8_t dnld_data[PHDNLD_MAX_PACKET |
| + PHDNLD_PAGE_SIZE]; |
| /** \internal Index used to refer and process the Download Data */ |
| volatile uint32_t dnld_index; |
| |
| /** \internal Response Data to process the response */ |
| phDnldNfc_sData_t dnld_resp; |
| |
| /** \internal Previously downloaded data stored |
| * to compare the written data */ |
| phNfc_sData_t dnld_store; |
| |
| /** \internal Previously downloaded trimmed data stored |
| * to compare the written data */ |
| phNfc_sData_t trim_store; |
| |
| uint8_t *p_resp_buffer; |
| |
| phDnldNfc_sChkCrcComplete_t chk_integrity_crc; |
| |
| phDnldNfc_eChkCrc_t chk_integrity_param; |
| |
| #define NXP_FW_SW_VMID_TRIM |
| #ifdef NXP_FW_SW_VMID_TRIM |
| |
| #define NXP_FW_VMID_TRIM_CHK_ADDR 0x0000813DU |
| #define NXP_FW_VMID_CARD_MODE_ADDR 0x00009931U |
| #define NXP_FW_VMID_RD_MODE_ADDR 0x00009981U |
| |
| uint8_t vmid_trim_update; |
| #endif /* #ifdef NXP_FW_SW_VMID_TRIM */ |
| |
| uint8_t cur_frame_info; |
| |
| uint8_t raw_mode_upgrade; |
| |
| uint8_t *p_patch_table_crc; |
| |
| uint8_t *p_flash_code_crc; |
| |
| uint8_t *p_patch_code_crc; |
| |
| uint16_t resp_length; |
| |
| /** \internal Current FW Section in Process */ |
| volatile uint8_t section_index; |
| |
| /** \internal Previous Command sent */ |
| volatile uint8_t prev_cmd; |
| |
| uint8_t dnld_retry; |
| |
| /** \internal Current Download State */ |
| volatile uint8_t cur_dnld_state; |
| /** \internal Next Download State */ |
| volatile uint8_t next_dnld_state; |
| |
| /** \internal Current step in Download Sequence */ |
| volatile uint8_t cur_dnld_seq; |
| /** \internal Next step in Download Sequence */ |
| volatile uint8_t next_dnld_seq; |
| |
| /* \internal Data Transmit information */ |
| phDnldNfc_TxInfo_t tx_info; |
| |
| /* \internal Data Receive information */ |
| phDnldNfc_RxInfo_t rx_info; |
| |
| |
| }phDnldNfc_sContext_t; |
| |
| |
| /* |
| ################################################################################ |
| ******************** Global and Static Variables Definition ******************** |
| ################################################################################ |
| */ |
| |
| #ifndef NFC_TIMER_CONTEXT |
| static phDnldNfc_sContext_t *gpphDnldContext = NULL; |
| #endif |
| |
| #ifdef NXP_FW_DNLD_CHECK_PHASE |
| |
| #define NXP_FW_DNLD_COMPLETE_PHASE 0x00U |
| #define NXP_FW_DNLD_SYSTEM_PHASE 0x01U |
| #define NXP_FW_DNLD_CFG_PHASE 0x02U |
| #define NXP_FW_DNLD_DATA_PHASE 0x03U |
| #define NXP_FW_DNLD_RAW_PHASE 0x04U |
| #define NXP_FW_DNLD_INVALID_PHASE 0xFFU |
| |
| static uint8_t gphDnldPhase = NXP_FW_DNLD_COMPLETE_PHASE; |
| |
| #endif /* #ifdef NXP_FW_DNLD_CHECK_PHASE */ |
| |
| /**/ |
| |
| /* |
| *************************** Static Function Declaration ************************** |
| */ |
| |
| STATIC |
| NFCSTATUS |
| phDnldNfc_Send_Command( |
| phDnldNfc_sContext_t *psDnldContext, |
| void *pHwRef, |
| uint8_t cmd, |
| void *params, |
| uint16_t param_length |
| ); |
| |
| static |
| NFCSTATUS |
| phDnldNfc_Process_FW( |
| phDnldNfc_sContext_t *psDnldContext, |
| phHal_sHwReference_t *pHwRef |
| #ifdef NXP_FW_PARAM |
| , |
| uint8_t *nxp_nfc_fw, |
| uint32_t fw_length |
| #endif |
| ); |
| |
| STATIC |
| void |
| phDnldNfc_Send_Complete ( |
| void *psContext, |
| void *pHwRef, |
| phNfc_sTransactionInfo_t *pInfo |
| ); |
| |
| STATIC |
| void |
| phDnldNfc_Receive_Complete ( |
| void *psContext, |
| void *pHwRef, |
| phNfc_sTransactionInfo_t *pInfo |
| ); |
| |
| STATIC |
| NFCSTATUS |
| phDnldNfc_Process_Response( |
| phDnldNfc_sContext_t *psDnldContext, |
| void *pHwRef, |
| void *pdata, |
| uint16_t length |
| ); |
| |
| |
| static |
| NFCSTATUS |
| phDnldNfc_Resume( |
| phDnldNfc_sContext_t *psDnldContext, |
| void *pHwRef, |
| void *pdata, |
| uint16_t length |
| ); |
| |
| static |
| NFCSTATUS |
| phDnldNfc_Resume_Write( |
| phDnldNfc_sContext_t *psDnldContext, |
| void *pHwRef |
| ); |
| |
| static |
| NFCSTATUS |
| phDnldNfc_Process_Write( |
| phDnldNfc_sContext_t *psDnldContext, |
| void *pHwRef, |
| section_info_t *p_sec_info, |
| uint32_t *p_sec_offset |
| ); |
| |
| static |
| NFCSTATUS |
| phDnldNfc_Sequence( |
| phDnldNfc_sContext_t *psDnldContext, |
| void *pHwRef, |
| void *pdata, |
| uint16_t length |
| ); |
| |
| static |
| NFCSTATUS |
| phDnldNfc_Upgrade_Sequence( |
| phDnldNfc_sContext_t *psDnldContext, |
| void *pHwRef, |
| void *pdata, |
| uint16_t length |
| ); |
| |
| STATIC |
| NFCSTATUS |
| phDnldNfc_Receive( |
| void *psContext, |
| void *pHwRef, |
| uint8_t *pdata, |
| uint16_t length |
| ); |
| |
| |
| STATIC |
| NFCSTATUS |
| phDnldNfc_Send ( |
| void *psContext, |
| void *pHwRef, |
| uint8_t *pdata, |
| uint16_t length |
| ); |
| |
| STATIC |
| NFCSTATUS |
| phDnldNfc_Set_Seq( |
| phDnldNfc_sContext_t *psDnldContext, |
| phDnldNfc_eSeqType_t seq_type |
| ); |
| |
| static |
| void |
| phDnldNfc_Notify( |
| pphNfcIF_Notification_CB_t p_upper_notify, |
| void *p_upper_context, |
| void *pHwRef, |
| uint8_t type, |
| void *pInfo |
| ); |
| |
| STATIC |
| NFCSTATUS |
| phDnldNfc_Allocate_Resource ( |
| void **ppBuffer, |
| uint16_t size |
| ); |
| |
| STATIC |
| void |
| phDnldNfc_Release_Resources ( |
| phDnldNfc_sContext_t **ppsDnldContext |
| ); |
| |
| STATIC |
| void |
| phDnldNfc_Release_Lower( |
| phDnldNfc_sContext_t *psDnldContext, |
| void *pHwRef |
| ); |
| |
| |
| static |
| NFCSTATUS |
| phDnldNfc_Read( |
| phDnldNfc_sContext_t *psDnldContext, |
| void *pHwRef, |
| section_info_t *p_sec_info |
| ); |
| |
| STATIC |
| void |
| phDnldNfc_Abort ( |
| uint32_t abort_id |
| #ifdef NFC_TIMER_CONTEXT |
| , void *dnld_cntxt |
| #endif |
| ); |
| |
| |
| #ifdef DNLD_CRC_CALC |
| |
| static |
| void |
| phDnldNfc_UpdateCrc16( |
| uint8_t crcByte, |
| uint16_t *pCrc |
| ); |
| |
| STATIC |
| uint16_t |
| phDnldNfc_ComputeCrc16( |
| uint8_t *pData, |
| uint16_t length |
| ); |
| |
| |
| /* |
| *************************** Function Definitions ************************** |
| */ |
| #define CRC32_POLYNOMIAL 0xEDB88320L |
| |
| static uint32_t CRC32Table[0x100]; |
| |
| void BuildCRCTable() |
| { |
| unsigned long crc; |
| uint8_t i = 0, j = 0; |
| |
| for ( i = 0; i <= 0xFF ; i++ ) |
| { |
| crc = i; |
| for ( j = 8 ; j> 0; j-- ) |
| { |
| if ( crc & 1 ) |
| { |
| crc = ( crc>> 1 ) ^ CRC32_POLYNOMIAL; |
| } |
| else |
| { |
| crc>>= 1; |
| } |
| } |
| CRC32Table[ i ] = crc; |
| } |
| } |
| |
| /* |
| * This routine calculates the CRC for a block of data using the |
| * table lookup method. It accepts an original value for the crc, |
| * and returns the updated value. |
| */ |
| |
| uint32_t CalculateCRC32( void *buffer , uint32_t count, uint32_t crc ) |
| { |
| uint8_t *p; |
| uint32_t temp1; |
| uint32_t temp2; |
| |
| p = (uint8_t *) buffer; |
| while ( count-- != 0 ) { |
| temp1 = ( crc>> 8 ) & 0x00FFFFFFL; |
| temp2 = CRC32Table[ ( (int) crc ^ *p++ ) & 0xff ]; |
| crc = temp1 ^ temp2; |
| } |
| return( crc ); |
| } |
| |
| |
| static |
| void |
| phDnldNfc_UpdateCrc16( |
| uint8_t crcByte, |
| uint16_t *pCrc |
| ) |
| { |
| crcByte = (crcByte ^ (uint8_t)((*pCrc) & 0x00FF)); |
| crcByte = (crcByte ^ (uint8_t)(crcByte << 4)); |
| *pCrc = (*pCrc >> 8) ^ ((uint16_t)crcByte << 8) ^ |
| ((uint16_t)crcByte << 3) ^ |
| ((uint16_t)crcByte >> 4); |
| } |
| |
| |
| STATIC |
| uint16_t |
| phDnldNfc_ComputeCrc16( |
| uint8_t *pData, |
| uint16_t length |
| ) |
| { |
| uint8_t crc_byte = 0; |
| uint16_t index = 0; |
| uint16_t crc = 0; |
| |
| #ifdef CRC_A |
| crc = 0x6363; /* ITU-V.41 */ |
| #else |
| crc = 0xFFFF; /* ISO/IEC 13239 (formerly ISO/IEC 3309) */ |
| #endif /* #ifdef CRC_A */ |
| |
| do |
| { |
| crc_byte = pData[index]; |
| phDnldNfc_UpdateCrc16(crc_byte, &crc); |
| index++; |
| } while (index < length); |
| |
| #ifndef INVERT_CRC |
| crc = ~crc; /* ISO/IEC 13239 (formerly ISO/IEC 3309) */ |
| #endif /* #ifndef INVERT_CRC */ |
| |
| /* *pCrc1 = (uint8_t) (crc & BYTE_MASK); |
| *pCrc2 = (uint8_t) ((crc >> 8) & BYTE_MASK); */ |
| return crc ; |
| } |
| |
| #endif /* #ifdef DNLD_CRC_CALC */ |
| |
| |
| /*! |
| * \brief Allocation of the Download Interface resources. |
| * |
| * This function releases and frees all the resources used by Download Mode |
| * Feature. |
| */ |
| |
| STATIC |
| NFCSTATUS |
| phDnldNfc_Allocate_Resource ( |
| void **ppBuffer, |
| uint16_t size |
| ) |
| { |
| NFCSTATUS status = NFCSTATUS_SUCCESS; |
| |
| *ppBuffer = (void *) phOsalNfc_GetMemory(size); |
| if( *ppBuffer != NULL ) |
| { |
| (void )memset(((void *)*ppBuffer), 0, |
| size); |
| } |
| else |
| { |
| *ppBuffer = NULL; |
| status = PHNFCSTVAL(CID_NFC_DNLD, |
| NFCSTATUS_INSUFFICIENT_RESOURCES); |
| } |
| return status; |
| } |
| |
| |
| /*! |
| * \brief Release of the Download Interface resources. |
| * |
| * This function releases and frees all the resources used by Download layer. |
| */ |
| |
| STATIC |
| void |
| phDnldNfc_Release_Resources ( |
| phDnldNfc_sContext_t **ppsDnldContext |
| ) |
| { |
| |
| if(NULL != (*ppsDnldContext)->p_resp_buffer) |
| { |
| phOsalNfc_FreeMemory((*ppsDnldContext)->p_resp_buffer); |
| (*ppsDnldContext)->p_resp_buffer = NULL; |
| } |
| if(NULL != (*ppsDnldContext)->dnld_store.buffer) |
| { |
| phOsalNfc_FreeMemory((*ppsDnldContext)->dnld_store.buffer); |
| (*ppsDnldContext)->dnld_store.buffer = NULL; |
| (*ppsDnldContext)->dnld_store.length = 0; |
| } |
| if(NULL != (*ppsDnldContext)->trim_store.buffer) |
| { |
| phOsalNfc_FreeMemory((*ppsDnldContext)->trim_store.buffer); |
| (*ppsDnldContext)->trim_store.buffer = NULL; |
| (*ppsDnldContext)->trim_store.length = 0; |
| } |
| if(NULL != (*ppsDnldContext)->p_fw_sec) |
| { |
| phOsalNfc_FreeMemory((*ppsDnldContext)->p_fw_sec); |
| (*ppsDnldContext)->p_fw_sec = NULL; |
| } |
| if ( NXP_INVALID_TIMER_ID != (*ppsDnldContext)->timer_id ) |
| { |
| phOsalNfc_Timer_Stop((*ppsDnldContext)->timer_id ); |
| phOsalNfc_Timer_Delete((*ppsDnldContext)->timer_id ); |
| (*ppsDnldContext)->timer_id = NXP_INVALID_TIMER_ID; |
| } |
| |
| phOsalNfc_FreeMemory((*ppsDnldContext)); |
| (*ppsDnldContext) = NULL; |
| |
| return ; |
| } |
| |
| |
| STATIC |
| void |
| phDnldNfc_Release_Lower( |
| phDnldNfc_sContext_t *psDnldContext, |
| void *pHwRef |
| ) |
| { |
| phNfc_sLowerIF_t *plower_if = |
| &(psDnldContext->lower_interface); |
| NFCSTATUS status = NFCSTATUS_SUCCESS; |
| |
| PHNFC_UNUSED_VARIABLE(status); |
| |
| if(NULL != plower_if->release) |
| { |
| #ifdef DNLD_LOWER_RELEASE |
| status = plower_if->release((void *)plower_if->pcontext, |
| (void *)pHwRef); |
| #else |
| PHNFC_UNUSED_VARIABLE(pHwRef); |
| |
| #endif |
| (void)memset((void *)plower_if, |
| 0, sizeof(phNfc_sLowerIF_t)); |
| DNLD_DEBUG(" FW_DNLD: Releasing the Lower Layer Resources: Status = %02X\n" |
| ,status); |
| } |
| |
| return; |
| } |
| |
| |
| |
| static |
| void |
| phDnldNfc_Notify( |
| pphNfcIF_Notification_CB_t p_upper_notify, |
| void *p_upper_context, |
| void *pHwRef, |
| uint8_t type, |
| void *pInfo |
| ) |
| { |
| if( ( NULL != p_upper_notify) ) |
| { |
| /* Notify the to the Upper Layer */ |
| (p_upper_notify)(p_upper_context, pHwRef, type, pInfo); |
| } |
| } |
| |
| |
| STATIC |
| NFCSTATUS |
| phDnldNfc_Set_Seq( |
| phDnldNfc_sContext_t *psDnldContext, |
| phDnldNfc_eSeqType_t seq_type |
| ) |
| { |
| NFCSTATUS status = NFCSTATUS_SUCCESS; |
| static uint8_t prev_temp_state = 0; |
| static uint8_t prev_temp_seq = |
| (uint8_t) phDnld_Activate_Patch; |
| |
| switch(seq_type) |
| { |
| case DNLD_SEQ_RESET: |
| case DNLD_SEQ_INIT: |
| { |
| psDnldContext->cur_dnld_state = |
| (uint8_t) phDnld_Reset_State; |
| psDnldContext->next_dnld_state = |
| (uint8_t)phDnld_Upgrade_State; |
| psDnldContext->cur_dnld_seq = |
| (uint8_t)phDnld_Upgrade_Section; |
| psDnldContext->next_dnld_seq = |
| psDnldContext->cur_dnld_seq; |
| break; |
| } |
| case DNLD_SEQ_RAW: |
| { |
| psDnldContext->cur_dnld_state = |
| (uint8_t) phDnld_Reset_State; |
| psDnldContext->next_dnld_state = |
| (uint8_t)phDnld_Upgrade_State; |
| psDnldContext->cur_dnld_seq = |
| (uint8_t)phDnld_Raw_Upgrade; |
| psDnldContext->next_dnld_seq = |
| psDnldContext->cur_dnld_seq; |
| break; |
| } |
| case DNLD_SEQ_UNLOCK: |
| { |
| psDnldContext->cur_dnld_state = |
| (uint8_t) phDnld_Reset_State; |
| |
| #ifdef NXP_FW_DNLD_CHECK_PHASE |
| if( NXP_FW_DNLD_SYSTEM_PHASE < gphDnldPhase ) |
| { |
| psDnldContext->next_dnld_state = |
| (uint8_t)phDnld_Upgrade_State; |
| psDnldContext->cur_dnld_seq = |
| (uint8_t)phDnld_Upgrade_Section; |
| } |
| else |
| #endif /* NXP_FW_DNLD_CHECK_PHASE */ |
| { |
| psDnldContext->next_dnld_state = |
| (uint8_t) phDnld_Unlock_State; |
| psDnldContext->cur_dnld_seq = |
| (uint8_t) phDnld_Activate_Patch; |
| } |
| psDnldContext->next_dnld_seq = |
| psDnldContext->cur_dnld_seq; |
| break; |
| } |
| case DNLD_SEQ_LOCK: |
| { |
| psDnldContext->cur_dnld_state = |
| (uint8_t) phDnld_Reset_State; |
| psDnldContext->next_dnld_state = |
| (uint8_t) phDnld_Reset_State; |
| psDnldContext->cur_dnld_seq = |
| (uint8_t) phDnld_Lock_System; |
| psDnldContext->next_dnld_seq = |
| psDnldContext->cur_dnld_seq; |
| break; |
| } |
| case DNLD_SEQ_UPDATE: |
| { |
| prev_temp_state = (uint8_t) psDnldContext->cur_dnld_state; |
| psDnldContext->cur_dnld_state = |
| psDnldContext->next_dnld_state; |
| /* psDnldContext->next_dnld_state = |
| (uint8_t)phDnld_Invalid_State ; */ |
| prev_temp_seq = (uint8_t) psDnldContext->cur_dnld_seq; |
| psDnldContext->cur_dnld_seq = |
| psDnldContext->next_dnld_seq; |
| break; |
| } |
| case DNLD_SEQ_ROLLBACK: |
| { |
| psDnldContext->cur_dnld_seq = (uint8_t) prev_temp_seq; |
| psDnldContext->next_dnld_seq = |
| (uint8_t)phDnld_Invalid_Seq ; |
| prev_temp_seq = 0; |
| |
| psDnldContext->cur_dnld_state = (uint8_t) prev_temp_state; |
| /* psDnldContext->next_dnld_state = |
| (uint8_t)phDnld_Invalid_State ; */ |
| prev_temp_state = 0; |
| break; |
| } |
| case DNLD_SEQ_COMPLETE: |
| { |
| psDnldContext->cur_dnld_state = |
| (uint8_t) phDnld_Reset_State; |
| psDnldContext->next_dnld_state = |
| (uint8_t) phDnld_Verify_State; |
| psDnldContext->cur_dnld_seq = |
| (uint8_t) phDnld_Verify_Integrity; |
| psDnldContext->next_dnld_seq = |
| psDnldContext->cur_dnld_seq ; |
| break; |
| } |
| default: |
| { |
| break; |
| } |
| } |
| |
| return status; |
| } |
| |
| |
| |
| /*! |
| * \brief Sends the data the corresponding peripheral device. |
| * |
| * This function sends the Download data to the connected NFC Pheripheral device |
| */ |
| |
| |
| STATIC |
| NFCSTATUS |
| phDnldNfc_Send ( |
| void *psContext, |
| void *pHwRef, |
| uint8_t *pdata, |
| uint16_t length |
| ) |
| { |
| phDnldNfc_sContext_t *psDnldContext= (phDnldNfc_sContext_t *)psContext; |
| NFCSTATUS status = NFCSTATUS_SUCCESS; |
| |
| phNfc_sLowerIF_t *plower_if = &(psDnldContext->lower_interface); |
| |
| if( (NULL != plower_if) |
| && (NULL != plower_if->send) |
| ) |
| { |
| #ifndef DNLD_SUMMARY |
| DNLD_PRINT_BUFFER("Send Buffer",pdata,length); |
| #endif |
| status = plower_if->send((void *)plower_if->pcontext, |
| (void *)pHwRef, pdata, length); |
| |
| #if defined(FW_DOWNLOAD_TIMER) && \ |
| (FW_DOWNLOAD_TIMER == 2) |
| if ( |
| (NFCSTATUS_PENDING == status) |
| && ( NXP_INVALID_TIMER_ID != psDnldContext->timer_id ) |
| ) |
| { |
| psDnldContext->dnld_timeout = NXP_DNLD_COMPLETE_TIMEOUT; |
| |
| if ( psDnldContext->dnld_timeout |
| < DNLD_DEFAULT_RESPONSE_TIMEOUT) |
| { |
| psDnldContext->dnld_timeout |
| = DNLD_DEFAULT_RESPONSE_TIMEOUT; |
| } |
| /* Start the Download Timer */ |
| phOsalNfc_Timer_Start( psDnldContext->timer_id, |
| psDnldContext->dnld_timeout, |
| (ppCallBck_t) phDnldNfc_Abort |
| #ifdef NFC_TIMER_CONTEXT |
| , (void *) psDnldContext |
| #endif |
| ); |
| |
| DNLD_DEBUG(" DNLD : Timer %X Started ", psDnldContext->timer_id); |
| DNLD_DEBUG(" \t\t With %U Timeout \n", psDnldContext->dnld_timeout); |
| } |
| |
| #endif /* (NXP_NFC_DNLD_TIMER == 1) */ |
| } |
| |
| return status; |
| } |
| |
| |
| /*! |
| * \brief Receives the Download Mode Response from the corresponding peripheral device. |
| * |
| * This function receives the Download Command Response to the connected NFC |
| * Pheripheral device. |
| */ |
| |
| STATIC |
| NFCSTATUS |
| phDnldNfc_Receive( |
| void *psContext, |
| void *pHwRef, |
| uint8_t *pdata, |
| uint16_t length |
| ) |
| { |
| phDnldNfc_sContext_t *psDnldContext= (phDnldNfc_sContext_t *)psContext; |
| phNfc_sLowerIF_t *plower_if = NULL ; |
| NFCSTATUS status = NFCSTATUS_SUCCESS; |
| |
| if(NULL == psDnldContext ) |
| { |
| status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); |
| } |
| else |
| { |
| plower_if = &(psDnldContext->lower_interface); |
| |
| if( (NULL != plower_if) |
| && (NULL != plower_if->receive) |
| ) |
| { |
| status = plower_if->receive((void *)plower_if->pcontext, |
| (void *)pHwRef, pdata, length); |
| } |
| } |
| return status; |
| } |
| |
| |
| static |
| NFCSTATUS |
| phDnldNfc_Read( |
| phDnldNfc_sContext_t *psDnldContext, |
| void *pHwRef, |
| section_info_t *p_sec_info |
| ) |
| { |
| NFCSTATUS status = NFCSTATUS_SUCCESS; |
| phDnldNfc_sData_t *p_dnld_data = |
| (phDnldNfc_sData_t *)psDnldContext->dnld_data; |
| phDnldNfc_sParam_t *p_data_param = |
| &p_dnld_data->param_info.data_param; |
| uint32_t read_addr = (p_sec_info->p_sec_hdr->section_address |
| + p_sec_info->section_offset); |
| static unsigned sec_type = 0; |
| uint8_t i = 0; |
| uint16_t read_size = 0 ; |
| |
| sec_type = (unsigned int)p_sec_info->p_sec_hdr->section_mem_type; |
| |
| if( ( FALSE == p_sec_info->section_read ) |
| && ((sec_type & DNLD_TRIM_MASK)) |
| && (FALSE == p_sec_info->trim_write) ) |
| { |
| read_size = (uint16_t) p_sec_info->p_sec_hdr->section_length; |
| DNLD_DEBUG(" FW_DNLD: Section Read = %X \n", read_size); |
| } |
| else |
| { |
| if (( FALSE == p_sec_info->section_read ) |
| && ((sec_type & DNLD_VERIFY_MASK)) |
| ) |
| { |
| read_size = (uint16_t)(psDnldContext->prev_dnld_size ); |
| DNLD_DEBUG(" FW_DNLD: Section Read = %X \n", read_size); |
| } |
| else if( ( TRUE == p_sec_info->section_read ) |
| && ( TRUE == p_sec_info->section_write ) |
| ) |
| { |
| /*Already Read the Data Hence Ignore the Read */ |
| DNLD_DEBUG(" FW_DNLD: Already Read, Read Ignored, read_size = %X \n", read_size); |
| } |
| else |
| { |
| /* Ignore the Read */ |
| DNLD_DEBUG(" FW_DNLD: Section Read Status = %X \n", p_sec_info->section_read); |
| DNLD_DEBUG(" FW_DNLD: Section Write Status = %X \n", p_sec_info->section_write); |
| DNLD_DEBUG(" FW_DNLD: No Read Required, Read_size = %X \n", read_size); |
| } |
| } |
| |
| if (read_size != 0) |
| { |
| |
| read_size = (uint16_t)((PHDNLD_DATA_SIZE >= read_size)? |
| read_size: PHDNLD_DATA_SIZE); |
| |
| p_dnld_data->frame_length[i] = (uint8_t)0; |
| /* Update the LSB of the Data and the Address Parameter*/ |
| p_data_param->data_addr[i] = (uint8_t)((read_addr >> |
| (BYTE_SIZE + BYTE_SIZE)) & BYTE_MASK); |
| p_data_param->data_len[i] = (uint8_t)((read_size >> |
| BYTE_SIZE) & BYTE_MASK); |
| i++; |
| |
| p_dnld_data->frame_length[i] = (uint8_t) |
| ( PHDNLD_CMD_READ_LEN & BYTE_MASK); |
| /* Update the 2nd byte of the Data and the Address Parameter*/ |
| p_data_param->data_addr[i] = (uint8_t)((read_addr >> |
| BYTE_SIZE) & BYTE_MASK); |
| p_data_param->data_len[i] = (uint8_t) (read_size & BYTE_MASK); |
| i++; |
| |
| /* Update the 3rd byte of the the Address Parameter*/ |
| p_data_param->data_addr[i] = (uint8_t)(read_addr & BYTE_MASK); |
| |
| status = phDnldNfc_Send_Command( psDnldContext, pHwRef, |
| PHDNLD_CMD_READ, NULL , 0 ); |
| |
| if ( NFCSTATUS_PENDING == status ) |
| { |
| p_sec_info->section_read = TRUE ; |
| psDnldContext->next_dnld_state = phDnld_Upgrade_State; |
| DNLD_DEBUG(" FW_DNLD: Memory Read at Address %X : ", read_addr); |
| DNLD_DEBUG(" of Size %X \n", read_size); |
| } |
| |
| } |
| return status; |
| } |
| |
| |
| |
| static |
| NFCSTATUS |
| phDnldNfc_Process_Write( |
| phDnldNfc_sContext_t *psDnldContext, |
| void *pHwRef, |
| section_info_t *p_sec_info, |
| uint32_t *p_sec_offset |
| ) |
| { |
| NFCSTATUS status = NFCSTATUS_SUCCESS; |
| phDnldNfc_sData_t *p_dnld_data = |
| (phDnldNfc_sData_t *)psDnldContext->dnld_data; |
| phDnldNfc_sParam_t *dnld_data = |
| &p_dnld_data->param_info.data_param; |
| uint8_t *p_sm_trim_data = (uint8_t *)psDnldContext-> |
| dnld_resp.param_info.response_data; |
| uint32_t dnld_addr = 0; |
| #ifdef NXP_FW_SW_VMID_TRIM |
| uint32_t trim_addr = 0; |
| #endif /* #ifdef NXP_FW_SW_VMID_TRIM */ |
| static unsigned sec_type = 0; |
| uint8_t i = 0; |
| uint16_t dnld_size = 0; |
| int cmp_val = 0x00; |
| |
| |
| sec_type = (unsigned int)p_sec_info->p_sec_hdr->section_mem_type; |
| |
| status = phDnldNfc_Read(psDnldContext, pHwRef, p_sec_info); |
| if( NFCSTATUS_PENDING != status ) |
| { |
| if( (TRUE == p_sec_info->trim_write) |
| && (TRUE == p_sec_info->section_read) |
| && ((sec_type & DNLD_VERIFY_MASK)) |
| ) |
| { |
| if(NULL != psDnldContext->trim_store.buffer) |
| { |
| uint32_t trim_cmp_size = psDnldContext->prev_dnld_size; |
| |
| if( p_sec_info->p_sec_hdr->section_address |
| < (DNLD_CFG_PG_ADDR + PHDNLD_PAGE_SIZE) ) |
| { |
| trim_cmp_size = trim_cmp_size - 2; |
| } |
| |
| /* Below Comparison fails due to the checksum */ |
| cmp_val = phOsalNfc_MemCompare( |
| psDnldContext->trim_store.buffer, |
| &psDnldContext->dnld_resp. |
| param_info.response_data[0] |
| ,trim_cmp_size); |
| DNLD_DEBUG(" FW_DNLD: %X Bytes Trim Write Complete ", |
| psDnldContext->prev_dnld_size); |
| DNLD_DEBUG(" Comparison Status %X\n", cmp_val); |
| } |
| p_sec_info->trim_write = FALSE; |
| DNLD_DEBUG(" FW_DNLD: TRIMMED %X Bytes Write Complete\n", psDnldContext->prev_dnld_size); |
| } |
| else |
| { |
| if((NULL != psDnldContext->dnld_store.buffer) |
| && ((sec_type & DNLD_VERIFY_MASK)) |
| && (TRUE == p_sec_info->section_write) |
| && (TRUE == p_sec_info->section_read) |
| ) |
| { |
| cmp_val = phOsalNfc_MemCompare( |
| psDnldContext->dnld_store.buffer, |
| &psDnldContext->dnld_resp. |
| param_info.response_data[0] |
| ,psDnldContext->dnld_store.length); |
| p_sec_info->section_read = FALSE; |
| p_sec_info->section_write = FALSE; |
| DNLD_DEBUG(" FW_DNLD: %X Bytes Write Complete ", |
| psDnldContext->dnld_store.length); |
| DNLD_DEBUG(" Comparison Status %X\n", cmp_val); |
| } |
| else |
| { |
| if(( TRUE == p_sec_info->section_write) |
| && ( FALSE == p_sec_info->section_read) |
| ) |
| { |
| p_sec_info->section_write = FALSE; |
| } |
| } |
| /* p_sec_info->section_read = FALSE; */ |
| } |
| |
| if (( 0 == psDnldContext->dnld_retry ) |
| && (0 == cmp_val) |
| ) |
| { |
| p_sec_info->sec_verify_retry = 0; |
| p_sec_info->section_offset = p_sec_info->section_offset + |
| psDnldContext->prev_dnld_size; |
| psDnldContext->prev_dnld_size = 0; |
| DNLD_DEBUG(" FW_DNLD: Memory Write Retry - %X \n", |
| psDnldContext->dnld_retry); |
| } |
| else |
| { |
| p_sec_info->sec_verify_retry++; |
| DNLD_DEBUG(" FW_DNLD: Memory Verification Failed, Retry = %X \n", |
| p_sec_info->sec_verify_retry); |
| } |
| |
| if( p_sec_info->sec_verify_retry < NXP_MAX_SECTION_WRITE ) |
| { |
| |
| dnld_addr = (p_sec_info->p_sec_hdr->section_address + *p_sec_offset); |
| dnld_size = (uint16_t)(p_sec_info->p_sec_hdr->section_length |
| - *p_sec_offset); |
| } |
| else |
| { |
| status = NFCSTATUS_FAILED; |
| DNLD_DEBUG(" FW_DNLD: Memory Verification - Maximum Limit, Retry = %X \n", |
| p_sec_info->sec_verify_retry); |
| } |
| } |
| |
| |
| if (dnld_size != 0) |
| { |
| |
| dnld_size = (uint16_t)((PHDNLD_DATA_SIZE >= dnld_size)? |
| dnld_size: PHDNLD_DATA_SIZE); |
| |
| /* Update the LSB of the Data and the Address Parameter*/ |
| dnld_data->data_addr[i] = (uint8_t)((dnld_addr >> |
| (BYTE_SIZE + BYTE_SIZE)) & BYTE_MASK); |
| dnld_data->data_len[i] = (uint8_t)((dnld_size >> BYTE_SIZE) |
| & BYTE_MASK); |
| p_dnld_data->frame_length[i] = (uint8_t) |
| (((dnld_size + PHDNLD_CMD_WRITE_MIN_LEN) >> BYTE_SIZE) |
| & BYTE_MASK); |
| i++; |
| /* Update the 2nd byte of the Data and the Address Parameter*/ |
| dnld_data->data_addr[i] = (uint8_t)((dnld_addr >> BYTE_SIZE) |
| & BYTE_MASK); |
| dnld_data->data_len[i] = (uint8_t) (dnld_size & BYTE_MASK); |
| p_dnld_data->frame_length[i] = (uint8_t) ((dnld_size + |
| PHDNLD_CMD_WRITE_MIN_LEN) & BYTE_MASK); |
| i++; |
| /* Update the 3rd byte of the the Address Parameter*/ |
| dnld_data->data_addr[i] = (uint8_t)(dnld_addr & BYTE_MASK); |
| |
| (void)memcpy( dnld_data->data_packet, |
| (p_sec_info->p_sec_data + *p_sec_offset), dnld_size ); |
| |
| if( ((sec_type & DNLD_TRIM_MASK)) |
| && (p_sec_info->sec_verify_retry != 0) |
| && (NULL != psDnldContext->trim_store.buffer) |
| ) |
| { |
| (void)memcpy( dnld_data->data_packet, |
| psDnldContext->trim_store.buffer, dnld_size ); |
| } |
| else if(((sec_type & DNLD_TRIM_MASK)) |
| && ( TRUE == p_sec_info->section_read ) |
| ) |
| { |
| for(i = 0; i < *(p_sec_info->p_trim_data);i++) |
| { |
| |
| #ifdef NXP_FW_SW_VMID_TRIM |
| |
| /* |
| if(bit 0 of 0x813D is equal to 1) then |
| |
| Do not overwrite 0x9931 / 0x9981 during download |
| |
| else |
| |
| @0x9931 = 0x79 // card Mode |
| @0x9981 = 0x79 // Reader Mode |
| */ |
| trim_addr = p_sec_info->p_sec_hdr->section_address |
| + p_sec_info->p_trim_data[i+1]; |
| if (NXP_FW_VMID_TRIM_CHK_ADDR == trim_addr) |
| { |
| psDnldContext->vmid_trim_update = |
| p_sm_trim_data[p_sec_info->p_trim_data[i+1]] ; |
| } |
| |
| if((NXP_FW_VMID_CARD_MODE_ADDR == trim_addr) |
| || (NXP_FW_VMID_RD_MODE_ADDR == trim_addr)) |
| { |
| if (TRUE == psDnldContext->vmid_trim_update) |
| { |
| dnld_data->data_packet[p_sec_info->p_trim_data[i+1]] = |
| p_sm_trim_data[p_sec_info->p_trim_data[i+1]] ; |
| } |
| } |
| else |
| |
| #endif |
| { |
| dnld_data->data_packet[p_sec_info->p_trim_data[i+1]] = |
| p_sm_trim_data[p_sec_info->p_trim_data[i+1]] ; |
| } |
| } |
| if(NULL != psDnldContext->trim_store.buffer) |
| { |
| phOsalNfc_FreeMemory(psDnldContext->trim_store.buffer); |
| psDnldContext->trim_store.buffer = NULL; |
| psDnldContext->trim_store.length = 0; |
| } |
| #if 1 |
| (void) |
| phDnldNfc_Allocate_Resource((void **) |
| &(psDnldContext->trim_store.buffer),dnld_size); |
| #else |
| psDnldContext->trim_store.buffer = |
| (uint8_t *) phOsalNfc_GetMemory(dnld_size); |
| #endif |
| |
| if(NULL != psDnldContext->trim_store.buffer) |
| { |
| (void )memset((void *)psDnldContext->trim_store.buffer,0, |
| dnld_size); |
| (void)memcpy( psDnldContext->trim_store.buffer, |
| dnld_data->data_packet, dnld_size ); |
| psDnldContext->trim_store.length = dnld_size; |
| DNLD_DEBUG(" FW_DNLD: Write with Trimming at Address %X ", dnld_addr ); |
| DNLD_DEBUG(" of Size %X and ", dnld_size ); |
| DNLD_DEBUG(" with %X Trimming Values \n", *(p_sec_info->p_trim_data) ); |
| |
| } |
| } |
| else |
| { |
| if(NULL != psDnldContext->dnld_store.buffer) |
| { |
| phOsalNfc_FreeMemory(psDnldContext->dnld_store.buffer); |
| psDnldContext->dnld_store.buffer = NULL; |
| psDnldContext->dnld_store.length = 0; |
| } |
| #if 1 |
| (void) |
| phDnldNfc_Allocate_Resource((void **) |
| &(psDnldContext->dnld_store.buffer),dnld_size); |
| #else |
| psDnldContext->dnld_store.buffer = |
| (uint8_t *) phOsalNfc_GetMemory(dnld_size); |
| #endif |
| if(NULL != psDnldContext->dnld_store.buffer) |
| { |
| (void )memset((void *)psDnldContext->dnld_store.buffer,0, |
| dnld_size); |
| (void)memcpy( psDnldContext->dnld_store.buffer, |
| dnld_data->data_packet, dnld_size ); |
| psDnldContext->dnld_store.length = dnld_size; |
| DNLD_DEBUG(" FW_DNLD: Memory Write at Address %X ", dnld_addr ); |
| DNLD_DEBUG(" of Size %X ", dnld_size ); |
| } |
| } |
| |
| if(PHDNLD_FW_PATCH_SEC != psDnldContext->p_fw_hdr->fw_patch) |
| { |
| status = phDnldNfc_Send_Command( psDnldContext, pHwRef, |
| PHDNLD_CMD_WRITE, NULL , 0 ); |
| } |
| else |
| { |
| status = phDnldNfc_Send_Command( psDnldContext, pHwRef, |
| PHDNLD_CMD_SEC_WRITE, NULL , 0 ); |
| } |
| |
| DNLD_DEBUG(" FW_DNLD: Memory Write Status = %X \n", status); |
| if ( NFCSTATUS_PENDING == status ) |
| { |
| psDnldContext->prev_dnld_size = dnld_size; |
| cmp_val = 0x00; |
| if((sec_type & DNLD_TRIM_MASK)) |
| { |
| p_sec_info->trim_write = TRUE; |
| DNLD_DEBUG(" FW_DNLD: Bytes Downloaded (Trimming Values) = %X Bytes \n", |
| dnld_size); |
| } |
| else |
| { |
| p_sec_info->section_write = TRUE; |
| DNLD_DEBUG(" FW_DNLD: Bytes Downloaded = %X : ", |
| (*p_sec_offset + dnld_size)); |
| DNLD_DEBUG(" Bytes Remaining = %X \n", |
| (p_sec_info->p_sec_hdr->section_length - |
| (*p_sec_offset + dnld_size))); |
| } |
| |
| p_sec_info->section_read = FALSE; |
| } |
| } |
| return status; |
| } |
| |
| |
| |
| static |
| NFCSTATUS |
| phDnldNfc_Resume_Write( |
| phDnldNfc_sContext_t *psDnldContext, |
| void *pHwRef |
| ) |
| { |
| NFCSTATUS status = NFCSTATUS_SUCCESS; |
| uint8_t sec_index = psDnldContext->section_index; |
| section_info_t *p_sec_info = (psDnldContext->p_fw_sec + sec_index); |
| |
| while((sec_index < psDnldContext->p_fw_hdr->no_of_sections) |
| && (NFCSTATUS_SUCCESS == status ) |
| ) |
| { |
| |
| status = phDnldNfc_Process_Write(psDnldContext, pHwRef, |
| p_sec_info, (uint32_t *)&(p_sec_info->section_offset)); |
| if (NFCSTATUS_SUCCESS == status) |
| { |
| unsigned sec_type = 0; |
| sec_type = (unsigned int)p_sec_info->p_sec_hdr->section_mem_type; |
| |
| p_sec_info->section_offset = 0; |
| p_sec_info->section_read = FALSE; |
| p_sec_info->section_write = FALSE; |
| p_sec_info->trim_write = FALSE; |
| |
| DNLD_DEBUG(" FW_DNLD: Section %02X Download Complete\n", sec_index); |
| if((sec_type & DNLD_RESET_MASK)) |
| { |
| DNLD_DEBUG(" FW_DNLD: Reset After Section %02X Download \n", sec_index); |
| status = phDnldNfc_Send_Command( psDnldContext, pHwRef, |
| PHDNLD_CMD_RESET , NULL, 0 ); |
| } |
| DNLD_PRINT("*******************************************\n\n"); |
| |
| sec_index++; |
| |
| #ifdef NXP_FW_DNLD_CHECK_PHASE |
| if( p_sec_info->p_sec_hdr->section_address |
| < (DNLD_CFG_PG_ADDR + PHDNLD_PAGE_SIZE) ) |
| { |
| gphDnldPhase = NXP_FW_DNLD_DATA_PHASE; |
| |
| } |
| |
| p_sec_info = (psDnldContext->p_fw_sec + sec_index); |
| |
| if( (sec_index < psDnldContext->p_fw_hdr->no_of_sections) |
| && ( p_sec_info->p_sec_hdr->section_address |
| < (DNLD_CFG_PG_ADDR + PHDNLD_PAGE_SIZE) ) |
| ) |
| { |
| if( NXP_FW_DNLD_CFG_PHASE >= gphDnldPhase ) |
| { |
| gphDnldPhase = NXP_FW_DNLD_CFG_PHASE; |
| } |
| else |
| { |
| sec_index++; |
| p_sec_info = (psDnldContext->p_fw_sec + sec_index); |
| } |
| } |
| #else |
| p_sec_info = (psDnldContext->p_fw_sec + sec_index); |
| #endif /* #ifdef NXP_FW_DNLD_CHECK_PHASE */ |
| |
| psDnldContext->section_index = sec_index; |
| /* psDnldContext->next_dnld_state = (uint8_t) phDnld_Upgrade_State; */ |
| } |
| } |
| if (NFCSTATUS_PENDING == status) |
| { |
| psDnldContext->next_dnld_state = (uint8_t) phDnld_Upgrade_State; |
| } |
| else if (NFCSTATUS_SUCCESS == status) |
| { |
| /* Reset the PN544 Device */ |
| psDnldContext->next_dnld_state = (uint8_t) phDnld_Complete_State; |
| } |
| else |
| { |
| |
| } |
| return status; |
| } |
| |
| |
| #define NXP_DNLD_SM_UNLOCK_ADDR 0x008002U |
| |
| #if !defined (ES_HW_VER) |
| #define ES_HW_VER 32 |
| #endif |
| |
| #if (ES_HW_VER <= 30) |
| #define NXP_DNLD_PATCH_ADDR 0x01AFFFU |
| #else |
| #define NXP_DNLD_PATCH_ADDR 0x01A1E0U |
| #endif |
| |
| #if (ES_HW_VER <= 30) |
| #define NXP_DNLD_PATCH_TABLE_ADDR 0x008107U |
| #else |
| #define NXP_DNLD_PATCH_TABLE_ADDR 0x00825AU |
| #endif |
| |
| |
| static |
| NFCSTATUS |
| phDnldNfc_Sequence( |
| phDnldNfc_sContext_t *psDnldContext, |
| void *pHwRef, |
| void *pdata, |
| uint16_t length |
| ) |
| { |
| NFCSTATUS status = NFCSTATUS_SUCCESS; |
| uint32_t dnld_addr = 0; |
| phDnldNfc_sData_t *p_dnld_data = |
| (phDnldNfc_sData_t *)psDnldContext->dnld_data; |
| phDnldNfc_sParam_t *p_data_param = |
| & p_dnld_data->param_info.data_param; |
| uint8_t *p_data = NULL; |
| static uint32_t patch_size = 0; |
| |
| #if (ES_HW_VER == 32) |
| |
| static uint8_t patch_table[] = {0xA0, 0xA1, 0xE0, 0x80, 0xA9, 0x6C }; |
| static uint8_t patch_data[] = {0xA5, 0xD0, 0xFE, 0xA5, 0xD0, 0xFD, 0xA5, |
| 0xD0, 0xFC, 0xA5, 0x02, 0x80, 0xA9, 0x75}; |
| |
| #elif (ES_HW_VER == 31) |
| |
| static uint8_t patch_table[] = {0xA0, 0xAF, 0xE0, 0x80, 0x78, 0x84 }; |
| static uint8_t patch_data[] = {0xA5, 0xD0, 0xFE, 0xA5, 0xD0, 0xFD, 0xA5, |
| 0xD0, 0xFC, 0xD0, 0xE0, 0xA5, 0x02, 0x80, 0x78, 0x8D}; |
| |
| #elif (ES_HW_VER == 30) |
| |
| static uint8_t patch_table[] = {0x80, 0x91, 0x51, 0xA0, 0xAF, |
| 0xFF, 0x80, 0x91, 0x5A}; |
| static uint8_t patch_data[] = {0x22}; |
| |
| #endif |
| |
| static uint8_t unlock_data[] = {0x00, 0x00}; |
| static uint8_t lock_data[] = {0x0C, 0x00}; |
| |
| uint8_t i = 0; |
| |
| PHNFC_UNUSED_VARIABLE(pdata); |
| PHNFC_UNUSED_VARIABLE(length); |
| switch(psDnldContext->cur_dnld_seq) |
| { |
| case phDnld_Reset_Seq: |
| { |
| status = phDnldNfc_Send_Command( psDnldContext, pHwRef, |
| PHDNLD_CMD_RESET , NULL , 0 ); |
| /* status = (NFCSTATUS_PENDING == status)? NFCSTATUS_SUCCESS: |
| status; */ |
| DNLD_DEBUG(" FW_DNLD: Reset Seq.. Status = %X \n", status); |
| |
| break; |
| } |
| case phDnld_Activate_Patch: |
| { |
| uint8_t patch_activate = 0x01; |
| psDnldContext->next_dnld_seq = |
| (uint8_t)phDnld_Update_Patch; |
| #ifdef NXP_FW_DNLD_CHECK_PHASE |
| gphDnldPhase = NXP_FW_DNLD_SYSTEM_PHASE; |
| #endif /* NXP_FW_DNLD_CHECK_PHASE */ |
| |
| status = phDnldNfc_Send_Command( psDnldContext, pHwRef, |
| PHDNLD_CMD_ACTIVATE_PATCH , &patch_activate, sizeof(patch_activate) ); |
| DNLD_PRINT(" FW_DNLD: Activate the Patch Update .... \n"); |
| break; |
| } |
| case phDnld_Deactivate_Patch: |
| { |
| uint8_t patch_activate = 0x00; |
| |
| psDnldContext->next_dnld_state = |
| (uint8_t)phDnld_Reset_State; |
| |
| status = phDnldNfc_Send_Command( psDnldContext, pHwRef, |
| PHDNLD_CMD_ACTIVATE_PATCH , &patch_activate, sizeof(patch_activate) ); |
| DNLD_PRINT(" FW_DNLD: Deactivate the Patch Update .... \n"); |
| break; |
| } |
| case phDnld_Update_Patch: |
| { |
| dnld_addr = NXP_DNLD_PATCH_ADDR; |
| patch_size = sizeof(patch_data) ; |
| p_data = patch_data; |
| psDnldContext->next_dnld_seq = |
| (uint8_t)phDnld_Update_Patchtable; |
| DNLD_PRINT(" FW_DNLD: Patch Update Seq.... \n"); |
| break; |
| } |
| case phDnld_Update_Patchtable: |
| { |
| dnld_addr = NXP_DNLD_PATCH_TABLE_ADDR; |
| patch_size = sizeof(patch_table) ; |
| p_data = patch_table; |
| |
| psDnldContext->next_dnld_state = |
| (uint8_t)phDnld_Reset_State; |
| |
| DNLD_PRINT(" FW_DNLD: Patch Table Update Seq.... \n"); |
| break; |
| } |
| case phDnld_Unlock_System: |
| { |
| dnld_addr = NXP_DNLD_SM_UNLOCK_ADDR; |
| patch_size = sizeof(unlock_data) ; |
| p_data = unlock_data; |
| #define NXP_FW_PATCH_DISABLE |
| #ifdef NXP_FW_PATCH_DISABLE |
| psDnldContext->next_dnld_seq = |
| (uint8_t)phDnld_Deactivate_Patch; |
| #else |
| psDnldContext->next_dnld_state = |
| (uint8_t)phDnld_Reset_State; |
| #endif |
| |
| DNLD_PRINT(" FW_DNLD: System Memory Unlock Seq.... \n"); |
| break; |
| } |
| case phDnld_Lock_System: |
| { |
| dnld_addr = NXP_DNLD_SM_UNLOCK_ADDR; |
| patch_size = sizeof(lock_data) ; |
| p_data = lock_data; |
| psDnldContext->next_dnld_state = |
| (uint8_t) phDnld_Reset_State; |
| |
| DNLD_PRINT(" FW_DNLD: System Memory Lock Seq.... \n"); |
| break; |
| } |
| case phDnld_Upgrade_Section: |
| { |
| status = phDnldNfc_Resume_Write( |
| psDnldContext, pHwRef ); |
| break; |
| } |
| case phDnld_Verify_Integrity: |
| { |
| psDnldContext->next_dnld_state = |
| (uint8_t) phDnld_Reset_State; |
| |
| status = phDnldNfc_Send_Command( psDnldContext, pHwRef, |
| PHDNLD_CMD_CHECK_INTEGRITY , NULL, 0 ); |
| DNLD_PRINT(" FW_DNLD: System Memory Integrity Check Sequence.... \n"); |
| break; |
| } |
| case phDnld_Verify_Section: |
| { |
| break; |
| } |
| default: |
| { |
| break; |
| } |
| } |
| |
| if( NFCSTATUS_SUCCESS == status) |
| { |
| |
| /* Update the LSB of the Data and the Address Parameter*/ |
| p_data_param->data_addr[i] = (uint8_t)((dnld_addr >> |
| (BYTE_SIZE + BYTE_SIZE)) |
| & BYTE_MASK); |
| p_data_param->data_len[i] = (uint8_t)((patch_size >> BYTE_SIZE) |
| & BYTE_MASK); |
| p_dnld_data->frame_length[i] = (uint8_t) |
| (((patch_size + PHDNLD_CMD_WRITE_MIN_LEN) >> BYTE_SIZE) |
| & BYTE_MASK); |
| i++; |
| /* Update the 2nd byte of the Data and the Address Parameter*/ |
| p_data_param->data_addr[i] = (uint8_t)((dnld_addr >> BYTE_SIZE) |
| & BYTE_MASK); |
| p_data_param->data_len[i] = (uint8_t) (patch_size & BYTE_MASK); |
| p_dnld_data->frame_length[i] = (uint8_t) |
| ((patch_size + PHDNLD_CMD_WRITE_MIN_LEN) |
| & BYTE_MASK); |
| i++; |
| /* Update the 3rd byte of the the Address Parameter*/ |
| p_data_param->data_addr[i] = (uint8_t)(dnld_addr & BYTE_MASK); |
| |
| status = phDnldNfc_Send_Command( psDnldContext, pHwRef, |
| PHDNLD_CMD_WRITE,(void *)p_data , (uint8_t)patch_size ); |
| |
| if (NFCSTATUS_PENDING != status) |
| { |
| status = phDnldNfc_Set_Seq(psDnldContext, |
| DNLD_SEQ_ROLLBACK); |
| } |
| } |
| return status; |
| } |
| |
| #define FRAME_HEADER_LEN 0x03U |
| |
| |
| static |
| void |
| phDnldNfc_Tx_Reset(phDnldNfc_sContext_t *psDnldContext) |
| { |
| psDnldContext->tx_info.transmit_frame = NULL; |
| psDnldContext->tx_info.tx_total = 0x00; |
| psDnldContext->tx_info.tx_offset = 0x00; |
| psDnldContext->tx_info.tx_len = 0x00; |
| psDnldContext->tx_info.tx_chain = FALSE; |
| } |
| |
| STATIC |
| bool_t |
| phDnldNfc_Extract_Chunks( |
| uint8_t *frame_data, |
| uint16_t frame_offset, |
| uint16_t frame_length, |
| uint16_t max_frame , |
| uint16_t *chunk_length |
| ); |
| |
| |
| STATIC |
| bool_t |
| phDnldNfc_Extract_Chunks( |
| uint8_t *frame_data, |
| uint16_t frame_offset, |
| uint16_t frame_length, |
| uint16_t max_frame , |
| uint16_t *chunk_length |
| ) |
| { |
| bool_t chunk_present = FALSE; |
| |
| if( 0 == frame_offset) |
| { |
| if( max_frame >= (frame_length |
| - frame_offset)) |
| { |
| *chunk_length = (frame_length - frame_offset); |
| } |
| else |
| { |
| *chunk_length = max_frame |
| - FRAME_HEADER_LEN; |
| chunk_present = TRUE; |
| } |
| } |
| else |
| { |
| if( max_frame >= (frame_length |
| - frame_offset)) |
| { |
| *chunk_length = (frame_length - frame_offset); |
| } |
| else |
| { |
| *chunk_length = max_frame |
| - FRAME_HEADER_LEN; |
| chunk_present = TRUE; |
| } |
| } |
| |
| return chunk_present; |
| } |
| |
| |
| STATIC |
| NFCSTATUS |
| phDnldNfc_Send_Raw( |
| phDnldNfc_sContext_t *psDnldContext, |
| void *pHwRef, |
| uint8_t *raw_frame, |
| uint16_t frame_offset, |
| uint16_t frame_length |
| ) |
| { |
| NFCSTATUS status = NFCSTATUS_SUCCESS; |
| phDnldNfc_sRawHdr_t *raw_frame_hdr = ( phDnldNfc_sRawHdr_t * ) raw_frame; |
| |
| switch(raw_frame_hdr->frame_type) |
| { |
| case PHDNLD_CMD_RESET: |
| { |
| break; |
| } |
| case PHDNLD_CMD_READ: |
| { |
| /* TODO: To Update the length and the buffer to receive data */ |
| break; |
| } |
| case PHDNLD_CMD_WRITE: |
| { |
| phDnldNfc_sRawDataHdr_t *raw_data_hdr = |
| ( phDnldNfc_sRawDataHdr_t * ) (raw_frame + FRAME_HEADER_LEN); |
| |
| psDnldContext->resp_length = PHDNLD_MIN_PACKET; |
| |
| break; |
| } |
| case PHDNLD_CMD_SEC_WRITE: |
| { |
| uint16_t tx_length = 0x00; |
| uint16_t frame_offset = |
| psDnldContext->tx_info.tx_offset; |
| uint16_t chain = |
| psDnldContext->tx_info.tx_chain; |
| |
| chain = |
| phDnldNfc_Extract_Chunks( |
| raw_frame, |
| frame_offset, |
| frame_length, |
| PHDNLD_FW_TX_RX_LEN, |
| &tx_length |
| ); |
| |
| if( TRUE == chain ) |
| { |
| status = phDnldNfc_Send_Command( psDnldContext, |
| pHwRef, PHDNLD_CMD_ENCAPSULATE, |
| (raw_frame + frame_offset), |
| tx_length); |
| if(NFCSTATUS_PENDING == status) |
| { |
| psDnldContext->prev_cmd = raw_frame_hdr->frame_type; |
| /* TODO: Update for the Chaining */ |
| psDnldContext->tx_info.tx_offset += tx_length; |
| psDnldContext->tx_info.tx_chain = chain; |
| } |
| } |
| else if (0 != frame_offset) |
| { |
| status = phDnldNfc_Send_Command( psDnldContext, |
| pHwRef, PHDNLD_CMD_ENCAPSULATE, |
| (raw_frame + frame_offset), |
| tx_length); |
| if(NFCSTATUS_PENDING == status) |
| { |
| psDnldContext->prev_cmd = raw_frame_hdr->frame_type; |
| /* TODO: Update for the Chaining */ |
| psDnldContext->prev_dnld_size = frame_length; |
| phDnldNfc_Tx_Reset(psDnldContext); |
| } |
| } |
| else |
| { |
| phDnldNfc_sRawDataHdr_t *raw_data_hdr = |
| ( phDnldNfc_sRawDataHdr_t * ) (raw_frame + FRAME_HEADER_LEN); |
| psDnldContext->resp_length = PHDNLD_MIN_PACKET; |
| } |
| |
| break; |
| } |
| case PHDNLD_CMD_CHECK: |
| { |
| psDnldContext->resp_length = PHDNLD_MIN_PACKET; |
| break; |
| } |
| case PHDNLD_CMD_SET_HIF: |
| { |
| psDnldContext->resp_length = PHDNLD_MIN_PACKET; |
| break; |
| } |
| case PHDNLD_CMD_ACTIVATE_PATCH: |
| { |
| psDnldContext->resp_length = PHDNLD_MIN_PACKET; |
| break; |
| } |
| case PHDNLD_CMD_CHECK_INTEGRITY: |
| { |
| uint8_t integrity_param = |
| *(raw_frame + FRAME_HEADER_LEN); |
| switch(integrity_param) |
| { |
| case CHK_INTEGRITY_CONFIG_PAGE_CRC: |
| case CHK_INTEGRITY_PATCH_TABLE_CRC: |
| { |
| psDnldContext->resp_length = PHDNLD_MIN_PACKET |
| + CHECK_INTEGRITY_RESP_CRC16_LEN; |
| break; |
| } |
| case CHK_INTEGRITY_FLASH_CODE_CRC: |
| case CHK_INTEGRITY_PATCH_CODE_CRC: |
| { |
| psDnldContext->resp_length = PHDNLD_MIN_PACKET |
| + CHECK_INTEGRITY_RESP_CRC32_LEN; |
| break; |
| } |
| case CHK_INTEGRITY_COMPLETE_CRC: |
| default: |
| { |
| psDnldContext->resp_length = PHDNLD_MIN_PACKET |
| + CHECK_INTEGRITY_RESP_COMP_LEN; |
| break; |
| } |
| } |
| break; |
| } |
| default: |
| { |
| status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FEATURE_NOT_SUPPORTED); |
| break; |
| } |
| } |
| |
| if (NFCSTATUS_SUCCESS == status) |
| { |
| status = phDnldNfc_Send( psDnldContext, pHwRef , |
| raw_frame, frame_length); |
| |
| if(NFCSTATUS_PENDING == status) |
| { |
| psDnldContext->prev_cmd = raw_frame_hdr->frame_type; |
| /* TODO: Update for the Chaining */ |
| psDnldContext->prev_dnld_size = frame_length; |
| } |
| } |
| |
| return status; |
| } |
| |
| |
| static |
| NFCSTATUS |
| phDnldNfc_Frame_Complete(phDnldNfc_sContext_t *psDnldContext) |
| { |
| NFCSTATUS status = NFCSTATUS_SUCCESS; |
| phDnldNfc_sData_Hdr_t *p_dnld_raw = NULL; |
| uint32_t dnld_index = psDnldContext->dnld_index; |
| uint8_t *p_raw_sec_hdr = NULL; |
| uint16_t tx_length = 0x00; |
| |
| dnld_index = dnld_index + psDnldContext->prev_dnld_size; |
| p_raw_sec_hdr = psDnldContext->p_fw_raw + dnld_index; |
| dnld_index = dnld_index + *p_raw_sec_hdr; |
| |
| p_dnld_raw = (phDnldNfc_sData_Hdr_t *) (psDnldContext->p_fw_raw + |
| psDnldContext->dnld_index); |
| |
| tx_length = ((p_dnld_raw->frame_length[0] << BYTE_SIZE) | |
| p_dnld_raw->frame_length[1]); |
| |
| tx_length = tx_length + PHDNLD_MIN_PACKET; |
| |
| return status; |
| } |
| |
| |
| static |
| NFCSTATUS |
| phDnldNfc_Raw_Write( |
| phDnldNfc_sContext_t *psDnldContext, |
| void *pHwRef |
| ) |
| { |
| NFCSTATUS status = NFCSTATUS_SUCCESS; |
| uint32_t dnld_index = psDnldContext->dnld_index; |
| uint32_t tx_length = 0; |
| uint8_t *p_raw_sec_hdr = NULL; |
| uint8_t dnld_flag = FALSE; |
| uint8_t skip_frame = FALSE; |
| |
| if(NULL != psDnldContext->p_fw_raw) |
| { |
| |
| if( (TRUE != psDnldContext->tx_info.tx_chain) |
| && (0x00 == psDnldContext->dnld_retry) |
| ) |
| { |
| dnld_index = dnld_index + psDnldContext->prev_dnld_size; |
| p_raw_sec_hdr = psDnldContext->p_fw_raw + dnld_index; |
| dnld_index = dnld_index + *p_raw_sec_hdr; |
| } |
| else |
| { |
| phDnldNfc_sData_Hdr_t *p_dnld_raw = (phDnldNfc_sData_Hdr_t *) |
| (psDnldContext->p_fw_raw + |
| psDnldContext->dnld_index); |
| |
| tx_length = ((p_dnld_raw->frame_length[0] << BYTE_SIZE) | |
| p_dnld_raw->frame_length[1]); |
| |
| tx_length = tx_length + PHDNLD_MIN_PACKET; |
| |
| status = phDnldNfc_Send_Raw( psDnldContext, pHwRef, |
| (uint8_t *)(p_dnld_raw), |
| psDnldContext->tx_info.tx_offset, |
| (uint16_t)tx_length); |
| } |
| |
| |
| #define PHDNLD_MAJOR_OFFSET 0x04U |
| #define PHDNLD_MINOR_OFFSET 0x05U |
| #define PHDNLD_PHASE_OFFSET 0x06U |
| #define PHDNLD_FRAMETYPE_OFFSET 0x07U |
| |
| #define PHDNLD_NO_OPERATION 0x00U |
| #define PHDNLD_NORMAL_OPERATION 0x10U |
| #define PHDNLD_ADVANCED_OPERATION 0x20U |
| #define PHDNLD_SETUP_OPERATION 0x40U |
| #define PHDNLD_RECOVER_OPERATION 0x80U |
| #define PHDNLD_COMPLETE_OPERATION 0xF0U |
| |
| #define PHDNLD_TERMINATE_TYPE 0x0EU |
| |
| #define PHDNLD_MARKER_MASK 0x0FU |
| |
| while((NFCSTATUS_SUCCESS == status ) |
| && (FALSE == dnld_flag) |
| ) |
| { |
| phDnldNfc_sData_Hdr_t *p_dnld_raw = (phDnldNfc_sData_Hdr_t *) |
| (psDnldContext->p_fw_raw + dnld_index); |
| uint8_t frame_type = *(p_raw_sec_hdr + PHDNLD_FRAMETYPE_OFFSET); |
| |
| tx_length = ((p_dnld_raw->frame_length[0] << BYTE_SIZE) | |
| p_dnld_raw->frame_length[1]); |
| |
| tx_length = tx_length + PHDNLD_MIN_PACKET; |
| |
| skip_frame = FALSE; |
| |
| if( (0x00 == *(p_raw_sec_hdr + PHDNLD_PHASE_OFFSET)) |
| || (0xFF == *(p_raw_sec_hdr + PHDNLD_PHASE_OFFSET)) |
| || !( psDnldContext->raw_mode_upgrade |
| & (frame_type & (~PHDNLD_MARKER_MASK)) ) |
| ) |
| { |
| dnld_index = dnld_index + tx_length; |
| p_raw_sec_hdr = psDnldContext->p_fw_raw + dnld_index; |
| dnld_index = dnld_index + *p_raw_sec_hdr; |
| skip_frame = TRUE; |
| } |
| if (PHDNLD_TERMINATE_TYPE == |
| (frame_type & PHDNLD_MARKER_MASK)) |
| { |
| if(TRUE != skip_frame) |
| { |
| psDnldContext->raw_mode_upgrade = |
| (psDnldContext->raw_mode_upgrade & |
| ~(frame_type & ~PHDNLD_MARKER_MASK)); |
| } |
| |
| if(PHDNLD_NO_OPERATION == |
| psDnldContext->raw_mode_upgrade) |
| { |
| dnld_flag = TRUE; |
| } |
| } |
| else |
| { |
| |
| } |
| |
| if((FALSE == skip_frame) |
| && (FALSE == dnld_flag) |
| ) |
| { |
| status = phDnldNfc_Send_Raw( psDnldContext, pHwRef, |
| (uint8_t *)(p_dnld_raw), |
| psDnldContext->tx_info.tx_offset, |
| (uint16_t)tx_length); |
| } |
| |
| if( NFCSTATUS_PENDING == status ) |
| { |
| psDnldContext->dnld_index = dnld_index; |
| psDnldContext->cur_frame_info= frame_type; |
| } |
| } |
| } |
| |
| return status; |
| } |
| |
| static |
| NFCSTATUS |
| phDnldNfc_Upgrade_Sequence( |
| phDnldNfc_sContext_t *psDnldContext, |
| void *pHwRef, |
| void *pdata, |
| uint16_t length |
| ) |
| { |
| NFCSTATUS status = NFCSTATUS_SUCCESS; |
| |
| PHNFC_UNUSED_VARIABLE(pdata); |
| PHNFC_UNUSED_VARIABLE(length); |
| |
| if(phDnld_Raw_Upgrade == psDnldContext->cur_dnld_seq) |
| { |
| status = phDnldNfc_Raw_Write( psDnldContext, pHwRef ); |
| } |
| else |
| { |
| status = phDnldNfc_Resume_Write( psDnldContext, pHwRef ); |
| } |
| |
| return status; |
| } |
| |
| |
| |
| static |
| NFCSTATUS |
| phDnldNfc_Resume( |
| phDnldNfc_sContext_t *psDnldContext, |
| void *pHwRef, |
| void *pdata, |
| uint16_t length |
| ) |
| { |
| NFCSTATUS status = NFCSTATUS_SUCCESS; |
| phDnldNfc_eState_t dnld_next_state = (phDnldNfc_eState_t) |
| psDnldContext->cur_dnld_state; |
| phNfc_sCompletionInfo_t comp_info = {0,0,0}; |
| |
| switch( dnld_next_state ) |
| { |
| case phDnld_Reset_State: |
| { |
| status = phDnldNfc_Send_Command( psDnldContext, pHwRef, |
| PHDNLD_CMD_RESET , NULL, 0 ); |
| switch( psDnldContext->cur_dnld_seq ) |
| { |
| case phDnld_Update_Patchtable: |
| { |
| psDnldContext->next_dnld_state = |
| (uint8_t)phDnld_Unlock_State; |
| psDnldContext->next_dnld_seq = |
| (uint8_t)phDnld_Unlock_System; |
| break; |
| } |
| #ifdef NXP_FW_PATCH_DISABLE |
| case phDnld_Deactivate_Patch: |
| #else |
| case phDnld_Unlock_System: |
| #endif |
| { |
| psDnldContext->next_dnld_state = |
| (uint8_t)phDnld_Upgrade_State; |
| psDnldContext->next_dnld_seq = |
| (uint8_t)phDnld_Upgrade_Section; |
| #ifdef NXP_FW_DNLD_CHECK_PHASE |
| gphDnldPhase = NXP_FW_DNLD_CFG_PHASE; |
| #endif /* NXP_FW_DNLD_CHECK_PHASE */ |
| break; |
| } |
| case phDnld_Lock_System: |
| { |
| #if (NXP_FW_INTEGRITY_CHK >= 0x01) |
| psDnldContext->next_dnld_state = |
| (uint8_t)phDnld_Verify_State; |
| psDnldContext->next_dnld_seq = |
| (uint8_t)phDnld_Verify_Integrity; |
| #else |
| /* (void ) memset( (void *) &psDnldContext->chk_integrity_crc, |
| 0, sizeof(psDnldContext->chk_integrity_crc)); */ |
| psDnldContext->next_dnld_state = |
| (uint8_t) phDnld_Complete_State; |
| #endif /* #if (NXP_FW_INTEGRITY_CHK >= 0x01) */ |
| break; |
| } |
| case phDnld_Verify_Integrity: |
| { |
| psDnldContext->next_dnld_state = |
| (uint8_t) phDnld_Complete_State; |
| break; |
| } |
| default: |
| { |
| status = (NFCSTATUS_PENDING == status)? |
| NFCSTATUS_SUCCESS: status; |
| break; |
| } |
| } |
| break; |
| } |
| case phDnld_Unlock_State: |
| { |
| |
| status = phDnldNfc_Sequence( psDnldContext, pHwRef, |
| pdata, length); |
| break; |
| } |
| case phDnld_Upgrade_State: |
| { |
| status = phDnldNfc_Upgrade_Sequence( psDnldContext, pHwRef, |
| pdata, length); |
| if ((NFCSTATUS_SUCCESS == status ) |
| && (phDnld_Complete_State == psDnldContext->next_dnld_state)) |
| { |
| #if 0 |
| psDnldContext->cur_dnld_seq = |
| (uint8_t)phDnld_Lock_System; |
| psDnldContext->next_dnld_seq = |
| psDnldContext->cur_dnld_seq; |
| #endif |
| #if (NXP_FW_INTEGRITY_CHK >= 0x01) |
| psDnldContext->next_dnld_state = |
| (uint8_t)phDnld_Verify_State; |
| psDnldContext->next_dnld_seq = |
| (uint8_t)phDnld_Verify_Integrity; |
| psDnldContext->cur_dnld_seq = |
| psDnldContext->next_dnld_seq; |
| status = phDnldNfc_Sequence( psDnldContext, |
| pHwRef, pdata, length); |
| #else |
| /* (void ) memset( (void *) &psDnldContext->chk_integrity_crc, |
| 0, sizeof(psDnldContext->chk_integrity_crc)); */ |
| psDnldContext->next_dnld_state = |
| (uint8_t) phDnld_Complete_State; |
| #endif /* #if (NXP_FW_INTEGRITY_CHK >= 0x01) */ |
| } |
| break; |
| } |
| case phDnld_Verify_State: |
| { |
| status = phDnldNfc_Sequence( psDnldContext, |
| pHwRef, pdata, length); |
| break; |
| } |
| case phDnld_Complete_State: |
| { |
| uint8_t integrity_chk = 0xA5; |
| |
| #if (NXP_FW_INTEGRITY_CHK >= 0x01) |
| uint8_t verify_crc = 0x96; |
| |
| if ( (NULL != psDnldContext->p_flash_code_crc) |
| && (NULL != psDnldContext->p_patch_code_crc) |
| && (NULL != psDnldContext->p_patch_table_crc) |
| ) |
| { |
| uint8_t crc_i = 0; |
| uint16_t patch_table_crc = 0; |
| uint32_t flash_code_crc = 0; |
| uint32_t patch_code_crc = 0; |
| |
| for (crc_i = 0; crc_i < DNLD_CRC32_SIZE; crc_i++ ) |
| { |
| if (crc_i < DNLD_CRC16_SIZE ) |
| { |
| patch_table_crc = patch_table_crc |
| | psDnldContext->chk_integrity_crc.patch_table.Chk_Crc16[crc_i] |
| << (crc_i * BYTE_SIZE) ; |
| } |
| flash_code_crc = flash_code_crc |
| | psDnldContext->chk_integrity_crc.flash_code.Chk_Crc32[crc_i] |
| << (crc_i * BYTE_SIZE) ; |
| patch_code_crc = patch_code_crc |
| | psDnldContext->chk_integrity_crc.patch_code.Chk_Crc32[crc_i] |
| << (crc_i * BYTE_SIZE) ; |
| } |
| verify_crc =(uint8_t)( (*((uint32_t *) psDnldContext->p_flash_code_crc)) != |
| flash_code_crc ); |
| verify_crc |=(uint8_t)( (*((uint32_t *) psDnldContext->p_patch_code_crc)) != |
| patch_code_crc ); |
| verify_crc |=(uint8_t)( (*((uint16_t *) psDnldContext->p_patch_table_crc)) != |
| patch_table_crc ); |
| } |
| else |
| { |
| DNLD_PRINT(" FW_DNLD: Flash, Patch code and Patch Table CRC "); |
| DNLD_PRINT(" Not Available in the Firmware \n"); |
| } |
| |
| #endif /* #if (NXP_FW_INTEGRITY_CHK >= 0x01) */ |
| |
| integrity_chk = psDnldContext->chk_integrity_crc.config_page.Chk_status + |
| psDnldContext->chk_integrity_crc.patch_table.Chk_status + |
| psDnldContext->chk_integrity_crc.flash_code.Chk_status + |
| psDnldContext->chk_integrity_crc.patch_code.Chk_status; |
| |
| if ( ( 0 != integrity_chk ) |
| #if (NXP_FW_INTEGRITY_CHK >= 0x01) |
| || ( 0 != verify_crc ) |
| #endif /* #if (NXP_FW_INTEGRITY_CHK >= 0x01) */ |
| ) |
| { |
| status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED); |
| } |
| break; |
| } |
| default: |
| { |
| status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FAILED); |
| break; |
| } |
| } |
| |
| if (NFCSTATUS_PENDING == status) |
| { |
| /* Write/Receive is still pending */ |
| } |
| else |
| { |
| pphNfcIF_Notification_CB_t p_upper_notify = |
| psDnldContext->p_upper_notify; |
| void *p_upper_context = |
| psDnldContext->p_upper_context; |
| |
| DNLD_DEBUG(" FW_DNLD: Resume Termination Status = %X \n", status); |
| |
| comp_info.status = status; |
| |
| (void) phDal4Nfc_Unregister( |
| psDnldContext->lower_interface.pcontext, pHwRef); |
| phDnldNfc_Release_Lower(psDnldContext, pHwRef); |
| phDnldNfc_Release_Resources(&psDnldContext); |
| #ifndef NFC_TIMER_CONTEXT |
| gpphDnldContext = psDnldContext; |
| #endif |
| /* Notify the Error/Success Scenario to the upper layer */ |
| phDnldNfc_Notify( p_upper_notify, p_upper_context, pHwRef, (uint8_t) |
| ((NFCSTATUS_SUCCESS == comp_info.status )? NFC_IO_SUCCESS: NFC_IO_ERROR), |
| &comp_info ); |
| } |
| return status; |
| } |
| |
| STATIC |
| NFCSTATUS |
| phDnldNfc_Process_Response( |
| phDnldNfc_sContext_t *psDnldContext, |
| void *pHwRef, |
| void *pdata, |
| uint16_t length |
| ) |
| { |
| NFCSTATUS status = NFCSTATUS_SUCCESS; |
| phDnldNfc_sData_Hdr_t *resp_data = |
| (phDnldNfc_sData_Hdr_t *) pdata; |
| |
| PHNFC_UNUSED_VARIABLE(pHwRef); |
| DNLD_DEBUG(" FW_DNLD: Receive Length = %X \n", length ); |
| if(( psDnldContext->rx_info.rx_total == 0 ) |
| && (PHDNLD_MIN_PACKET <= length) |
| ) |
| { |
| psDnldContext->rx_info.rx_total = |
| ((uint16_t)resp_data->frame_length[0] << BYTE_SIZE)| |
| resp_data->frame_length[1]; |
| if( psDnldContext->rx_info.rx_total + PHDNLD_MIN_PACKET == length ) |
| { |
| |
| DNLD_DEBUG(" FW_DNLD: Success Memory Read = %X \n", |
| psDnldContext->rx_info.rx_total); |
| #ifndef DNLD_SUMMARY |
| /* DNLD_PRINT_BUFFER("Receive Buffer",pdata,length); */ |
| #endif |
| |
| } |
| else |
| { |
| /* status = phDnldNfc_Receive( psDnldContext, pHwRef, |
| psDnldContext->p_resp_buffer, |
| (uint8_t)((psDnldContext->rx_info.rx_total <= PHDNLD_MAX_PACKET)? |
| psDnldContext->rx_info.rx_total: PHDNLD_MAX_PACKET) ); */ |
| DNLD_PRINT(" FW_DNLD: Invalid Receive length "); |
| DNLD_DEBUG(": Length Expected = %X \n", |
| (psDnldContext->rx_info.rx_total + PHDNLD_MIN_PACKET)); |
| status = PHNFCSTVAL( CID_NFC_DNLD, |
| NFCSTATUS_INVALID_RECEIVE_LENGTH ); |
| } |
| } |
| else |
| { |
| /*TODO:*/ |
| psDnldContext->rx_info.rx_total = 0 ; |
| status = PHNFCSTVAL( CID_NFC_DNLD, |
| NFCSTATUS_INVALID_RECEIVE_LENGTH ); |
| } |
| |
| return status; |
| } |
| |
| |
| |
| STATIC |
| void |
| phDnldNfc_Receive_Complete ( |
| void *psContext, |
| void *pHwRef, |
| phNfc_sTransactionInfo_t *pInfo |
| ) |
| { |
| NFCSTATUS status = NFCSTATUS_SUCCESS ; |
| void *pdata = NULL ; |
| phDnldNfc_sData_Hdr_t *resp_data = NULL; |
| uint16_t length = 0 ; |
| phNfc_sCompletionInfo_t comp_info = {0,0,0}; |
| |
| DNLD_PRINT("\n FW_DNLD: Receive Response .... "); |
| if ( (NULL != psContext) |
| && (NULL != pInfo) |
| && (NULL != pHwRef) |
| ) |
| { |
| phDnldNfc_sContext_t *psDnldContext = |
| (phDnldNfc_sContext_t *)psContext; |
| status = pInfo->status ; |
| length = pInfo->length ; |
| pdata = pInfo->buffer; |
| |
| if(status != NFCSTATUS_SUCCESS) |
| { |
| DNLD_DEBUG(" Failed. Status = %02X\n",status); |
| /* Handle the Error Scenario */ |
| } |
| else if (NULL == pdata) |
| { |
| DNLD_DEBUG(" Failed. No data received. pdata = %02X\n",pdata); |
| /* Handle the Error Scenario */ |
| status = PHNFCSTVAL( CID_NFC_DNLD, NFCSTATUS_FAILED ); |
| } |
| else if ((0 == length) |
| || (PHDNLD_MIN_PACKET > length )) |
| { |
| DNLD_DEBUG(" Receive Response Length = %u .... \n",length); |
| /* Handle the Error Scenario */ |
| #ifndef HAL_SW_DNLD_RLEN |
| status = PHNFCSTVAL( CID_NFC_DNLD, |
| NFCSTATUS_INVALID_RECEIVE_LENGTH ); |
| #endif |
| } |
| else |
| { |
| |
| #if defined(FW_DOWNLOAD_TIMER) && \ |
| (FW_DOWNLOAD_TIMER == 2) |
| if ( NXP_INVALID_TIMER_ID != psDnldContext->timer_id ) |
| { |
| phOsalNfc_Timer_Stop( psDnldContext->timer_id ); |
| } |
| |
| #endif |
| |
| #ifndef DNLD_SUMMARY |
| DNLD_PRINT_BUFFER("Receive Buffer",pdata,length); |
| #endif |
| DNLD_DEBUG(" Receive Response Length = %X. \n", length); |
| |
| resp_data = (phDnldNfc_sData_Hdr_t *) pdata; |
| |
| switch(resp_data->frame_type) |
| { |
| case PHDNLD_RESP_SUCCESS: |
| { |
| uint16_t resp_length = |
| ((uint16_t)resp_data->frame_length[0] << BYTE_SIZE)| |
| resp_data->frame_length[1]; |
| switch ( psDnldContext->prev_cmd ) |
| { |
| case PHDNLD_CMD_READ : |
| { |
| if( PHDNLD_NO_OPERATION |
| == psDnldContext->raw_mode_upgrade) |
| { |
| status = phDnldNfc_Process_Response( |
| psDnldContext, pHwRef, pdata , length); |
| |
| if (NFCSTATUS_SUCCESS != status) |
| { |
| /* psDnldContext->dnld_retry++; */ |
| psDnldContext->dnld_retry = NXP_MAX_DNLD_RETRY; |
| /* psDnldContext->dnld_retry < NXP_MAX_DNLD_RETRY */ |
| } |
| } |
| else |
| { |
| |
| } |
| break; |
| } |
| case PHDNLD_CMD_CHECK_INTEGRITY : |
| { |
| if( PHDNLD_NO_OPERATION |
| == psDnldContext->raw_mode_upgrade) |
| { |
| #if (NXP_FW_INTEGRITY_CHK >= 0x01) |
| phDnldNfc_sChkCrcComplete_t *p_dnld_crc_all = |
| &psDnldContext->chk_integrity_crc; |
| switch(psDnldContext->chk_integrity_param) |
| { |
| case CHK_INTEGRITY_CONFIG_PAGE_CRC: |
| { |
| (void)memcpy(&p_dnld_crc_all->config_page, |
| (((uint8_t *)pdata) + PHDNLD_MIN_PACKET), resp_length); |
| break; |
| } |
| case CHK_INTEGRITY_PATCH_TABLE_CRC: |
| { |
| (void)memcpy(&p_dnld_crc_all->patch_table, |
| (((uint8_t *)pdata) + PHDNLD_MIN_PACKET), resp_length); |
| break; |
| } |
| case CHK_INTEGRITY_FLASH_CODE_CRC: |
| { |
| (void)memcpy(&p_dnld_crc_all->flash_code, |
| (((uint8_t *)pdata) + PHDNLD_MIN_PACKET), resp_length); |
| break; |
| } |
| case CHK_INTEGRITY_PATCH_CODE_CRC: |
| { |
| (void)memcpy(&p_dnld_crc_all->patch_code, |
| (((uint8_t *)pdata) + PHDNLD_MIN_PACKET), resp_length); |
| break; |
| } |
| case CHK_INTEGRITY_COMPLETE_CRC: |
| { |
| (void)memcpy(p_dnld_crc_all, |
| (((uint8_t *)pdata) + PHDNLD_MIN_PACKET), resp_length); |
| DNLD_DEBUG(" FW_DNLD: Check Integrity Complete Structure Size = %X \n", |
| sizeof(psDnldContext->chk_integrity_crc)); |
| break; |
| } |
| default: |
| { |
| status = PHNFCSTVAL(CID_NFC_DNLD, |
| NFCSTATUS_FEATURE_NOT_SUPPORTED); |
| break; |
| } |
| } |
| #endif /* #if (NXP_FW_INTEGRITY_CHK >= 0x01) */ |
| } |
| else |
| { |
| psDnldContext->raw_mode_upgrade = |
| (PHDNLD_SETUP_OPERATION | PHDNLD_ADVANCED_OPERATION); |
| /* psDnldContext->raw_mode_upgrade = |
| (psDnldContext->raw_mode_upgrade & |
| ( psDnldContext->cur_frame_info & ~PHDNLD_MARKER_MASK )); */ |
| } |
| break; |
| } |
| case PHDNLD_CMD_WRITE: |
| { |
| psDnldContext->dnld_retry = 0; |
| break; |
| } |
| case PHDNLD_CMD_SEC_WRITE: |
| { |
| psDnldContext->dnld_retry = 0; |
| break; |
| } |
| case PHDNLD_CMD_ACTIVATE_PATCH: |
| case PHDNLD_CMD_CHECK: |
| default: |
| { |
| if( PHDNLD_NO_OPERATION |
| == psDnldContext->raw_mode_upgrade) |
| { |
| if( ( (PHDNLD_MIN_PACKET > length) |
| || ( 0 != resp_length) ) |
| ) |
| { |
| psDnldContext->dnld_retry = NXP_MAX_DNLD_RETRY; |
| status = PHNFCSTVAL( CID_NFC_DNLD, |
| NFCSTATUS_INVALID_RECEIVE_LENGTH ); |
| } |
| else |
| { |
| psDnldContext->dnld_retry = 0; |
| } |
| } |
| else |
| { |
| psDnldContext->raw_mode_upgrade = |
| (psDnldContext->raw_mode_upgrade & ~PHDNLD_RECOVER_OPERATION); |
| } |
| break; |
| } |
| } /* End of the Previous Command Switch Case */ |
| break; |
| }/* Case PHDNLD_RESP_SUCCESS*/ |
| case PHDNLD_RESP_TIMEOUT: |
| case PHDNLD_RESP_CRC_ERROR: |
| case PHDNLD_RESP_WRITE_ERROR: |
| { |
| if(psDnldContext->dnld_retry < NXP_MAX_DNLD_RETRY ) |
| { |
| psDnldContext->dnld_retry++; |
| } |
| status = PHNFCSTVAL(CID_NFC_DNLD, |
| resp_data->frame_type); |
| break; |
| } |
| /* fall through */ |
| case PHDNLD_RESP_ACCESS_DENIED: |
| case PHDNLD_RESP_INVALID_PARAMETER: |
| case PHDNLD_RESP_INVALID_LENGTH: |
| /* Initial Frame Checksum */ |
| case PHDNLD_RESP_CHKSUM_ERROR: |
| case PHDNLD_RESP_MEMORY_UPDATE_ERROR: |
| { |
| psDnldContext->dnld_retry = NXP_MAX_DNLD_RETRY; |
| status = PHNFCSTVAL(CID_NFC_DNLD, |
| resp_data->frame_type); |
| break; |
| } |
| case PHDNLD_RESP_PROTOCOL_ERROR: |
| { |
| if(( PHDNLD_NO_OPERATION |
| == psDnldContext->raw_mode_upgrade) |
| || ( PHDNLD_ADVANCED_OPERATION |
| == psDnldContext->raw_mode_upgrade) |
| ) |
| { |
| psDnldContext->dnld_retry = NXP_MAX_DNLD_RETRY; |
| status = PHNFCSTVAL(CID_NFC_DNLD, |
| NFCSTATUS_INVALID_FORMAT); |
| } |
| else if( (PHDNLD_NORMAL_OPERATION |
| & psDnldContext->raw_mode_upgrade) |
| ) |
| { |
| psDnldContext->raw_mode_upgrade = |
| (psDnldContext->raw_mode_upgrade & ~PHDNLD_NORMAL_OPERATION); |
| } |
| else if ( PHDNLD_RECOVER_OPERATION |
| & psDnldContext->raw_mode_upgrade ) |
| { |
| psDnldContext->dnld_retry = NXP_MAX_DNLD_RETRY; |
| status = PHNFCSTVAL(CID_NFC_DNLD, |
| NFCSTATUS_INVALID_FORMAT); |
| } |
| else |
| { |
| psDnldContext->raw_mode_upgrade = |
| (psDnldContext->raw_mode_upgrade & |
| ~( psDnldContext->cur_frame_info & ~PHDNLD_MARKER_MASK )); |
| } |
| break; |
| } |
| case PHDNLD_RESP_VERSION_UPTODATE: |
| { |
| /* TODO: to make sure that the Advance Frames are sent to get |
| * the updated status */ |
| if ( PHDNLD_ADVANCED_OPERATION |
| == psDnldContext->raw_mode_upgrade) |
| { |
| status = ( CID_NFC_DNLD << BYTE_SIZE ) ; |
| } |
| else if ( PHDNLD_NO_OPERATION |
| != psDnldContext->raw_mode_upgrade) |
| { |
| |
| psDnldContext->raw_mode_upgrade = |
| (psDnldContext->raw_mode_upgrade & |
| ~( psDnldContext->cur_frame_info & ~PHDNLD_MARKER_MASK )); |
| } |
| else |
| { |
| } |
| break; |
| } |
| case PHDNLD_RESP_CMD_NOT_SUPPORTED: |
| { |
| |
| if ( PHDNLD_NO_OPERATION |
| == psDnldContext->raw_mode_upgrade) |
| { |
| status = PHNFCSTVAL(CID_NFC_DNLD, |
| NFCSTATUS_FEATURE_NOT_SUPPORTED); |
| } |
| else if ( PHDNLD_ADVANCED_OPERATION |
| == psDnldContext->raw_mode_upgrade) |
| { |
| status = PHNFCSTVAL(CID_NFC_DNLD, |
| NFCSTATUS_FEATURE_NOT_SUPPORTED); |
| } |
| #if 0 |
| else if( (PHDNLD_NORMAL_OPERATION |
| & psDnldContext->raw_mode_upgrade) |
| ) |
| { |
| psDnldContext->raw_mode_upgrade = |
| (psDnldContext->raw_mode_upgrade & ~PHDNLD_NORMAL_OPERATION); |
| } |
| else if ( PHDNLD_SETUP_OPERATION |
| & psDnldContext->raw_mode_upgrade ) |
| { |
| psDnldContext->raw_mode_upgrade = |
| (psDnldContext->raw_mode_upgrade & ~PHDNLD_SETUP_OPERATION); |
| } |
| #endif |
| else |
| { |
| psDnldContext->raw_mode_upgrade = |
| (psDnldContext->raw_mode_upgrade & |
| ~( psDnldContext->cur_frame_info & ~PHDNLD_MARKER_MASK )); |
| } |
| break; |
| } |
| /* The Chaining of the Command Frame |
| was Successful in the Download Mode */ |
| case PHDNLD_RESP_CHAINING_SUCCESS: |
| { |
| /* TODO: Handle the Corner Case Scenarios |
| * the updated status */ |
| psDnldContext->dnld_retry = 0x00; |
| break; |
| } |
| /* The Error during the Chaining the Command Frame in the Download Mode */ |
| case PHDNLD_RESP_CHAINING_ERROR: |
| { |
| /* TODO: Restart the Chunk in Corner Case |
| * the updated status */ |
| psDnldContext->dnld_retry++; |
| phDnldNfc_Tx_Reset(psDnldContext); |
| break; |
| } |
| /* The Command is not allowed anymore in the Download Mode */ |
| case PHDNLD_RESP_CMD_NOT_ALLOWED: |
| default: |
| { |
| psDnldContext->dnld_retry = NXP_MAX_DNLD_RETRY; |
| status = PHNFCSTVAL(CID_NFC_DNLD, |
| NFCSTATUS_NOT_ALLOWED); |
| break; |
| } |
| |
| } /* End of the Response Frame Type Switch */ |
| |
| if (NFCSTATUS_PENDING != status) |
| { |
| if ((NFCSTATUS_SUCCESS != status) && |
| (psDnldContext->dnld_retry >= NXP_MAX_DNLD_RETRY)) |
| { |
| pphNfcIF_Notification_CB_t p_upper_notify = |
| psDnldContext->p_upper_notify; |
| void *p_upper_context = |
| psDnldContext->p_upper_context; |
| |
| comp_info.status = status; |
| DNLD_DEBUG(" FW_DNLD: Termination in Receive, Status = %X \n", status); |
| status = phDal4Nfc_Unregister( |
| psDnldContext->lower_interface.pcontext, pHwRef); |
| phDnldNfc_Release_Lower(psDnldContext, pHwRef); |
| phDnldNfc_Release_Resources(&psDnldContext); |
| #ifndef NFC_TIMER_CONTEXT |
| gpphDnldContext = psDnldContext; |
| #endif |
| /* Notify the Error/Success Scenario to the upper layer */ |
| phDnldNfc_Notify( p_upper_notify, p_upper_context, pHwRef, |
| (uint8_t) NFC_IO_ERROR, &comp_info ); |
| } |
| else if ( (NFCSTATUS_SUCCESS != status) && |
| (NFCSTATUS_SUCCESS == PHNFCSTATUS(status)) |
| ) |
| { |
| pphNfcIF_Notification_CB_t p_upper_notify = |
| psDnldContext->p_upper_notify; |
| void *p_upper_context = |
| psDnldContext->p_upper_context; |
| |
| comp_info.status = NFCSTATUS_SUCCESS; |
| DNLD_DEBUG(" FW_DNLD: Termination in Receive, Status = %X \n", status); |
| status = phDal4Nfc_Unregister( |
| psDnldContext->lower_interface.pcontext, pHwRef); |
| phDnldNfc_Release_Lower(psDnldContext, pHwRef); |
| phDnldNfc_Release_Resources(&psDnldContext); |
| #ifndef NFC_TIMER_CONTEXT |
| gpphDnldContext = psDnldContext; |
| #endif |
| /* Notify the Error/Success Scenario to the upper layer */ |
| phDnldNfc_Notify( p_upper_notify, p_upper_context, pHwRef, |
| (uint8_t) NFC_IO_SUCCESS, &comp_info ); |
| |
| } |
| else if (NFCSTATUS_FEATURE_NOT_SUPPORTED == PHNFCSTATUS(status)) |
| { |
| pphNfcIF_Notification_CB_t p_upper_notify = |
| psDnldContext->p_upper_notify; |
| void *p_upper_context = |
| psDnldContext->p_upper_context; |
| |
| comp_info.status = status; |
| DNLD_DEBUG(" FW_DNLD: Termination in Receive, Status = %X \n", status); |
| status = phDal4Nfc_Unregister( |
| psDnldContext->lower_interface.pcontext, pHwRef); |
| phDnldNfc_Release_Lower(psDnldContext, pHwRef); |
| phDnldNfc_Release_Resources(&psDnldContext); |
| #ifndef NFC_TIMER_CONTEXT |
| gpphDnldContext = psDnldContext; |
| #endif |
| /* Notify the Error/Success Scenario to the upper layer */ |
| phDnldNfc_Notify( p_upper_notify, p_upper_context, pHwRef, |
| (uint8_t) NFC_IO_SUCCESS, &comp_info ); |
| |
| } |
| else |
| { |
| /* DNLD_PRINT(" FW_DNLD: Successful.\n"); */ |
| psDnldContext->resp_length = /* PHDNLD_MIN_PACKET */ 0 ; |
| status = phDnldNfc_Set_Seq(psDnldContext, |
| DNLD_SEQ_UPDATE); |
| status = phDnldNfc_Resume( psDnldContext, |
| pHwRef, pdata, length ); |
| } |
| } |
| } /* End of status != Success */ |
| } |
| } |
| |
| |
| STATIC |
| void |
| phDnldNfc_Send_Complete ( |
| void *psContext, |
| void *pHwRef, |
| phNfc_sTransactionInfo_t *pInfo |
| ) |
| { |
| NFCSTATUS status = NFCSTATUS_SUCCESS ; |
| uint16_t length = 0; |
| |
| DNLD_PRINT(" FW_DNLD: Send Data .... "); |
| if ( (NULL != psContext) |
| && (NULL != pInfo) |
| && (NULL != pHwRef) |
| ) |
| { |
| phDnldNfc_sContext_t *psDnldContext = |
| (phDnldNfc_sContext_t *)psContext; |
| status = pInfo->status ; |
| length = pInfo->length ; |
| if(status != NFCSTATUS_SUCCESS) |
| { |
| DNLD_DEBUG(" Failed. Status = %02X\n",status); |
| /* Handle the Error Scenario */ |
| } |
| else |
| { |
| DNLD_PRINT(" Successful.\n"); |
| (void)memset((void *)&psDnldContext->dnld_data, 0, |
| sizeof(psDnldContext->dnld_data)); |
| if ((PHDNLD_CMD_SET_HIF != psDnldContext->prev_cmd) |
| && (PHDNLD_CMD_RESET != psDnldContext->prev_cmd)) |
| { |
| psDnldContext->rx_info.rx_total = 0; |
| status = phDnldNfc_Receive( psDnldContext, pHwRef, |
| (uint8_t *)(&psDnldContext->dnld_resp), |
| psDnldContext->resp_length); |
| } |
| else |
| { |
| psDnldContext->resp_length = 0; |
| psDnldContext->dnld_retry = 0; |
| /* clock unstable after SW reset command, especially on UART |
| * platform because of its sensitivity to clock. Experimentally |
| * we found clock unstable for 750us. Delay for 5ms to be sure. |
| */ |
| if( PHDNLD_CMD_RESET == psDnldContext->prev_cmd ) |
| { |
| DO_DELAY(PHDNLD_DNLD_DELAY); |
| } |
| #if defined(FW_DOWNLOAD_TIMER) && \ |
| (FW_DOWNLOAD_TIMER == 2) |
| |
| if ( NXP_INVALID_TIMER_ID != psDnldContext->timer_id ) |
| { |
| phOsalNfc_Timer_Stop( psDnldContext->timer_id ); |
| } |
| #endif |
| |
| status = phDnldNfc_Set_Seq(psDnldContext, |
| DNLD_SEQ_UPDATE); |
| } |
| |
| if(NFCSTATUS_SUCCESS == status ) |
| { |
| status = phDnldNfc_Resume( psDnldContext, pHwRef, NULL, length); |
| } |
| |
| } /* End of status != Success */ |
| |
| } /* End of Context != NULL */ |
| } |
| |
| |
| |
| STATIC |
| NFCSTATUS |
| phDnldNfc_Send_Command( |
| phDnldNfc_sContext_t *psDnldContext, |
| void *pHwRef, |
| uint8_t cmd, |
| void *params, |
| uint16_t param_length |
| ) |
| { |
| NFCSTATUS status = NFCSTATUS_SUCCESS; |
| uint16_t tx_length = 0; |
| uint16_t rx_length = 0; |
| uint8_t **pp_resp_data = &psDnldContext->p_resp_buffer; |
| phDnldNfc_sData_t *p_dnld_data = |
| (phDnldNfc_sData_t *)psDnldContext->dnld_data; |
| |
| switch(cmd) |
| { |
| case PHDNLD_CMD_RESET: |
| { |
| (void)memset((void *)&psDnldContext->dnld_data, 0, |
| sizeof(psDnldContext->dnld_data)); |
| break; |
| } |
| case PHDNLD_CMD_READ: |
| { |
| phDnldNfc_sData_t *p_dnld_data = |
| (phDnldNfc_sData_t *)psDnldContext->dnld_data; |
| phDnldNfc_sParam_t *param_info = /* (phDnldNfc_sParam_t *)params */ |
| &p_dnld_data->param_info.data_param; |
| tx_length = PHDNLD_CMD_READ_LEN; |
| if (NULL != *pp_resp_data) |
| { |
| phOsalNfc_FreeMemory(*pp_resp_data); |
| *pp_resp_data = NULL; |
| } |
| rx_length = (uint16_t) (((uint16_t)param_info->data_len[0] |
| << BYTE_SIZE) + param_info->data_len[1]); |
| |
| psDnldContext->resp_length = |
| (( rx_length + PHDNLD_MIN_PACKET )); |
| (void)phDnldNfc_Allocate_Resource( (void **) pp_resp_data, |
| rx_length); |
| break; |
| } |
| case PHDNLD_CMD_WRITE: |
| case PHDNLD_CMD_SEC_WRITE: |
| { |
| phDnldNfc_sData_t *p_dnld_data = |
| (phDnldNfc_sData_t *)psDnldContext->dnld_data; |
| phDnldNfc_sParam_t *param_info = /* (phDnldNfc_sParam_t *)params */ |
| &p_dnld_data->param_info.data_param; |
| tx_length = (uint16_t) (((uint16_t)param_info->data_len[0] |
| << BYTE_SIZE) + param_info->data_len[1] |
| + PHDNLD_CMD_WRITE_MIN_LEN ); |
| |
| psDnldContext->resp_length = PHDNLD_MIN_PACKET; |
| if ((0 != param_length) && (NULL != params)) |
| { |
| (void)memcpy(param_info->data_packet, params, param_length); |
| } |
| break; |
| } |
| case PHDNLD_CMD_CHECK: |
| { |
| tx_length = PHDNLD_CMD_CHECK_LEN; |
| psDnldContext->resp_length = PHDNLD_MIN_PACKET; |
| break; |
| } |
| case PHDNLD_CMD_ENCAPSULATE: |
| { |
| uint8_t i = 0x00; |
| if ((0 != param_length) && (NULL != params)) |
| { |
| p_dnld_data->frame_type = |
| PHDNLD_CMD_ENCAPSULATE; |
| (void)memcpy((void *)( ((uint8_t *)p_dnld_data) |
| + PHDNLD_FRAME_DATA_OFFSET) |
| , params, param_length); |
| tx_length = param_length; |
| |
| p_dnld_data->frame_length[i++] = |
| (uint8_t)(tx_length >> BYTE_SIZE); |
| p_dnld_data->frame_length[i] = |
| (uint8_t)( tx_length & BYTE_MASK ); |
| tx_length += PHDNLD_FRAME_DATA_OFFSET; |
| |
| psDnldContext->resp_length = PHDNLD_MIN_PACKET; |
| |
| status = phDnldNfc_Send( psDnldContext, pHwRef , |
| (uint8_t *)p_dnld_data, tx_length); |
| } |
| else |
| { |
| status = PHNFCSTVAL(CID_NFC_DNLD, |
| NFCSTATUS_NOT_ALLOWED); |
| } |
| break; |
| } |
| case PHDNLD_CMD_SET_HIF: |
| { |
| tx_length++; |
| psDnldContext->resp_length = PHDNLD_MIN_PACKET; |
| break; |
| } |
| case PHDNLD_CMD_ACTIVATE_PATCH: |
| { |
| psDnldContext->resp_length = PHDNLD_MIN_PACKET; |
| if ((NULL != params) && ( param_length > 0 )) |
| { |
| p_dnld_data->param_info.cmd_param = |
| (*(uint8_t *)params); |
| tx_length = param_length; |
| } |
| else |
| { |
| p_dnld_data->param_info.cmd_param = FALSE; |
| tx_length++; |
| } |
| break; |
| } |
| case PHDNLD_CMD_CHECK_INTEGRITY: |
| { |
| #if (NXP_FW_INTEGRITY_CHK >= 0x01) |
| if ((NULL != params) && ( param_length > 0 )) |
| { |
| psDnldContext->chk_integrity_param = |
| (phDnldNfc_eChkCrc_t)(*(uint8_t *)params); |
| tx_length = param_length; |
| } |
| else |
| { |
| psDnldContext->chk_integrity_param = CHK_INTEGRITY_COMPLETE_CRC; |
| tx_length++; |
| } |
| p_dnld_data->param_info.cmd_param = |
| (uint8_t) psDnldContext->chk_integrity_param; |
| switch(psDnldContext->chk_integrity_param) |
| { |
| case CHK_INTEGRITY_CONFIG_PAGE_CRC: |
| case CHK_INTEGRITY_PATCH_TABLE_CRC: |
| { |
| psDnldContext->resp_length = PHDNLD_MIN_PACKET |
| + CHECK_INTEGRITY_RESP_CRC16_LEN; |
| break; |
| } |
| case CHK_INTEGRITY_FLASH_CODE_CRC: |
| case CHK_INTEGRITY_PATCH_CODE_CRC: |
| { |
| psDnldContext->resp_length = PHDNLD_MIN_PACKET |
| + CHECK_INTEGRITY_RESP_CRC32_LEN; |
| break; |
| } |
| case CHK_INTEGRITY_COMPLETE_CRC: |
| default: |
| { |
| psDnldContext->resp_length = PHDNLD_MIN_PACKET |
| + CHECK_INTEGRITY_RESP_COMP_LEN; |
| break; |
| } |
| } |
| #else |
| tx_length++; |
| p_dnld_data->param_info.cmd_param = |
| (uint8_t) CHK_INTEGRITY_COMPLETE_CRC; |
| |
| #endif /* #if (NXP_FW_INTEGRITY_CHK >= 0x01) */ |
| break; |
| } |
| default: |
| { |
| status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_FEATURE_NOT_SUPPORTED); |
| break; |
| } |
| } |
| if (NFCSTATUS_SUCCESS == status) |
| { |
| uint8_t i = 0; |
| |
| p_dnld_data->frame_type = cmd; |
| p_dnld_data->frame_length[i++] = |
| (uint8_t)(tx_length >> BYTE_SIZE); |
| p_dnld_data->frame_length[i] = |
| (uint8_t)( tx_length & BYTE_MASK ); |
| tx_length = tx_length + PHDNLD_MIN_PACKET; |
| status = phDnldNfc_Send( psDnldContext, pHwRef , |
| (uint8_t *)p_dnld_data, tx_length); |
| if(NFCSTATUS_PENDING == status) |
| { |
| psDnldContext->prev_cmd = cmd; |
| |
| if( PHDNLD_CMD_RESET == cmd ) |
| DO_DELAY(PHDNLD_DNLD_DELAY); //this seems like its on the wrong thread |
| } |
| } |
| |
| return status; |
| } |
| |
| static |
| NFCSTATUS |
| phDnldNfc_Check_FW( |
| phHal_sHwReference_t *pHwRef, |
| fw_data_hdr_t *cur_fw_hdr |
| ) |
| { |
| NFCSTATUS status = NFCSTATUS_FAILED; |
| |
| if ( !pHwRef->device_info.fw_version ) |
| { |
| /* Override the Firmware Version Check and upgrade*/; |
| DNLD_PRINT(" FW_DNLD_CHK: Forceful Upgrade of the Firmware .... Required \n"); |
| status = NFCSTATUS_SUCCESS; |
| } |
| else if ( (pHwRef->device_info.fw_version >> (BYTE_SIZE * 2)) |
| != ( cur_fw_hdr->fw_version >> (BYTE_SIZE * 2) )) |
| { |
| /* Check for the Compatible Romlib Version for the Hardware */ |
| DNLD_PRINT(" FW_DNLD: IC Hardware Version Mismatch.. \n"); |
| status = PHNFCSTVAL( CID_NFC_DNLD, NFCSTATUS_NOT_ALLOWED ); |
| } |
| else if (( pHwRef->device_info.fw_version < cur_fw_hdr->fw_version ) |
| ) |
| { |
| /* TODO: Firmware Version Check and upgrade*/ |
| DNLD_PRINT(" FW_DNLD: Older Firmware Upgrading to newerone.... \n"); |
| status = NFCSTATUS_SUCCESS; |
| } |
| #ifdef NXP_FW_CHK_LATEST |
| else if (( pHwRef->device_info.fw_version > cur_fw_hdr->fw_version ) |
| ) |
| { |
| DNLD_PRINT(" FW_DNLD: Newer than the Stored One .... \n"); |
| status = PHNFCSTVAL( CID_NFC_DNLD, NFCSTATUS_NOT_ALLOWED ); |
| } |
| #endif /* NXP_FW_CHK_LATEST */ |
| else |
| { |
| DNLD_PRINT(" FW_DNLD: Already Updated .... \n"); |
| status = ( CID_NFC_DNLD << BYTE_SIZE ) ; |
| } |
| |
| return status; |
| } |
| |
| |
| static |
| NFCSTATUS |
| phDnldNfc_Process_FW( |
| phDnldNfc_sContext_t *psDnldContext, |
| phHal_sHwReference_t *pHwRef |
| #ifdef NXP_FW_PARAM |
| ,uint8_t *nxp_nfc_fw |
| ,uint32_t nxp_fw_len |
| #endif |
| ) |
| { |
| NFCSTATUS status = NFCSTATUS_FAILED; |
| section_info_t *p_cur_sec = NULL; |
| static unsigned sec_type; |
| uint32_t fw_index = 0; |
| #ifdef NXP_NFC_MULTIPLE_FW |
| phDnldNfc_sFwImageInfo_t *p_cur_fw = NULL; |
| #endif /* #ifdef NXP_NFC_MULTIPLE_FW */ |
| fw_data_hdr_t *cur_fw_hdr = NULL; |
| uint8_t sec_index = 0; |
| uint8_t i = 0; |
| |
| psDnldContext->p_img_hdr = (img_data_hdr_t *) nxp_nfc_fw; |
| |
| #ifdef NXP_NFC_MULTIPLE_FW |
| |
| /* TODO: Create a memory of pointers to store all the Firmwares */ |
| if( (NXP_NFC_IMAG_FW_MAX > psDnldContext->p_img_hdr->no_of_fw_img) |
| && (0 != psDnldContext->p_img_hdr->no_of_fw_img) |
| ) |
| { |
| ( void )phDnldNfc_Allocate_Resource((void **)&psDnldContext->p_img_info, |
| (psDnldContext->p_img_hdr->no_of_fw_img * sizeof(phDnldNfc_sFwImageInfo_t))); |
| |
| if(NULL != psDnldContext->p_img_info) |
| { |
| p_cur_fw = psDnldContext->p_img_info; |
| } |
| } |
| #endif /* #ifdef NXP_NFC_MULTIPLE_FW */ |
| |
| fw_index = sizeof (img_data_hdr_t); |
| |
| for ( i=0; i < psDnldContext->p_img_hdr->no_of_fw_img; i++ ) |
| { |
| |
| psDnldContext->p_fw_hdr = (fw_data_hdr_t *) ( nxp_nfc_fw + fw_index ); |
| |
| #ifdef NXP_NFC_MULTIPLE_FW |
| if(NULL != p_cur_fw) |
| { |
| ( p_cur_fw + i)->p_fw_hdr = psDnldContext->p_fw_hdr; |
| } |
| #endif /* #ifdef NXP_NFC_MULTIPLE_FW */ |
| cur_fw_hdr = psDnldContext->p_fw_hdr; |
| |
| fw_index = fw_index + (cur_fw_hdr->fw_hdr_len * PNDNLD_WORD_LEN); |
| |
| status = phDnldNfc_Check_FW( pHwRef, cur_fw_hdr); |
| |
| } |
| |
| if ( ( NFCSTATUS_SUCCESS == status ) |
| #if defined (NXP_FW_INTEGRITY_VERIFY) |
| || (NFCSTATUS_SUCCESS == PHNFCSTATUS(status) ) |
| #endif /* !defined (NXP_FW_INTEGRITY_VERIFY) */ |
| ) |
| { |
| if( (BYTE_MASK > cur_fw_hdr->no_of_sections) |
| && (0 != cur_fw_hdr->no_of_sections) |
| ) |
| { |
| (void) phDnldNfc_Allocate_Resource((void **)&psDnldContext->p_fw_sec, |
| (cur_fw_hdr->no_of_sections * sizeof(section_info_t))); |
| |
| if(NULL != psDnldContext->p_fw_sec) |
| { |
| DNLD_DEBUG(" FW_DNLD: FW Index : %x \n", |
| fw_index ); |
| |
| DNLD_DEBUG(" FW_DNLD: No of Sections : %x \n\n", |
| cur_fw_hdr->no_of_sections); |
| |
| for(sec_index = 0; sec_index |
| < cur_fw_hdr->no_of_sections; sec_index++ ) |
| { |
| p_cur_sec = ((section_info_t *) |
| (psDnldContext->p_fw_sec + sec_index )); |
| |
| p_cur_sec->p_sec_hdr = (section_hdr_t *) |
| (nxp_nfc_fw + fw_index); |
| |
| DNLD_DEBUG(" FW_DNLD: Section %x \n", sec_index); |
| DNLD_DEBUG(" FW_DNLD: Section Header Len : %x ", |
| p_cur_sec->p_sec_hdr->section_hdr_len); |
| DNLD_DEBUG(" Section Address : %x ", |
| p_cur_sec->p_sec_hdr->section_address); |
| DNLD_DEBUG(" Section Length : %x ", |
| p_cur_sec->p_sec_hdr->section_length); |
| DNLD_DEBUG(" Section Memory Type : %x \n", |
| p_cur_sec->p_sec_hdr->section_mem_type); |
| |
| sec_type = (unsigned int)p_cur_sec->p_sec_hdr->section_mem_type; |
| |
| if((sec_type & DNLD_TRIM_MASK)) |
| { |
| p_cur_sec->p_trim_data = (uint8_t *) |
| (nxp_nfc_fw + fw_index + sizeof(section_hdr_t)); |
| } |
| else |
| { |
| p_cur_sec->p_trim_data = NULL; |
| } |
| |
| if (0 == sec_index) |
| { |
| if ((sec_type & DNLD_SM_UNLOCK_MASK)) |
| { |
| (void)phDnldNfc_Set_Seq(psDnldContext, |
| DNLD_SEQ_UNLOCK); |
| } |
| else |
| { |
| (void)phDnldNfc_Set_Seq(psDnldContext, |
| DNLD_SEQ_INIT); |
| } |
| } |
| p_cur_sec->section_read = FALSE; |
| |
| p_cur_sec->section_offset = 0; |
| |
| p_cur_sec->p_sec_data = ((uint8_t *) nxp_nfc_fw) + fw_index + |
| (p_cur_sec->p_sec_hdr->section_hdr_len * PNDNLD_WORD_LEN); |
| |
| fw_index = fw_index + |
| (p_cur_sec->p_sec_hdr->section_hdr_len * PNDNLD_WORD_LEN) |
| + p_cur_sec->p_sec_hdr->section_length; |
| |
| |
| if( 0 != p_cur_sec->p_sec_hdr->section_checksum ) |
| { |
| DNLD_DEBUG(" FW_DNLD: Section checksum : %x \n", |
| p_cur_sec->p_sec_hdr->section_checksum ); |
| |
| p_cur_sec->p_sec_chksum = ( uint8_t *)(nxp_nfc_fw + fw_index); |
| |
| fw_index = fw_index + |
| p_cur_sec->p_sec_hdr->section_checksum; |
| } |
| |
| DNLD_DEBUG(" FW_DNLD: FW Index : %x \n", fw_index ); |
| |
| #if (NXP_FW_INTEGRITY_CHK >= 0x01) |
| switch( p_cur_sec->p_sec_hdr->section_address ) |
| { |
| case DNLD_FW_CODE_ADDR: |
| { |
| psDnldContext->p_flash_code_crc = |
| p_cur_sec->p_sec_data |
| + p_cur_sec->p_sec_hdr->section_length |
| - DNLD_CRC32_SIZE; |
| break; |
| } |
| case DNLD_PATCH_CODE_ADDR: |
| { |
| psDnldContext->p_patch_code_crc = |
| p_cur_sec->p_sec_data |
| + p_cur_sec->p_sec_hdr->section_length |
| - DNLD_CRC32_SIZE; |
| break; |
| } |
| case DNLD_PATCH_TABLE_ADDR: |
| { |
| psDnldContext->p_patch_table_crc = |
| p_cur_sec->p_sec_data |
| + p_cur_sec->p_sec_hdr->section_length |
| - DNLD_CRC16_SIZE; |
| break; |
| } |
| default: |
| { |
| break; |
| } |
| |
| } /* End of Address Switch */ |
| #endif /* #if (NXP_FW_INTEGRITY_CHK >= 0x01) */ |
| } /* End of For Loop */ |
| } /* End of the Null Check */ |
| else |
| { |
| status = PHNFCSTVAL(CID_NFC_DNLD, |
| NFCSTATUS_INSUFFICIENT_RESOURCES); |
| } |
| |
| } |
| else if ( |
| (0 == cur_fw_hdr->no_of_sections) |
| && (PHDNLD_FW_PATCH_SEC == cur_fw_hdr->fw_patch) |
| ) |
| { |
| psDnldContext->p_fw_raw = (uint8_t *)(nxp_nfc_fw + fw_index); |
| |
| psDnldContext->raw_mode_upgrade = PHDNLD_COMPLETE_OPERATION; |
| |
| (void)phDnldNfc_Set_Seq(psDnldContext, |
| DNLD_SEQ_RAW); |
| } |
| else |
| { |
| DNLD_PRINT("********* Empty Section and Firmware ******************\n\n"); |
| } |
| |
| DNLD_PRINT("*******************************************\n\n"); |
| |
| } |
| return status; |
| } |
| |
| #if !defined (NXP_FW_INTEGRITY_VERIFY) |
| |
| NFCSTATUS |
| phDnldNfc_Run_Check( |
| phHal_sHwReference_t *pHwRef |
| #ifdef NXP_FW_PARAM |
| ,uint8_t *nxp_nfc_fw |
| uint32_t fw_length |
| #endif |
| ) |
| { |
| NFCSTATUS status = NFCSTATUS_FAILED; |
| uint32_t fw_index = 0; |
| img_data_hdr_t *p_img_hdr = NULL; |
| fw_data_hdr_t *p_fw_hdr = NULL; |
| fw_data_hdr_t *cur_fw_hdr = NULL; |
| uint8_t i = 0; |
| |
| p_img_hdr = (img_data_hdr_t *) nxp_nfc_fw; |
| |
| fw_index = sizeof (img_data_hdr_t); |
| |
| for ( i=0; i < p_img_hdr->no_of_fw_img; i++ ) |
| { |
| p_fw_hdr = (fw_data_hdr_t *) ( nxp_nfc_fw + fw_index ); |
| /* TODO: Create a memory of pointers to store all the Firmwares */ |
| cur_fw_hdr = p_fw_hdr; |
| |
| fw_index = fw_index + (cur_fw_hdr->fw_hdr_len * PNDNLD_WORD_LEN); |
| |
| status = phDnldNfc_Check_FW( pHwRef, cur_fw_hdr); |
| } |
| return status; |
| } |
| |
| #endif /* #if !defined (NXP_FW_INTEGRITY_VERIFY) */ |
| |
| |
| STATIC |
| void |
| phDnldNfc_Abort ( |
| uint32_t abort_id |
| #ifdef NFC_TIMER_CONTEXT |
| , void *dnld_cntxt |
| #endif |
| ) |
| { |
| |
| phNfc_sCompletionInfo_t comp_info = {0,0,0}; |
| |
| phDnldNfc_sContext_t *p_dnld_context = NULL; |
| |
| #ifdef NFC_TIMER_CONTEXT |
| p_dnld_context = (phDnldNfc_sContext_t *)dnld_cntxt; |
| #else |
| p_dnld_context = gpphDnldContext; |
| #endif |
| |
| if ( ( NULL != p_dnld_context) |
| && (abort_id == p_dnld_context->timer_id )) |
| { |
| pphNfcIF_Notification_CB_t p_upper_notify = |
| p_dnld_context->p_upper_notify; |
| void *p_upper_context = |
| p_dnld_context->p_upper_context; |
| phHal_sHwReference_t *pHwRef = p_dnld_context->p_hw_ref; |
| |
| (void)phDal4Nfc_Unregister( |
| p_dnld_context->lower_interface.pcontext, pHwRef ); |
| phDnldNfc_Release_Lower(p_dnld_context, pHwRef); |
| phDnldNfc_Release_Resources(&p_dnld_context); |
| #ifndef NFC_TIMER_CONTEXT |
| gpphDnldContext = p_dnld_context; |
| #endif |
| |
| /* Notify the Error/Success Scenario to the upper layer */ |
| DNLD_DEBUG(" FW_DNLD: FW_DNLD Aborted with %x Timer Timeout \n", |
| abort_id); |
| comp_info.status = NFCSTATUS_FAILED ; |
| phDnldNfc_Notify( p_upper_notify, p_upper_context, |
| pHwRef, (uint8_t) NFC_IO_ERROR, &comp_info ); |
| } |
| |
| return ; |
| } |
| |
| |
| |
| NFCSTATUS |
| phDnldNfc_Upgrade ( |
| phHal_sHwReference_t *pHwRef, |
| #ifdef NXP_FW_PARAM |
| uint8_t type, |
| uint8_t *nxp_nfc_fw, |
| uint32_t fw_length, |
| #endif |
| pphNfcIF_Notification_CB_t upgrade_complete, |
| void *context |
| ) |
| { |
| phDnldNfc_sContext_t *psDnldContext = NULL; |
| phNfcIF_sReference_t dnldReference = { NULL,0,0 }; |
| phNfcIF_sCallBack_t if_callback = { NULL, NULL, NULL, NULL }; |
| phNfc_sLowerIF_t *plower_if = NULL; |
| NFCSTATUS status = NFCSTATUS_SUCCESS; |
| section_info_t *p_cur_sec = NULL; |
| unsigned sec_type = 0; |
| |
| if( (NULL == pHwRef) |
| ) |
| { |
| status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INVALID_PARAMETER); |
| } |
| else |
| { |
| DNLD_PRINT(" FW_DNLD: Starting the FW Upgrade Sequence .... \n"); |
| |
| (void) |
| phDnldNfc_Allocate_Resource((void **) |
| &psDnldContext,sizeof(phDnldNfc_sContext_t)); |
| if(psDnldContext != NULL) |
| { |
| #ifndef NFC_TIMER_CONTEXT |
| gpphDnldContext = psDnldContext; |
| #endif |
| psDnldContext->p_hw_ref = pHwRef; |
| psDnldContext->timer_id = NXP_INVALID_TIMER_ID; |
| |
| DNLD_PRINT(" FW_DNLD: Initialisation in Progress.... \n"); |
| |
| if_callback.pif_ctxt = psDnldContext ; |
| if_callback.send_complete = &phDnldNfc_Send_Complete; |
| if_callback.receive_complete= &phDnldNfc_Receive_Complete; |
| /* if_callback.notify = &phDnldNfc_Notify_Event; */ |
| plower_if = dnldReference.plower_if = &(psDnldContext->lower_interface); |
| status = phDal4Nfc_Register(&dnldReference, if_callback, |
| NULL); |
| DNLD_DEBUG(" FW_DNLD: Lower Layer Register, Status = %02X\n",status); |
| |
| if( (NFCSTATUS_SUCCESS == status) && (NULL != plower_if->init)) |
| { |
| /* psDnldContext->p_config_params = pHwConfig ; */ |
| status = plower_if->init((void *)plower_if->pcontext, |
| (void *)pHwRef); |
| DNLD_DEBUG(" FW_DNLD: Lower Layer Initialisation, Status = %02X\n",status); |
| } |
| else |
| { |
| /* TODO: Handle Initialisation in the Invalid State */ |
| } |
| /* The Lower layer Initialisation successful */ |
| if (NFCSTATUS_SUCCESS == status) |
| { |
| psDnldContext->p_upper_notify = upgrade_complete; |
| psDnldContext->p_upper_context = context; |
| |
| status = phDnldNfc_Process_FW( psDnldContext, pHwRef |
| #ifdef NXP_FW_PARAM |
| ,*nxp_nfc_fw , fw_length |
| #endif |
| ); |
| |
| if (NFCSTATUS_SUCCESS == status) |
| { |
| status = phDnldNfc_Send_Command( psDnldContext, pHwRef, |
| PHDNLD_CMD_RESET , NULL , 0 ); |
| if (NFCSTATUS_PENDING == status) |
| { |
| DNLD_PRINT("\n FW_DNLD: Initial Reset .... \n"); |
| |
| #if defined(FW_DOWNLOAD_TIMER) |
| |
| psDnldContext->timer_id = phOsalNfc_Timer_Create( ); |
| |
| #if (FW_DOWNLOAD_TIMER < 2) |
| phOsalNfc_Timer_Start( psDnldContext->timer_id, |
| NXP_DNLD_COMPLETE_TIMEOUT, |
| (ppCallBck_t) phDnldNfc_Abort |
| #ifdef NFC_TIMER_CONTEXT |
| , (void *) psDnldContext |
| #endif |
| ); |
| |
| #endif /* #if (FW_DOWNLOAD_TIMER < 2) */ |
| |
| #endif /* #if defined(FW_DOWNLOAD_TIMER) */ |
| |
| } |
| } |
| else if (NFCSTATUS_SUCCESS == PHNFCSTATUS(status)) |
| { |
| #if defined (NXP_FW_INTEGRITY_VERIFY) |
| /* |
| * To check for the integrity if the firmware is already |
| * Upgraded. |
| */ |
| status = phDnldNfc_Send_Command( psDnldContext, pHwRef, |
| PHDNLD_CMD_RESET , NULL , 0 ); |
| if (NFCSTATUS_PENDING == status) |
| { |
| DNLD_PRINT("\n FW_DNLD: Integrity Reset .... \n"); |
| (void)phDnldNfc_Set_Seq(psDnldContext, DNLD_SEQ_COMPLETE); |
| status = PHNFCSTVAL( CID_NFC_DNLD, |
| NFCSTATUS_PENDING ); |
| #if defined(FW_DOWNLOAD_TIMER) |
| psDnldContext->timer_id = phOsalNfc_Timer_Create( ); |
| #if (FW_DOWNLOAD_TIMER < 2) |
| phOsalNfc_Timer_Start( psDnldContext->timer_id, |
| NXP_DNLD_COMPLETE_TIMEOUT, |
| (ppCallBck_t) phDnldNfc_Abort |
| #ifdef NFC_TIMER_CONTEXT |
| , (void *) psDnldContext |
| #endif |
| ); |
| |
| #endif /* #if (FW_DOWNLOAD_TIMER < 2) */ |
| |
| #endif /* #if defined(FW_DOWNLOAD_TIMER) */ |
| } |
| |
| #else |
| status = NFCSTATUS_SUCCESS; |
| |
| #endif /* #if defined (NXP_FW_INTEGRITY_VERIFY) */ |
| |
| } |
| else |
| { |
| DNLD_PRINT(" FW_DNLD Initialisation in Failed \n"); |
| } |
| } |
| |
| if (NFCSTATUS_PENDING != PHNFCSTATUS(status)) |
| { |
| (void)phDal4Nfc_Unregister( |
| psDnldContext->lower_interface.pcontext, pHwRef); |
| phDnldNfc_Release_Lower(psDnldContext, pHwRef); |
| phDnldNfc_Release_Resources(&psDnldContext); |
| #ifndef NFC_TIMER_CONTEXT |
| gpphDnldContext = psDnldContext; |
| #endif |
| } |
| } /* End of Status Check for Memory */ |
| else |
| { |
| status = PHNFCSTVAL(CID_NFC_DNLD, NFCSTATUS_INSUFFICIENT_RESOURCES); |
| |
| DNLD_PRINT(" FW_DNLD: Memory Allocation of Context Failed\n"); |
| } |
| } |
| |
| return status; |
| } |