Merge "Mobicore: Update internally managed branch"
diff --git a/daemon/ClientLib/ClientLib.cpp b/daemon/ClientLib/ClientLib.cpp
index 8a17f23..8bbd5e8 100644
--- a/daemon/ClientLib/ClientLib.cpp
+++ b/daemon/ClientLib/ClientLib.cpp
@@ -63,12 +63,12 @@
 
 using namespace std;
 
-list<Device *> devices;
+static list<Device *> devices;
 
 // Forward declarations.
 uint32_t getDaemonVersion(Connection *devCon, uint32_t *version);
 
-CMutex devMutex;
+static CMutex devMutex;
 //------------------------------------------------------------------------------
 Device *resolveDeviceId(uint32_t deviceId)
 {
diff --git a/daemon/ClientLib/public/MobiCoreDriverApi.h b/daemon/ClientLib/public/MobiCoreDriverApi.h
index 64f369e..8d36fc0 100644
--- a/daemon/ClientLib/public/MobiCoreDriverApi.h
+++ b/daemon/ClientLib/public/MobiCoreDriverApi.h
@@ -228,6 +228,7 @@
  * @return MC_DRV_ERR_UNKNOWN_DEVICE when device id is invalid.
  * @return MC_DRV_ERR_DAEMON_UNREACHABLE when problems with daemon socket occur.
  * @return MC_DRV_ERR_UNKNOWN_DEVICE when daemon returns an error.
+ * @return MC_DRV_ERR_TRUSTLET_NOT_FOUND when trustlet or driver cannot be loaded.
  *
  * Uses a Mutex.
  */
@@ -256,6 +257,7 @@
  * @return MC_DRV_ERR_UNKNOWN_DEVICE when device id is invalid.
  * @return MC_DRV_ERR_DAEMON_UNREACHABLE when problems with daemon socket occur.
  * @return MC_DRV_ERR_UNKNOWN_DEVICE when daemon returns an error.
+ * @return MC_DRV_ERR_TRUSTLET_NOT_FOUND when trustlet cannot be loaded.
  *
  * Uses a Mutex.
  */
diff --git a/daemon/Common/CMutex.cpp b/daemon/Common/CMutex.cpp
index d66fc80..618ae99 100644
--- a/daemon/Common/CMutex.cpp
+++ b/daemon/Common/CMutex.cpp
@@ -31,6 +31,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "CMutex.h"
+#include "log.h"
 
 
 //------------------------------------------------------------------------------
diff --git a/daemon/Daemon/Device/DeviceIrqHandler.cpp b/daemon/Daemon/Device/DeviceIrqHandler.cpp
index 4264750..1c4b104 100644
--- a/daemon/Daemon/Device/DeviceIrqHandler.cpp
+++ b/daemon/Daemon/Device/DeviceIrqHandler.cpp
@@ -31,7 +31,7 @@
  */
 
 #include "DeviceIrqHandler.h"
-
+#include "log.h"
 
 //------------------------------------------------------------------------------
 void DeviceIrqHandler::run(
diff --git a/daemon/Daemon/Device/MobiCoreDevice.cpp b/daemon/Daemon/Device/MobiCoreDevice.cpp
index 59ea36c..dda93a3 100644
--- a/daemon/Daemon/Device/MobiCoreDevice.cpp
+++ b/daemon/Daemon/Device/MobiCoreDevice.cpp
@@ -53,14 +53,22 @@
 //------------------------------------------------------------------------------
 MobiCoreDevice::MobiCoreDevice()
 {
+    nq = NULL;
+    mcFlags = NULL;
+    mcVersionInfo = NULL;
     mcFault = false;
+    mciReused = false;
 }
 
 //------------------------------------------------------------------------------
 MobiCoreDevice::~MobiCoreDevice()
 {
+    mciReused = false;
+    mcFault = false;
     delete mcVersionInfo;
     mcVersionInfo = NULL;
+    mcFlags = NULL;
+    nq = NULL;
 }
 
 //------------------------------------------------------------------------------
@@ -84,6 +92,7 @@
 
     while (pWsm) {
         unlockWsmL2(pWsm->handle);
+        delete pWsm;
         pWsm = session->popBulkBuff();
     }
     LOG_I("Finished unlocking session buffers!");
diff --git a/daemon/Daemon/Device/Platforms/Generic/TrustZoneDevice.cpp b/daemon/Daemon/Device/Platforms/Generic/TrustZoneDevice.cpp
index db9c236..07f9174 100644
--- a/daemon/Daemon/Device/Platforms/Generic/TrustZoneDevice.cpp
+++ b/daemon/Daemon/Device/Platforms/Generic/TrustZoneDevice.cpp
@@ -258,8 +258,7 @@
     }
 
     // Notify MobiCore about new data
-
-notification_t notification = { sessionId :
+    notification_t notification = { sessionId :
                                     sessionId, payload : 0
                                   };
 
diff --git a/daemon/Daemon/Device/TrustletSession.cpp b/daemon/Daemon/Device/TrustletSession.cpp
index a27b240..8eda1c8 100644
--- a/daemon/Daemon/Device/TrustletSession.cpp
+++ b/daemon/Daemon/Device/TrustletSession.cpp
@@ -108,7 +108,7 @@
     return true;
 }
 
-
+//------------------------------------------------------------------------------
 CWsm_ptr TrustletSession::popBulkBuff()
 {
     if (buffers.empty()) {
diff --git a/daemon/Daemon/MobiCoreDriverDaemon.cpp b/daemon/Daemon/MobiCoreDriverDaemon.cpp
index 4fd0595..faeb6fc 100644
--- a/daemon/Daemon/MobiCoreDriverDaemon.cpp
+++ b/daemon/Daemon/MobiCoreDriverDaemon.cpp
@@ -37,24 +37,21 @@
 #include <fcntl.h>
 #include <stdio.h>
 
-#include "MobiCoreDriverApi.h"
-#include "MobiCoreDriverCmd.h"
 #include "mcVersion.h"
 #include "mcVersionHelper.h"
 #include "mc_linux.h"
+#include "log.h"
+#include "Mci/mci.h"
 
+#include "MobiCoreDriverApi.h"
+#include "MobiCoreDriverCmd.h"
 #include "MobiCoreDriverDaemon.h"
 #include "PrivateRegistry.h"
 #include "MobiCoreDevice.h"
-
 #include "NetlinkServer.h"
 
-#include "log.h"
-
 #define DRIVER_TCI_LEN 4096
 
-#include "Mci/mci.h"
-
 MC_CHECK_VERSION(MCI, 0, 2);
 MC_CHECK_VERSION(SO, 2, 0);
 MC_CHECK_VERSION(MCLF, 2, 0);
@@ -64,7 +61,6 @@
 
 #define LOG_I_RELEASE(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
 
-
 //------------------------------------------------------------------------------
 MobiCoreDriverDaemon::MobiCoreDriverDaemon(
     bool enableScheduler,
diff --git a/daemon/Kernel/Platforms/Generic/CMcKMod.cpp b/daemon/Kernel/Platforms/Generic/CMcKMod.cpp
index 2f130a4..06e1e5c 100644
--- a/daemon/Kernel/Platforms/Generic/CMcKMod.cpp
+++ b/daemon/Kernel/Platforms/Generic/CMcKMod.cpp
@@ -66,9 +66,7 @@
     }
 
     // mapping response data is in the buffer
-struct mc_ioctl_map mapParams = { len:
-        len
-    };
+    struct mc_ioctl_map mapParams = { len : len };
 
     ret = ioctl(fdKMod, MC_IO_MAP_WSM, &mapParams);
     if (ret != 0) {
@@ -112,9 +110,7 @@
 {
     LOG_I("Mapping MCI: len=%d", len);
     // mapping response data is in the buffer
-struct mc_ioctl_map mapParams = { len:
-        len
-    };
+    struct mc_ioctl_map mapParams = { len : len };
 
     if (!isOpen()) {
         LOG_E("no connection to kmod");
@@ -245,9 +241,7 @@
     }
 
     // Init MC with NQ and MCP buffer addresses
-struct mc_ioctl_info fcInfoParams = {ext_info_id :
-        extInfoId
-    };
+    struct mc_ioctl_info fcInfoParams = { ext_info_id : extInfoId };
     ret = ioctl(fdKMod, MC_IO_INFO, &fcInfoParams);
     if (ret != 0) {
         LOG_ERRNO("ioctl MC_IO_INFO");
@@ -358,7 +352,7 @@
 
     int ret = ioctl(fdKMod, MC_IO_REG_WSM, &params);
     if (ret != 0) {
-        LOG_ERRNO("ioctl MC_IO_UNREG_WSM");
+        LOG_ERRNO("ioctl MC_IO_REG_WSM");
         return MAKE_MC_DRV_KMOD_WITH_ERRNO(errno);
     }
 
@@ -409,7 +403,7 @@
 
     ret = ioctl(fdKMod, MC_IO_LOCK_WSM, handle);
     if (ret != 0) {
-        LOG_ERRNO("ioctl MC_IO_UNREG_WSM");
+        LOG_ERRNO("ioctl MC_IO_LOCK_WSM");
         LOG_E("ret = %d", ret);
     }
 
@@ -447,6 +441,7 @@
 
     wsm.handle = handle;
     wsm.fd = fd;
+    wsm.phys = 0;
 
     LOG_I(" Resolving the WSM l2 for handle=%u", handle);
 
@@ -472,13 +467,15 @@
     struct mc_ioctl_resolv_cont_wsm wsm;
 
     wsm.handle = handle;
+    wsm.phys = 0;
+    wsm.length = 0;
     wsm.fd = fd;
 
     LOG_I(" Resolving the contiguous WSM l2 for handle=%u", handle);
 
     if (!isOpen()) {
         LOG_E("no connection to kmod");
-        return NULL;
+        return MC_DRV_ERR_KMOD_NOT_OPEN;
     }
 
     ret = ioctl(fdKMod, MC_IO_RESOLVE_CONT_WSM, &wsm);
@@ -506,7 +503,7 @@
 
     ret = ioctl(fdKMod, MC_IO_CLEAN_WSM, 0);
     if (ret != 0) {
-        LOG_ERRNO("ioctl MC_IO_UNREG_WSM");
+        LOG_ERRNO("ioctl MC_IO_CLEAN_WSM");
         LOG_E("ret = %d", ret);
     }
 
@@ -527,7 +524,7 @@
 
     ret = ioctl(fdKMod, MC_IO_LOG_SETUP, 0);
     if (ret != 0) {
-        LOG_ERRNO("ioctl MC_IO_UNREG_WSM");
+        LOG_ERRNO("ioctl MC_IO_LOG_SETUP");
         LOG_E("ret = %d", ret);
     }
 
diff --git a/daemon/PaApi/tlcCmApi.cpp b/daemon/PaApi/tlcCmApi.cpp
index f9fef07..a8bc260 100644
--- a/daemon/PaApi/tlcCmApi.cpp
+++ b/daemon/PaApi/tlcCmApi.cpp
@@ -38,8 +38,6 @@
 #include <assert.h>
 #include <stdlib.h>
 
-
-static const uint32_t DEVICE_ID = MC_DEVICE_ID_DEFAULT;
 static mcSessionHandle_t m_sessionHandle = { 0, 0 };
 
 mcResult_t cmOpen(cmp_t **cmp)
@@ -52,12 +50,12 @@
         return MC_DRV_ERR_INVALID_PARAMETER;
     }
 
-    result = mcOpenDevice(DEVICE_ID);
+    result = mcOpenDevice(MC_DEVICE_ID_DEFAULT);
     if (MC_DRV_OK != result) {
         LOG_E("Error opening device: %d", result);
         return result;
     }
-    result = mcMallocWsm(DEVICE_ID, 0, sizeof(cmp_t), (uint8_t **)cmp, 0);
+    result = mcMallocWsm(MC_DEVICE_ID_DEFAULT, 0, sizeof(cmp_t), (uint8_t **)cmp, 0);
     if (MC_DRV_OK != result) {
         LOG_E("Allocation of CMP WSM failed: %d", result);
         return result;
@@ -82,7 +80,7 @@
     if (MC_DRV_OK != result) {
         LOG_E("Closing session failed: %d", result);
     }
-    result = mcCloseDevice(DEVICE_ID);
+    result = mcCloseDevice(MC_DEVICE_ID_DEFAULT);
     if (MC_DRV_OK != result) {
         LOG_E("Closing MobiCore device failed: %d", result);
     }
diff --git a/daemon/Registry/PrivateRegistry.cpp b/daemon/Registry/PrivateRegistry.cpp
index 8943260..b8a306c 100755
--- a/daemon/Registry/PrivateRegistry.cpp
+++ b/daemon/Registry/PrivateRegistry.cpp
@@ -63,20 +63,19 @@
 // Asserts expression at compile-time (to be used within a function body).
 #define ASSERT_STATIC(e) do { enum { assert_static__ = 1 / (e) }; } while (0)
 
+#define MC_REGISTRY_CONTAINER_PATH "/data/app/mcRegistry"
+#define MC_REGISTRY_DEFAULT_PATH "/system/app/mcRegistry"
+#define MC_REGISTRY_FALLBACK_PATH "/data/app/mcRegistry"
+#define AUTH_TOKEN_FILE_NAME "00000000.authtokcont"
+#define ENV_MC_AUTH_TOKEN_PATH "MC_AUTH_TOKEN_PATH"
+#define ROOT_FILE_NAME "00000000.rootcont"
+#define SP_CONT_FILE_EXT ".spcont"
+#define TL_CONT_FILE_EXT ".tlcont"
+#define DATA_CONT_FILE_EXT ".datacont"
+#define TL_BIN_FILE_EXT ".tlbin"
+
 using namespace std;
 
-static const string MC_REGISTRY_CONTAINER_PATH = "/data/app/mcRegistry";
-static const string MC_REGISTRY_DEFAULT_PATH = "/system/app/mcRegistry";
-static const string MC_REGISTRY_FALLBACK_PATH = "/data/app/mcRegistry";
-static const string AUTH_TOKEN_FILE_NAME = "00000000.authtokcont";
-static const string ROOT_FILE_NAME = "00000000.rootcont";
-static const string SP_CONT_FILE_EXT = ".spcont";
-static const string TL_CONT_FILE_EXT = ".tlcont";
-static const string TL_BIN_FILE_EXT = ".tlbin";
-static const string DATA_CONT_FILE_EXT = ".datacont";
-
-static const string ENV_MC_AUTH_TOKEN_PATH = "MC_AUTH_TOKEN_PATH";
-
 //------------------------------------------------------------------------------
 static string byteArrayToString(const void *bytes, size_t elems)
 {
@@ -87,6 +86,7 @@
     }
     return string(hx);
 }
+
 //------------------------------------------------------------------------------
 static string uint32ToString(uint32_t value)
 {
@@ -120,17 +120,16 @@
     return registryPath;
 }
 
-
 //------------------------------------------------------------------------------
 static string getTlRegistryPath()
 {
     string registryPath;
 
     // First, attempt to use regular registry environment variable.
-    if (doesDirExist(MC_REGISTRY_DEFAULT_PATH.c_str())) {
+    if (doesDirExist(MC_REGISTRY_DEFAULT_PATH)) {
         registryPath = MC_REGISTRY_DEFAULT_PATH;
         LOG_I("getTlRegistryPath(): Using MC_REGISTRY_PATH %s", registryPath.c_str());
-    } else if (doesDirExist(MC_REGISTRY_FALLBACK_PATH.c_str())) {
+    } else if (doesDirExist(MC_REGISTRY_FALLBACK_PATH)) {
         // Second, attempt to use fallback registry environment variable.
         registryPath = MC_REGISTRY_FALLBACK_PATH;
         LOG_I("getTlRegistryPath(): Using MC_REGISTRY_FALLBACK_PATH %s", registryPath.c_str());
@@ -154,7 +153,7 @@
     string authTokenPath;
 
     // First, attempt to use regular auth token path environment variable.
-    path = getenv(ENV_MC_AUTH_TOKEN_PATH.c_str());
+    path = getenv(ENV_MC_AUTH_TOKEN_PATH);
     if (doesDirExist(path)) {
         LOG_I("getAuthTokenFilePath(): Using MC_AUTH_TOKEN_PATH %s", path);
         authTokenPath = path;
@@ -548,7 +547,9 @@
                 }
             }
         }
-        closedir(dp);
+        if (dp) {
+            closedir(dp);
+        }
         LOG_I("delete dir: %s", pathname.c_str());
         if (0 != (e = rmdir(pathname.c_str()))) {
             LOG_E("remove UUID-dir failed! errno: %d", e);
@@ -612,7 +613,9 @@
                 }
             }
         }
-        closedir(dp);
+        if (dp) {
+            closedir(dp);
+        }
         LOG_I("delete dir: %s", pathname.c_str());
         if (0 != (e = rmdir(pathname.c_str()))) {
             LOG_E("remove SPID-dir failed! error: %d", e);
@@ -675,14 +678,14 @@
 
     // Check service blob size.
     if (tlSize > MAX_TL_SIZE ) {
-        LOG_E("mcRegistryGetServiceBlob() failed: service blob too big: %d", tlSize);
+        LOG_E("mcRegistryMemGetServiceBlob() failed: service blob too big: %d", tlSize);
         return NULL;
     }
 
     mclfIntro_t *pIntro = (mclfIntro_t *)trustlet;
     // Check TL magic value.
     if (pIntro->magic != MC_SERVICE_HEADER_MAGIC_BE) {
-        LOG_E("mcRegistryGetServiceBlob() failed: wrong header magic value: %d", pIntro->magic);
+        LOG_E("mcRegistryMemGetServiceBlob() failed: wrong header magic value: %d", pIntro->magic);
         return NULL;
     }
 
@@ -704,7 +707,7 @@
     if (pHeader->serviceType == SERVICE_TYPE_DRIVER  || pHeader->serviceType == SERVICE_TYPE_SYSTEM_TRUSTLET) {
         // Take trustlet blob 'as is'.
         if (NULL == (regobj = (regObject_t *) (malloc(sizeof(regObject_t) + tlSize)))) {
-            LOG_E("mcRegistryGetServiceBlob() failed: Out of memory");
+            LOG_E("mcRegistryMemGetServiceBlob() failed: Out of memory");
             return NULL;
         }
         regobj->len = tlSize;
@@ -718,7 +721,7 @@
 
         // Prepare registry object.
         if (NULL == (regobj = (regObject_t *) malloc(sizeof(regObject_t) + regObjValueSize))) {
-            LOG_E("mcRegistryGetServiceBlob() failed: Out of memory");
+            LOG_E("mcRegistryMemGetServiceBlob() failed: Out of memory");
             return NULL;
         }
         regobj->len = regObjValueSize;
@@ -788,7 +791,7 @@
         } while (false);
 
         if (MC_DRV_OK != ret) {
-            LOG_E("mcRegistryGetServiceBlob() failed: Error code: %d", ret);
+            LOG_E("mcRegistryMemGetServiceBlob() failed: Error code: %d", ret);
             free(regobj);
             return NULL;
         }
@@ -799,7 +802,7 @@
                         lenInfo->tlContBlobSize;
         // Any other service type.
     } else {
-        LOG_E("mcRegistryGetServiceBlob() failed: Unsupported service type %u", pHeader->serviceType);
+        LOG_E("mcRegistryMemGetServiceBlob() failed: Unsupported service type %u", pHeader->serviceType);
     }
     return regobj;
 }
@@ -825,13 +828,13 @@
     }
 
     if (fstat(fd, &sb) == -1){
-        LOG_E("mcRegistryGetServiceBlob() failed: Cound't get file size");
+        LOG_E("mcRegistryFileGetServiceBlob() failed: Cound't get file size");
         goto error;
     }
 
     buffer = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
     if (buffer == MAP_FAILED) {
-        LOG_E("mcRegistryGetServiceBlob(): Failed to map file to memory");
+        LOG_E("mcRegistryFileGetServiceBlob(): Failed to map file to memory");
         goto error;
     }
 
@@ -839,12 +842,12 @@
 
     // We don't actually care if either of them fails but should still print warnings
     if (munmap(buffer, sb.st_size)) {
-        LOG_E("mcRegistryGetServiceBlob(): Failed to unmap memory");
+        LOG_E("mcRegistryFileGetServiceBlob(): Failed to unmap memory");
     }
 
 error:
     if (close(fd)) {
-        LOG_E("mcRegistryGetServiceBlob(): Failed to close file %s", trustlet);
+        LOG_E("mcRegistryFileGetServiceBlob(): Failed to close file %s", trustlet);
     }
 
     return regobj;
@@ -862,11 +865,12 @@
 
     // Open service blob file.
     string tlBinFilePath = getTlBinFilePath(uuid);
-    LOG_I(" Loading %s", tlBinFilePath.c_str());
+    LOG_I("Loading %s", tlBinFilePath.c_str());
 
     return mcRegistryFileGetServiceBlob(tlBinFilePath.c_str());
 }
 
+
 //------------------------------------------------------------------------------
 regObject_t *mcRegistryGetDriverBlob(const char *filename)
 {
@@ -882,7 +886,7 @@
 
     // If file is not a driver we are not interested
     if (pHeader->serviceType != SERVICE_TYPE_DRIVER) {
-        LOG_E("mcRegistryGetServiceBlob() failed: Unsupported service type %u", pHeader->serviceType);
+        LOG_E("mcRegistryGetDriverBlob() failed: Unsupported service type %u", pHeader->serviceType);
         pHeader = NULL;
         free(regobj);
         regobj = NULL;
diff --git a/daemon/Registry/Registry.cpp b/daemon/Registry/Registry.cpp
index 2ada6ac..a520f4e 100755
--- a/daemon/Registry/Registry.cpp
+++ b/daemon/Registry/Registry.cpp
@@ -312,6 +312,10 @@
         mcSpid_t spid;
     } cmd;
 
+    if(uuid == NULL) {
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+
     cmd.commandId = MC_DRV_REG_DELETE_TL_CONT;
     cmd.spid = spid;
     memcpy(&cmd.uuid, uuid, sizeof(mcUuid_t));
diff --git a/daemon/buildTag.h b/daemon/buildTag.h
index 0b2a793..9c02d33 100644
--- a/daemon/buildTag.h
+++ b/daemon/buildTag.h
@@ -1,4 +1,4 @@
-/** Build tag created during build by ./Out/_build/_src/Scripts/trunk/00035338/Out/setBuildTag.sh.
+/** Build tag created during build by ./Out/_build/_src/Scripts/tags/t-base-202_V001/Out/setBuildTag.sh.
  * <-- Copyright Trustonic Limited 2013 -->
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,4 +26,4 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #define MOBICORE_COMPONENT_BUILD_TAG \
-		"*** GC_MSM8960_Release_V019 ###"
+		"*** t-base-202_V001 ###"
diff --git a/include/Public/mc_linux.h b/include/Public/mc_linux.h
index 9c49aef..af027dc 100644
--- a/include/Public/mc_linux.h
+++ b/include/Public/mc_linux.h
@@ -43,6 +43,10 @@
 
 #include "version.h"
 
+#ifndef __KERNEL__
+#include <stdint.h>
+#endif
+
 #define MC_ADMIN_DEVNODE	"mobicore"
 #define MC_USER_DEVNODE		"mobicore-user"
 
diff --git a/rootpa/Code/Android/app/Android.mk b/rootpa/Code/Android/app/Android.mk
index 438c6f0..3e97ae5 100755
--- a/rootpa/Code/Android/app/Android.mk
+++ b/rootpa/Code/Android/app/Android.mk
@@ -13,6 +13,8 @@
 LOCAL_MODULE_TAGS := optional
 LOCAL_CERTIFICATE := platform
 
+LOCAL_PROGUARD_FLAGS := -include $(LOCAL_PATH)/proguard-project.txt
+
 include $(BUILD_PACKAGE)
 
 include $(CLEAR_VARS)
diff --git a/rootpa/Code/Android/app/jni/CommonPAWrapper/com_gd_mobicore_pa_jni_CommonPAWrapper.h b/rootpa/Code/Android/app/jni/CommonPAWrapper/com_gd_mobicore_pa_jni_CommonPAWrapper.h
index 5a376ec..8312793 100755
--- a/rootpa/Code/Android/app/jni/CommonPAWrapper/com_gd_mobicore_pa_jni_CommonPAWrapper.h
+++ b/rootpa/Code/Android/app/jni/CommonPAWrapper/com_gd_mobicore_pa_jni_CommonPAWrapper.h
@@ -137,10 +137,9 @@
 /*
  * Class:     com_gd_mobicore_pa_jni_CommonPAWrapper
  * Method:    installTrustlet
- * Signature: (I[B[B)I
  */
 JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_installTrustlet
-  (JNIEnv *, jobject, jint, jbyteArray, jint, jbyteArray, jbyteArray);
+  (JNIEnv *, jobject, jint, jbyteArray, jint, jbyteArray, jint, jbyteArray, jint, jint, jint, jbyteArray);
 
 /*
  * Class:     com_gd_mobicore_pa_jni_CommonPAWrapper
diff --git a/rootpa/Code/Android/app/jni/CommonPAWrapper/commonwrapper.cpp b/rootpa/Code/Android/app/jni/CommonPAWrapper/commonwrapper.cpp
index 32ada01..9867029 100755
--- a/rootpa/Code/Android/app/jni/CommonPAWrapper/commonwrapper.cpp
+++ b/rootpa/Code/Android/app/jni/CommonPAWrapper/commonwrapper.cpp
@@ -530,7 +530,17 @@
 
 
 JNIEXPORT jint JNICALL Java_com_gd_mobicore_pa_jni_CommonPAWrapper_installTrustlet
-  (JNIEnv* envP, jobject obj, jint spid, jbyteArray uuid, jint requestDataType, jbyteArray tltOrKeyData, jbyteArray seAddress)
+(JNIEnv* envP, jobject obj, 
+jint spid, 
+jbyteArray uuid, 
+jint requestDataType, 
+jbyteArray tltOrKeyData, 
+jint minTltVersion,
+jbyteArray tltPukHash,
+jint memoryType, 
+jint numberOfInstances, 
+jint flags, 
+jbyteArray seAddress)
 {
     LOGD(">>Java_com_gd_mobicore_pa_jni_CommonPAWrapper_installTrustlet %ld %ld\n", (long int) stateUpdateCallback, (long int) getSystemInfoCallback);
     setFilesPath(envP, obj);
@@ -552,6 +562,12 @@
         trustletInstallationData_t tltData;        
         tltData.dataP=(uint8_t*) jniHelp.jByteArrayToCByteArray(tltOrKeyData, &tltData.dataLength);
         tltData.dataType=(TltInstallationRequestDataType) requestDataType;
+        tltData.minTltVersion=minTltVersion;
+        tltData.tltPukHashP=(uint8_t*) jniHelp.jByteArrayToCByteArray(tltPukHash, &tltData.tltPukHashLength);
+        tltData.memoryType=memoryType;
+        tltData.numberOfInstances=numberOfInstances;
+        tltData.flags=flags;
+        
         uint32_t uuidLength=0;
         uint8_t* uuidP=(uint8_t*) jniHelp.jByteArrayToCByteArray(uuid, &uuidLength);
         if(UUID_LENGTH != uuidLength){
diff --git a/rootpa/Code/Android/app/proguard-project.txt b/rootpa/Code/Android/app/proguard-project.txt
index f2fe155..39b3569 100755
--- a/rootpa/Code/Android/app/proguard-project.txt
+++ b/rootpa/Code/Android/app/proguard-project.txt
@@ -18,3 +18,56 @@
 #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
 #   public *;
 #}
+
+############## proguard-android.txt
+
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-verbose
+
+-dontoptimize
+-dontpreverify
+
+-keepattributes *Annotation*
+-keep public class com.google.vending.licensing.ILicensingService
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+    native <methods>;
+}
+
+-keepclassmembers public class * extends android.view.View {
+   void set*(***);
+   *** get*();
+}
+
+-keepclassmembers class * extends android.app.Activity {
+   public void *(android.view.View);
+}
+
+-keepclassmembers enum * {
+    public static **[] values();
+    public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+  public static final android.os.Parcelable$Creator *;
+}
+
+-keepclassmembers class **.R$* {
+    public static <fields>;
+}
+
+-dontwarn android.support.**
+
+##############
+
+
+# plus rootpa specifics
+
+-dontobfuscate
+
+-keep class com.gd.mobicore.pa.ifc.* { public *; }
+-keep class com.gd.mobicore.pa.jni.CommonPAWrapper { public *; }
+
+
diff --git a/rootpa/Code/Android/app/project.properties b/rootpa/Code/Android/app/project.properties
index 52e5e2b..f91ff48 100755
--- a/rootpa/Code/Android/app/project.properties
+++ b/rootpa/Code/Android/app/project.properties
@@ -10,6 +10,7 @@
 # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
 #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
 
+proguard.config=proguard-project.txt
 
 android.library.reference.1=../lib/
 
diff --git a/rootpa/Code/Android/app/res/values/version.xml b/rootpa/Code/Android/app/res/values/version.xml
index a943b2a..d91fbcb 100644
--- a/rootpa/Code/Android/app/res/values/version.xml
+++ b/rootpa/Code/Android/app/res/values/version.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-    <string name="name">1.0003 (34387)</string>
-    <integer name="code">0x10003</integer>
+    <string name="name">2.0025 (37085)</string>
+    <integer name="code">0x20019</integer>
 </resources>
diff --git a/rootpa/Code/Android/app/src/com/gd/mobicore/pa/jni/CommonPAWrapper.java b/rootpa/Code/Android/app/src/com/gd/mobicore/pa/jni/CommonPAWrapper.java
index fbb3fd5..3f7e7aa 100755
--- a/rootpa/Code/Android/app/src/com/gd/mobicore/pa/jni/CommonPAWrapper.java
+++ b/rootpa/Code/Android/app/src/com/gd/mobicore/pa/jni/CommonPAWrapper.java
@@ -66,7 +66,16 @@
     public native int getSPContainerState(int spid, int[] state);
     public native int getSPContainerStructure(int spid, int[] ints, byte[][] uuidArray, int[] trustletStates);
     public native int doProvisioning(int uid, int spid, byte[] seAddress);
-	public native int installTrustlet(int spid, byte[] uuid, int dataType, byte[] tltOrKeyData, byte[] seAddress);
+	public native int installTrustlet(int spid, 
+                                      byte[] uuid, 
+                                      int dataType, 
+                                      byte[] tltOrKeyData,
+                                      int minTltVersion,
+                                      byte[] tltPukHash,
+                                      int memoryType, 
+                                      int numberOfInstances, 
+                                      int flags, 
+                                      byte[] seAddress);
     public native int unregisterRootContainer(byte[] seAddress);
     public native void setEnvironmentVariable(byte[] variable, byte[] value);    
 
diff --git a/rootpa/Code/Android/app/src/com/gd/mobicore/pa/service/DeveloperService.java b/rootpa/Code/Android/app/src/com/gd/mobicore/pa/service/DeveloperService.java
index 9cc30bc..2f22828 100755
--- a/rootpa/Code/Android/app/src/com/gd/mobicore/pa/service/DeveloperService.java
+++ b/rootpa/Code/Android/app/src/com/gd/mobicore/pa/service/DeveloperService.java
@@ -50,6 +50,13 @@
     private final RootPADeveloperIfc.Stub mBinder = new ServiceIfc();
     private static final int DEVELOPER_UID_FOR_LOCK=0x22220000;
     private static final int UUID_LENGTH=16;
+    private static final int EXTERNAL_MEMORY=2;
+    private static final int DEFAULT_MEMORY_TYPE=EXTERNAL_MEMORY;
+    private static final int DEFAULT_NUMBER_OF_INSTANCES=1;
+    private static final int DEFAULT_FLAGS=0;    
+    private static final byte[] DEFAULT_PUKHASH={0,0,0,0,0,0,0,0,0,0,
+                                                 0,0,0,0,0,0,0,0,0,0,
+                                                 0,0,0,0,0,0,0,0,0,0,0,0};
     private class ServiceIfc extends RootPADeveloperIfc.Stub {
         public ServiceIfc(){
             super();
@@ -73,10 +80,13 @@
             return true;
         }
         
-        public CommandResult installTrustlet(int spid, byte[] uuid, byte[] trustletBinary, byte[] key){
-            Log.d(TAG,">>DeveloperService.Stub.installTrustlet"); 
-
-            if((trustletBinary == null && key == null) || (trustletBinary != null && key != null) || 0==spid || !uuidOk(uuid)){
+        public CommandResult installTrustletOrKey(int spid, byte[] uuid, byte[] trustletBinary, byte[] key, int minTltVersion, byte[] tltPukHash){
+            Log.d(TAG,">>DeveloperService.Stub.installTrustletOrKey"); 
+            if(tltPukHash==null){
+                tltPukHash=DEFAULT_PUKHASH;
+            }
+            
+            if((trustletBinary == null && key == null) || (trustletBinary != null && key != null) || 0==spid || !uuidOk(uuid) ){
                 return new CommandResult(CommandResult.ROOTPA_ERROR_ILLEGAL_ARGUMENT);
             }
 
@@ -98,7 +108,62 @@
                     dataType=REQUEST_DATA_KEY;
                 }
                 setupProxy();    
-                err=commonPAWrapper().installTrustlet(spid, uuid, dataType, data, se_);
+                err=commonPAWrapper().installTrustlet(spid, 
+                                                      uuid, 
+                                                      dataType, 
+                                                      data,  
+                                                      minTltVersion, 
+                                                      tltPukHash, 
+                                                      DEFAULT_MEMORY_TYPE, 
+                                                      DEFAULT_NUMBER_OF_INSTANCES, 
+                                                      DEFAULT_FLAGS, 
+                                                      se_);
+            }catch(Exception e){
+                Log.e(TAG,"CommonPAWrapper().installTrustletOrKey exception: ", e);
+                err=CommandResult.ROOTPA_ERROR_INTERNAL;
+            }
+
+            Log.d(TAG,"<<DeveloperService.Stub.installTrustletOrKey");
+            return new CommandResult(err);
+        }
+        
+        public CommandResult installTrustlet(int spid, 
+                                             byte[] uuid, 
+                                             byte[] trustletBinary, 
+                                             int minTltVersion, 
+                                             byte[] tltPukHash, 
+                                             int memoryType, 
+                                             int numberOfInstances, 
+                                             int flags){
+            Log.d(TAG,">>DeveloperService.Stub.installTrustlet"); 
+            if(tltPukHash==null){
+                tltPukHash=DEFAULT_PUKHASH;
+            }
+
+                                                 
+            if(trustletBinary == null || 0==spid || !uuidOk(uuid) || memoryType > EXTERNAL_MEMORY){
+                return new CommandResult(CommandResult.ROOTPA_ERROR_ILLEGAL_ARGUMENT);
+            }
+
+            int tmpSuid=DEVELOPER_UID_FOR_LOCK+new Random().nextInt(); 
+
+            if(!DeveloperService.this.acquireLock(tmpSuid, false).isOk()){
+                return new CommandResult(CommandResult.ROOTPA_ERROR_LOCK);
+            }
+            doProvisioningLockSuid_=tmpSuid;
+            int err=0;
+            try{
+                setupProxy();    
+                err=commonPAWrapper().installTrustlet(spid, 
+                                                      uuid, 
+                                                      REQUEST_DATA_TLT, 
+                                                      trustletBinary, 
+                                                      minTltVersion, 
+                                                      tltPukHash,
+                                                      memoryType, 
+                                                      numberOfInstances, 
+                                                      flags, 
+                                                      se_);
             }catch(Exception e){
                 Log.e(TAG,"CommonPAWrapper().installTrustlet exception: ", e);
                 err=CommandResult.ROOTPA_ERROR_INTERNAL;
@@ -106,8 +171,7 @@
 
             Log.d(TAG,"<<DeveloperService.Stub.installTrustlet");
             return new CommandResult(err);
-        }
-        
+        }        
     }
     
     @Override
diff --git a/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/RootPADeveloperIfc.aidl b/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/RootPADeveloperIfc.aidl
index 69d9e79..e69a760 100755
--- a/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/RootPADeveloperIfc.aidl
+++ b/rootpa/Code/Android/lib/src/com/gd/mobicore/pa/ifc/RootPADeveloperIfc.aidl
@@ -54,7 +54,7 @@
      * This method can be used for installing "developer trustlet" that is not tied to any 
      * service provider and/or service manager. It contacts Service Enabler and asks it to 
      * perform the tasks, so the device has to be connected to network in order for this to
-     * succeed.
+     * succeed.   
      *
      * The service progress is informed with the same Intents as is progress of the 
      * @ref RootPAServiceIfc#doProvisioning, however there is an additional 
@@ -64,20 +64,71 @@
      *
      * There are constants related to the intents in @ref RootPAProvisioningIntents
      *
+     * @param spid service provider id
+     * @param uuid uuid of the trustlet in hex, without dashes. Needs to be correct length.
+     * @param trustletBinary trustlet binary to be encrypted with and returned back. 
+     *        If the binary is already encrypted, this array must be empty. The binary 
+     *        has to be encrypted for transfer. Note that only either trustletBinary 
+     *        or key can be given. There are sperate instructions on how the binary is to 
+     *        be encrypted and packaged. Key and trustletBinary are exclusive, only one of 
+     *        them can be given. This methods uses default values for memoryType (2), 
+     *        numberOfInstances (1) and flags (0) when trustlet binary is installed.
+     * @param key a key that has been used to encrypt the trustlet binary in case when 
+     *        the trustlet binary is not given as a parameter. This key has to be 
+     *        encrypted for transfer. There are sperate instructions on how the key is to 
+     *        be encrypted and packaged. Key and trustletBinary are exclusive, only one of 
+     *        them can be given.
+     * @param minTltVersion minimum version of the trustlet
+     * @param tltPukHash this field is not used at the moment, null is fine here.
+     *
+     * @return indication of successful start of provisioning thread (ROOTPA_OK) or an error code
+     */
+    CommandResult installTrustletOrKey(in int spid, 
+                                       in byte[] uuid, 
+                                       in byte[] trustletBinary, 
+                                       in byte[] key,                                   
+                                       in int minTltVersion, 
+                                       in byte[] tltPukHash);
+    
+    /**
+     * This method can be used for installing "developer trustlet" that is not tied to any 
+     * service provider and/or service manager. It contacts Service Enabler and asks it to 
+     * perform the tasks, so the device has to be connected to network in order for this to
+     * succeed.
+     *
+     * The service progress is informed with the same Intents as is progress of the 
+     * @ref RootPAServiceIfc#doProvisioning, however there is an additional 
+     * Intent com.gd.mobicore.pa.service.INSTALL_TRUSTLET for returning the encrypted 
+     * trustlet binary.
+     *
+     * There are constants related to the intents in @ref RootPAProvisioningIntents
      *
      * @param spid service provider id
      * @param uuid uuid of the trustlet in hex, without dashes. Needs to be correct length.
      * @param trustletBinary trustlet binary to be encrypted with and returned back. 
      *        If the binary is already encrypted, this array must be empty. The binary 
      *        has to be encrypted for transfer. Note that only either trustletBinary 
-     *        or key can be given.
-     * @param key a key that has been used to encrypt the trustlet binary in case when 
-     *        the trustlet binary is not given as a parameter. This The key has to be 
-     *        encrypted for transfer.  Note that only either trustletBinary 
-     *        or key can be given.
+     *        or key can be given. There are sperate instructions on how the binary is to 
+     *        be encrypted and packaged.
+     * @param minTltVersion minimum version of the trustlet
+     * @param tltPukHash this field is not used at the moment, null is fine here.
+     * @param memoryType memory where the trustlet is to be loaded and executed: 0 - if enough space is available, 
+              load the Trustlet into the internal memory, otherwise into the external memory, 1 - internal memory, 
+              2 - external memory
+     * @param numberOfInstances indicates how many instances of a trustlet can be installed (run) in parallel
+     * @param flags current flags are: 1 - permanent, 2 - service has no WSW control interface,  4 - debuggable
+     *
      * @return indication of successful start of provisioning thread (ROOTPA_OK) or an error code
      */
-    CommandResult installTrustlet(in int spid, in byte[] uuid, in byte[] trustletBinary, in byte[] key);
+    CommandResult installTrustlet(in int spid, 
+                                  in byte[] uuid, 
+                                  in byte[] trustletBinary, 
+                                  in int minTltVersion, 
+                                  in byte[] tltPukHash, 
+                                  in int memoryType, 
+                                  in int numberOfInstances, 
+                                  in int flags);
+
 }
 
 /**@}*/
diff --git a/rootpa/Code/Common/commandhandler.c b/rootpa/Code/Common/commandhandler.c
index 2b5c88f..a80ad7b 100755
--- a/rootpa/Code/Common/commandhandler.c
+++ b/rootpa/Code/Common/commandhandler.c
@@ -367,6 +367,7 @@
     if(((provisioningparams_t*)paramsP)->tltInstallationDataP)
     {
         free((char*)((provisioningparams_t*)paramsP)->tltInstallationDataP->dataP);
+        free((char*)((provisioningparams_t*)paramsP)->tltInstallationDataP->tltPukHashP);
         free(((provisioningparams_t*)paramsP)->tltInstallationDataP);
     }
     free(paramsP);
@@ -400,8 +401,13 @@
             return ROOTPA_ERROR_OUT_OF_MEMORY;
         }
 
+    // copy the whole struct
+        
         memset(paramsP->tltInstallationDataP,0,sizeof(trustletInstallationData_t)); // initialize in order to satisfy valgrind
+        memcpy(paramsP->tltInstallationDataP, tltDataP, sizeof(trustletInstallationData_t));
 
+    // malloc and copy data from/to the pointers
+        
         paramsP->tltInstallationDataP->dataP=malloc(tltDataP->dataLength);
         if(!paramsP->tltInstallationDataP->dataP)
         {
@@ -410,11 +416,18 @@
             return ROOTPA_ERROR_OUT_OF_MEMORY;
         }
         memset((char*)paramsP->tltInstallationDataP->dataP,0,tltDataP->dataLength); // initialize in order to satisfy valgrind
-        memcpy((char*)paramsP->tltInstallationDataP->dataP, tltDataP->dataP, sizeof(tltDataP->dataLength));
+        memcpy((char*)paramsP->tltInstallationDataP->dataP, tltDataP->dataP, tltDataP->dataLength);
 
-        paramsP->tltInstallationDataP->dataLength = tltDataP->dataLength;
-        paramsP->tltInstallationDataP->dataType = tltDataP->dataType;
-        memcpy(&paramsP->tltInstallationDataP->uuid, &tltDataP->uuid, UUID_LENGTH);
+        paramsP->tltInstallationDataP->tltPukHashP=malloc(tltDataP->tltPukHashLength);
+        if(!paramsP->tltInstallationDataP->tltPukHashP)
+        {
+            free((void*) paramsP->tltInstallationDataP->dataP);
+            free((void*) paramsP->tltInstallationDataP);
+            free(paramsP);
+            return ROOTPA_ERROR_OUT_OF_MEMORY;
+        }        
+        memset((char*)paramsP->tltInstallationDataP->tltPukHashP,0,tltDataP->tltPukHashLength); // initialize in order to satisfy valgrind
+        memcpy((char*)paramsP->tltInstallationDataP->tltPukHashP, tltDataP->tltPukHashP, tltDataP->tltPukHashLength);
     }
     else
     {
diff --git a/rootpa/Code/Common/enrollmentservicexmlschema.h b/rootpa/Code/Common/enrollmentservicexmlschema.h
index 4210f04..4e62c32 100755
--- a/rootpa/Code/Common/enrollmentservicexmlschema.h
+++ b/rootpa/Code/Common/enrollmentservicexmlschema.h
@@ -92,6 +92,58 @@
 		<xsd:attribute name=\"id\" type=\"xsd:int\" use=\"required\" /> \
 	</xsd:complexType> \
  \
+  	<xsd:complexType name=\"TrustletEncryptionKey\"> \
+		<xsd:simpleContent> \
+			<xsd:extension base=\"xsd:base64Binary\"> \
+				<xsd:attribute name=\"minTltVersion\" type=\"mcpt:Version\" use=\"required\" /> \
+				<xsd:attribute name=\"tltPukHash\" type=\"xsd:base64Binary\" use=\"required\" /> \
+			</xsd:extension> \
+		</xsd:simpleContent> \
+	</xsd:complexType> \
+\
+	<xsd:simpleType name=\"TrustletMemoryType\"> \
+		<xsd:restriction base=\"xsd:int\"> \
+			<xsd:enumeration value=\"0\"> \
+				<xsd:annotation> \
+					<xsd:documentation> \
+	If enough space is available in the internal \
+	memory the trustlet will be loaded into the internal memory, else into the external \
+					</xsd:documentation> \
+				</xsd:annotation> \
+			</xsd:enumeration> \
+			<xsd:enumeration value=\"1\"> \
+				<xsd:annotation> \
+					<xsd:documentation> \
+						Use internal memory only. \
+					</xsd:documentation> \
+				</xsd:annotation> \
+			</xsd:enumeration> \
+			<xsd:enumeration value=\"2\"> \
+				<xsd:annotation> \
+					<xsd:documentation> \
+						Use external memory only. \
+					</xsd:documentation> \
+				</xsd:annotation> \
+			</xsd:enumeration> \
+		</xsd:restriction> \
+	</xsd:simpleType> \
+ \
+	<xsd:complexType name=\"TrustletAXF\"> \
+		<xsd:simpleContent> \
+			<xsd:extension base=\"xsd:base64Binary\"> \
+				<xsd:attribute name=\"minTltVersion\" type=\"mcpt:Version\" \
+					use=\"required\" /> \
+				<xsd:attribute name=\"tltPukHash\" type=\"xsd:base64Binary\" \
+					use=\"required\" /> \
+				<xsd:attribute name=\"memoryType\" type=\"mces:TrustletMemoryType\" \
+					default=\"2\" /> \
+				<xsd:attribute name=\"numberOfInstances\" type=\"xsd:int\" \
+					default=\"1\" /> \
+				<xsd:attribute name=\"flags\" type=\"xsd:int\" default=\"0\" /> \
+			</xsd:extension> \
+		</xsd:simpleContent> \
+	</xsd:complexType> \
+\
 	<xsd:complexType name=\"TrustletInstallationRequest\"> \
 		<xsd:annotation> \
 			<xsd:documentation> \
@@ -123,12 +175,12 @@
 		</xsd:annotation> \
 		<xsd:sequence> \
 			<xsd:choice> \
-				<xsd:element name=\"tltBinary\" type=\"xsd:base64Binary\" /> \
-				<xsd:element name=\"tltEncryptionKey\" type=\"xsd:base64Binary\" /> \
+				<xsd:element name=\"trustletAxf\" type=\"mces:TrustletAXF\" /> \
+				<xsd:element name=\"tltEncryptionKey\" type=\"mces:TrustletEncryptionKey\" /> \
 			</xsd:choice> \
 		</xsd:sequence> \
 	</xsd:complexType> \
-	 \
+\
 	<xsd:complexType name=\"CommandResultList\"> \
 		<xsd:sequence> \
 			<xsd:element name=\"commandResult\" type=\"mces:CommandResult\" maxOccurs=\"unbounded\" /> \
@@ -185,7 +237,7 @@
 	xmlns:mcpt=\"http://www.mcore.gi-de.com/2012/02/schema/MCPlatformTypes\" \
 	targetNamespace=\"http://www.mcore.gi-de.com/2012/02/schema/MCPlatformTypes\" \
 	elementFormDefault=\"qualified\"> \
-	 \
+\
 	<xsd:simpleType name=\"Version\"> \
 		<xsd:annotation> \
 			<xsd:documentation> \
@@ -194,7 +246,7 @@
 		</xsd:annotation> \
 		<xsd:restriction base=\"xsd:int\" /> \
 	</xsd:simpleType> \
-		 \
+\
 	<xsd:complexType name=\"McVersion\"> \
 		<xsd:annotation> \
 			<xsd:documentation> \
@@ -231,6 +283,7 @@
 		<xsd:attribute name=\"manufacturer\" type=\"xsd:string\" use=\"optional\" /> \
 		<xsd:attribute name=\"hardware\" type=\"xsd:string\" use=\"optional\" /> \
 		<xsd:attribute name=\"model\" type=\"xsd:string\" use=\"optional\" /> \
+        <xsd:attribute name=\"sip\" type=\"xsd:string\" use=\"optional\" /> \
 		<xsd:attribute name=\"version\" type=\"xsd:string\" use=\"optional\" /> \
 	</xsd:complexType> \
 </xsd:schema>"
diff --git a/rootpa/Code/Common/include/rootpa.h b/rootpa/Code/Common/include/rootpa.h
index fe35267..7f1e4d8 100755
--- a/rootpa/Code/Common/include/rootpa.h
+++ b/rootpa/Code/Common/include/rootpa.h
@@ -194,6 +194,40 @@
     uuid of the trustlet
     */
     mcUuid_t uuid;
+    
+    /**
+    minimum version of the trustlet
+    */
+    uint32_t minTltVersion;
+
+    /**
+    pointer to tltPukHash
+    */
+    const uint8_t* tltPukHashP;
+
+    /**
+    length of data pointed by tltPukHashP
+    */
+    uint32_t tltPukHashLength;
+
+    /**
+    memory where the trustlet is to be loaded and executed: 
+    0 - if enough space is available, load the Trustlet into the internal memory, otherwise into the external memory, 
+    1 - internal memory, 
+    2 - external memory
+    */
+    uint32_t memoryType;
+
+    /**
+    indicates how many instances of a trustlet can be installed (run) in parallel
+    */
+    uint32_t numberOfInstances;
+    
+    /**
+    current flags are: 1 - permanent, 2 - service has no WSW control interface, 4 - debuggable
+    */
+    uint32_t flags;
+    
 }trustletInstallationData_t;
 
 #ifdef __cplusplus
