Patch to add Secure Download Mechanism in the libnfc

This patch permit to support secure download update and
also to avoid locking states in case of download failures

Change-Id: I98aa80976a67b18562ddcff4d085ed415dac4933
diff --git a/Android.mk b/Android.mk
index 79c5fb7..2ae7f39 100644
--- a/Android.mk
+++ b/Android.mk
@@ -106,11 +106,11 @@
 LOCAL_SRC_FILES += Linux_x86/phDal4Nfc_messageQueueLib.c
 
 # Really verbose:
-#LOCAL_CFLAGS += -DNXP_MESSAGING -DANDROID -DDEBUG -DDAL_TRACE -DINCLUDE_DALINIT_DEINIT -pipe -fomit-frame-pointer -Wall -Wno-trigraphs -Werror-implicit-function-declaration  -fno-strict-aliasing -mapcs -mno-sched-prolog -mabi=aapcs-linux -mno-thumb-interwork -msoft-float -Uarm -fno-common -fpic
+#LOCAL_CFLAGS += -DNXP_MESSAGING -DANDROID -DDEBUG -DNFC_TIMER_CONTEXT -DDAL_TRACE -DINCLUDE_DALINIT_DEINIT -pipe -fomit-frame-pointer -Wall -Wno-trigraphs -Werror-implicit-function-declaration  -fno-strict-aliasing -mapcs -mno-sched-prolog -mabi=aapcs-linux -mno-thumb-interwork -msoft-float -Uarm -fno-common -fpic
 # Just show I2C traffic:
-#LOCAL_CFLAGS += -DNXP_MESSAGING -DANDROID -DINCLUDE_DALINIT_DEINIT -DLOW_LEVEL_TRACES -pipe -fomit-frame-pointer -Wall -Wno-trigraphs -Werror-implicit-function-declaration  -fno-strict-aliasing -mapcs -mno-sched-prolog -mabi=aapcs-linux -mno-thumb-interwork -msoft-float -Uarm -fno-common -fpic
+#LOCAL_CFLAGS += -DNXP_MESSAGING -DANDROID -DNFC_TIMER_CONTEXT -DINCLUDE_DALINIT_DEINIT -DLOW_LEVEL_TRACES -pipe -fomit-frame-pointer -Wall -Wno-trigraphs -Werror-implicit-function-declaration  -fno-strict-aliasing -mapcs -mno-sched-prolog -mabi=aapcs-linux -mno-thumb-interwork -msoft-float -Uarm -fno-common -fpic
 # Quiet:
-LOCAL_CFLAGS += -DNXP_MESSAGING -DANDROID -DINCLUDE_DALINIT_DEINIT -pipe -fomit-frame-pointer -Wall -Wno-trigraphs -Werror-implicit-function-declaration  -fno-strict-aliasing -fpic
+LOCAL_CFLAGS += -DNXP_MESSAGING -DANDROID -DNFC_TIMER_CONTEXT -DINCLUDE_DALINIT_DEINIT -pipe -fomit-frame-pointer -Wall -Wno-trigraphs -Werror-implicit-function-declaration  -fno-strict-aliasing -fpic
 ifeq ($(TARGET_ARCH),arm)
 LOCAL_CFLAGS += -mapcs -mno-sched-prolog -mabi=aapcs-linux -mno-thumb-interwork -msoft-float -Uarm -fno-common
 endif
diff --git a/inc/phNfcConfig.h b/inc/phNfcConfig.h
index 19a881b..b11e79d 100644
--- a/inc/phNfcConfig.h
+++ b/inc/phNfcConfig.h
@@ -369,11 +369,15 @@
 /**< Macro to Enable the Card Emulation Feature */
 /* #define HOST_EMULATION */
 
+#define NXP_HAL_VERIFY_EEPROM_CRC  0x01U
+
 /**< Macro to Enable the Download Mode Feature */
 #define FW_DOWNLOAD
 
 /**< Macro to Enable the Firmware Download Timer */
-#define FW_DOWNLOAD_TIMER
+/* 0x01U to use overall timeout */
+/* 0x02U to use per frame timeout */
+#define FW_DOWNLOAD_TIMER   0x02U
 
 /**< Macro to Verify the Firmware Download */
 /* #define FW_DOWNLOAD_VERIFY */
@@ -382,6 +386,9 @@
 #define NXP_FW_INTEGRITY_CHK    1
 #endif
 
+/* To specify the Maximum TX/RX Len */
+#define NXP_FW_MAX_TX_RX_LEN   0x200
+
 #define UICC_CONNECTIVITY_PATCH
 
 /* Work around to Delay the initiator activation */
diff --git a/inc/phNfcHalTypes.h b/inc/phNfcHalTypes.h
index a242450..47e9036 100644
--- a/inc/phNfcHalTypes.h
+++ b/inc/phNfcHalTypes.h
@@ -36,6 +36,8 @@
  *
  * File: \ref phNfcHalTypes.h
  *
+ * Developed By: Ravindra U.
+ *
  */
 
 /*@{*/
@@ -47,6 +49,26 @@
 #include <phNfcCompId.h>
 #include <phNfcConfig.h>
 
+#ifndef NXP_HAL_MEM_INFO_SIZE
+#define NXP_HAL_MEM_INFO_SIZE           0x01U
+#endif
+
+#if (NXP_HAL_MEM_INFO_SIZE > 0x01)
+#define NXP_FW_UPLOAD_PROGRESS          0x965AU
+#define NXP_FW_UPLOAD_SUCCESS           0x0000U
+#else
+#define NXP_FW_UPLOAD_PROGRESS          0x5AU
+#define NXP_FW_UPLOAD_SUCCESS           0x00U
+#endif
+
+
+typedef struct phHal_sMemInfo
+{
+    uint16_t            fw_magic;
+    uint16_t            fw_rfu;
+    uint32_t            hal_version;
+}phHal_sMemInfo_t;
+
 
 /** \ingroup  grp_hal_common
  *
@@ -836,6 +858,7 @@
     NFC_INFO_TXLDO_OVERCUR       = 0x71U,
     NFC_INFO_MEM_VIOLATION       = 0x73U,
     NFC_INFO_TEMP_OVERHEAT       = 0x74U,
+    NFC_INFO_LLC_ERROR           = 0x75U,
 
     /* NXP EVENTS */
     NFC_EVT_MIFARE_ACCESS          = 0x35,
diff --git a/src/phDnldNfc.c b/src/phDnldNfc.c
index 76fd88b..0c11377 100644
--- a/src/phDnldNfc.c
+++ b/src/phDnldNfc.c
@@ -58,9 +58,6 @@
 #define STATIC static
 #endif
 
-#define SECTION_HDR
-
-
 #if defined (DNLD_SUMMARY) && !defined (DNLD_TRACE)
 #define DNLD_TRACE
 #endif
@@ -91,12 +88,53 @@
 #define DNLD_PRINT_BUFFER(msg,buf,len)
 #endif
 
+#define DO_DELAY(period)        { unsigned i=0; for(;i<period;i++); }
+
+#define PHDNLD_DNLD_DELAY        0x1000U
+#define PHDNLD_MAX_PACKET        0x0200U  /* 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_MIN_PACKET        0x03U    /* Minimum Packet Size is 3*/
-#define PHDNLD_MAX_PACKET        0x0200U  /* Max Total Packet Size is 512 */
-#define PHDNLD_DATA_SIZE         0x01F8U  /* Max Data Size is 504 */
+#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 */
 
@@ -104,11 +142,14 @@
 
 #define DNLD_CRC32_SIZE			 0x04U
 
-#define DNLD_FW_CODE_ADDR        0x00800000
-#define DNLD_PATCH_CODE_ADDR     0x00018800
-#define DNLD_PATCH_TABLE_ADDR    0x00008200
+#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 */
@@ -116,6 +157,7 @@
 #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 */
@@ -136,6 +178,9 @@
 /* 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
@@ -153,8 +198,23 @@
 #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
 
@@ -162,7 +222,7 @@
 
 #define NXP_MAX_DNLD_RETRY              0x02U
 
-#define NXP_MAX_SECTION_WRITE           0x04U
+#define NXP_MAX_SECTION_WRITE           0x05U
 
 #define NXP_PATCH_VER_INDEX             0x05U
 
@@ -176,6 +236,7 @@
 typedef enum phDnldNfc_eSeqType{
     DNLD_SEQ_RESET                              = 0x00U,
     DNLD_SEQ_INIT,
+    DNLD_SEQ_RAW,
     DNLD_SEQ_LOCK,
     DNLD_SEQ_UNLOCK,
     DNLD_SEQ_UPDATE,
@@ -197,6 +258,8 @@
 typedef enum phDnldNfc_eSeq
 {
     phDnld_Reset_Seq        = 0x00,
+    phDnld_Activate_Patch,
+    phDnld_Deactivate_Patch,
     phDnld_Update_Patch,
     phDnld_Update_Patchtable,
     phDnld_Lock_System,
@@ -205,6 +268,7 @@
     phDnld_Verify_Integrity,
     phDnld_Verify_Section,
     phDnld_Complete_Seq,
+    phDnld_Raw_Upgrade,
     phDnld_Invalid_Seq
 }phDnldNfc_eSeq_t;
 
@@ -233,7 +297,7 @@
   uint8_t           img_data_offset;
   /* Number of fimware images available in the img_data */
   uint8_t           no_of_fw_img;
-  /* Number of fimware images available in the img_data */
+  /* 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;
@@ -262,25 +326,12 @@
 {
   uint8_t            section_hdr_len;
   uint8_t            section_mem_type;
-  uint16_t           section_data_crc;
+  uint8_t            section_checksum;
+  uint8_t            section_conf;
   uint32_t           section_address;
   uint32_t           section_length;
 }section_hdr_t;
 
-
-typedef struct section_type
-{
-    unsigned system_mem_unlock:1;
-    unsigned trim_val:1;
-    unsigned reset_required:1;
-    unsigned verify_mem:1;
-    unsigned trim_check:1;
-    unsigned section_crc_check:1;
-    unsigned section_type_rfu:2;
-    unsigned section_type_pad:24;
-
-}section_type_t;
-
 typedef struct section_info
 {
    section_hdr_t *p_sec_hdr;
@@ -289,6 +340,10 @@
    * 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;
@@ -314,13 +369,24 @@
     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;
@@ -352,10 +418,58 @@
     {
         phDnldNfc_sParam_t data_param;
         uint8_t            response_data[PHDNLD_MAX_PACKET];
-        uint8_t            config_verify_param;
+        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
 {
@@ -374,18 +488,29 @@
 
     /** \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 */
