Merge pi-qpr1-release PQ1A.181105.017.A1 to pi-platform-release

Change-Id: I098c224e8646e610dcfde3eb5ef018f651bc8e34
diff --git a/1.0/android.hardware.secure_element@1.0-service-disabled.rc b/1.0/android.hardware.secure_element@1.0-service-disabled.rc
new file mode 100644
index 0000000..bb6ea2f
--- /dev/null
+++ b/1.0/android.hardware.secure_element@1.0-service-disabled.rc
@@ -0,0 +1,5 @@
+service secure_element_hal_service /vendor/bin/hw/android.hardware.secure_element@1.0-service-disabled
+    disabled
+    interface android.hardware.secure_element@1.0::ISecureElement eSE1
+    user secure_element
+    group secure_element
diff --git a/1.0/android.hardware.secure_element@1.0-service.rc b/1.0/android.hardware.secure_element@1.0-service.rc
index e446ada..f1e0966 100644
--- a/1.0/android.hardware.secure_element@1.0-service.rc
+++ b/1.0/android.hardware.secure_element@1.0-service.rc
@@ -1,4 +1,5 @@
 service secure_element_hal_service /vendor/bin/hw/android.hardware.secure_element@1.0-service
     class hal
+    interface android.hardware.secure_element@1.0::ISecureElement eSE1
     user secure_element
     group secure_element
diff --git a/Android.bp b/Android.bp
old mode 100644
new mode 100755
index 24fd3cd..e76951c
--- a/Android.bp
+++ b/Android.bp
@@ -71,17 +71,18 @@
     shared_libs: [
         "ese_spi_nxp",
         "android.hardware.secure_element@1.0",
+        "libcutils",
         "liblog",
         "libhidlbase",
         "liblog",
         "libutils",
+        "libcrypto"
     ],
 }
 
-cc_binary {
-    name: "android.hardware.secure_element@1.0-service",
+cc_defaults {
+    name: "android.hardware.secure_element@1.0_defaults",
     relative_install_path: "hw",
-    init_rc: ["1.0/android.hardware.secure_element@1.0-service.rc"],
     proprietary: true,
     defaults: ["hidl_defaults"],
     srcs: [
@@ -106,3 +107,15 @@
         "vendor.nxp.nxpnfc@1.0",
     ],
 }
+
+cc_binary {
+    name: "android.hardware.secure_element@1.0-service",
+    init_rc: ["1.0/android.hardware.secure_element@1.0-service.rc"],
+    defaults: ["android.hardware.secure_element@1.0_defaults"],
+}
+
+cc_binary {
+    name: "android.hardware.secure_element@1.0-service-disabled",
+    init_rc: ["1.0/android.hardware.secure_element@1.0-service-disabled.rc"],
+    defaults: ["android.hardware.secure_element@1.0_defaults"],
+}
diff --git a/ls_client/inc/LsClient.h b/ls_client/inc/LsClient.h
old mode 100644
new mode 100755
index c2e9e01..01facdb
--- a/ls_client/inc/LsClient.h
+++ b/ls_client/inc/LsClient.h
@@ -24,7 +24,9 @@
 typedef enum {
   LSCSTATUS_SUCCESS = (0x0000),
   LSCSTATUS_FAILED = (0x0003),
-  LSCSTATUS_FILE_NOT_FOUND = (0x0005)
+  LSCSTATUS_SELF_UPDATE_DONE = (0x0005),
+  LSCSTATUS_HASH_SLOT_EMPTY = (0x0006),
+  LSCSTATUS_HASH_SLOT_INVALID = (0x0007)
 } LSCSTATUS;
 
 using ::android::hardware::secure_element::V1_0::ISecureElementHalCallback;
diff --git a/ls_client/inc/LsLib.h b/ls_client/inc/LsLib.h
old mode 100644
new mode 100755
index 44e77ab..b7f8329
--- a/ls_client/inc/LsLib.h
+++ b/ls_client/inc/LsLib.h
@@ -48,8 +48,16 @@
   int bytes_wrote;
   Lsc_ChannelInfo_t Channel_Info[10];
   uint8_t channel_cnt;
+  uint8_t initChannelNum;
 } Lsc_ImageInfo_t;
 