diff --git a/rootpa/Code/Common/include/version.h b/rootpa/Code/Common/include/version.h
index 043ba73..b307caa 100755
--- a/rootpa/Code/Common/include/version.h
+++ b/rootpa/Code/Common/include/version.h
@@ -34,7 +34,7 @@
 #ifndef ROOTPA_VERSION_H_
 #define ROOTPA_VERSION_H_
 
-#define ROOTPA_VERSION_MAJOR 1
-#define ROOTPA_VERSION_MINOR 3
+#define ROOTPA_VERSION_MAJOR 2
+#define ROOTPA_VERSION_MINOR 25
 
 #endif /** ROOTPA_VERSION_H_ */
diff --git a/rootpa/Code/Common/provisioningengine.c b/rootpa/Code/Common/provisioningengine.c
index a8ba1bd..67d0547 100755
--- a/rootpa/Code/Common/provisioningengine.c
+++ b/rootpa/Code/Common/provisioningengine.c
@@ -44,14 +44,14 @@
 
 
 
-static const char* const SE_URL="https://se.cgbe.trustonic.com:8443/"; // note that there has to be slash at the end since we are adding suid to it next
-//static const char* const SE_URL="http://se.cgbe.trustonic.com:8080/"; // note that there has to be slash at the end since we are adding suid to it next
+static const char* const SE_URL="https://se.cgbe.trustonic.com:8443/service-enabler/enrollment/"; // note that there has to be slash at the end since we are adding suid to it next
+
 
 static const char* const RELATION_SELF  =      "relation/self";
 static const char* const RELATION_SYSTEMINFO = "relation/system_info";
 static const char* const RELATION_RESULT   =   "relation/command_result";
 static const char* const RELATION_NEXT    =    "relation/next";