-    phDnldNfc_sData_t           dnld_data;
+    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;
 
@@ -413,11 +538,12 @@
 #define NXP_FW_VMID_CARD_MODE_ADDR  0x00009931U
 #define NXP_FW_VMID_RD_MODE_ADDR    0x00009981U
 
-    unsigned                    vmid_trim_update:1;
-    unsigned                    trim_bits_rfu:31;
+    uint8_t                     vmid_trim_update;
 #endif /* #ifdef  NXP_FW_SW_VMID_TRIM */
 
-	uint8_t						*p_system_mem_crc;
+    uint8_t						cur_frame_info;
+
+    uint8_t						raw_mode_upgrade;
 
 	uint8_t						*p_patch_table_crc;
 
@@ -427,18 +553,12 @@
 
     uint16_t                    resp_length;
 
-    /** \internal Total length of the received buffer */
-    volatile uint16_t           rx_total;
-
     /** \internal Current FW Section in Process */
     volatile uint8_t            section_index;
 
     /** \internal Previous Command sent */
     volatile uint8_t            prev_cmd;
 
-    /** \internal Download Response pending */
-    volatile uint8_t            recv_pending;
-
     uint8_t                     dnld_retry;
 
 	/** \internal Current Download State */
@@ -451,8 +571,14 @@
     /** \internal Next step in Download Sequence */
     volatile uint8_t            next_dnld_seq;
 
-}phDnldNfc_sContext_t;
+    /* \internal Data Transmit information */
+    phDnldNfc_TxInfo_t          tx_info;
 
+    /* \internal Data Receive information */
+    phDnldNfc_RxInfo_t          rx_info;
+
+
+}phDnldNfc_sContext_t;
 
 
 /*
@@ -460,7 +586,23 @@
 ******************** 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 */
 
 /**/
 
@@ -627,8 +769,10 @@
 STATIC
 void
 phDnldNfc_Abort (
-                    uint32_t abort_id   ,
-                    void * pcontext
+                    uint32_t abort_id
+#ifdef NFC_TIMER_CONTEXT
+                    , void     *dnld_cntxt
+#endif
                 );
 
 
@@ -894,7 +1038,7 @@
     NFCSTATUS                       status = NFCSTATUS_SUCCESS;
     static  uint8_t                 prev_temp_state = 0;
     static  uint8_t                 prev_temp_seq =
-                                (uint8_t) phDnld_Update_Patch;
+                                (uint8_t) phDnld_Activate_Patch;
 
     switch(seq_type)
     {
@@ -905,12 +1049,49 @@
                                 (uint8_t) phDnld_Reset_State;
             psDnldContext->next_dnld_state =
                             (uint8_t)phDnld_Upgrade_State;
-            psDnldContext->next_dnld_seq =
+            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 =
@@ -923,18 +1104,6 @@
                                 psDnldContext->cur_dnld_seq;
             break;
         }
-        case DNLD_SEQ_UNLOCK:
-        {
-            psDnldContext->cur_dnld_state =
-                                (uint8_t) phDnld_Reset_State;
-            psDnldContext->next_dnld_state =
-                                (uint8_t) phDnld_Unlock_State;
-            psDnldContext->cur_dnld_seq =
-                                (uint8_t) phDnld_Update_Patch;
-            psDnldContext->next_dnld_seq =
-                                psDnldContext->cur_dnld_seq;
-            break;
-        }
         case DNLD_SEQ_UPDATE:
         {
             prev_temp_state = (uint8_t) psDnldContext->cur_dnld_state;
@@ -972,26 +1141,6 @@
                                 psDnldContext->cur_dnld_seq ;
             break;
         }
-#if 0
-        case DNLD_UPDATE_STATE1:
-        {
-            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 ; */
-            break;
-        }
-        case DNLD_ROLLBACK_STATE1:
-        {
-            psDnldContext->cur_dnld_state = (uint8_t)  prev_temp_state;
-            /* psDnldContext->next_dnld_state =
-                        (uint8_t)phDnld_Invalid_State ; */
-            prev_temp_state = 0;
-
-            break;
-        }
-#endif
         default:
         {
             break;
@@ -1033,6 +1182,36 @@
 #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;
@@ -1088,8 +1267,10 @@
                    )
 {
     NFCSTATUS               status = NFCSTATUS_SUCCESS;
-    phDnldNfc_sParam_t      *p_dnld_data =
-                        &psDnldContext->dnld_data.param_info.data_param;
+    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;
@@ -1099,7 +1280,7 @@
     sec_type = (unsigned int)p_sec_info->p_sec_hdr->section_mem_type;
 
     if( ( FALSE ==  p_sec_info->section_read )
-    && (TRUE == ((section_type_t *)(&sec_type))->trim_val)
+    && ((sec_type & DNLD_TRIM_MASK))
     && (FALSE == p_sec_info->trim_write) )
     {
         read_size = (uint16_t) p_sec_info->p_sec_hdr->section_length;
@@ -1107,18 +1288,26 @@
     }
     else
     {
-#ifdef FW_DOWNLOAD_VERIFY
         if (( FALSE ==  p_sec_info->section_read ) 
-            && (TRUE == ((section_type_t *)(&sec_type))->verify_mem ))
+            && ((sec_type & DNLD_VERIFY_MASK))
+            )
         {
             read_size = (uint16_t)(psDnldContext->prev_dnld_size );
             DNLD_DEBUG(" FW_DNLD: Section Read  = %X \n", read_size);
         }
-        else
-#endif /* #ifdef FW_DOWNLOAD_VERIFY  */
+        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 Back Ignored = %X \n", read_size);
+           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);
         }
     }
 
@@ -1128,24 +1317,24 @@
         read_size = (uint16_t)((PHDNLD_DATA_SIZE >= read_size)?
                                             read_size: PHDNLD_DATA_SIZE);
 
-        psDnldContext->dnld_data.frame_length[i] = (uint8_t)0;
+        p_dnld_data->frame_length[i] = (uint8_t)0;
         /* Update the LSB of the Data and the Address Parameter*/