+typedef struct Lsc_HashInfo {
+  uint16_t readHashLen;
+  uint8_t* lsRawScriptBuf = nullptr;
+  uint8_t* lsScriptHash = nullptr;
+  uint8_t* readBuffHash = nullptr;
+} Lsc_HashInfo_t;
+
 typedef enum {
   LS_Default = 0x00,
   LS_Cert = 0x7F21,
@@ -60,21 +68,13 @@
 static uint8_t OpenChannel[] = {0x00, 0x70, 0x00, 0x00, 0x01};
 static uint8_t GetData[] = {0x80, 0xCA, 0x00, 0x46, 0x00};
 
-static uint8_t SelectLsc[] = {0x00, 0xA4, 0x04, 0x00, 0x0F, 0xA0, 0x00,
-                              0x00, 0x03, 0x96, 0x54, 0x43, 0x00, 0x00,
-                              0x00, 0x01, 0x00, 0x0B, 0x00, 0x01};
+static const uint8_t SelectLsc[] = {0xA4, 0x04, 0x00, 0x0E, 0xA0, 0x00,
+                                    0x00, 0x03, 0x96, 0x54, 0x43, 0x00,
+                                    0x00, 0x00, 0x01, 0x00, 0x0B, 0x00};
 
-/*LSC2*/
-#define NOOFAIDS 0x03
-#define LENOFAIDS 0x16
-
-static uint8_t ArrayOfAIDs[NOOFAIDS][LENOFAIDS] = {
-    {0x14, 0x00, 0xA4, 0x04, 0x00, 0x0F, 0xA0, 0x00, 0x00, 0x03, 0x96,
-     0x54, 0x43, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x02, 0x00},
-    {0x14, 0x00, 0xA4, 0x04, 0x00, 0x0F, 0xA0, 0x00, 0x00, 0x03, 0x96,
-     0x54, 0x43, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x01, 0x00},
-    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
+static uint8_t SelectLscSlotHash[] = {0x00, 0xA4, 0x04, 0x00, 0x10, 0xA0, 0x00,
+                                      0x00, 0x03, 0x96, 0x54, 0x53, 0x00, 0x00,
+                                      0x00, 0x01, 0x00, 0x60, 0x00, 0x00, 0x00};
 
 #define TAG_CERTIFICATE 0x7F21
 #define TAG_LSES_RESP 0x4E
@@ -97,7 +97,6 @@
 
 #define LS_ABORT_SW1 0x69
 #define LS_ABORT_SW2 0x87
-#define AID_MEM_PATH "/data/vendor/secure_element/AID_MEM.txt"
 #define LS_STATUS_PATH "/data/vendor/secure_element/LS_Status.txt"
 #define LS_SRC_BACKUP "/data/vendor/secure_element/LS_Src_Backup.txt"
 #define LS_DST_BACKUP "/data/vendor/secure_element/LS_Dst_Backup.txt"
@@ -162,6 +161,19 @@
 
 /*******************************************************************************
 **
+** Function:        LSC_ResetChannel
+**
+** Description:     Reset(Open & Close) next available logical channel
+**
+** Returns:         Success if ok.
+**
+*******************************************************************************/
+static LSCSTATUS LSC_ResetChannel(Lsc_ImageInfo_t* pContext, LSCSTATUS status,
+                                  Lsc_TranscieveInfo_t* pInfo)
+    __attribute__((unused));
+
+/*******************************************************************************
+**
 ** Function:        LSC_SelectLsc
 **
 ** Description:     Creates the logical channel with lsc
@@ -451,6 +463,51 @@
 
 /*******************************************************************************
 **
+** Function:        LSC_CloseAllLogicalChannels
+**
+** Description:     Close all opened logical channels
+**
+** Returns:         SUCCESS/FAILURE
+**
+*******************************************************************************/
+LSCSTATUS LSC_CloseAllLogicalChannels(Lsc_ImageInfo_t* Os_info);
+
+/*******************************************************************************
+**
+** Function:        LSC_SelectLsHash
+**
+** Description:     Selects LS Hash applet
+**
+** Returns:         SUCCESS/FAILURE
+**
+*******************************************************************************/
+
+LSCSTATUS LSC_SelectLsHash();
+
+/*******************************************************************************
+**
+** Function:        LSC_ReadLsHash
+**
+** Description:     Read the LS SHA1 for the intended slot
+**
+** Returns:         SUCCESS/FAILURE
+**
+*******************************************************************************/
+LSCSTATUS LSC_ReadLsHash(uint8_t* hash, uint16_t* readHashLen, uint8_t slotId);
+
+/*******************************************************************************
+**
+** Function:        LSC_UpdateLsHash
+**
+** Description:     Updates SHA1 of LS script to the respective Slot ID
+**
+** Returns:         Update status
+**
+*******************************************************************************/
+LSCSTATUS LSC_UpdateLsHash(uint8_t* hash, long hashLen, uint8_t slotId);
+
+/*******************************************************************************
+**
 ** Function:        Numof_lengthbytes
 **
 ** Description:     Checks the number of length bytes and assigns
diff --git a/ls_client/src/LsClient.cpp b/ls_client/src/LsClient.cpp
old mode 100644
new mode 100755
index 8922f38..50ea3d1
--- a/ls_client/src/LsClient.cpp
+++ b/ls_client/src/LsClient.cpp
@@ -17,16 +17,54 @@
  ******************************************************************************/
 #define LOG_TAG "LSClient"
 #include "LsClient.h"
+#include <cutils/properties.h>
 #include <dirent.h>
 #include <log/log.h>
+#include <openssl/evp.h>
 #include <pthread.h>
 #include <stdlib.h>
+#include <string>
 #include "LsLib.h"
 
 uint8_t datahex(char c);
+unsigned char* getHASH(uint8_t* buffer, size_t buffSize);
 extern bool ese_debug_enabled;
+
+#define ls_script_source_prefix "/vendor/etc/loaderservice_updater_"
+#define ls_script_source_suffix ".lss"
+#define ls_script_output_prefix \
+  "/data/vendor/secure_element/loaderservice_updater_out_"
+#define ls_script_output_suffix ".txt"
+const size_t HASH_DATA_LENGTH = 21;
+const uint16_t HASH_STATUS_INDEX = 20;
+const uint8_t LS_MAX_COUNT = 10;
+const uint8_t LS_DOWNLOAD_SUCCESS = 0x00;
+const uint8_t LS_DOWNLOAD_FAILED = 0x01;
+
 static android::sp<ISecureElementHalCallback> cCallback;
 void* performLSDownload_thread(void* data);
+static void getLSScriptSourcePrefix(std::string& prefix);
+
+void getLSScriptSourcePrefix(std::string& prefix) {
+  char source_path[PROPERTY_VALUE_MAX] = {0};
+  int len = property_get("vendor.ese.loader_script_path", source_path, "");
+  if (len > 0) {
+    FILE* fd = fopen(source_path, "rb");
+    if (fd != NULL) {
+      char c;
+      while (!feof(fd) && fread(&c, 1, 1, fd) == 1) {
+        if (c == ' ' || c == '\n' || c == '\r' || c == 0x00) break;
+        prefix.push_back(c);
+      }
+    } else {
+      ALOGD("%s Cannot open file %s\n", __func__, source_path);
+    }
+  }
+  if (prefix.empty()) {
+    prefix.assign(ls_script_source_prefix);
+  }
+}
+
 /*******************************************************************************
 **
 ** Function:        LSC_Start
@@ -88,13 +126,7 @@
 **
 *******************************************************************************/
 void* performLSDownload_thread(__attribute__((unused)) void* data) {
-  ALOGD_IF(ese_debug_enabled, "%s enter:  ", __func__);
-
-  const char* lsUpdateBackupPath =
-      "/data/vendor/secure_element/loaderservice_updater.txt";
-  const char* lsUpdateBackupOutPath =
-      "/data/vendor/secure_element/loaderservice_updater_out.txt";
-
+  ALOGD_IF(ese_debug_enabled, "%s enter  ", __func__);
   /*generated SHA-1 string for secureElementLS
   This will remain constant as handled in secureElement HAL*/
   char sha1[] = "6d583e84f2710e6b0f06beebc1a12a1083591373";
@@ -106,64 +138,122 @@
   }
 
   uint8_t resSW[4] = {0x4e, 0x02, 0x69, 0x87};
-  FILE* fIn = fopen(lsUpdateBackupPath, "rb");
-  if (fIn == NULL) {
-    ALOGE("%s Cannot open LS script file %s\n", __func__, lsUpdateBackupPath);
-    ALOGE("%s Error : %s", __func__, strerror(errno));
-    cCallback->onStateChange(true);
-  } else {
+
+  std::string sourcePath;
+  std::string sourcePrefix;
+  std::string outPath;
+  int index = 1;
+  LSCSTATUS status = LSCSTATUS_SUCCESS;
+  Lsc_HashInfo_t lsHashInfo;
+
+  getLSScriptSourcePrefix(sourcePrefix);
+  do {
+    /*Open the script file from specified location and name*/
+    sourcePath.assign(sourcePrefix);
+    sourcePath += ('0' + index);
+    sourcePath += ls_script_source_suffix;
+    FILE* fIn = fopen(sourcePath.c_str(), "rb");
+    if (fIn == NULL) {
+      ALOGE("%s Cannot open LS script file %s\n", __func__, sourcePath.c_str());
+      ALOGE("%s Error : %s", __func__, strerror(errno));
+      break;
+    }
     ALOGD_IF(ese_debug_enabled, "%s File opened %s\n", __func__,
-             lsUpdateBackupPath);
+             sourcePath.c_str());
+
+    /*Read the script content to a local buffer*/
     fseek(fIn, 0, SEEK_END);
-    long fsize = ftell(fIn);
+    long lsBufSize = ftell(fIn);
     rewind(fIn);
+    if (lsHashInfo.lsRawScriptBuf == nullptr) {
+      lsHashInfo.lsRawScriptBuf = (uint8_t*)phNxpEse_memalloc(lsBufSize + 1);
+    }
+    memset(lsHashInfo.lsRawScriptBuf, 0x00, (lsBufSize + 1));
+    fread(lsHashInfo.lsRawScriptBuf, lsBufSize, 1, fIn);
 
-    char* lsUpdateBuf = (char*)phNxpEse_memalloc(fsize + 1);
-    fread(lsUpdateBuf, fsize, 1, fIn);
+    LSCSTATUS lsHashStatus = LSCSTATUS_FAILED;
 
-    FILE* fOut = fopen(lsUpdateBackupOutPath, "wb+");
+    /*Get 20bye SHA1 of the script*/
+    lsHashInfo.lsScriptHash =
+        getHASH(lsHashInfo.lsRawScriptBuf, (size_t)lsBufSize);
+    phNxpEse_free(lsHashInfo.lsRawScriptBuf);
+    lsHashInfo.lsRawScriptBuf = nullptr;
+    if (lsHashInfo.lsScriptHash == nullptr) break;
+
+    if (lsHashInfo.readBuffHash == nullptr) {
+      lsHashInfo.readBuffHash = (uint8_t*)phNxpEse_memalloc(HASH_DATA_LENGTH);
+    }
+    memset(lsHashInfo.readBuffHash, 0x00, HASH_DATA_LENGTH);
+
+    /*Read the hash from applet for specified slot*/
+    lsHashStatus =
+        LSC_ReadLsHash(lsHashInfo.readBuffHash, &lsHashInfo.readHashLen, index);
+
+    /*Check if previously script is successfully installed.
+    if yes, continue reading next script else try update wit current script*/
+    if ((lsHashStatus == LSCSTATUS_SUCCESS) &&
+        (lsHashInfo.readHashLen == HASH_DATA_LENGTH) &&
+        (0 == memcmp(lsHashInfo.lsScriptHash, lsHashInfo.readBuffHash,
+                     HASH_DATA_LENGTH)) &&
+        (lsHashInfo.readBuffHash[HASH_STATUS_INDEX] == LS_DOWNLOAD_SUCCESS)) {
+      ALOGD_IF(ese_debug_enabled, "%s LS Loader sript is already installed \n",
+               __func__);
+      continue;
+    }
+
+    /*Create output file to write response data*/
+    outPath.assign(ls_script_output_prefix);
+    outPath += ('0' + index);
+    outPath += ls_script_output_suffix;
+
+    FILE* fOut = fopen(outPath.c_str(), "wb+");
     if (fOut == NULL) {
-      ALOGE("%s Failed to open file %s\n", __func__, lsUpdateBackupOutPath);
-      phNxpEse_free(lsUpdateBuf);
-      pthread_exit(NULL);
-      cCallback->onStateChange(true);
-      return NULL;
+      ALOGE("%s Failed to open file %s\n", __func__, outPath.c_str());
+      break;
     }
+    fclose(fOut);
 
-    long size = fwrite(lsUpdateBuf, 1, fsize, fOut);
-    if (size != fsize) {
-      ALOGE("%s ERROR - Failed to write %ld bytes to file\n", __func__, fsize);
-      phNxpEse_free(lsUpdateBuf);
-      pthread_exit(NULL);
-      cCallback->onStateChange(true);
-      return NULL;
-    }
-
-    LSCSTATUS status = LSC_Start(lsUpdateBackupPath, lsUpdateBackupOutPath,
-                                 (uint8_t*)hash, (uint16_t)sizeof(hash), resSW);
-    ALOGD_IF(ese_debug_enabled, "%s LSC_Start completed\n", __func__);
-    if (status == LSCSTATUS_SUCCESS) {
-      if (remove(lsUpdateBackupPath) == 0) {
-        ALOGD_IF(ese_debug_enabled, "%s  : %s file deleted successfully\n",
-                 __func__, lsUpdateBackupPath);
-      } else {
-        ALOGD_IF(ese_debug_enabled, "%s  : %s file deletion failed!!!\n",
-                 __func__, lsUpdateBackupPath);
+    /*Uptdates current script*/
+    status = LSC_Start(sourcePath.c_str(), outPath.c_str(), (uint8_t*)hash,
+                       (uint16_t)sizeof(hash), resSW);
+    ALOGD_IF(ese_debug_enabled, "%s script %s perform done, result = %d\n",
+             __func__, sourcePath.c_str(), status);
+    if (status != LSCSTATUS_SUCCESS) {
+      lsHashInfo.lsScriptHash[HASH_STATUS_INDEX] = LS_DOWNLOAD_FAILED;
+      /*If current script updation fails, update the status with hash to the
+       * applet then clean and exit*/
+      lsHashStatus =
+          LSC_UpdateLsHash(lsHashInfo.lsScriptHash, HASH_DATA_LENGTH, index);
+      if (lsHashStatus != LSCSTATUS_SUCCESS) {
+        ALOGD_IF(ese_debug_enabled, "%s LSC_UpdateLsHash Failed\n", __func__);
       }
-      cCallback->onStateChange(true);
-    } else {
-      ESESTATUS status = phNxpEse_deInit();
-      if (status == ESESTATUS_SUCCESS) {
-        status = phNxpEse_close();
-        if (status == ESESTATUS_SUCCESS) {
+      ESESTATUS estatus = phNxpEse_deInit();
+      if (estatus == ESESTATUS_SUCCESS) {
+        estatus = phNxpEse_close();
+        if (estatus == ESESTATUS_SUCCESS) {
           ALOGD_IF(ese_debug_enabled, "%s: Ese_close success\n", __func__);
         }
       } else {
         ALOGE("%s: Ese_deInit failed", __func__);
       }
       cCallback->onStateChange(false);
+      break;
+    } else {
+      /*If current script execution is succes, update the status along with the
+       * hash to the applet*/
+      lsHashInfo.lsScriptHash[HASH_STATUS_INDEX] = LS_DOWNLOAD_SUCCESS;
+      lsHashStatus =
+          LSC_UpdateLsHash(lsHashInfo.lsScriptHash, HASH_DATA_LENGTH, index);
+      if (lsHashStatus != LSCSTATUS_SUCCESS) {
+        ALOGD_IF(ese_debug_enabled, "%s LSC_UpdateLsHash Failed\n", __func__);
+      }
     }
-    phNxpEse_free(lsUpdateBuf);
+  } while (++index <= LS_MAX_COUNT);
+
+  phNxpEse_free(lsHashInfo.readBuffHash);
+
+  if (status == LSCSTATUS_SUCCESS) {
+    cCallback->onStateChange(true);
   }
   pthread_exit(NULL);
   ALOGD_IF(ese_debug_enabled, "%s pthread_exit\n", __func__);
@@ -172,6 +262,30 @@
 
 /*******************************************************************************
 **
+** Function:        getHASH
+**
+** Description:     generates SHA1 of given buffer
+**
+** Returns:         20 bytes of SHA1
+**
+*******************************************************************************/
+unsigned char* getHASH(uint8_t* buffer, size_t buffSize) {
+  static uint8_t outHash[HASH_DATA_LENGTH] = {0};
+  unsigned int md_len = -1;
+  const EVP_MD* md = EVP_get_digestbyname("SHA1");
+  if (NULL != md) {
+    EVP_MD_CTX mdctx;
+    EVP_MD_CTX_init(&mdctx);
+    EVP_DigestInit_ex(&mdctx, md, NULL);
+    EVP_DigestUpdate(&mdctx, buffer, buffSize);
+    EVP_DigestFinal_ex(&mdctx, outHash, &md_len);
+    EVP_MD_CTX_cleanup(&mdctx);
+  }
+  return outHash;
+}
+
+/*******************************************************************************
+**
 ** Function:        datahex
 **
 ** Description:     Converts char to uint8_t
diff --git a/ls_client/src/LsLib.cpp b/ls_client/src/LsLib.cpp
old mode 100644
new mode 100755
index 0a43c7f..0e8f129
--- a/ls_client/src/LsLib.cpp
+++ b/ls_client/src/LsLib.cpp
@@ -39,7 +39,8 @@
 
 LSCSTATUS(*Applet_load_seqhandler[])
 (Lsc_ImageInfo_t* pContext, LSCSTATUS status, Lsc_TranscieveInfo_t* pInfo) = {
-    LSC_OpenChannel, LSC_SelectLsc, LSC_StoreData, LSC_loadapplet, NULL};
+    LSC_OpenChannel, LSC_ResetChannel, LSC_SelectLsc,
+    LSC_StoreData,   LSC_loadapplet,   NULL};
 
 /*******************************************************************************
 **
@@ -119,6 +120,12 @@
       ALOGE("%s: exiting; status=0x0%X", fn, status);
       break;
     }
+
+    if ((seq_counter == 0x00) &&
+        update_info.Channel_Info[update_info.channel_cnt - 1].isOpend) {
+      update_info.initChannelNum =
+          update_info.Channel_Info[update_info.channel_cnt - 1].channel_id;
+    }
     seq_counter++;
   }
 
@@ -179,6 +186,69 @@
   ALOGD_IF(ese_debug_enabled, "%s: exit; status=0x%x", fn, status);
   return status;
 }
+/*******************************************************************************
+**
+** Function:        LSC_ResetChannel
+**
+** Description:     Reset(Open & Close) next available logical channel
+**
+** Returns:         Success if ok.
+**
+*******************************************************************************/
+LSCSTATUS LSC_ResetChannel(Lsc_ImageInfo_t* Os_info, LSCSTATUS status,
+                           Lsc_TranscieveInfo_t* pTranscv_Info) {
+  static const char fn[] = "LSC_ResetChannel";
+
+  ALOGD_IF(ese_debug_enabled, "%s: enter", fn);
+  if (Os_info == NULL || pTranscv_Info == NULL) {
+    ALOGE("%s: Invalid parameter", fn);
+    return LSCSTATUS_FAILED;
+  }
+
+  ESESTATUS eseStat = ESESTATUS_FAILED;
+  bool bResetCompleted = false;
+  phNxpEse_data cmdApdu;
+  phNxpEse_data rspApdu;
+  phNxpEse_memset(&cmdApdu, 0x00, sizeof(phNxpEse_data));
+  phNxpEse_memset(&rspApdu, 0x00, sizeof(phNxpEse_data));
+  cmdApdu.len = (int32_t)sizeof(OpenChannel);
+  cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(cmdApdu.len * sizeof(uint8_t));
+  memcpy(cmdApdu.p_data, OpenChannel, cmdApdu.len);
+
+  do {
+    ALOGD_IF(ese_debug_enabled, "%s: Calling Secure Element Transceive", fn);
+    eseStat = phNxpEse_Transceive(&cmdApdu, &rspApdu);
+    if (eseStat != ESESTATUS_SUCCESS && (rspApdu.len < 0x03)) {
+      status = LSCSTATUS_FAILED;
+      ALOGE("%s: SE transceive failed status = 0x%X", fn, status);
+    } else if (((rspApdu.p_data[rspApdu.len - 2] != 0x90) &&
+                (rspApdu.p_data[rspApdu.len - 1] != 0x00))) {
+      status = LSCSTATUS_FAILED;
+      ALOGE("%s: invalid response = 0x%X", fn, status);
+    } else if (!bResetCompleted) {
+      /*close the previously opened channel*/
+      uint8_t xx = 0;
+      cmdApdu.p_data[xx++] = rspApdu.p_data[rspApdu.len - 3]; /*channel id*/
+      cmdApdu.p_data[xx++] = 0x70;
+      cmdApdu.p_data[xx++] = 0x80;
+      cmdApdu.p_data[xx++] = rspApdu.p_data[rspApdu.len - 3];
+      cmdApdu.p_data[xx++] = 0x00;
+      cmdApdu.len = 5;
+      bResetCompleted = true;
+      phNxpEse_free(rspApdu.p_data);
+      status = LSCSTATUS_SUCCESS;
+    } else {
+      ALOGD_IF(ese_debug_enabled, "%s: Channel reset success", fn);
+      status = LSCSTATUS_SUCCESS;
+      break;
+    }
+  } while (status == LSCSTATUS_SUCCESS);
+
+  phNxpEse_free(cmdApdu.p_data);
+  phNxpEse_free(rspApdu.p_data);
+  ALOGD_IF(ese_debug_enabled, "%s: exit; status=0x%x", fn, status);
+  return status;
+}
 
 /*******************************************************************************
 **
@@ -207,73 +277,33 @@
   phNxpEse_memset(&cmdApdu, 0x00, sizeof(phNxpEse_data));
   phNxpEse_memset(&rspApdu, 0x00, sizeof(phNxpEse_data));
 
-  uint8_t selectCnt = 3;
-  while ((selectCnt--) > 0) {
-    if (selectCnt == 2) {
-      cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(
-          ((ArrayOfAIDs[selectCnt - 1][0]) - 1) * sizeof(uint8_t));
-      cmdApdu.len = (int32_t)ArrayOfAIDs[selectCnt - 1][0];
-    } else {
-      cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(
-          ((ArrayOfAIDs[selectCnt][0]) - 1) * sizeof(uint8_t));
-      cmdApdu.len = (int32_t)ArrayOfAIDs[selectCnt][0];
+  /*p_data will have channel_id (1 byte) + SelectLsc APDU*/
+  cmdApdu.len = (int32_t)(sizeof(SelectLsc) + 1);
+  cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(cmdApdu.len * sizeof(uint8_t));
+  cmdApdu.p_data[0] = Os_info->Channel_Info[0].channel_id;
+
+  memcpy(&(cmdApdu.p_data[1]), SelectLsc, sizeof(SelectLsc));
+
+  ALOGD_IF(ese_debug_enabled,
+           "%s: Calling Secure Element Transceive with Loader service AID", fn);
+
+  ESESTATUS eseStat = phNxpEse_Transceive(&cmdApdu, &rspApdu);
+
+  if (eseStat != ESESTATUS_SUCCESS && (rspApdu.len == 0x00)) {
+    status = LSCSTATUS_FAILED;
+    ALOGE("%s: SE transceive failed status = 0x%X", fn, status);
+  } else if (((rspApdu.p_data[rspApdu.len - 2] == 0x90) &&
+              (rspApdu.p_data[rspApdu.len - 1] == 0x00))) {
+    status = Process_SelectRsp(rspApdu.p_data, (rspApdu.len - 2));
+    if (status != LSCSTATUS_SUCCESS) {
+      ALOGE("%s: Select Lsc Rsp doesnt have a valid key; status = 0x%X", fn,
+            status);
     }
-
-    cmdApdu.p_data[0] = Os_info->Channel_Info[0].channel_id;
-
-    memcpy(&(cmdApdu.p_data[1]), &ArrayOfAIDs[selectCnt][2],
-           ((ArrayOfAIDs[selectCnt][0]) - 1));
-
-    /*If NFC/SPI Deinitialize requested*/
-    ALOGD_IF(ese_debug_enabled,
-             "%s: Calling Secure Element Transceive with Loader service AID",
-             fn);
-
-    ESESTATUS eseStat = phNxpEse_Transceive(&cmdApdu, &rspApdu);
-
-    if (eseStat != ESESTATUS_SUCCESS && (rspApdu.len == 0x00)) {
-      status = LSCSTATUS_FAILED;
-      ALOGE("%s: SE transceive failed status = 0x%X", fn, status);
-      break;
-    } else if (((rspApdu.p_data[rspApdu.len - 2] == 0x90) &&
-                (rspApdu.p_data[rspApdu.len - 1] == 0x00))) {
-      status = Process_SelectRsp(rspApdu.p_data, (rspApdu.len - 2));
-      if (status != LSCSTATUS_SUCCESS) {
-        ALOGE("%s: Select Lsc Rsp doesnt have a valid key; status = 0x%X", fn,
-              status);
-      }
-      /*If AID is found which is successfully selected break while loop*/
-      if (status == LSCSTATUS_SUCCESS) {
-        uint8_t totalLen = ArrayOfAIDs[selectCnt][0];
-        uint8_t cnt = 0;
-        int32_t wStatus = 0;
-        status = LSCSTATUS_FAILED;
-
-        FILE* fAidMem = fopen(AID_MEM_PATH, "w+");
-
-        if (fAidMem == NULL) {
-          ALOGE("Error opening AID data file for writing: %s", strerror(errno));
-          phNxpEse_free(cmdApdu.p_data);
-          return status;
-        }
-        while (cnt <= totalLen) {
-          wStatus = fprintf(fAidMem, "%02x", ArrayOfAIDs[selectCnt][cnt++]);
-          if (wStatus != 2) {
-            ALOGE("%s: Error writing AID data to AID_MEM file: %s", fn,
-                  strerror(errno));
-            break;
-          }
-        }
-        if (wStatus == 2) status = LSCSTATUS_SUCCESS;
-        fclose(fAidMem);
-        break;
-      }
-    } else if (((rspApdu.p_data[rspApdu.len - 2] != 0x90))) {
-      /*Copy the response SW in failure case*/
-      memcpy(&gsLsExecuteResp[2], &(rspApdu.p_data[rspApdu.len - 2]), 2);
-    } else {
-      status = LSCSTATUS_FAILED;
-    }
+  } else if (((rspApdu.p_data[rspApdu.len - 2] != 0x90))) {
+    /*Copy the response SW in failure case*/
+    memcpy(&gsLsExecuteResp[2], &(rspApdu.p_data[rspApdu.len - 2]), 2);
+  } else {
+    status = LSCSTATUS_FAILED;
   }
   phNxpEse_free(cmdApdu.p_data);
   phNxpEse_free(rspApdu.p_data);
@@ -439,35 +469,13 @@
       status = LSC_SendtoLsc(Os_info, status, pTranscv_Info, LS_Comm);
       if (status != LSCSTATUS_SUCCESS) {
         /*When the switching of LS 6320 case*/
-        if (status == LSCSTATUS_FILE_NOT_FOUND) {
-          /*When 6320 occurs close the existing channels*/
-          LSC_CloseChannel(Os_info, status, pTranscv_Info);
-
-          status = LSCSTATUS_FAILED;
-          status = LSC_OpenChannel(Os_info, status, pTranscv_Info);
-          if (status == LSCSTATUS_SUCCESS) {
-            ALOGD_IF(ese_debug_enabled,
-                     "%s: SUCCESS:Post Switching LS open channel", fn);
-            status = LSCSTATUS_FAILED;
-            status = LSC_SelectLsc(Os_info, status, pTranscv_Info);
-            if (status == LSCSTATUS_SUCCESS) {
-              ALOGD_IF(ese_debug_enabled,
-                       "%s: SUCCESS:Post Switching LS select", fn);
-              status = LSCSTATUS_FAILED;
-              status = LSC_StoreData(Os_info, status, pTranscv_Info);
-              if (status == LSCSTATUS_SUCCESS) {
-                /*Enable certificate and signature verification*/
-                tag40_found = LSCSTATUS_SUCCESS;
-                gsLsExecuteResp[2] = 0x90;
-                gsLsExecuteResp[3] = 0x00;
-                reachEOFCheck = true;
-                continue;
-              }
-              ALOGE("%s: Post Switching LS store data failure", fn);
-            }
-            ALOGE("%s: Post Switching LS select failure", fn);
+        if (status == LSCSTATUS_SELF_UPDATE_DONE) {
+          status = LSC_CloseAllLogicalChannels(Os_info);
+          if (status != LSCSTATUS_SUCCESS) {
+            ALOGE("%s: CleanupLsUpdaterChannels failed", fn);
           }
-          ALOGE("%s: Post Switching LS failure", fn);
+          status = LSCSTATUS_SUCCESS;
+          goto exit;
         }
         ALOGE("%s: Sending packet to lsc failed", fn);
         goto exit;
@@ -934,6 +942,9 @@
                (rspApdu.p_data[rspApdu.len - 1] == 0x00)) {
       ALOGD_IF(ese_debug_enabled, "%s: Close channel id = 0x0%x success", fn,
                Os_info->Channel_Info[cnt].channel_id);
+      if (Os_info->Channel_Info[cnt].channel_id == Os_info->initChannelNum) {
+        Os_info->initChannelNum = 0x00;
+      }
       status = LSCSTATUS_SUCCESS;
     } else {
       ALOGD_IF(ese_debug_enabled, "%s: Close channel id = 0x0%x failed", fn,
@@ -1002,39 +1013,9 @@
     }
     status = LSC_SendtoEse(image_info, status, trans_info);
   } else if ((recvlen > 0x02) && (sw[0] == 0x63) && (sw[1] == 0x20)) {
-    uint8_t aid_array[22];
-    aid_array[0] = recvlen + 3;
-    aid_array[1] = 00;
-    aid_array[2] = 0xA4;
-    aid_array[3] = 0x04;
-    aid_array[4] = 0x00;
-    aid_array[5] = recvlen - 2;
-    memcpy(&aid_array[6], &RecvData[0], recvlen - 2);
-    memcpy(&ArrayOfAIDs[2][0], &aid_array[0], recvlen + 4);
-
-    FILE* fAidMem = fopen(AID_MEM_PATH, "w");
-
-    if (fAidMem == NULL) {
-      ALOGE("%s: Error opening AID data for writing: %s", fn, strerror(errno));
-      return LSCSTATUS_FAILED;
-    }
-
-    /*Updating the AID_MEM with new value into AID file*/
-    uint8_t respLen = 0;
-    int32_t wStatus = 0;
-    while (respLen <= (recvlen + 4)) {
-      wStatus = fprintf(fAidMem, "%2x", aid_array[respLen++]);
-      if (wStatus != 2) {
-        ALOGE("%s: Invalid Response during fprintf; status=0x%x", fn, wStatus);
-        fclose(fAidMem);
-        break;
-      }
-    }
-    if (wStatus == 2) {
-      status = LSCSTATUS_FILE_NOT_FOUND;
-    } else {
-      status = LSCSTATUS_FAILED;
-    }
+    /*In case of self update, status 0x6320 indicates script execution success
+    and response data has new AID*/
+    status = LSCSTATUS_SELF_UPDATE_DONE;
   } else if ((recvlen >= 0x02) &&
              ((sw[0] != 0x90) && (sw[0] != 0x63) && (sw[0] != 0x61))) {
     Write_Response_To_OutFile(image_info, RecvData, recvlen, tType);
@@ -1945,3 +1926,203 @@
   fclose(fLsStatus);
   return LSCSTATUS_SUCCESS;
 }
+
+/*******************************************************************************
+**
+** Function:        LSC_CloseAllLogicalChannels
+**
+** Description:     Close all opened logical channels
+**
+** Returns:         SUCCESS/FAILURE
+**
+*******************************************************************************/
+LSCSTATUS LSC_CloseAllLogicalChannels(Lsc_ImageInfo_t* Os_info) {
+  ESESTATUS status = ESESTATUS_FAILED;
+  LSCSTATUS lsStatus = LSCSTATUS_FAILED;
+  phNxpEse_data cmdApdu;
+  phNxpEse_data rspApdu;
+
+  ALOGD_IF(ese_debug_enabled, "%s: Enter", __func__);
+  for (uint8_t channelNumber = 0x01; channelNumber < 0x04; channelNumber++) {
+    if (channelNumber == Os_info->initChannelNum) continue;
+    phNxpEse_memset(&cmdApdu, 0x00, sizeof(phNxpEse_data));
+    phNxpEse_memset(&rspApdu, 0x00, sizeof(phNxpEse_data));
+    cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(5 * sizeof(uint8_t));
+    if (cmdApdu.p_data != NULL) {
+      uint8_t xx = 0;
+
+      cmdApdu.p_data[xx++] = channelNumber;
+      cmdApdu.p_data[xx++] = 0x70;           // INS
+      cmdApdu.p_data[xx++] = 0x80;           // P1
+      cmdApdu.p_data[xx++] = channelNumber;  // P2
+      cmdApdu.p_data[xx++] = 0x00;           // Lc
+      cmdApdu.len = xx;
+
+      status = phNxpEse_Transceive(&cmdApdu, &rspApdu);
+    }
+    if (status != ESESTATUS_SUCCESS) {
+      lsStatus = LSCSTATUS_FAILED;
+    } else if ((rspApdu.p_data[rspApdu.len - 2] == 0x90) &&
+               (rspApdu.p_data[rspApdu.len - 1] == 0x00)) {
+      lsStatus = LSCSTATUS_SUCCESS;
+    } else {
+      lsStatus = LSCSTATUS_FAILED;
+    }
+
+    phNxpEse_free(cmdApdu.p_data);
+    phNxpEse_free(rspApdu.p_data);
+  }
+  return lsStatus;
+}
+
+/*******************************************************************************
+**
+** Function:        LSC_SelectLsHash
+**
+** Description:     Selects LS Hash applet
+**
+** Returns:         SUCCESS/FAILURE
+**
+*******************************************************************************/
+LSCSTATUS LSC_SelectLsHash() {
+  phNxpEse_data cmdApdu;
+  phNxpEse_data rspApdu;
+  LSCSTATUS lsStatus = LSCSTATUS_FAILED;
+  ALOGD_IF(ese_debug_enabled, "%s: Enter ", __func__);
+  phNxpEse_memset(&cmdApdu, 0x00, sizeof(phNxpEse_data));
+  phNxpEse_memset(&rspApdu, 0x00, sizeof(phNxpEse_data));
+
+  cmdApdu.len = (int32_t)(sizeof(SelectLscSlotHash));
+  cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(cmdApdu.len * sizeof(uint8_t));
+  memcpy(cmdApdu.p_data, SelectLscSlotHash, sizeof(SelectLscSlotHash));
+
+  ESESTATUS eseStat = phNxpEse_Transceive(&cmdApdu, &rspApdu);
+
+  if ((eseStat != ESESTATUS_SUCCESS) ||
+      ((rspApdu.p_data[rspApdu.len - 2] != 0x90) &&
+       (rspApdu.p_data[rspApdu.len - 1] != 0x00))) {
+    lsStatus = LSCSTATUS_FAILED;
+  } else {
+    lsStatus = LSCSTATUS_SUCCESS;
+  }
+
+  phNxpEse_free(cmdApdu.p_data);
+  phNxpEse_free(rspApdu.p_data);
+  return lsStatus;
+}
+/*******************************************************************************
+**
+** Function:        LSC_ReadLsHash
+**
+** Description:     Read the LS SHA1 for the intended slot
+**
+** Returns:         SUCCESS/FAILURE
+**
+*******************************************************************************/
+LSCSTATUS LSC_ReadLsHash(uint8_t* hash, uint16_t* readHashLen, uint8_t slotId) {
+  phNxpEse_data cmdApdu;
+  phNxpEse_data rspApdu;
+  LSCSTATUS lsStatus = LSCSTATUS_FAILED;
+
+  lsStatus = LSC_SelectLsHash();
+  if (lsStatus != LSCSTATUS_SUCCESS) {
+    return lsStatus;
+  }
+
+  phNxpEse_memset(&cmdApdu, 0x00, sizeof(phNxpEse_data));
+  phNxpEse_memset(&rspApdu, 0x00, sizeof(phNxpEse_data));
+  cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(5 * sizeof(uint8_t));
+
+  if (cmdApdu.p_data != NULL) {
+    uint8_t xx = 0;
+    cmdApdu.p_data[xx++] = 0x80;    // CLA
+    cmdApdu.p_data[xx++] = 0x02;    // INS
+    cmdApdu.p_data[xx++] = slotId;  // P1
+    cmdApdu.p_data[xx++] = 0x00;    // P2
+    cmdApdu.len = xx;
+
+    ESESTATUS eseStat = phNxpEse_Transceive(&cmdApdu, &rspApdu);
+
+    if ((eseStat == ESESTATUS_SUCCESS) &&
+        ((rspApdu.p_data[rspApdu.len - 2] == 0x90) &&
+         (rspApdu.p_data[rspApdu.len - 1] == 0x00))) {
+      ALOGD_IF(ese_debug_enabled, "%s: rspApdu.len : %u", __func__,
+               rspApdu.len);
+      *readHashLen = rspApdu.len - 2;
+      memcpy(hash, rspApdu.p_data, rspApdu.len);
+
+      lsStatus = LSCSTATUS_SUCCESS;
+    } else {
+      if ((rspApdu.p_data[rspApdu.len - 2] == 0x6A) &&
+          (rspApdu.p_data[rspApdu.len - 1] == 0x86)) {
+        ALOGD_IF(ese_debug_enabled, "%s: slot id is invalid", __func__);
+        lsStatus = LSCSTATUS_HASH_SLOT_INVALID;
+      } else if ((rspApdu.p_data[rspApdu.len - 2] == 0x6A) &&
+                 (rspApdu.p_data[rspApdu.len - 1] == 0x83)) {
+        ALOGD_IF(ese_debug_enabled, "%s: slot is empty", __func__);
+        lsStatus = LSCSTATUS_HASH_SLOT_EMPTY;
+      } else {
+        lsStatus = LSCSTATUS_FAILED;
+      }
+    }
+    phNxpEse_free(cmdApdu.p_data);
+    phNxpEse_free(rspApdu.p_data);
+  }
+  return lsStatus;
+}
+
+/*******************************************************************************
+**
+** Function:        LSC_UpdateLsHash
+**
+** Description:     Updates the SHA1 for the intended slot
+**
+** Returns:         SUCCESS/FAILURE
+**
+*******************************************************************************/
+LSCSTATUS LSC_UpdateLsHash(uint8_t* hash, long hashLen, uint8_t slotId) {
+  phNxpEse_data cmdApdu;
+  phNxpEse_data rspApdu;
+  LSCSTATUS lsStatus = LSCSTATUS_FAILED;
+  ALOGD_IF(ese_debug_enabled, "%s: Enter ", __func__);
+
+  lsStatus = LSC_SelectLsHash();
+  if (lsStatus != LSCSTATUS_SUCCESS) {
+    return lsStatus;
+  }
+
+  phNxpEse_memset(&cmdApdu, 0x00, sizeof(phNxpEse_data));
+  phNxpEse_memset(&rspApdu, 0x00, sizeof(phNxpEse_data));
+
+  cmdApdu.len = (int32_t)(5 + hashLen);
+  cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(cmdApdu.len * sizeof(uint8_t));
+
+  if (cmdApdu.p_data != NULL) {
+    uint8_t xx = 0;
+    cmdApdu.p_data[xx++] = 0x80;
+    cmdApdu.p_data[xx++] = 0x01;     // INS
+    cmdApdu.p_data[xx++] = slotId;   // P1
+    cmdApdu.p_data[xx++] = 0x00;     // P2
+    cmdApdu.p_data[xx++] = hashLen;  // Lc
+    memcpy(&cmdApdu.p_data[xx], hash, hashLen);
+
+    ESESTATUS eseStat = phNxpEse_Transceive(&cmdApdu, &rspApdu);
+
+    if ((eseStat == ESESTATUS_SUCCESS) &&
+        ((rspApdu.p_data[rspApdu.len - 2] == 0x90) &&
+         (rspApdu.p_data[rspApdu.len - 1] == 0x00))) {
+      lsStatus = LSCSTATUS_SUCCESS;
+    } else {
+      if ((rspApdu.p_data[rspApdu.len - 2] == 0x6A) &&
+          (rspApdu.p_data[rspApdu.len - 1] == 0x86)) {
+        ALOGD_IF(ese_debug_enabled, "%s: if slot id is invalid", __func__);
+      }
+      lsStatus = LSCSTATUS_FAILED;
+    }
+  }
+
+  ALOGD_IF(ese_debug_enabled, "%s: Exit ", __func__);
+  phNxpEse_free(cmdApdu.p_data);
+  phNxpEse_free(rspApdu.p_data);
+  return lsStatus;
+}