-static const uint8_t* const SLASH="/";
+static const uint8_t* const SLASH= (uint8_t*)"/";
 
 static const char* const RELATION_INITIAL_POST="initial_post"; // this will make us to send HTTP GET, which
                                       // is the right thing to do since we do not 
@@ -73,7 +73,7 @@
 
 void addBytesToUri(char* uriP, uint8_t* bytes, uint32_t length, bool uuid )
 {
-    LOGD(">>add bytes to URI %d", length);
+    LOGD(">>addBytesToUri %d", length);
     int uriidx=strlen(uriP);
     int i;
     uint8_t singleNumber=0;
@@ -85,12 +85,13 @@
         singleNumber=(bytes[i]&0x0F);
         singleNumber=((singleNumber<0xA)?(singleNumber+0x30):(singleNumber+0x57));
         uriP[uriidx++]=singleNumber;
+
         if(true==uuid && (3 == i || 5 == i || 7 == i || 9 == i))
         {
             uriP[uriidx++]='-';
         }
     }
-    LOGD("<<add bytes to URI %s %d", uriP, uriidx);
+    LOGD("<<addBytesToUri %s %d", uriP, uriidx);
 }
 
 void addIntToUri(char* uriP, uint32_t addThis)
@@ -397,7 +398,7 @@
                 workToDo=false;
             }
 