-        p_dnld_data->data_addr[i] = (uint8_t)((read_addr  >>
+        p_data_param->data_addr[i] = (uint8_t)((read_addr  >>
                                  (BYTE_SIZE + BYTE_SIZE)) & BYTE_MASK);
-        p_dnld_data->data_len[i] = (uint8_t)((read_size >>
+        p_data_param->data_len[i] = (uint8_t)((read_size >>
                                     BYTE_SIZE) & BYTE_MASK);
         i++;
 
-        psDnldContext->dnld_data.frame_length[i] = (uint8_t)
+        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_dnld_data->data_addr[i] = (uint8_t)((read_addr  >>
+        p_data_param->data_addr[i] = (uint8_t)((read_addr  >>
                                BYTE_SIZE) & BYTE_MASK);
-        p_dnld_data->data_len[i] = (uint8_t) (read_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_dnld_data->data_addr[i] = (uint8_t)(read_addr & BYTE_MASK);
+        p_data_param->data_addr[i] = (uint8_t)(read_addr & BYTE_MASK);
 
         status = phDnldNfc_Send_Command( psDnldContext, pHwRef,
                     PHDNLD_CMD_READ, NULL , 0 );
@@ -1174,8 +1363,10 @@
                      )
 {
     NFCSTATUS               status = NFCSTATUS_SUCCESS;
+    phDnldNfc_sData_t       *p_dnld_data =
+                 (phDnldNfc_sData_t *)psDnldContext->dnld_data;
     phDnldNfc_sParam_t      *dnld_data =
-                        &psDnldContext->dnld_data.param_info.data_param;
+                             &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;
@@ -1185,9 +1376,7 @@
     static unsigned         sec_type = 0;
     uint8_t                 i = 0;
     uint16_t                dnld_size = 0;
-#ifdef FW_DOWNLOAD_VERIFY
         int cmp_val = 0x00;
-#endif /* #ifdef FW_DOWNLOAD_VERIFY */
 
 
     sec_type = (unsigned int)p_sec_info->p_sec_hdr->section_mem_type;
@@ -1197,27 +1386,38 @@
     {
         if( (TRUE == p_sec_info->trim_write)
             && (TRUE == p_sec_info->section_read)
+               && ((sec_type & DNLD_VERIFY_MASK))
           )
         {
-#ifdef FW_DOWNLOAD_VERIFY
             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]
-                                          ,psDnldContext->prev_dnld_size);
+                                          ,trim_cmp_size);
+                DNLD_DEBUG(" FW_DNLD: %X Bytes Trim Write Complete ",
+                                    psDnldContext->prev_dnld_size);
+                DNLD_DEBUG(" Comparison Status %X\n", cmp_val);
             }
-#endif /* #ifdef FW_DOWNLOAD_VERIFY  */
             p_sec_info->trim_write = FALSE;
             DNLD_DEBUG(" FW_DNLD: TRIMMED %X Bytes Write Complete\n", psDnldContext->prev_dnld_size);
         }
         else
         {
-#ifdef FW_DOWNLOAD_VERIFY
             if((NULL != psDnldContext->dnld_store.buffer)
-                && (TRUE == ((section_type_t *)(&sec_type))->verify_mem )
+                && ((sec_type & DNLD_VERIFY_MASK))
+                && (TRUE == p_sec_info->section_write)
+                && (TRUE == p_sec_info->section_read)
                 )
             {
                 cmp_val = phOsalNfc_MemCompare(
@@ -1225,18 +1425,26 @@
                                &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);
             }
-#endif /* #ifdef FW_DOWNLOAD_VERIFY  */
+            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 )
-#ifdef FW_DOWNLOAD_VERIFY
             && (0 == cmp_val)
-#endif
             )
         {
             p_sec_info->sec_verify_retry = 0;
@@ -1272,7 +1480,6 @@
     if (dnld_size != 0)
     {
 
-
         dnld_size = (uint16_t)((PHDNLD_DATA_SIZE >= dnld_size)?
                                         dnld_size: PHDNLD_DATA_SIZE);
 
@@ -1281,7 +1488,7 @@
                                   (BYTE_SIZE + BYTE_SIZE)) & BYTE_MASK);
         dnld_data->data_len[i] = (uint8_t)((dnld_size >> BYTE_SIZE)
                                         & BYTE_MASK);
-        psDnldContext->dnld_data.frame_length[i] = (uint8_t)
+        p_dnld_data->frame_length[i] = (uint8_t)
                     (((dnld_size + PHDNLD_CMD_WRITE_MIN_LEN) >> BYTE_SIZE)
                                         & BYTE_MASK);
         i++;
@@ -1289,7 +1496,7 @@
         dnld_data->data_addr[i] = (uint8_t)((dnld_addr  >> BYTE_SIZE)
                                         & BYTE_MASK);
         dnld_data->data_len[i] = (uint8_t) (dnld_size & BYTE_MASK);
-        psDnldContext->dnld_data.frame_length[i] = (uint8_t) ((dnld_size +
+        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*/
@@ -1298,7 +1505,15 @@
         (void)memcpy( dnld_data->data_packet,
                         (p_sec_info->p_sec_data + *p_sec_offset), dnld_size );
 
-        if((TRUE == ((section_type_t *)(&sec_type))->trim_val )
+        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 )
             )
         {
@@ -1348,8 +1563,14 @@
                 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)
             {
@@ -1372,8 +1593,14 @@
                 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,
@@ -1385,14 +1612,24 @@
                 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(" : Memory Write Status = %X \n", status);
+        DNLD_DEBUG(" FW_DNLD: Memory Write Status = %X \n", status);
         if ( NFCSTATUS_PENDING == status )
         {
             psDnldContext->prev_dnld_size = dnld_size;
-            if(TRUE == ((section_type_t *)(&sec_type))->trim_val )
+            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",
@@ -1400,6 +1637,7 @@
             }
             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",
@@ -1440,10 +1678,11 @@
 
             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(TRUE == ((section_type_t *)(&sec_type))->reset_required )
+            if((sec_type & DNLD_RESET_MASK))
             {
                 DNLD_DEBUG(" FW_DNLD: Reset After Section %02X Download \n", sec_index);
                 status = phDnldNfc_Send_Command( psDnldContext, pHwRef,
@@ -1452,7 +1691,36 @@
             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; */
         }
@@ -1483,7 +1751,7 @@
 #if (ES_HW_VER <= 30)
 #define NXP_DNLD_PATCH_ADDR             0x01AFFFU
 #else
-#define NXP_DNLD_PATCH_ADDR             0x01AFE0U
+#define NXP_DNLD_PATCH_ADDR             0x01A1E0U
 #endif
 
 #if  (ES_HW_VER <= 30)
@@ -1504,14 +1772,16 @@
 {
     NFCSTATUS           status = NFCSTATUS_SUCCESS;
     uint32_t            dnld_addr = 0;
-    phDnldNfc_sParam_t  *dnld_data =  &psDnldContext->dnld_data
-                                            .param_info.data_param;
+    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, 0xAF, 0xE0, 0x80, 0xA9, 0x6C };
+    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};
 
@@ -1548,6 +1818,32 @@
 
             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;
@@ -1575,8 +1871,14 @@
             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;
@@ -1622,25 +1924,25 @@
     {
 
         /* Update the LSB of the Data and the Address Parameter*/
-        dnld_data->data_addr[i] = (uint8_t)((dnld_addr  >>
+        p_data_param->data_addr[i] = (uint8_t)((dnld_addr  >>
                                             (BYTE_SIZE + BYTE_SIZE))
                                                     & BYTE_MASK);
-        dnld_data->data_len[i] = (uint8_t)((patch_size >> BYTE_SIZE)
+        p_data_param->data_len[i] = (uint8_t)((patch_size >> BYTE_SIZE)
                                                     & BYTE_MASK);
-        psDnldContext->dnld_data.frame_length[i] = (uint8_t)
+        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*/
-        dnld_data->data_addr[i] = (uint8_t)((dnld_addr  >> BYTE_SIZE)
+        p_data_param->data_addr[i] = (uint8_t)((dnld_addr  >> BYTE_SIZE)
                                                 & BYTE_MASK);
-        dnld_data->data_len[i] = (uint8_t) (patch_size & BYTE_MASK);
-        psDnldContext->dnld_data.frame_length[i] = (uint8_t)
+        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*/
-        dnld_data->data_addr[i] = (uint8_t)(dnld_addr & BYTE_MASK);
+        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 );
@@ -1654,6 +1956,386 @@
     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
@@ -1665,13 +2347,18 @@
                         )
 {
     NFCSTATUS               status = NFCSTATUS_SUCCESS;
-    /* section_info_t          *p_cur_sec = psDnldContext->p_fw_sec +
-                                  psDnldContext->section_index; */
 
     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;
 }
@@ -1708,27 +2395,34 @@
                                     (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
+#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) */
+#endif /* #if  (NXP_FW_INTEGRITY_CHK >= 0x01) */
                     break;
                 }
                 case phDnld_Verify_Integrity:
@@ -1766,21 +2460,21 @@
                 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
+#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) */
+#endif /* #if  (NXP_FW_INTEGRITY_CHK >= 0x01) */
             }
             break;
         }
@@ -1878,12 +2572,14 @@
                             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;
 }
 
@@ -1901,20 +2597,19 @@
                         (phDnldNfc_sData_Hdr_t *) pdata;
 
     PHNFC_UNUSED_VARIABLE(pHwRef);
-    /* DNLD_DEBUG(" FW_DNLD: Receive Length = %X \n", length ); */
-    if(( psDnldContext->rx_total == 0 )
+    DNLD_DEBUG(" FW_DNLD: Receive Length = %X \n", length );
+    if(( psDnldContext->rx_info.rx_total == 0 )
         && (PHDNLD_MIN_PACKET <= length)
-        /* && (FALSE == psDnldContext->recv_pending) */
         )
     {
-        psDnldContext->rx_total =
+        psDnldContext->rx_info.rx_total =
             ((uint16_t)resp_data->frame_length[0] << BYTE_SIZE)|
                         resp_data->frame_length[1];
-        if( psDnldContext->rx_total + PHDNLD_MIN_PACKET == length )
+        if( psDnldContext->rx_info.rx_total + PHDNLD_MIN_PACKET == length )
         {
 
             DNLD_DEBUG(" FW_DNLD: Success Memory Read = %X \n",
-                                                psDnldContext->rx_total);
+                                                psDnldContext->rx_info.rx_total);
 #ifndef DNLD_SUMMARY
             /* DNLD_PRINT_BUFFER("Receive Buffer",pdata,length); */
 #endif
@@ -1924,13 +2619,11 @@
         {
            /* status = phDnldNfc_Receive( psDnldContext, pHwRef,
                 psDnldContext->p_resp_buffer,
-               (uint8_t)((psDnldContext->rx_total <= PHDNLD_MAX_PACKET)?
-                    psDnldContext->rx_total: PHDNLD_MAX_PACKET) );
-            psDnldContext->recv_pending =
-                        (uint8_t)( NFCSTATUS_PENDING == status); */
+               (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_total + PHDNLD_MIN_PACKET));
+            (psDnldContext->rx_info.rx_total + PHDNLD_MIN_PACKET));
             status = PHNFCSTVAL( CID_NFC_DNLD,
                                     NFCSTATUS_INVALID_RECEIVE_LENGTH );
         }
@@ -1938,7 +2631,7 @@
     else
     {
         /*TODO:*/
-        psDnldContext->rx_total = 0 ;
+        psDnldContext->rx_info.rx_total = 0 ;
         status = PHNFCSTVAL( CID_NFC_DNLD,
                                 NFCSTATUS_INVALID_RECEIVE_LENGTH );
     }
@@ -1973,6 +2666,7 @@
         status = pInfo->status ;
         length = pInfo->length ;
         pdata = pInfo->buffer;
+
         if(status != NFCSTATUS_SUCCESS)
         {
             DNLD_DEBUG(" Failed. Status = %02X\n",status);
@@ -1984,9 +2678,10 @@
             /* Handle the Error Scenario */
             status = PHNFCSTVAL( CID_NFC_DNLD,  NFCSTATUS_FAILED );
         }
-        else if (0 == length)
+        else if ((0 == length) 
+            || (PHDNLD_MIN_PACKET > length ))
         {
-            DNLD_PRINT(" Receive Response Length = 0 .... \n");
+            DNLD_DEBUG(" Receive Response Length = %u .... \n",length);
             /* Handle the Error Scenario */
 #ifndef HAL_SW_DNLD_RLEN
              status = PHNFCSTVAL( CID_NFC_DNLD,
@@ -1996,6 +2691,15 @@
         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
@@ -2014,6 +2718,9 @@
                     {
                         case PHDNLD_CMD_READ :
                         {
+							if( PHDNLD_NO_OPERATION
+							       == psDnldContext->raw_mode_upgrade)
+                            {
                             status = phDnldNfc_Process_Response(
                                     psDnldContext, pHwRef, pdata , length);
 
@@ -2023,10 +2730,18 @@
                                 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;
@@ -2071,8 +2786,16 @@
                                     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:
@@ -2080,10 +2803,18 @@
                             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) )
                                 )
@@ -2096,14 +2827,20 @@
                             {
                                 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_WRITE_ERROR:
                 case PHDNLD_RESP_CRC_ERROR:
+                case PHDNLD_RESP_WRITE_ERROR:
                 {
                     if(psDnldContext->dnld_retry < NXP_MAX_DNLD_RETRY )
                     {
@@ -2115,22 +2852,139 @@
                 }
                 /* fall through */
                 case PHDNLD_RESP_ACCESS_DENIED:
-                case PHDNLD_RESP_PROTOCOL_ERROR:
                 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_FEATURE_NOT_SUPPORTED);
+                                        NFCSTATUS_NOT_ALLOWED);
                     break;
                 }
+
             } /* End of the Response Frame Type Switch */
 
             if (NFCSTATUS_PENDING != status)
@@ -2149,10 +3003,57 @@
                                 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"); */
@@ -2202,17 +3103,28 @@
             if ((PHDNLD_CMD_SET_HIF != psDnldContext->prev_cmd)
                 && (PHDNLD_CMD_RESET != psDnldContext->prev_cmd))
             {
-                psDnldContext->rx_total = 0;
+                psDnldContext->rx_info.rx_total = 0;
                 status = phDnldNfc_Receive( psDnldContext, pHwRef,
                             (uint8_t *)(&psDnldContext->dnld_resp),
                                            psDnldContext->resp_length);
-                /* psDnldContext->recv_pending =
-                                (uint8_t)( NFCSTATUS_PENDING == status); */
             }
             else
             {
                 psDnldContext->resp_length = 0;
                 psDnldContext->dnld_retry = 0;
+                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);
             }
@@ -2228,6 +3140,7 @@
 }
 
 
+
 STATIC
 NFCSTATUS
 phDnldNfc_Send_Command(
@@ -2242,6 +3155,8 @@
     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)
     {
@@ -2253,8 +3168,10 @@
         }
         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 */
-                                &psDnldContext->dnld_data.param_info.data_param;
+                               &p_dnld_data->param_info.data_param;
             tx_length = PHDNLD_CMD_READ_LEN;
             if (NULL != *pp_resp_data)
             {
@@ -2265,21 +3182,18 @@
                                    << BYTE_SIZE) + param_info->data_len[1]);
 
             psDnldContext->resp_length =
-#if 0
-                (((rx_length > PHDNLD_DATA_SIZE)?
-                            PHDNLD_DATA_SIZE + PHDNLD_MIN_PACKET:
-#else
-                ((
-#endif
-                               rx_length + PHDNLD_MIN_PACKET ));
+                (( 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 */
-                                &psDnldContext->dnld_data.param_info.data_param;
+                                &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 );
@@ -2297,6 +3211,36 @@
             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++;
@@ -2305,8 +3249,18 @@
         }
         case PHDNLD_CMD_ACTIVATE_PATCH:
         {
-            tx_length++;
             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:
@@ -2314,7 +3268,7 @@
 #if  (NXP_FW_INTEGRITY_CHK >= 0x01)
             if ((NULL != params) && ( param_length > 0 ))
             {
-                psDnldContext->chk_integrity_param = 
+                psDnldContext->chk_integrity_param =
                             (phDnldNfc_eChkCrc_t)(*(uint8_t *)params);
                 tx_length = param_length ;
             }
@@ -2323,7 +3277,7 @@
                 psDnldContext->chk_integrity_param = CHK_INTEGRITY_COMPLETE_CRC;
                 tx_length++;
             }
-            psDnldContext->dnld_data.param_info.config_verify_param = 
+            p_dnld_data->param_info.cmd_param =
                                 (uint8_t) psDnldContext->chk_integrity_param;
             switch(psDnldContext->chk_integrity_param)
             {
@@ -2351,7 +3305,7 @@
             }
 #else
             tx_length++;
-            psDnldContext->dnld_data.param_info.config_verify_param = 
+            p_dnld_data->param_info.cmd_param = 
                                 (uint8_t) CHK_INTEGRITY_COMPLETE_CRC;
 
 #endif /* #if  (NXP_FW_INTEGRITY_CHK >= 0x01) */
@@ -2367,19 +3321,19 @@
     {
         uint8_t     i = 0;
 
-        psDnldContext->dnld_data.frame_type = cmd;
-        psDnldContext->dnld_data.frame_length[i++] =
+        p_dnld_data->frame_type = cmd;
+        p_dnld_data->frame_length[i++] =
                                     (uint8_t)(tx_length >> BYTE_SIZE);
-        psDnldContext->dnld_data.frame_length[i]   =
+        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 *)(&psDnldContext->dnld_data), tx_length);
+                            (uint8_t *)p_dnld_data, tx_length);
         if(NFCSTATUS_PENDING == status)
         {
             psDnldContext->prev_cmd = cmd;
-        }
 
+        }
     }
 
     return status;