-            LOGD("end of provisioning loop work to do: %d, responseP %ld", workToDo, responseP);
+            LOGD("end of provisioning loop work to do: %d, responseP %ld", workToDo, (long int) responseP);
         } 
 
         // last round cleaning in order to make sure both original and user pointers are released, but only once
diff --git a/rootpa/Code/Common/seclient.c b/rootpa/Code/Common/seclient.c
index a4fd992..0cb6600 100755
--- a/rootpa/Code/Common/seclient.c
+++ b/rootpa/Code/Common/seclient.c
@@ -185,7 +185,7 @@
     }
     else
     {
-        LOGD("curl: no debug msg %d %d", info, debugMessageSize);
+        LOGD("curl: no debug msg %d %d", info, (int) debugMessageSize);
     }
     return 0;
 }
@@ -458,7 +458,7 @@
 
 bool setPostOpt(CURL* curl_handle, const char* inputP)
 {
-    LOGD(">>setPostOpt %ld %d", inputP, inputP?strlen(inputP):0);
+    LOGD(">>setPostOpt %ld %d", (long int) inputP, inputP?(int)strlen(inputP):0);
     
     if (curl_easy_setopt(curl_handle, CURLOPT_POST, 1L)!=CURLE_OK)
     {
diff --git a/rootpa/Code/Common/xmlmessagehandler.c b/rootpa/Code/Common/xmlmessagehandler.c
index 7de588d..861fd6f 100755
--- a/rootpa/Code/Common/xmlmessagehandler.c
+++ b/rootpa/Code/Common/xmlmessagehandler.c
@@ -58,6 +58,11 @@
 
 #define UNKNOWN_ID 0xFFFFFFFF
 
+#define EXTERNAL_MEMORY 2
+#define DEFAULT_MEMORY_TYPE EXTERNAL_MEMORY
+#define DEFAULT_NUMBER_OF_INSTANCES 1
+#define DEFAULT_FLAGS 0
+
 typedef enum
 {
     CMP,
@@ -452,7 +457,7 @@
 {
     LOGD(">>handleUploadResponses %d", numberOfUploadResponses);
     rootpaerror_t ret=ROOTPA_OK;
-
+    char zero=0;
     uint32_t i;
     for(i=0; (i < numberOfUploadResponses) && (ROOTPA_OK==ret); i++)
     {
@@ -460,8 +465,8 @@
         if(ROOTPA_OK == uploadResponsesP[i].ret)
         {
             // in success case TLT_UPLOAD and SO_UPLOAD return "0" (encoded) in the resultValue 
-            // field (discussed and agreed with Dimi Jan 10, 2013 */
-            encodedResponseP=base64EncodeAddEndZero("0", 1);
+            // field (discussed and agreed with Dimi Jan 10, 2013)
+            encodedResponseP=base64EncodeAddEndZero(&zero, 1);
         }
         
         if( addCommandResultData(rspResultElementP, uploadResponsesP[i].id, encodedResponseP,  uploadResponsesP[i].ret, uploadResponsesP[i].intRet )==false)
@@ -873,6 +878,7 @@
 
 rootpaerror_t buildXmlTrustletInstallationRequest(const char** responseP, trustletInstallationData_t data )
 {
+    char intBuffer[11];
     LOGD(">>buildXmlTrustletInstallationRequest %ld (%ld %d %d)", (long int) responseP, (long int) data.dataP, data.dataLength, data.dataType);
     rootpaerror_t ret=ROOTPA_OK;
     if(NULL ==  responseP) return ROOTPA_ERROR_ILLEGAL_ARGUMENT; // data content checked earlier in commandhandler.c
@@ -888,18 +894,65 @@
     char* encodedDataP=base64EncodeAddEndZero((char*) data.dataP, data.dataLength);
     if(NULL==encodedDataP)
     {
-        LOGE("buildXmlTrustletInstallationRequest: base64 encoding failed");
+        LOGE("buildXmlTrustletInstallationRequest: base64 encoding of data failed");
         return ROOTPA_ERROR_INTERNAL;
     }
     
     if(data.dataType == REQUEST_DATA_TLT)
     {
-        mcDataNode = xmlNewChild(systemInfoNode, nameSpace_, BAD_CAST "tltBinary", BAD_CAST encodedDataP);
+        mcDataNode = xmlNewChild(systemInfoNode, nameSpace_, BAD_CAST "trustletAxf", BAD_CAST encodedDataP);
+        if(data.memoryType != DEFAULT_MEMORY_TYPE)
+        {
+            sprintf(intBuffer,"%d",data.memoryType);
+            if(xmlNewProp(mcDataNode, BAD_CAST "memoryType", BAD_CAST intBuffer)==NULL)
+            {
+                free(encodedDataP);
+                return ROOTPA_ERROR_XML;
+            }
+        }
+
+        if(data.numberOfInstances != DEFAULT_NUMBER_OF_INSTANCES)
+        {
+            sprintf(intBuffer,"%d",data.numberOfInstances);
+            if(xmlNewProp(mcDataNode, BAD_CAST "numberOfInstances", BAD_CAST intBuffer)==NULL)
+            {
+                free(encodedDataP);
+                return ROOTPA_ERROR_XML;
+            }
+        }
+
+        if(data.flags != DEFAULT_FLAGS)
+        {
+            sprintf(intBuffer,"%d",data.flags);                        
+            if(xmlNewProp(mcDataNode, BAD_CAST "flags", BAD_CAST intBuffer)==NULL)
+            {
+                free(encodedDataP);
+                return ROOTPA_ERROR_XML;
+            }
+        }
     }
     else
     {
-        mcDataNode = xmlNewChild(systemInfoNode, nameSpace_, BAD_CAST "tltEncryptionKey", BAD_CAST encodedDataP);        
+        mcDataNode = xmlNewChild(systemInfoNode, nameSpace_, BAD_CAST "trustletEncryptionKey", BAD_CAST encodedDataP);        
     }
+    
+    sprintf(intBuffer,"%d",data.minTltVersion);
+    if(xmlNewProp(mcDataNode, BAD_CAST "minTltVersion", BAD_CAST intBuffer)==NULL)
+    {
+        free(encodedDataP);
+        return ROOTPA_ERROR_XML;
+    }
+    
+    char* pukHashStringP=base64EncodeAddEndZero((char*) data.tltPukHashP, data.tltPukHashLength);
+    if(NULL==pukHashStringP)
+    {
+        LOGE("buildXmlTrustletInstallationRequest: base64 encoding of PukHash failed");
+        free(encodedDataP);        
+        return ROOTPA_ERROR_INTERNAL;
+    }
+    if(xmlNewProp(mcDataNode, BAD_CAST "tltPukHash", BAD_CAST pukHashStringP)==NULL) return ROOTPA_ERROR_XML;
+
+    free(pukHashStringP);
     free(encodedDataP);
     if(NULL==mcDataNode) return ROOTPA_ERROR_XML;
     
diff --git a/rootpa/Test/Android/RootPAClient/res/values/version.xml b/rootpa/Test/Android/RootPAClient/res/values/version.xml
index a943b2a..d91fbcb 100644
--- a/rootpa/Test/Android/RootPAClient/res/values/version.xml
+++ b/rootpa/Test/Android/RootPAClient/res/values/version.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-    <string name="name">1.0003 (34387)</string>
-    <integer name="code">0x10003</integer>
+    <string name="name">2.0025 (37085)</string>
+    <integer name="code">0x20019</integer>
 </resources>
diff --git a/rootpa/Test/Android/RootPAClient/src/com/gd/mobicore/pa/service/Test/RootPAClient.java b/rootpa/Test/Android/RootPAClient/src/com/gd/mobicore/pa/service/Test/RootPAClient.java
index f3b9abf..33836a5 100755
--- a/rootpa/Test/Android/RootPAClient/src/com/gd/mobicore/pa/service/Test/RootPAClient.java
+++ b/rootpa/Test/Android/RootPAClient/src/com/gd/mobicore/pa/service/Test/RootPAClient.java
@@ -128,13 +128,14 @@
             psintent.putExtra("LOG", loggingLevel);        
             bindService(psintent, provisioningServiceConnection_, Context.BIND_AUTO_CREATE);
             provisioningServiceIsBound_=true;
+            callCounter_++;            
         
             Intent dsintent=new Intent(RootPAProvisioningIntents.DEVELOPER_SERVICE);
             dsintent.putExtra("SE", address);
             dsintent.putExtra("LOG", loggingLevel);
             bindService(dsintent, developerServiceConnection_, Context.BIND_AUTO_CREATE);       
             developerServiceIsBound_=true;
-            callCounter_++;            
+            callCounter_++;
 
             Intent osintent=new Intent(RootPAProvisioningIntents.OEM_SERVICE);
             osintent.putExtra("SE", address);
diff --git a/rootpa/Test/Android/RootPAClient/src/com/gd/mobicore/pa/service/Test/TestDeveloperService.java b/rootpa/Test/Android/RootPAClient/src/com/gd/mobicore/pa/service/Test/TestDeveloperService.java
index 89fe741..0b266c4 100755
--- a/rootpa/Test/Android/RootPAClient/src/com/gd/mobicore/pa/service/Test/TestDeveloperService.java
+++ b/rootpa/Test/Android/RootPAClient/src/com/gd/mobicore/pa/service/Test/TestDeveloperService.java
@@ -57,6 +57,7 @@
     RootPADeveloperIfc developerServiceIfc_=null;
     private static final String TESTTAG = "RootPA-Test";
     private static final String TAG = "RootPA-T";
+    private byte[] pukHash_={1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2};
     
     RootPAClient parent_=null;
     TestDeveloperService(RootPAClient parent){
@@ -181,7 +182,7 @@
     // installTrustlet, trustlet binary
         
         try{
-            tret=developerServiceIfc_.installTrustlet(TLT_INSTALL_TEST_SPID, CmpTest.TLTUUID, TEST_TRUSTLET, null);
+            tret=developerServiceIfc_.installTrustlet(TLT_INSTALL_TEST_SPID, CmpTest.TLTUUID, TEST_TRUSTLET, 1, pukHash_, 1, 3, 4);
         }catch(Throwable e){
             logi = logi.concat("FAILURE: call to installTrustlet with trustlet failed: " + e + "\n");
             overallsuccess=false;
@@ -212,7 +213,7 @@
         
         done_=false; // another call
         try{
-            kret=developerServiceIfc_.installTrustlet(TLT_INSTALL_TEST_SPID, CmpTest.TLTUUID, null, TEST_KEY);
+            kret=developerServiceIfc_.installTrustletOrKey(TLT_INSTALL_TEST_SPID, CmpTest.TLTUUID, null, TEST_KEY, 1, pukHash_);
         }catch(Throwable e){
             logi = logi.concat("FAILURE: call to installTrustlet with key failed: " + e + "\n");
             overallsuccess=false;
@@ -254,7 +255,7 @@
     // error cases
         CommandResult err1ret=new CommandResult(0x0FFF0000);
         try{
-            err1ret=developerServiceIfc_.installTrustlet(TLT_INSTALL_TEST_SPID, CmpTest.TLTUUID, TEST_TRUSTLET, TEST_KEY);
+            err1ret=developerServiceIfc_.installTrustletOrKey(TLT_INSTALL_TEST_SPID, CmpTest.TLTUUID, TEST_TRUSTLET, TEST_KEY, 1, pukHash_);
         }catch(Throwable e){
             logi = logi.concat("FAILURE: call to installTrustlet with trustlet failed: " + e + "\n");
             overallsuccess=false;
@@ -263,7 +264,7 @@
         CommandResult err2ret=new CommandResult(0x0FFF0000);
         
         try{
-            err2ret=developerServiceIfc_.installTrustlet(TLT_INSTALL_TEST_SPID, CmpTest.TLTUUID, null, null);
+            err2ret=developerServiceIfc_.installTrustletOrKey(TLT_INSTALL_TEST_SPID, CmpTest.TLTUUID, null, null, 1, pukHash_);
         }catch(Throwable e){
             logi = logi.concat("FAILURE: call to installTrustlet with trustlet failed: " + e + "\n");
             overallsuccess=false;
diff --git a/rootpa/Test/Linux/commonClient/Makefile b/rootpa/Test/Linux/commonClient/Makefile
index 23679e5..afead74 100755
--- a/rootpa/Test/Linux/commonClient/Makefile
+++ b/rootpa/Test/Linux/commonClient/Makefile
@@ -53,7 +53,8 @@
 VALGRIND=valgrind
 VALGRINDPARAMS=-v  --leak-check=full  --show-reachable=yes --track-origins=yes
 
-CFLAGS= -Wall -D_GNU_SOURCE   # -D_GNU_SOURCE is here for removing warnings and making sure strcasestr works properly
+CFLAGS= -Wall -D_GNU_SOURCE # -D_GNU_SOURCE is here for removing warnings and making sure strcasestr works properly
+CFLAGS+= -Wall -D__DEBUG 
 
 LDFLAGS=rcs
 INCDIR=-I../../../Code/Common/include -I/usr/include/libxml2 -I/usr/include/curl -I$(TLSDK)/Out/Public/MobiCore/inc -I$(TLCM)/Out/Public -I$(MOBICOREDRIVERLIB)/Out/Public
diff --git a/rootpa/Test/Linux/commonClient/rootpaclient.cpp b/rootpa/Test/Linux/commonClient/rootpaclient.cpp
index b9ee744..31d8105 100755
--- a/rootpa/Test/Linux/commonClient/rootpaclient.cpp
+++ b/rootpa/Test/Linux/commonClient/rootpaclient.cpp
@@ -66,7 +66,7 @@
 static const int EXPECTED_SP_CONT_STATE =  MC_CONT_STATE_SP_LOCKED;  // 4

 static const int EXPECTED_TLT_CONT_STATE =  MC_CONT_STATE_SP_LOCKED;  // 4

 static const mcUuid_t EXPECTED_TLT_ID={{0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06}};

-

+static const int WAIT_TIMEOUT=15;

 static bool testStatus_=true;

 

 #define STATES_DONE_IDX 0

@@ -168,7 +168,7 @@
     if(false==result)

     {

         cout << "==== FAILURE: "<< testCase << "\n";

-        testStatus_ = false;        

+        testStatus_ = false;

     }

     else

     {

@@ -185,7 +185,7 @@
 int main(int argc, char* argv[] )

 {   

 //    printSizes();

-    setPaths("./", "./");

+    setPaths(".", ".");

     checkResult(setSeAddress(SEADDRESS, sizeof(SEADDRESS)),"setSeAddress");

     

     checkResult(openSessionToCmtl(), "openSessionToCmtl");

@@ -247,34 +247,56 @@
     memset(states_,0,NUMBER_OF_STATES);

     if(checkResult(doProvisioning(spid, stateCallback, sysInfoCallback),"doProvisioning"))

     {

-        checkResult(waitUntilDone(4), "doProvisioning, waitUntilDone");

-        statesOkProvisioning();

+        checkResult(waitUntilDone(WAIT_TIMEOUT), "doProvisioning, waitUntilDone");

+        if(!statesOkProvisioning())

+        {

+            testStatus_=false;

+        }

     }

 

     memset(states_,0,NUMBER_OF_STATES);

     if(checkResult(unregisterRootContainer(stateCallback, sysInfoCallback),"unregisterRootContainer"))

     {

-        checkResult(waitUntilDone(4), "unregisterRootContainer, waitUntilDone");

-        statesOkDelete();

+        checkResult(waitUntilDone(WAIT_TIMEOUT), "unregisterRootContainer, waitUntilDone");

+        if(!statesOkDelete())

+        {

+            testStatus_=false;

+        }

     }

 

     trustletInstallationData_t tltData;

+    memset(&tltData, 0, sizeof(tltData));

     tltData.dataP=(uint8_t*)"AAAAAAAAAABBBBBBBBBBCCCCCCCCCC";

     tltData.dataLength=30;

     tltData.dataType=REQUEST_DATA_TLT;

+    memcpy(&tltData.uuid, &EXPECTED_TLT_ID,sizeof(EXPECTED_TLT_ID));    

+    tltData.minTltVersion=1;

+    tltData.tltPukHashP=(uint8_t*)"DDDDDDDDDDEEEEEEEEEEFFFFFFFFFF00";

+    tltData.tltPukHashLength=32;

+    tltData.memoryType=2;

+    tltData.numberOfInstances=1;

+    tltData.flags=0;

+

+    

     memset(states_,0,NUMBER_OF_STATES);

     if(checkResult(installTrustlet(spid, stateCallback, sysInfoCallback, &tltData),"installTrustlet tlt"))

     {

-        checkResult(waitUntilDone(4), "installTrustlet tlt, waitUntilDone");

-        statesOkInstall();

+        checkResult(waitUntilDone(WAIT_TIMEOUT), "installTrustlet tlt, waitUntilDone");

+        if(!statesOkInstall())

+        {

+            testStatus_=false;

+        }            

     }

 

     tltData.dataType=REQUEST_DATA_KEY; // since we are not dealing with real data we use the same for both

     memset(states_,0,NUMBER_OF_STATES);

     if(checkResult(installTrustlet(spid, stateCallback, sysInfoCallback, &tltData),"installTrustlet key"))

     {

-        checkResult(waitUntilDone(4), "installTrustlet key, waitUntilDone");

-        statesOkProvisioning(); // not checking install state since the tlt will not be sent back

+        checkResult(waitUntilDone(WAIT_TIMEOUT), "installTrustlet key, waitUntilDone");

+        if(!statesOkProvisioning()) // not checking install state since the tlt will not be sent back

+        {

+            testStatus_=false;

+        }            

     }

 

     CmpMessage* commandsP=NULL;

@@ -284,7 +306,10 @@
     if(checkResult( executeCmpCommands(numberOfCommands, commandsP, responsesP, &internalError),"executeCmpCommands" ))

     {

         checkResult( 0==internalError,"executeCmpCommands, internalError");

-        testStatus_=checkCmpResults(numberOfCommands, responsesP);

+        if(checkCmpResults(numberOfCommands, responsesP)==false)

+        {

+            testStatus_=false;

+        }            

     }

     cleanup(numberOfCommands, commandsP, responsesP);

     

diff --git a/rootpa/Test/Misc/httpd.conf b/rootpa/Test/Misc/httpd.conf
index 74555df..cdb4921 100755
--- a/rootpa/Test/Misc/httpd.conf
+++ b/rootpa/Test/Misc/httpd.conf
@@ -32,7 +32,7 @@
 
 
 # intial POST/Install uses this
-<Location /00000000445566778899aabbccddeeff/10/03030303040404040505050506060606>
+<Location /00000000445566778899aabbccddeeff/10/03030303-0404-0404-0505-050506060606>
     Header set Link <http://10.0.2.2/activity/00000000-4455-6677-8899-aabbccddee00>;rel="http://10.0.2.2/relation/command_result"
     SetHandler perl-script
     PerlResponseHandler ReceiveDeleteCommand
diff --git a/rootpa/Test/Misc/setupApache.sh b/rootpa/Test/Misc/setupApache.sh
index 3e9d641..032062b 100755
--- a/rootpa/Test/Misc/setupApache.sh
+++ b/rootpa/Test/Misc/setupApache.sh
@@ -24,12 +24,12 @@
 
 apache2-ssl-certificate
 
-# This should be taken care of when ssl module is take into use. If problems, you may need to check and add to /etc/apache2/ports.conf
-# Listen 443
+# This should be taken care of when ssl module is take into use. If problems,
+# you may need to check and add to /etc/apache2/ports.conf "Listen 443"
 
 # always after adding modules, configuring or even changing script you need to restart 
 # apache for example with command
 
 apache2ctl restart
 
-./configureApache.sh
\ No newline at end of file
+./configureApache.sh