@@ -2387,34 +3341,12 @@
 
 static
 NFCSTATUS
-phDnldNfc_Process_FW(
-                        phDnldNfc_sContext_t    *psDnldContext,
-                        phHal_sHwReference_t    *pHwRef
-#ifdef NXP_FW_PARAM
-                        ,uint8_t                 *nxp_nfc_fw
-#endif
+phDnldNfc_Check_FW(
+                    phHal_sHwReference_t    *pHwRef,
+                    fw_data_hdr_t           *cur_fw_hdr
                      )
 {
     NFCSTATUS               status = NFCSTATUS_FAILED;
-    section_info_t          *p_cur_sec = NULL;
-    static unsigned         sec_type;
-    uint32_t                fw_index = 0;
-    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;
-
-    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 );
-        /* TODO: Create a memory of pointers to store all the Firmwares */
-        cur_fw_hdr = psDnldContext->p_fw_hdr;
-
-        fw_index = fw_index + (cur_fw_hdr->fw_hdr_len * PNDNLD_WORD_LEN);
 
         if ( !pHwRef->device_info.fw_version )
         {
@@ -2430,9 +3362,6 @@
             status = PHNFCSTVAL( CID_NFC_DNLD, NFCSTATUS_NOT_ALLOWED );
         }
         else if (( pHwRef->device_info.fw_version < cur_fw_hdr->fw_version  )
-#ifdef NXP_FW_PATCH_VERIFY
-            && (pHwRef->device_info.full_version[NXP_PATCH_VER_INDEX] < cur_fw_hdr->fw_patch )
-#endif
             )
         {
             /* TODO: Firmware Version Check and upgrade*/
@@ -2452,22 +3381,87 @@
             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)
-        {
-            status = PHNFCSTVAL(CID_NFC_DNLD,
-                            NFCSTATUS_INSUFFICIENT_RESOURCES);
-        }
-        else
+
+            if(NULL != psDnldContext->p_fw_sec)
         {
             DNLD_DEBUG(" FW_DNLD: FW Index : %x \n",
                                             fw_index );
@@ -2496,7 +3490,7 @@
 
                 sec_type = (unsigned int)p_cur_sec->p_sec_hdr->section_mem_type;
 
-                if(TRUE == ((section_type_t *)(&sec_type))->trim_val )
+                    if((sec_type & DNLD_TRIM_MASK))
                 {
                     p_cur_sec->p_trim_data = (uint8_t *)
                                (nxp_nfc_fw + fw_index + sizeof(section_hdr_t));
@@ -2506,25 +3500,42 @@
                     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 +
-#ifdef SECTION_HDR
                     (p_cur_sec->p_sec_hdr->section_hdr_len * PNDNLD_WORD_LEN);
-#else
-                        sizeof (section_hdr_t) ;
-#endif
 
                 fw_index = fw_index +
-#ifdef SECTION_HDR
                     (p_cur_sec->p_sec_hdr->section_hdr_len * PNDNLD_WORD_LEN)
-#else
-                    sizeof (section_hdr_t)
-#endif
                    + 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)
@@ -2558,13 +3569,37 @@
                    {
                        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;
 }
@@ -2599,45 +3634,7 @@
 
         fw_index = fw_index + (cur_fw_hdr->fw_hdr_len * PNDNLD_WORD_LEN);
 
-        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  )
-#ifdef NXP_FW_PATCH_VERIFY
-            && (pHwRef->device_info.full_version[NXP_PATCH_VER_INDEX] < cur_fw_hdr->fw_patch )
-#endif
-            )
-        {
-            /* TODO: Firmware Version Check and upgrade*/
-            DNLD_PRINT(" FW_DNLD_CHK: Older Firmware. Upgrading to newer one.... \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_CHK: Already Updated .... \n");
-            status = ( CID_NFC_DNLD << BYTE_SIZE ) ;
-        }
-    }
-    if( NFCSTATUS_SUCCESS == status )
-    {
+        status = phDnldNfc_Check_FW( pHwRef, cur_fw_hdr);
     }
     return status;
 }
@@ -2648,26 +3645,39 @@
 STATIC
 void
 phDnldNfc_Abort (
-                    uint32_t    abort_id  ,
-                    void * pContext
+                    uint32_t    abort_id
+#ifdef NFC_TIMER_CONTEXT
+                    , void     *dnld_cntxt
+#endif
                 )
 {
 
     phNfc_sCompletionInfo_t  comp_info = {0};
 
-    if ( ( NULL != gpphDnldContext)
-            && (abort_id == gpphDnldContext->timer_id ))
+    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 =
-            gpphDnldContext->p_upper_notify;
+            p_dnld_context->p_upper_notify;
         void                        *p_upper_context =
-                                gpphDnldContext->p_upper_context;
-        phHal_sHwReference_t        *pHwRef = gpphDnldContext->p_hw_ref;
+                                p_dnld_context->p_upper_context;
+        phHal_sHwReference_t        *pHwRef = p_dnld_context->p_hw_ref;
 
         (void)phDal4Nfc_Unregister(
-                     gpphDnldContext->lower_interface.pcontext, pHwRef );
-        phDnldNfc_Release_Lower(gpphDnldContext, pHwRef);
-        phDnldNfc_Release_Resources(&gpphDnldContext);
+                     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",
@@ -2686,6 +3696,7 @@
 phDnldNfc_Upgrade (
                         phHal_sHwReference_t            *pHwRef,
 #ifdef NXP_FW_PARAM
+                        uint8_t                          type,
                         uint8_t                         *nxp_nfc_fw,
                         uint32_t                         fw_length,
 #endif
@@ -2709,16 +3720,15 @@
     else
     {
         DNLD_PRINT(" FW_DNLD: Starting the FW Upgrade Sequence .... \n");
-        /* Create the memory for Download Mgmt Context */
-        psDnldContext = (phDnldNfc_sContext_t *)
-                        phOsalNfc_GetMemory(sizeof(phDnldNfc_sContext_t));
 
+        (void)
+             phDnldNfc_Allocate_Resource((void **)
+                              &psDnldContext,sizeof(phDnldNfc_sContext_t));
         if(psDnldContext != NULL)
         {
-            (void ) memset((void *)psDnldContext,0,
-                                            sizeof(phDnldNfc_sContext_t));
-
+#ifndef NFC_TIMER_CONTEXT
             gpphDnldContext = psDnldContext;
+#endif
             psDnldContext->p_hw_ref = pHwRef;
             psDnldContext->timer_id = NXP_INVALID_TIMER_ID;
 
@@ -2752,7 +3762,7 @@
 
                 status = phDnldNfc_Process_FW( psDnldContext, pHwRef
 #ifdef NXP_FW_PARAM
-                ,*nxp_nfc_fw /*, fw_length */
+                ,*nxp_nfc_fw , fw_length
 #endif
                  );
 
@@ -2763,27 +3773,24 @@
                     if (NFCSTATUS_PENDING == status)
                     {
                         DNLD_PRINT("\n FW_DNLD: Initial Reset .... \n");
-                        p_cur_sec = ((section_info_t *)
-                            (psDnldContext->p_fw_sec ));
-                        sec_type = (unsigned )
-                            (p_cur_sec->p_sec_hdr->section_mem_type);
 
-                        if(TRUE == ((section_type_t *)
-                                (&sec_type))->system_mem_unlock )
-                        {
-                            (void)phDnldNfc_Set_Seq(psDnldContext,
-                                                            DNLD_SEQ_UNLOCK);
-                        }
-                        else
-                        {
-                            (void)phDnldNfc_Set_Seq(psDnldContext,
-                                                            DNLD_SEQ_INIT);
-                        }
-#ifdef FW_DOWNLOAD_TIMER
+#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, phDnldNfc_Abort, NULL );
+                                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))
@@ -2801,16 +3808,27 @@
                         (void)phDnldNfc_Set_Seq(psDnldContext, DNLD_SEQ_COMPLETE);
                         status = PHNFCSTVAL( CID_NFC_DNLD, 
                                         NFCSTATUS_PENDING );
-#ifdef FW_DOWNLOAD_TIMER
+#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, phDnldNfc_Abort, NULL );
+                                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
+
+#endif /* #if  defined (NXP_FW_INTEGRITY_VERIFY) */
+
                 }
                 else
                 {
@@ -2821,9 +3839,12 @@
             if (NFCSTATUS_PENDING != PHNFCSTATUS(status))
             {
                 (void)phDal4Nfc_Unregister(
-                            gpphDnldContext->lower_interface.pcontext, pHwRef);
-                phDnldNfc_Release_Lower(gpphDnldContext, pHwRef);
-                phDnldNfc_Release_Resources(&gpphDnldContext);
+                            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
diff --git a/src/phHal4Nfc.c b/src/phHal4Nfc.c
index 3e7c163..726b4b5 100644
--- a/src/phHal4Nfc.c
+++ b/src/phHal4Nfc.c
@@ -153,7 +153,11 @@
         gpphHal4Nfc_Hwref = NULL;
         PHDBG_INFO("Hal4:Open Failed");
         /*Call upper layer's Open Cb with error status*/
+        if(NULL != pUpper_OpenCb)
+        {
+            /*Upper layer's Open Cb*/
         (*pUpper_OpenCb)(pUpper_Context,status);
+        }
     }
     return;
 }
@@ -404,7 +408,7 @@
             if( openRetVal == NFCSTATUS_SUCCESS )
             {
                 /*update Next state*/
-                Hal4Ctxt->Hal4NextState = (HCI_SELF_TEST == eHciInitType?
+                Hal4Ctxt->Hal4NextState = (HCI_NFC_DEVICE_TEST == eHciInitType?
                                 eHal4StateSelfTestMode:eHal4StateOpenAndReady);
                 /*Store callback and context ,and set Default settings in Context*/
                 Hal4Ctxt->sUpperLayerInfo.pUpperOpenCb = pOpenCallback;
@@ -468,13 +472,17 @@
     else if(NULL == psHwReference->hal_context)
     {
 #ifdef FW_DOWNLOAD
+
+#if  !defined (NXP_FW_INTEGRITY_VERIFY)
         if(NFC_FW_DOWNLOAD_CHECK == IoctlCode)
         {
             RetStatus = phDnldNfc_Run_Check(
                 psHwReference                       
                 );
         }
-        else if((NFC_FW_DOWNLOAD == IoctlCode)
+        else
+#endif /* !defined (NXP_FW_INTEGRITY_VERIFY) */
+        if((NFC_FW_DOWNLOAD == IoctlCode)
             &&(NULL == gpphHal4Nfc_Hwref))/*Indicates current state is shutdown*/
         {
             Hal4Ctxt = (phHal4Nfc_Hal4Ctxt_t *)
@@ -503,7 +511,9 @@
                         phHal4Nfc_DownloadComplete,
                         Hal4Ctxt
                         );
-                if(NFCSTATUS_SUCCESS == RetStatus)
+                if((NFCSTATUS_SUCCESS == RetStatus)
+                    || (NFCSTATUS_PENDING != PHNFCSTATUS(RetStatus))
+                    )
                 {
                     phOsalNfc_FreeMemory(Hal4Ctxt);
                     ((phHal_sHwReference_t *)psHwReference)->hal_context = NULL;
@@ -1006,10 +1016,15 @@
                 break;
             case NFC_NOTIFY_DEVICE_ERROR:
             {
+                NFCSTATUS status = NFCSTATUS_BOARD_COMMUNICATION_ERROR;
+                pphHal4Nfc_GenCallback_t pUpper_OpenCb
+                                                = Hal4Ctxt->sUpperLayerInfo.pUpperOpenCb;
+                void                   *pUpper_Context
+                                            = Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt;
                 static phHal4Nfc_NotificationInfo_t uNotificationInfo;
-                Hal4Ctxt->Hal4NextState = eHal4StateInvalid;
                 if(NULL != Hal4Ctxt->sUpperLayerInfo.pDefaultEventHandler)
                 {                    
+                    Hal4Ctxt->Hal4NextState = eHal4StateInvalid;
                     Hal4Ctxt->sUpperLayerInfo.pDefaultEventHandler(
                         Hal4Ctxt->sUpperLayerInfo.DefaultListenerCtxt,
                         NFC_EVENT_NOTIFICATION,
@@ -1017,8 +1032,31 @@
                         NFCSTATUS_BOARD_COMMUNICATION_ERROR
                         );
                 }
+                else if (( eHal4StateSelfTestMode == Hal4Ctxt->Hal4NextState )
+                    || ( eHal4StateOpenAndReady == Hal4Ctxt->Hal4NextState ) )
+                {
+                    Hal4Ctxt->Hal4CurrentState = eHal4StateClosed;
+                    Hal4Ctxt->Hal4NextState = eHal4StateInvalid;
+                    (void)phHciNfc_Release((void *)Hal4Ctxt->psHciHandle,
+                                              pHwRef, (pphNfcIF_Notification_CB_t)NULL,
+                                               (void *)Hal4Ctxt);/*Clean up Hci*/
+                    Hal4Ctxt->psHciHandle = NULL;
+                    phOsalNfc_FreeMemory((void *)Hal4Ctxt->pHal4Nfc_LayerCfg);
+                    Hal4Ctxt->pHal4Nfc_LayerCfg = NULL;
+                    phOsalNfc_FreeMemory((void *)Hal4Ctxt);
+                    gpphHal4Nfc_Hwref->hal_context = NULL;
+                    gpphHal4Nfc_Hwref = NULL;
+                    PHDBG_INFO("Hal4:Open Failed");
+                    /*Call upper layer's Open Cb with error status*/
+                    if(NULL != pUpper_OpenCb)
+                    {
+                        /*Upper layer's Open Cb*/
+                        (*pUpper_OpenCb)(pUpper_Context,status);
+                    }
+                }
                 else
                 {
+                    Hal4Ctxt->Hal4NextState = eHal4StateInvalid;
                     phOsalNfc_RaiseException(phOsalNfc_e_UnrecovFirmwareErr,1);
                 }
                 break;
@@ -1216,6 +1254,7 @@
         case NFC_INFO_TXLDO_OVERCUR:
         case NFC_INFO_MEM_VIOLATION:
         case NFC_INFO_TEMP_OVERHEAT:
+        case NFC_INFO_LLC_ERROR:
         {
             sNotificationInfo.info = psEventInfo;
             sNotificationInfo.status = NFCSTATUS_SUCCESS;
@@ -1292,10 +1331,23 @@
         = Hal4Ctxt->sUpperLayerInfo.pUpperIoctlCb;
     void  *pUpper_Context = Hal4Ctxt->sUpperLayerInfo.psUpperLayerCtxt;
     /*check for Success*/
-    if((SelfTestResults->length > 0) && (0 == SelfTestResults->buffer[0]))
+    if(( DEVMGMT_SWP_TEST == Hal4Ctxt->Ioctl_Type )
+        || ( DEVMGMT_ANTENNA_TEST == Hal4Ctxt->Ioctl_Type ))
     {
         status = NFCSTATUS_SUCCESS;
     }
+    else if((SelfTestResults->length > 0) && (0 == SelfTestResults->buffer[0]))
+    {
+        status = NFCSTATUS_SUCCESS;
+    }
+    else
+    {
+        if (NULL != pInfo)
+        {
+            status = ((phNfc_sCompletionInfo_t *)pInfo)->status;
+        }
+    }
+
     /*Copy response buffer and length*/
     (void)memcpy(Hal4Ctxt->sUpperLayerInfo.pIoctlOutParam->buffer,
                  SelfTestResults->buffer,
@@ -1354,7 +1406,8 @@
     {
         /*for NFC_MEM_READ and NFC_GPIO_READ ,provide one Byte Response*/
         if ((NFC_MEM_READ == Hal4Ctxt->Ioctl_Type)
-            || (NFC_GPIO_READ == Hal4Ctxt->Ioctl_Type))
+            || (NFC_GPIO_READ == Hal4Ctxt->Ioctl_Type)
+            )
         {
             Hal4Ctxt->sUpperLayerInfo.pIoctlOutParam->length 
                 = sizeof (uint8_t);
diff --git a/src/phHciNfc.h b/src/phHciNfc.h
index f360413..4f52b4a 100644
--- a/src/phHciNfc.h
+++ b/src/phHciNfc.h
@@ -78,8 +78,9 @@
 typedef enum phHciNfc_Init
 {
   HCI_SESSION = 0x00,
-  HCI_SELF_TEST,
-  HCI_CUSTOM_INIT
+  HCI_NFC_DEVICE_TEST,
+  HCI_CUSTOM_INIT,
+  HCI_SELF_TEST
 }phHciNfc_Init_t;
 
 /** \ingroup  grp_hal_hci
@@ -263,7 +264,7 @@
  *                                      of the HCI Layer.
  *  \param[in]  pHwRef                  pHwRef is the Information of
  *                                      the Device Interface Link .
- *  \param[in]  re_poll                 If True: Start re-polling of the target
+ *  \param[in]  discovery_type                 If True: Start re-polling of the target
  *                                      after the Target Device is de-activated
  *                                      or else - continue discovery with next
  *                                      technology.
@@ -279,7 +280,7 @@
  phHciNfc_Restart_Discovery (
                         void                            *psHciHandle,
                         void                            *pHwRef,
-                        uint8_t                         repoll
+                        uint8_t                         discovery_type
                      );
 
 
@@ -495,10 +496,11 @@
  *                                      of the HCI Layer.
  *  \param[in]  pHwRef                  pHwRef is the Information of
  *                                      the Device Interface Link .
- *  \param[in]  re_poll                 If True: Start re-polling of the target
- *                                      after the Target Device is de-activated
- *                                      or else - continue discovery with next
- *                                      technology.
+ *  \param[in]  discovery_type          If NFC_RF_DISCOVERY_REPOLL: Start re-polling of
+ *                                      the target after the Target Device is
+ *                                      de-activatedor if NFC_RF_DISCOVERY_CONTINUE -
+ *                                      continue discovery with next technology or
+ *                                      stop the discovery wheel.
  *
  *  \retval NFCSTATUS_PENDING           To De-select the remote target pending.
  *  \retval NFCSTATUS_INVALID_PARAMETER One or more of the supplied parameters
@@ -512,7 +514,7 @@
  phHciNfc_Disconnect (
                     void                            *psHciHandle,
                     void                            *pHwRef,
-                    uint8_t                         re_poll
+                    uint8_t                         discovery_type
                  );
 
 
diff --git a/src/phHciNfc_DevMgmt.c b/src/phHciNfc_DevMgmt.c
index 32662c1..5b3eddc 100644
--- a/src/phHciNfc_DevMgmt.c
+++ b/src/phHciNfc_DevMgmt.c
@@ -71,6 +71,7 @@
 #define NXP_EVT_INFO_EXT_RF_FIELD    0x12U
 #define NXP_EVT_INFO_MEM_VIOLATION   0x13U
 #define NXP_EVT_INFO_TEMP_OVERHEAT   0x14U
+#define NXP_EVT_INFO_LLC_ERROR       0x15U
 
 #define NFC_DEV_TXLDO_MASK           0x03U
 
@@ -518,7 +519,8 @@
                     if(status == NFCSTATUS_SUCCESS)
                     {
                         
-                        if (HCI_SELF_TEST == psHciContext->init_mode )
+                        if ((HCI_SELF_TEST == psHciContext->init_mode )
+                            || (HCI_NFC_DEVICE_TEST == psHciContext->init_mode ))
                         {
                             p_device_mgmt_info->next_seq =
                                                 DEV_MGMT_GPIO_PDIR;
@@ -641,18 +643,27 @@
 #endif /* #if  ( NXP_NFC_IFC_TIMEOUT & 0x01 ) */
                 case DEV_MGMT_TX_LDO:
                 {
-                    config = (NFC_DEV_HWCONF_DEFAULT |
-                                    (NXP_DEFAULT_TX_LDO & NFC_DEV_TXLDO_MASK));
-                    status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef,
-                            NFC_ADDRESS_HW_CONF , config );
-                    if(NFCSTATUS_PENDING == status )
+#if ( NXP_HAL_VERIFY_EEPROM_CRC & 0x01U )
+                    if (0 != p_device_mgmt_info->eeprom_crc)
                     {
-#if ( SW_TYPE_RF_TUNING_BF & 0x01)
-                        p_device_mgmt_info->next_seq = DEV_MGMT_ANAIRQ_CONF;
-#else
-                        p_device_mgmt_info->next_seq = DEV_MGMT_CLK_REQ;
+                        status = NFCSTATUS_FAILED;
+                    }
+                    else
 #endif
-                        /* status = NFCSTATUS_SUCCESS; */
+                    {
+                       config = (NFC_DEV_HWCONF_DEFAULT |
+                                    (NXP_DEFAULT_TX_LDO & NFC_DEV_TXLDO_MASK));
+                       status = phHciNfc_DevMgmt_Configure( psHciContext, pHwRef,
+                            NFC_ADDRESS_HW_CONF , config );
+                       if(NFCSTATUS_PENDING == status )
+                       {
+#if ( SW_TYPE_RF_TUNING_BF & 0x01)
+                           p_device_mgmt_info->next_seq = DEV_MGMT_ANAIRQ_CONF;
+#else
+                           p_device_mgmt_info->next_seq = DEV_MGMT_CLK_REQ;
+#endif
+                           /* status = NFCSTATUS_SUCCESS; */
+                       }
                     }
                     break;
                 }
@@ -1052,17 +1063,20 @@
             {
                 p_device_mgmt_info->current_seq = DEV_MGMT_PIPE_OPEN;
                 p_device_mgmt_info->next_seq = DEV_MGMT_PIPE_OPEN ;
-            }break;
+                break;
+            }
             case UPDATE_SEQ:
             {
                 p_device_mgmt_info->current_seq = p_device_mgmt_info->next_seq;
             
-            }break;
+                break;
+            }
             case REL_SEQ:
             {
                 p_device_mgmt_info->current_seq = DEV_MGMT_EVT_AUTONOMOUS;
                 p_device_mgmt_info->next_seq = DEV_MGMT_EVT_AUTONOMOUS ;
-            }break;
+                break;
+            }
             default:
             {
                 break;
@@ -1107,6 +1121,8 @@
     }
     else
     {
+        phHciNfc_DevMgmt_Info_t *p_device_mgmt_info = (phHciNfc_DevMgmt_Info_t *)
+                                        psHciContext->p_device_mgmt_info ;
         p_pipe_info = ((phHciNfc_DevMgmt_Info_t *)
                        psHciContext->p_device_mgmt_info)->p_pipe_info ;
         switch(test_type)
@@ -1124,6 +1140,8 @@
                         p_pipe_info->param_info = test_param->buffer;
                         p_pipe_info->param_length = (uint8_t)test_param->length;
                     }
+                    p_device_mgmt_info->test_result.buffer = NULL;
+                    p_device_mgmt_info->test_result.length = 0;
                     status = 
                         phHciNfc_Send_DevMgmt_Command( psHciContext, pHwRef, 
                             pipe_id, (uint8_t)test_type );
@@ -1213,15 +1231,15 @@
                 break;
             }
             case NXP_DBG_READ:
-            {
-                *p_device_mgmt_info->p_val = (uint8_t)( length > HCP_HEADER_LEN ) ?
-                                    pResponse[HCP_HEADER_LEN]: 0;
-                p_device_mgmt_info->p_val = NULL;
-
-            }
             /* fall through */
             case NXP_DBG_WRITE:
             {
+                if( NULL != p_device_mgmt_info->p_val )
+                {
+                    *p_device_mgmt_info->p_val = (uint8_t)( length > HCP_HEADER_LEN ) ?
+                                        pResponse[HCP_HEADER_LEN]: 0;
+                    p_device_mgmt_info->p_val = NULL;
+                }
                 break;
             }
             /* Self Test Commands */
@@ -1350,6 +1368,11 @@
                                     p_device_mgmt_info->overheat_status;
                 break;
             }
+            case NXP_EVT_INFO_LLC_ERROR:
+            {
+                event_info.eventType = NFC_INFO_LLC_ERROR;
+                break;
+            }
             default:
             {
                 status = PHNFCSTVAL(CID_NFC_HCI,
diff --git a/src/phHciNfc_Generic.h b/src/phHciNfc_Generic.h
index 5410325..b4f8a6d 100644
--- a/src/phHciNfc_Generic.h
+++ b/src/phHciNfc_Generic.h
@@ -458,6 +458,7 @@
 
     /* HCI Device Management Sequence */
     DEV_INIT_SEQ,
+    DEV_HAL_INFO_SEQ,
     DEV_CONFIG_SEQ,
     DEV_REL_SEQ,
 
@@ -611,8 +612,8 @@
     /** \internal Mode of HCI Initialisation */
     phHciNfc_Init_t             init_mode;
 
-    /** \internal Mode of HCI Initialisation */
-    void                        *p_io_params;
+    /** \internal Memory Information for HCI Initialisation */
+    uint8_t                     hal_mem_info[NXP_HAL_MEM_INFO_SIZE];
 
     /** \internal HCI Configuration Type */
     phHciNfc_eConfigType_t      config_type;
diff --git a/src/phHciNfc_Sequence.c b/src/phHciNfc_Sequence.c
index 13b8ad5..53e8b70 100644
--- a/src/phHciNfc_Sequence.c
+++ b/src/phHciNfc_Sequence.c
@@ -65,6 +65,10 @@
 ################################################################################
 */
 
+/* Address Definitions for HAL Configuration */
+#define NFC_ADDRESS_HAL_CONF            0x9FD0U
+
+
 /*
 ################################################################################
 ********************** Structure/Enumeration Definitions ***********************
@@ -243,8 +247,10 @@
                         /* Initialise to Perform Test on 
                            the Antenna/SWP Link */
                         case hciState_Test:
+                        {
                             status = NFCSTATUS_SUCCESS;
                             break;
+                        }
                         default:
                             break;
                     }
@@ -266,8 +272,10 @@
                         case hciState_Listen:
                         /* Specifies the Starting of the Release Sequence */
                         case hciState_Release:
+                        {
                             status = NFCSTATUS_SUCCESS;
                             break;
+                        }
                         default:
                             break;
                     }
@@ -306,8 +314,10 @@
                         case hciState_Connect:
                         /* Specifies the Starting of the Release Sequence */
                         case hciState_Release:
+                        {
                             status = NFCSTATUS_SUCCESS;
                             break;
+                        }
                         default:
                             break;
                     }
@@ -338,8 +348,10 @@
                         case hciState_Disconnect:
                         /* Specifies the Starting of the Release Sequence */
                         case hciState_Release:
+                        {
                             status = NFCSTATUS_SUCCESS;
                             break;
+                        }
                         default:
                             break;
                     }
@@ -363,8 +375,10 @@
                         case hciState_Transact:
                         /* Specifies the Starting of the Release Sequence */
                         case hciState_Release:
+                        {
                             status = NFCSTATUS_SUCCESS;
                             break;
+                        }
                         default:
                             break;
                     }
@@ -386,8 +400,10 @@
                         case hciState_Config:
                         /* Specifies the Starting of the Release Sequence */
                         case hciState_Release:
+                        {
                             status = NFCSTATUS_SUCCESS;
                             break;
+                        }
                         default:
                             break;
                     }
@@ -412,10 +428,14 @@
                         case hciState_Listen:
                         /* Specifies the Starting of the Release Sequence */
                         case hciState_Release:
+                        {
                             status = NFCSTATUS_SUCCESS;
                             break;
+                        }
                         default:
+                        {
                             break;
+                        }
                     }
                     break;
                 }
@@ -640,7 +660,7 @@
             {
                 if (hciState_Reset == psHciContext->hci_state.cur_state)
                 {
-                    phNfc_sCompletionInfo_t     comp_info;
+                    phNfc_sCompletionInfo_t     comp_info={FALSE,0, NULL};
 
                     phHciNfc_Release_Lower( psHciContext, pHwRef );
                     /* Release all the resources and 
@@ -654,7 +674,7 @@
                 {
                     /* Notify the Poll/Emulation Configure failure to the upper layer */
 
-                    phNfc_sCompletionInfo_t     comp_info;
+                    phNfc_sCompletionInfo_t     comp_info={FALSE,0, NULL};
 
                     comp_info.status = error_status ;
 
@@ -671,7 +691,8 @@
                 {
 
                     /* Notify the Poll Configure failure to the upper layer */
-                    phNfc_sCompletionInfo_t     comp_info;
+                    phNfc_sCompletionInfo_t     comp_info={FALSE,0, NULL};
+
 
                     psHciContext->error_status = error_status;
                     status = phHciNfc_Pending_Sequence(psHciContext, pHwRef );
@@ -700,7 +721,7 @@
             case hciState_Config:
             {
                 /* Notify the Configure failure to the upper layer */
-                phNfc_sCompletionInfo_t     comp_info;
+                phNfc_sCompletionInfo_t     comp_info={FALSE,0, NULL};
 
                 psHciContext->error_status = error_status;
                 status = phHciNfc_Pending_Sequence(psHciContext, pHwRef );
@@ -716,7 +737,7 @@
             case hciState_Select:
             {
                 /* Notify the Configure failure to the upper layer */
-                phNfc_sCompletionInfo_t     comp_info={FALSE};
+                phNfc_sCompletionInfo_t     comp_info={FALSE,0, NULL};
 
                 /* Rollback the FSM as the Target Discovery Failed */
                 phHciNfc_FSM_Rollback(psHciContext);
@@ -742,7 +763,7 @@
             case hciState_Transact:
                 /* Notify the Transceive failure to the upper layer */
             {
-                phNfc_sTransactionInfo_t        transact_info; 
+                phNfc_sTransactionInfo_t        transact_info={FALSE,0,NULL,NULL,0};
 
                 /* Rollback the FSM as the Transceive Failed */
                 phHciNfc_FSM_Rollback(psHciContext);
@@ -759,7 +780,7 @@
             case hciState_Connect:
             {
                 /* Notify the General failure to the upper layer */
-                phNfc_sCompletionInfo_t     comp_info;
+                phNfc_sCompletionInfo_t     comp_info={FALSE,0, NULL};
 
                 /* psHciContext->host_rf_type = phHal_eUnknown_DevType; */
                 status = phHciNfc_ReaderMgmt_Update_Sequence(
@@ -776,7 +797,7 @@
             case hciState_Reactivate:
             {
                 /* Notify the General failure to the upper layer */
-                phNfc_sCompletionInfo_t     comp_info={FALSE};
+                phNfc_sCompletionInfo_t     comp_info={FALSE,0, NULL};
 
                 /* psHciContext->host_rf_type = phHal_eUnknown_DevType; 
                 status = phHciNfc_ReaderMgmt_Update_Sequence(
@@ -792,7 +813,7 @@
             }
             case hciState_Presence:
             {
-                phNfc_sCompletionInfo_t     comp_info;
+                phNfc_sCompletionInfo_t     comp_info={FALSE,0, NULL};
 
                 /* Roll Back to Connect State as Presence Check is Complete */
                 phHciNfc_FSM_Rollback(psHciContext);
@@ -809,7 +830,7 @@
             case hciState_Disconnect:
             {
                 /* Notify the General failure to the upper layer */
-                phNfc_sCompletionInfo_t     comp_info;
+                phNfc_sCompletionInfo_t     comp_info={FALSE,0, NULL};
 
                 phHciNfc_FSM_Rollback(psHciContext);
                 comp_info.status = error_status ;
@@ -823,7 +844,7 @@
 #ifdef NXP_HCI_SHUTDOWN_OVERRIDE
                 status = phHciNfc_Release_Sequence(psHciContext ,pHwRef);
 #else
-                phNfc_sCompletionInfo_t     comp_info;
+                phNfc_sCompletionInfo_t     comp_info={FALSE,0, NULL};
 
                 phHciNfc_Release_Lower( psHciContext, pHwRef );
                 /* Release all the resources and 
@@ -838,7 +859,7 @@
             default:
             {
                 /* Notify the General failure to the upper layer */
-                phNfc_sCompletionInfo_t     comp_info;
+                phNfc_sCompletionInfo_t     comp_info={FALSE,0, NULL};
 
                 phHciNfc_FSM_Rollback(psHciContext);
                 comp_info.status = error_status ;
@@ -859,8 +880,7 @@
     else
     {
         /* Notify the General failure to the upper layer */
-        phNfc_sCompletionInfo_t     comp_info;
-
+        phNfc_sCompletionInfo_t     comp_info={FALSE,0, NULL};
         phHciNfc_FSM_Rollback(psHciContext);
         comp_info.status = error_status ;
         /* Disable the Notification to the Upper Layer */
@@ -926,7 +946,7 @@
                 case hciState_Select:
                 case hciState_Connect:
                 {
-                    phNfc_sCompletionInfo_t     comp_info;
+                    phNfc_sCompletionInfo_t     comp_info={FALSE,0, NULL};
 
                     /* Update to the Intialise state as the discovery wheel is 
                      * restarted.
@@ -983,7 +1003,7 @@
         }
         case hciState_Presence:
         {
-            phNfc_sCompletionInfo_t     comp_info;
+            phNfc_sCompletionInfo_t     comp_info={FALSE,0, NULL};
 
             /* Roll Back to Connect State as Presence Check is Complete */
             phHciNfc_FSM_Rollback(psHciContext);
@@ -1102,7 +1122,7 @@
                 }
                 else
                 {
-#ifdef ESTABLISH_SESSION
+#if defined( ESTABLISH_SESSION )
                     NFCSTATUS info_status = NFCSTATUS_SUCCESS;
                     PHNFC_UNUSED_VARIABLE(info_status);
                     info_status = phHciNfc_IDMgmt_Update_Sequence( 
@@ -1110,7 +1130,11 @@
 
                     if(NFCSTATUS_SUCCESS == info_status)
                     {
+#if ( NXP_HAL_MEM_INFO_SIZE > 0x00U )
+                        psHciContext->hci_seq = DEV_HAL_INFO_SEQ;
+#else
                         psHciContext->hci_seq = IDENTITY_INFO_SEQ;
+#endif /* #if ( NXP_HAL_MEM_INFO_SIZE > 0x00U ) */
                     }
                     else
                     {
@@ -1118,10 +1142,11 @@
                         status = PHNFCSTVAL(CID_NFC_HCI,
                                     NFCSTATUS_INVALID_HCI_SEQUENCE);
                     }
+#elif ( NXP_HAL_MEM_INFO_SIZE > 0x00U )
+                    psHciContext->hci_seq = DEV_HAL_INFO_SEQ;
 #else
                     psHciContext->hci_seq = HCI_END_SEQ;
-
-#endif
+#endif /* #ifdef ESTABLISH_SESSION */
                 }
 
             }
@@ -1158,8 +1183,10 @@
             status = phHciNfc_EmuMgmt_Initialise( psHciContext,pHwRef );
             if(NFCSTATUS_SUCCESS == status)
             {
-#ifdef ESTABLISH_SESSION
+#if defined( ESTABLISH_SESSION )
                 psHciContext->hci_seq = ADMIN_SESSION_SEQ;
+#elif ( NXP_HAL_MEM_INFO_SIZE > 0x00U )
+                psHciContext->hci_seq = DEV_HAL_INFO_SEQ;
 #else
                 psHciContext->hci_seq = HCI_END_SEQ;
 #endif
@@ -1172,7 +1199,11 @@
             status = phHciNfc_Admin_Initialise( psHciContext,pHwRef );
             if(NFCSTATUS_SUCCESS == status)
             {
+#if ( NXP_HAL_MEM_INFO_SIZE > 0x00U )
+                psHciContext->hci_seq = DEV_HAL_INFO_SEQ;
+#else
                 psHciContext->hci_seq = IDENTITY_INFO_SEQ;
+#endif /* #if ( NXP_HAL_MEM_INFO_SIZE > 0x00U ) */
             }
             break;
         }
@@ -1182,11 +1213,13 @@
                                                 psHciContext, pHwRef );
             if(NFCSTATUS_SUCCESS == status)
             {
-#ifdef SW_AUTO_ACTIVATION
+#if defined( SW_AUTO_ACTIVATION )
                 psHciContext->hci_seq = READER_SW_AUTO_SEQ;
+#elif ( NXP_HAL_MEM_INFO_SIZE > 0x00U )
+                psHciContext->hci_seq = DEV_HAL_INFO_SEQ;
 #else
                 psHciContext->hci_seq = IDENTITY_INFO_SEQ;
-#endif
+#endif /* #if ( NXP_HAL_MEM_INFO_SIZE > 0x00U ) */
             }
             break;
         }
@@ -1219,7 +1252,8 @@
             {
                 if ((HCI_SELF_TEST != psHciContext->init_mode)
                     /* && ( TRUE == ((phHal_sHwReference_t *)pHwRef)->se_detect ) */
-                    && (HCI_CUSTOM_INIT != psHciContext->init_mode))
+                    && (HCI_CUSTOM_INIT != psHciContext->init_mode)
+                    && (HCI_NFC_DEVICE_TEST != psHciContext->init_mode))
                 {
                     NFCSTATUS info_status = NFCSTATUS_SUCCESS;
                     PHNFC_UNUSED_VARIABLE(info_status);
@@ -1247,10 +1281,42 @@
             }
             break;
         }
-#endif
+#endif /* #ifdef ESTABLISH_SESSION */
+
+#if ( NXP_HAL_MEM_INFO_SIZE > 0x00U )
+        case DEV_HAL_INFO_SEQ:
+        {
+            static uint8_t      mem_index = 0;
+            status = phHciNfc_DevMgmt_Get_Info(psHciContext, pHwRef,
+                        (NFC_ADDRESS_HAL_CONF + mem_index),
+                            (psHciContext->hal_mem_info + mem_index));
+            if(NFCSTATUS_PENDING == status)
+            {
+                mem_index++;
+                if (NXP_HAL_MEM_INFO_SIZE <= mem_index )
+                {
+                    NFCSTATUS info_status = NFCSTATUS_SUCCESS;
+                    PHNFC_UNUSED_VARIABLE(info_status);
+                    info_status = phHciNfc_IDMgmt_Update_Sequence(
+                                                psHciContext, INFO_SEQ );
+                    mem_index = 0;
+                    psHciContext->hci_seq = IDENTITY_INFO_SEQ;
+                    /* psHciContext->hci_seq =
+                            (HCI_SELF_TEST != psHciContext->init_mode)?
+                                    IDENTITY_INFO_SEQ : HCI_END_SEQ; */
+                }
+            }
+            break;
+        }
+#endif /* #if ( NXP_HAL_MEM_INFO_SIZE > 0x00U ) */
         case HCI_END_SEQ:
         {
-            if (HCI_SELF_TEST == psHciContext->init_mode )
+            phHal_sMemInfo_t    *p_mem_info =
+                    (phHal_sMemInfo_t *) ( psHciContext->hal_mem_info );
+            if (
+                (HCI_SELF_TEST == psHciContext->init_mode )
+                || (HCI_NFC_DEVICE_TEST == psHciContext->init_mode )
+                )
             {
                 psHciContext->hci_state.next_state
                     = (uint8_t) hciState_Test;
@@ -1260,10 +1326,17 @@
             phHciNfc_Uicc_Connectivity( psHciContext, pHwRef );
 #endif /* #ifdef UICC_CONNECTIVITY_PATCH */
 
+#if ( NXP_HAL_MEM_INFO_SIZE > 0x00U )
+            if(NXP_FW_UPLOAD_SUCCESS != p_mem_info->fw_magic )
+            {
+                status = PHNFCSTVAL( CID_NFC_HCI, NFCSTATUS_FAILED );
+            }
+#endif /* #if ( NXP_HAL_MEM_INFO_SIZE > 0x00U ) */
+
             /* Initialisation Complete Notification to the Upper Layer */
             if(NFCSTATUS_SUCCESS == status)
             {
-                phNfc_sCompletionInfo_t     comp_info;
+                phNfc_sCompletionInfo_t     comp_info={FALSE,0, NULL};
 
                 comp_info.status = status;
                 phHciNfc_Notify(psHciContext->p_upper_notify,
@@ -1333,6 +1406,10 @@
         }
         case DEV_REL_SEQ:
         {
+            NFCSTATUS info_status = NFCSTATUS_SUCCESS;
+            PHNFC_UNUSED_VARIABLE(info_status);
+            info_status = phHciNfc_DevMgmt_Update_Sequence(
+                                            psHciContext, REL_SEQ );
             status = phHciNfc_DevMgmt_Release( psHciContext, pHwRef );
             if(NFCSTATUS_SUCCESS == status)
             {
@@ -1434,7 +1511,7 @@
                         )
 {
     NFCSTATUS                   status = NFCSTATUS_SUCCESS;
-    phNfc_sCompletionInfo_t     comp_info;
+    phNfc_sCompletionInfo_t     comp_info = {FALSE,0,NULL};
 
     switch(psHciContext->config_type)
     {
@@ -1760,7 +1837,7 @@
                          )
 {
     NFCSTATUS               status = NFCSTATUS_SUCCESS;
-    static phNfc_sCompletionInfo_t      comp_info;
+    static phNfc_sCompletionInfo_t      comp_info = {FALSE,0,NULL};
 #if defined(HOST_EMULATION)
     phHciNfc_GateID_t       ce_gate = phHciNfc_UnknownGate;
 #endif  /* #ifdef HOST_EMULATION */
@@ -1907,8 +1984,7 @@
     NFCSTATUS           status = NFCSTATUS_SUCCESS;
     phHal_sADD_Cfg_t    *p_poll_config = (phHal_sADD_Cfg_t * )
         psHciContext->p_config_params;
-    phNfc_sCompletionInfo_t     comp_info;
-
+    phNfc_sCompletionInfo_t     comp_info = {FALSE,0,NULL};
     if (NULL != p_poll_config)
     {
         switch(psHciContext->hci_seq)
@@ -2014,7 +2090,7 @@
                          )
 {
     NFCSTATUS           status = NFCSTATUS_SUCCESS;
-    static phNfc_sCompletionInfo_t      comp_info;
+    static phNfc_sCompletionInfo_t      comp_info = {FALSE,0,NULL};
     phHal_eRemDevType_t         target_type = phHal_eUnknown_DevType;
 
     if( NULL != psHciContext->p_target_info )
@@ -2126,7 +2202,7 @@
                          )
 {
     NFCSTATUS           status = NFCSTATUS_SUCCESS;
-    static phNfc_sCompletionInfo_t      comp_info;
+    static phNfc_sCompletionInfo_t      comp_info = {FALSE, 0 , NULL};
     phHal_eRemDevType_t         target_type = phHal_eUnknown_DevType;
     uint8_t             re_poll = 0;
 
@@ -2210,7 +2286,7 @@
                             void                    *pHwRef
                          )
 {
-    static phNfc_sTransactionInfo_t transact_info;
+    static phNfc_sTransactionInfo_t transact_info = {FALSE,0,NULL,NULL,0};
 
     pphNfcIF_Notification_CB_t  p_upper_notify = psHciContext->p_upper_notify;
     void                        *pcontext = psHciContext->p_upper_context;
@@ -2357,8 +2433,8 @@
                          )
 {
     NFCSTATUS           status = NFCSTATUS_SUCCESS;
-    static phNfc_sCompletionInfo_t      comp_info;
-    static phNfc_sData_t test_result;
+    static phNfc_sCompletionInfo_t      comp_info = {0};
+    static phNfc_sData_t test_result= {NULL,0};
 
     /* Complete the Test Sequence and notify the HAL */
     status = phHciNfc_FSM_Complete ( psHciContext );
@@ -2380,7 +2456,7 @@
         phHciNfc_Notify(psHciContext->p_upper_notify,
                         psHciContext->p_upper_context, pHwRef,
                         NFC_NOTIFY_RESULT , &comp_info);
-        HCI_PRINT(" HCI System Test Completed. \n");
+        HCI_DEBUG(" HCI System Test Completed : Status = %u\n", test_status);
     }
     else
     {
@@ -2406,7 +2482,7 @@
                          )
 {
     NFCSTATUS           status = NFCSTATUS_SUCCESS;
-    static phNfc_sCompletionInfo_t      comp_info;
+    static phNfc_sCompletionInfo_t      comp_info = {0};
 
     /* To remove "warning (VS 4100) : unreferenced formal parameter" */
     PHNFC_UNUSED_VARIABLE(pdata);
diff --git a/src/phLibNfc_Ioctl.c b/src/phLibNfc_Ioctl.c
index 9983c60..08f34b5 100644
--- a/src/phLibNfc_Ioctl.c
+++ b/src/phLibNfc_Ioctl.c
@@ -238,8 +238,11 @@
                               NFCSTATUS      status )
 {
     phLibNfc_Ioctl_Cntx_t *pIoctlCntx=NULL;
-
-    if(PHNFCSTATUS(status)!=NFCSTATUS_SUCCESS)
+    if(PHNFCSTATUS(status) == NFCSTATUS_FEATURE_NOT_SUPPORTED)
+    {
+        status = NFCSTATUS_FEATURE_NOT_SUPPORTED;
+    }
+    else if(PHNFCSTATUS(status)!=NFCSTATUS_SUCCESS)
     {
         status = NFCSTATUS_FAILED;
     }