manta: add MobiCore userspace daemon and libraries

Change-Id: Ide5a137050bf384a5409bec6806018ae84d34767
Signed-off-by: DongJin Park <djpax.park@samsung.com>
diff --git a/Android.mk b/Android.mk
index 3656a1e..399a89a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -29,7 +29,8 @@
 	libv4l2 \
 	libhwjpeg \
 	libhwc \
-	libcamera2
+	libcamera2 \
+	mobicore
 
 BOARD_USE_V4L2 := true
 BOARD_USE_V4L2_ION := true
diff --git a/exynos5.mk b/exynos5.mk
index ecef01b..2776260 100644
--- a/exynos5.mk
+++ b/exynos5.mk
@@ -30,3 +30,11 @@
 # hw composer HAL
 PRODUCT_PACKAGES += \
 	hwcomposer.exynos5
+
+# MobiCore
+PRODUCT_PACKAGES += \
+	libMcClient \
+	libMcRegistry \
+	libPaApi \
+	mcDriverDaemon \
+	gdmcprov
diff --git a/mobicore/Android.mk b/mobicore/Android.mk
new file mode 100755
index 0000000..9d7f28c
--- /dev/null
+++ b/mobicore/Android.mk
@@ -0,0 +1,25 @@
+# =============================================================================
+#
+# Makefile pointing to all makefiles within the project.
+#
+# =============================================================================
+MOBICORE_PROJECT_PATH := $(call my-dir)
+# Setup common variables
+COMP_PATH_Logwrapper := $(MOBICORE_PROJECT_PATH)/common/LogWrapper
+COMP_PATH_MobiCore := $(MOBICORE_PROJECT_PATH)/common/MobiCore
+COMP_PATH_MobiCoreDriverMod := $(MOBICORE_PROJECT_PATH)/include
+
+
+# Include the Daemon
+include $(MOBICORE_PROJECT_PATH)/daemon/Android.mk
+
+MC_INCLUDE_DIR := $(COMP_PATH_MobiCore)/inc \
+    $(COMP_PATH_MobiCore)/inc/TlCm \
+    $(MOBICORE_PROJECT_PATH)/daemon/ClientLib/public \
+    $(MOBICORE_PROJECT_PATH)/daemon/Registry/Public
+MC_DEBUG := _DEBUG
+SYSTEM_LIB_DIR=/system/lib
+GDM_PROVLIB_SHARED_LIBS=libMcClient
+# Include the provisioning lib
+include $(MOBICORE_PROJECT_PATH)/provlib/Android.mk
+
diff --git a/mobicore/common/LogWrapper/Android.mk b/mobicore/common/LogWrapper/Android.mk
new file mode 100644
index 0000000..b869c2b
--- /dev/null
+++ b/mobicore/common/LogWrapper/Android.mk
@@ -0,0 +1,15 @@
+# =============================================================================
+#
+# MobiCore log wrapper to be included by Android components / products
+#
+# =============================================================================
+
+# This is not a separate module.
+# Only for inclusion by other modules.
+
+LOCAL_SHARED_LIBRARIES += liblog
+
+# Enable logging to logcat per default
+LOCAL_CFLAGS += -DLOG_ANDROID
+
+LOCAL_C_INCLUDES += $(call my-dir)
\ No newline at end of file
diff --git a/mobicore/common/LogWrapper/log.h b/mobicore/common/LogWrapper/log.h
new file mode 100644
index 0000000..f289b73
--- /dev/null
+++ b/mobicore/common/LogWrapper/log.h
@@ -0,0 +1,191 @@
+/** Log wrapper for Android.
+ * @{
+ * @file
+ *
+ * Maps LOG_*() macros to __android_log_print() if LOG_ANDROID is defined.
+ * Adds some extra info to log output like LOG_TAG, file name and line number.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2010 - 2011 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef TLCWRAPPERANDROIDLOG_H_
+#define TLCWRAPPERANDROIDLOG_H_
+
+#include <unistd.h>
+#include <stdio.h>
+#include <android/log.h>
+
+
+#define EOL "\n"
+#define DUMMY_FUNCTION()    do{}while(0)
+
+
+#ifdef LOG_ANDROID
+
+#ifdef NDEBUG
+    #define LOG_I(fmt, args...) DUMMY_FUNCTION()
+    #define LOG_W(fmt, args...) DUMMY_FUNCTION()
+#else
+    #define LOG_I(fmt, args...) LOG_i("%d : "fmt , __LINE__ , ## args)
+    #define LOG_W(fmt, args...) LOG_w("%d : "fmt , __LINE__ , ## args)
+#endif
+    #define _LOG_E(fmt, args...) LOG_e("%d : "fmt , __LINE__ , ## args)
+
+    #define LOG_i(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
+    #define LOG_w(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
+    #define LOG_e(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+
+#else //!defined(LOG_ANDROID)
+
+    // #level / #LOG_TAG ( process_id): __VA_ARGS__
+    // Example:
+    // I/McDrvBasicTest_0_1( 4075): setUp
+    #define _LOG_x(_x_,...) \
+                do \
+                { \
+                    printf("%s/%s(%d): ",_x_,LOG_TAG,getpid()); \
+                    printf(__VA_ARGS__); \
+                    printf(EOL); \
+                } while(1!=1)
+
+
+#ifdef NDEBUG
+    #define LOG_I(fmt, args...) DUMMY_FUNCTION()
+    #define LOG_W(fmt, args...) DUMMY_FUNCTION()
+#else
+    #define LOG_I(...)  _LOG_x("I",__VA_ARGS__)
+    #define LOG_W(...)  _LOG_x("W",__VA_ARGS__)
+#endif
+    #define _LOG_E(...)  _LOG_x("E",__VA_ARGS__)
+
+#endif //defined(LOG_ANDROID)
+
+
+/** LOG_E() needs to be more prominent:
+ * Display "*********** ERROR ***********" before actual error message.
+ */
+#define LOG_E(...) \
+            do \
+            { \
+                _LOG_E("*****************************"); \
+                _LOG_E("*********   ERROR   *********"); \
+                _LOG_E(__VA_ARGS__); \
+            } while(1!=1)
+
+
+#define LOG_I_BUF   LOG_I_Buf
+
+__attribute__ ((unused))
+static void LOG_I_Buf(
+	const char *  szDescriptor,
+	const void *  blob,
+	size_t        sizeOfBlob
+) {
+
+	#define CPL         0x10  // chars per line
+	#define OVERHEAD    20
+
+	char buffer[CPL * 4 + OVERHEAD];
+
+	uint32_t index = 0;
+
+	uint32_t moreThanOneLine = (sizeOfBlob > CPL);
+	uint32_t blockLen = CPL;
+	uint32_t addr = 0;
+	uint32_t i = 0;
+
+	if (NULL != szDescriptor)
+	{
+		index += sprintf(&buffer[index], "%s", szDescriptor);
+	}
+
+	if (moreThanOneLine)
+	{
+		if (NULL == szDescriptor)
+		{
+			index += sprintf(&buffer[index], "memory dump");
+		}
+		index += sprintf(&buffer[index], " (0x%08x, %d bytes)", (uint32_t)blob,sizeOfBlob);
+		LOG_I("%s", buffer);
+		index = 0;
+	}
+	else if (NULL == szDescriptor)
+	{
+		index += sprintf(&buffer[index], "Data at 0x%08x: ", (uint32_t)blob);
+	}
+
+	if(sizeOfBlob == 0) {
+		LOG_I("%s", buffer);
+	}
+	else
+	{
+		while (sizeOfBlob > 0)
+		{
+			if (sizeOfBlob < blockLen)
+			{
+				blockLen = sizeOfBlob;
+			}
+
+			// address
+			if (moreThanOneLine)
+			{
+				index += sprintf(&buffer[index], "0x%08X | ",addr);
+				addr += CPL;
+			}
+			// bytes as hex
+			for (i=0; i<blockLen; ++i)
+			{
+				index += sprintf(&buffer[index], "%02x ", ((const char *)blob)[i] );
+			}
+			// spaces if necessary
+			if ((blockLen < CPL) && (moreThanOneLine))
+			{
+				// add spaces
+				for (i=0; i<(3*(CPL-blockLen)); ++i) {
+				index += sprintf(&buffer[index], " ");
+				}
+			}
+			// bytes as ASCII
+			index += sprintf(&buffer[index], "| ");
+			for (i=0; i<blockLen; ++i)
+			{
+				char c = ((const char *)blob)[i];
+				index += sprintf(&buffer[index], "%c",(c>32)?c:'.');
+			}
+
+			blob = &(((const char *)blob)[blockLen]);
+			sizeOfBlob -= blockLen;
+
+			// print line to logcat / stdout
+			LOG_I("%s", buffer);
+			index = 0;
+		}
+	}
+}
+
+#endif /** TLCWRAPPERANDROIDLOG_H_ */
+
+/** @} */
diff --git a/mobicore/common/MobiCore/inc/Mci/mci.h b/mobicore/common/MobiCore/inc/Mci/mci.h
new file mode 100644
index 0000000..6bd6f10
--- /dev/null
+++ b/mobicore/common/MobiCore/inc/Mci/mci.h
@@ -0,0 +1,96 @@
+/** @mainpage MobiCore Control Interface - MCI
+ *
+ * <h2>Introduction</h2>
+ * The MobiCore Control Interface (MCI) is the interface for integrating G&D MobiCore technology into the
+ * rich operating system running in the non-secure part of an ARM TrustZone enabled platform.
+ *
+ * <h2>Interface overview</h2>
+ * The Structure of the MobiCore control interface is depicted in the figure below:
+ * @image html DoxyOverviewMci500x.png "MobiCore control interface"
+ * @image latex DoxyOverviewMci500x.png "MobiCore control interface" width=12cm
+ *
+ * The MCI is composed of the following interfaces:
+ * <ul>
+ *
+ * <li><b>MobiCore control protocol (MCP) interface.</b></li><br>
+ * The MCP interface is responsible for the main communicating with the MobiCore. This involves sending commands for starting
+ * and stopping of Trustlets as well as checking their corresponding answers. MCP information is exchanged in a
+ * world shared memory buffer which needs to be initially established between NWd and SWd using the FastCall interface.<br>
+ *
+ * <li><b>Notification queue interface.</b></li><br>
+ * Notifications inform the MobiCore runtime environment that information is pending in a WSM buffer.
+ * The Trustlet Connector (TLC) and the corresponding Trustlet also utilize this buffer to
+ * notify each other about new data within the Trustlet Connector Interface (TCI). Therefore the TLC writes
+ * a notification including the session ID to the buffer. The driver informs the MobiCore
+ * about the availability of a notification with the use of a SIQ. On the secure side the Runtime Management
+ * notifies the Trustlet, according to the given session ID, about the availability of new data.
+ * The same mechanism is used vice versa for writing data back to the None-secure world.
+ *
+ * <li><b>FastCall interface.</b></li><br>
+ * The FastCall interface of the MobiCore system is used to transfer control from the Non-secure World (NWd) to the
+ * Secure World (SWd) and back. There are three mechanisms the NWd shall use to interact with the MobiCore Monitor:
+ * FastCall, N-SIQ and NQ-IRQ (Notification IRQ). FastCall and N-SIQ operations are used to hand over control
+ * to the MobiCore. Both functions make use of the SMC [ARM11] operation.
+ *
+ * </ul>
+ *
+ * You can find more information about the interfaces in the respective modules description.
+ *
+ * <h2>Version history</h2>
+ * <table class="customtab">
+ * <tr><td width="100px"><b>Date</b></td><td width="80px"><b>Version</b></td><td><b>Changes</b></td></tr>
+ * <tr><td>2009-06-25</td><td>0.1</td><td>Initial Release</td></tr>
+ * <tr><td>2009-07-01</td><td>0.2</td><td>Major rewrite</td></tr>
+ * <tr><td>2009-08-06</td><td>0.3</td><td>Added documentation for FastCall helper functions</td></tr>
+ * <tr><td>2009-09-10</td><td>0.4</td><td>Update of constant naming. Modification of doxygen config.</td></tr>
+ * <tr><td>2010-03-09</td><td>0.5</td><td>Added fastCallPower() helper function for MC_FC_POWER.</td></tr> 
+ * <tr><td>2010-05-10</td><td>0.6</td><td>Restructuring of load format header.</td></tr>
+ * <tr><td>2011-07-19</td><td>0.7</td><td>update to reflect current code changes.</td></tr> 
+ * </table>
+ *
+ *
+ * @file
+ * @defgroup FCI    FastCall Interface
+ *
+ * @defgroup NQ     Notification Queue
+ *
+ * @defgroup MCP    MobiCore Control Protocol
+ *
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef MCI_H_
+#define MCI_H_
+
+#include "version.h"
+#include "mcifc.h"
+#include "mcinq.h"
+#include "mcimcp.h"
+
+#endif /** MCI_H_ */
+
+/** @} */
diff --git a/mobicore/common/MobiCore/inc/Mci/mcifc.h b/mobicore/common/MobiCore/inc/Mci/mcifc.h
new file mode 100644
index 0000000..696e41c
--- /dev/null
+++ b/mobicore/common/MobiCore/inc/Mci/mcifc.h
@@ -0,0 +1,129 @@
+/** @addtogroup FCI
+ * @{
+ * @file
+ * FastCall declarations.
+ *
+ * Holds the functions for SIQ, YIELD and FastCall for switching to the secure world.
+ * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef MCIFC_H_
+#define MCIFC_H_
+
+/** @name MobiCore FastCall Defines
+ * Defines for the two different FastCall's.
+ */
+/** @{ */
+
+// --- global ----
+#define MC_FC_INVALID                ((uint32_t)  0 )  /**< Invalid FastCall ID */
+#define MC_FC_INIT                   ((uint32_t)(-1))  /**< Initializing FastCall. */
+#define MC_FC_INFO                   ((uint32_t)(-2))  /**< Info FastCall. */
+
+// following defines are currently frozen, so they will candidate for later big-change
+// --- sleep modes ---
+#define MC_FC_SLEEP                  ((uint32_t)(-3))  /**< enter power-sleep */
+#define MC_FC_AFTR                   ((uint32_t)(-5))  /**< enter AFTR-sleep (called from core-0) */
+// --- wake-up access ---
+#define MC_FC_CORE_X_WAKEUP          ((uint32_t)(-4))  /**< wakeup/boot core-x (optional core-number in r1, not "0" ) */
+#define MC_FC_C15_RESUME             ((uint32_t)(-11)) /**< Write power control & diag registers */
+#define MC_FC_CMD_SAVE               ((uint32_t)(-6))  /**< Save core context to CP15 table(r1 is core number) */
+#define MC_FC_CMD_SHUTDOWN           ((uint32_t)(-7))  /**< Shutdown core(r1 is core number, cache flush is expected) */
+// --- L2 cache access ---
+#define MC_FC_L2X0_CTRL             ((uint32_t)(-21))  /**< Write to L2X0 control register */
+#define MC_FC_L2X0_SETUP1           ((uint32_t)(-22))  /**< Setup L2X0 register - part 1 */
+#define MC_FC_L2X0_SETUP2           ((uint32_t)(-23))  /**< Setup L2X0 register - part 2 */
+#define MC_FC_L2X0_INVALL           ((uint32_t)(-24))  /**< Invalidate all L2 cache */
+#define MC_FC_L2X0_DEBUG            ((uint32_t)(-25))  /**< Write L2X0 debug register */
+// --- MEM traces ---
+#define MC_FC_MEM_TRACE             ((uint32_t)(-31))  /**< Enable SWd tracing via memory */
+// --- write access to CP15 regs ---
+#define MC_FC_CP15_REG             ((uint32_t)(-101))  /**< general CP15/cache register update */
+// --- store value in sDDRRAM ---
+#define MC_FC_STORE_BINFO          ((uint32_t)(-201))  /**< write a 32bit value in secure DDRRAM in incremented art (max 2kB) */
+
+#define MC_FC_MAX_ID         ((uint32_t)(0xFFFF0000))  /**< Maximum allowed FastCall ID */
+
+// r1 is requested status (0,1,2), on return r2 holds this status value
+
+/** @} */
+
+/** @name MobiCore SMC Defines
+ * Defines the different secure monitor calls (SMC) for world switching.
+ * @{ */
+#define MC_SMC_N_YIELD     0x3     /**< Yield to switch from NWd to SWd. */
+#define MC_SMC_N_SIQ       0x4     /**< SIQ to switch from NWd to SWd. */
+/** @} */
+
+/** @name MobiCore status
+ *  MobiCore status information.
+ * @{ */
+#define MC_STATUS_NOT_INITIALIZED  0   /**< MobiCore is not yet initialized. FastCall FcInit() has to be used function to set up MobiCore.*/
+#define MC_STATUS_BAD_INIT         1   /**< Bad parameters have been passed in FcInit(). */
+#define MC_STATUS_INITIALIZED      2   /**< MobiCore did initialize properly. */
+#define MC_STATUS_HALT             3   /**< MobiCore kernel halted due to an unrecoverable exception. Further information is available extended info */
+/** @} */
+
+/** @name Extended Info Identifiers
+ *  Extended info parameters for MC_FC_INFO to obtain further information depending on MobiCore state.
+ * @{ */
+#define MC_EXT_INFO_ID_MCI_VERSION      0 /**< Version of the MobiCore Control Interface (MCI) */
+#define MC_EXT_INFO_ID_FLAGS            1 /**< MobiCore control flags */
+#define MC_EXT_INFO_ID_HALT_CODE        2 /**< MobiCore halt condition code */
+#define MC_EXT_INFO_ID_HALT_IP          3 /**< MobiCore halt condition instruction pointer */
+#define MC_EXT_INFO_ID_FAULT_CNT        4 /**< MobiCore fault counter */
+#define MC_EXT_INFO_ID_FAULT_CAUSE      5 /**< MobiCore last fault cause */
+#define MC_EXT_INFO_ID_FAULT_META       6 /**< MobiCore last fault meta */
+#define MC_EXT_INFO_ID_FAULT_THREAD     7 /**< MobiCore last fault threadid */
+#define MC_EXT_INFO_ID_FAULT_IP         8 /**< MobiCore last fault instruction pointer */
+#define MC_EXT_INFO_ID_FAULT_SP         9 /**< MobiCore last fault stack pointer */
+#define MC_EXT_INFO_ID_FAULT_ARCH_DFSR  10 /**< MobiCore last fault ARM arch information */
+#define MC_EXT_INFO_ID_FAULT_ARCH_ADFSR 11 /**< MobiCore last fault ARM arch information */
+#define MC_EXT_INFO_ID_FAULT_ARCH_DFAR  12 /**< MobiCore last fault ARM arch information */
+#define MC_EXT_INFO_ID_FAULT_ARCH_IFSR  13 /**< MobiCore last fault ARM arch information */
+#define MC_EXT_INFO_ID_FAULT_ARCH_AIFSR 14 /**< MobiCore last fault ARM arch information */
+#define MC_EXT_INFO_ID_FAULT_ARCH_IFAR  15 /**< MobiCore last fault ARM arch information */
+#define MC_EXT_INFO_ID_MC_CONFIGURED    16 /**< MobiCore configured by Daemon via fc_init flag */
+#define MC_EXT_INFO_ID_MC_SCHED_STATUS  17 /**< MobiCore scheduling status: idle/non-idle */
+#define MC_EXT_INFO_ID_MC_STATUS        18 /**< MobiCore runtime status: initialized, halted */
+#define MC_EXT_INFO_ID_MC_EXC_PARTNER   19 /**< MobiCore exception handler last partner */
+#define MC_EXT_INFO_ID_MC_EXC_IPCPEER   20 /**< MobiCore exception handler last peer */
+#define MC_EXT_INFO_ID_MC_EXC_IPCMSG    21 /**< MobiCore exception handler last IPC message */
+#define MC_EXT_INFO_ID_MC_EXC_IPCDATA   22 /**< MobiCore exception handler last IPC data */
+
+/** @} */
+
+/** @name FastCall return values
+ * Return values of the MobiCore FastCalls.
+ * @{ */
+#define MC_FC_RET_OK                       0     /**< No error. Everything worked fine. */
+#define MC_FC_RET_ERR_INVALID              1     /**< FastCall was not successful. */
+#define MC_FC_RET_ERR_ALREADY_INITIALIZED  5     /**< MobiCore has already been initialized. */
+/** @} */
+
+#endif /** MCIFC_H_ */
+
+/** @} */
diff --git a/mobicore/common/MobiCore/inc/Mci/mcifcfunc.h b/mobicore/common/MobiCore/inc/Mci/mcifcfunc.h
new file mode 100644
index 0000000..69fbbc1
--- /dev/null
+++ b/mobicore/common/MobiCore/inc/Mci/mcifcfunc.h
@@ -0,0 +1,187 @@
+/** @addtogroup FCI
+ * @{
+ * @file
+ * Declaration of FastCall helper functions.
+ *
+ * @attention Helper functions are mostly RealView (ARM CC) specific.
+ *
+ * Holds the functions for SIQ, YIELD and FastCall for switching to the secure world.
+ * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MCIFCFUNC_H_
+#define MCIFCFUNC_H_
+
+#include "mcifc.h"
+/**
+ * Execute a secure monitor call (SMC).
+ *
+ * @param mode SMC mode affects the way SMC is handled
+ *
+ * @attention This function shall not be used directly. Use N_Siq() or Yield() instead.
+ */
+__smc(0) void smc(int32_t mode);
+
+/**
+ * N-SIQ switch from NWd to SWd.
+ * Execution will continue in the SWd. The notification queue will be drained by the MC4 and MC4 system schedules its services.
+ */
+inline void N_Siq(void) { smc(MC_SMC_N_SIQ); }
+
+/**
+ * Yield switch from NWd to SWd.
+ * Execution will continue in the SWd without scheduling MC4 services.
+ */
+inline void Yield(void) { smc(MC_SMC_N_YIELD); }
+
+/** Wrapper structure for parameter passing in registers.
+ *  This structure is used as a "wrapper" return value for functions that
+ *  return data in the registers r0 to r3. With the RealView compiler such
+ *  function are declare as:  _value_in_regs reg_r0_r1_r2_r3_t foo()
+
+ */
+typedef struct {
+    uint32_t r0;
+    uint32_t r1;
+    uint32_t r2;
+    uint32_t r3;
+} reg_r0_r1_r2_r3_t;
+
+/** Parameterized SMC for FastCalls.
+ * @attention This function shall not be used directly.
+ */
+__smc(0) __value_in_regs  reg_r0_r1_r2_r3_t smcFc(
+        uint32_t r0,
+        uint32_t r1,
+        uint32_t r2,
+        uint32_t r3
+);
+
+/** FastCall helper function.
+ * @attention This function shall not be used directly.
+ */
+inline static __value_in_regs reg_r0_r1_r2_r3_t fastCall(
+        uint32_t r0,
+        uint32_t r1,
+        uint32_t r2,
+        uint32_t r3
+) {
+    return smcFc(r0,r1,r2,r3);
+}
+
+/**
+ * Initialize the MobiCore.
+ * The FcMc4init FastCall shall be used to set up the MCI. The function passes the message buffers used in the MCI to the MC4 system.
+ * As long as the buffers are not set up the MC4 message passing mechanisms (notifications, MCP commands) are not available.
+ * NQ buffer and MCP buffer as well as length calculations are described in the "MobiCore4 Driver Interface Specification".
+ * <br> The fastCallInit() will not check the parameters for validity. Instead the MC4 will perform a check on first usage of the parameters.
+ *
+ * @image html DoxyMciBuffer.png "MCI buffer"
+ * @image latex DoxyMciBuffer.png "MCI buffer" width=12cm
+ *
+ * @param base      Physical start address of the MCI buffer. Must be 4kB aligned.
+ * @param nqOffset  Offset in bytes  to the beginning of the NQ buffer.
+ * @param nqLength  Length of the NQ buffer in bytes.
+ * @param mcpOffset Offset in bytes to the beginning of the MCP buffer.
+ * @param mcpLength Length of the MCP buffer in bytes
+ *
+ */
+inline static uint32_t fastCallInit(
+        uint8_t *base,
+        uint32_t  nqOffset,
+        uint32_t  nqLength,
+        uint32_t  mcpOffset,
+        uint32_t  mcpLength
+) {
+
+    reg_r0_r1_r2_r3_t ret;
+
+    ret = fastCall(
+            MC_FC_INIT,
+            (uint32_t)base,
+            ((nqOffset << 16) | (nqLength & 0xFFFF)),
+            ((mcpOffset << 16) | (mcpLength & 0xFFFF)) );
+
+
+    return ret.r1;
+}
+
+
+/** Get status information about MobiCore.
+ * The FcMcGetInfo FastCall provides information about the current state of the MobiCore.
+ * In certain states extended information is provided.
+ *
+ * @param extInfoId Extended info word to be obtained.
+ * @param mc4state Current state of the MobiCore.
+ * @param extInfo Extended information depending on state.
+ */
+inline static uint32_t fastCallGetInfo(
+        uint32_t extInfoId,
+        uint32_t *mc4state,
+        uint32_t *extInfo
+) {
+    reg_r0_r1_r2_r3_t ret;
+
+    ret = fastCall(MC_FC_INFO,extInfoId,0,0);
+
+    if (MC_FC_RET_OK == ret.r1)
+    {
+        *mc4state = ret.r2;
+        *extInfo = ret.r3;
+    }
+
+    return ret.r1;
+}
+
+/**
+ * Power management.
+ * The power management FastCall is platform specific.
+ *
+ * @param param0  platform specific parameter.
+ * @param param1  platform specific parameter.
+ * @param param2  platform specific parameter.
+ */
+inline static uint32_t fastCallPower(
+        uint32_t param0,
+        uint32_t param1,
+        uint32_t param2
+) {
+
+    reg_r0_r1_r2_r3_t ret;
+
+    ret = fastCall(
+            MC_FC_POWER,
+            param0,
+            param1,
+            param2 );
+
+    return ret.r1;
+}
+
+#endif /* MCIFCFUNC_H_ */
+/**
+ * @}*/
diff --git a/mobicore/common/MobiCore/inc/Mci/mcimcp.h b/mobicore/common/MobiCore/inc/Mci/mcimcp.h
new file mode 100644
index 0000000..e2eb1b6
--- /dev/null
+++ b/mobicore/common/MobiCore/inc/Mci/mcimcp.h
@@ -0,0 +1,404 @@
+/** @addtogroup MCP
+ * @{
+ * The MCP defines commands and responses which are used to control the MobiCore system.
+ * MCP information is exchanged in a world share memory buffer which has been established prior between NWd
+ * and SWd using the FastCall interface. The buffer needs to be provided by the MobiCore driver and is utilized
+ * to send MCP commands to the MobiCore as well as receiving responses from the MobiCore.
+ * The command of the normal world will be overwritten with the response from the secure side.
+ *
+ * @file
+ * MCP command interface definitions.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef MCP_H_
+#define MCP_H_
+
+#include "mcUuid.h"
+#include "mcLoadFormat.h"
+#include "mcVersionInfo.h"
+
+/** MobiCore Return Code Defines.
+ * List of the possible MobiCore return codes.
+ */
+typedef enum {
+    MC_MCP_RET_OK                                   =  0, /**< Memory has successfully been mapped. */
+    MC_MCP_RET_ERR_INVALID_SESSION                  =  1, /**< The session ID is invalid. */
+    MC_MCP_RET_ERR_UNKNOWN_UUID                     =  2, /**< The UUID of the Trustlet is unknown. */
+    MC_MCP_RET_ERR_UNKNOWN_DRIVER_ID                =  3, /**< The ID of the driver is unknown. */
+    MC_MCP_RET_ERR_NO_MORE_SESSIONS                 =  4, /**< No more session are allowed. */
+    MC_MCP_RET_ERR_CONTAINER_INVALID                =  5, /**< The container is invalid. */
+    MC_MCP_RET_ERR_TRUSTLET_INVALID                 =  6, /**< The Trustlet is invalid. */
+    MC_MCP_RET_ERR_ALREADY_MAPPED                   =  7, /**< The memory block has already been mapped before. */
+    MC_MCP_RET_ERR_INVALID_PARAM                    =  8, /**< Alignment or length error in the command parameters. */
+    MC_MCP_RET_ERR_OUT_OF_RESOURCES                 =  9, /**< No space left in the virtual address space of the session. */
+    MC_MCP_RET_ERR_INVALID_WSM                      = 10, /**< WSM type unknown or broken WSM */
+    MC_MCP_RET_ERR_UNKNOWN                          = 11, /**< unknown error. */
+    MC_MCP_RET_ERR_INVALID_MAPPING_LENGTH           = 12, /**< Lenght of map invalid */
+    MC_MCP_RET_ERR_MAPPING_TARGET                   = 13, /**< Map can only be applied to Trustlet session */
+    MC_MCP_RET_ERR_OUT_OF_CRYPTO_RESSOURCES         = 14, /**< Couldn't open crypto session. */
+    MC_MCP_RET_ERR_SIGNATURE_VERIFICATION_FAILED    = 15, /**< System Trustlet signature verification failed. */
+    MC_MCP_RET_ERR_WRONG_PUBLIC_KEY                 = 16, /**< System Trustlet public key is wrong. */
+    MC_MCP_RET_ERR_CONTAINER_TYPE_MISMATCH          = 17, /**< Wrong containter type(s). */
+    MC_MCP_RET_ERR_CONTAINER_LOCKED                 = 18, /**< Container is locked (or not activated). */
+    MC_MCP_RET_ERR_SP_NO_CHILD                      = 19, /**< SPID is not registered with root container. */
+    MC_MCP_RET_ERR_TL_NO_CHILD                      = 20, /**< UUID is not registered with sp container. */
+    MC_MCP_RET_ERR_UNWRAP_ROOT_FAILED               = 21, /**< Unwrapping of root container failed. */
+    MC_MCP_RET_ERR_UNWRAP_SP_FAILED                 = 22, /**< Unwrapping of service provider container failed. */
+    MC_MCP_RET_ERR_UNWRAP_TRUSTLET_FAILED           = 23, /**< Unwrapping of Trustlet container failed. */
+    MC_MCP_RET_ERR_CONTAINER_VERSION_MISMATCH       = 24, /**< Container version mismatch. */
+    MC_MCP_RET_ERR_SP_TL_DECRYPTION_FAILED          = 25, /**< Decryption of service provider trustlet failed. */
+    MC_MCP_RET_ERR_SP_TL_HASH_CHECK_FAILED          = 26, /**< Hash check of service provider trustlet failed. */
+    MC_MCP_RET_ERR_LAUNCH_TASK_FAILED               = 27, /**< Activation/starting of task failed. */
+
+    // used for command verification
+    MC_MCP_RET_ERR_UNKNOWN_COMMAND                  = 50, /**< The command is unknown. */
+    MC_MCP_RET_ERR_INVALID_DATA                     = 51  /**< The command data is invalid. */
+} mcpResult_t;
+
+/** Possible MCP Command IDs
+ * Command ID must be between 0 and 0x7FFFFFFF.
+ */
+typedef enum {
+    MC_MCP_CMD_ID_INVALID                = 0x00000000,   /**< Invalid command ID. */
+    // Session commands
+    MC_MCP_CMD_OPEN_SESSION              = 0x00000001,   /**< Open a session to a service. */
+    MC_MCP_CMD_CLOSE_SESSION             = 0x00000003,   /**< Close an existing service session. */
+    MC_MCP_CMD_MAP                       = 0x00000004,   /**< Map a block of WSM to a session. */
+    MC_MCP_CMD_UNMAP                     = 0x00000005,   /**< Unmap a block of WSM from a session. */
+    MC_MCP_CMD_SUSPEND                   = 0x00000006,   /**< Prepare MobiCore for suspend. */
+    MC_MCP_CMD_RESUME                    = 0x00000007,   /**< Resume MobiCore from suspension. */
+    MC_MCP_CMD_DONATE_RAM                = 0x00000008,   /**< Donate RAM to MobiCore. */
+    MC_MCP_CMD_GET_MOBICORE_VERSION      = 0x00000009,   /**< Get MobiCore version information. */
+} mcpCmdId_t;
+
+
+#define FLAG_RESPONSE       (1U << 31)  /**< Flag to indicate that this is the response to a MCP command. */
+
+
+/** Types of WSM known to the MobiCore.
+ */
+typedef enum {
+    WSM_INVALID     = 0,    /**< Invalid memory type */
+    WSM_CONTIGUOUS  = 1,    /**< Reference to WSM points to a contiguous region of pages. */
+    WSM_L2          = 2,    /**< Reference to WSM points to an L2 table describing the memory region to share */
+}wsmType_t;
+
+/** Types of RAM known to the MobiCore.
+ */
+typedef enum {
+    RAM_INVALID     = 0,    /**< Invalid memory type */
+    RAM_GENERIC     = 1,    /**< Generic RAM of no special type. */
+}ramType_t;
+
+/** Command header.
+ * It just contains the command ID. Only values specified in mcpCmdId_t are allowed as command IDs.
+ * If the command ID is unspecified the MobiCore returns an empty response with the result set to MC_MCP_RET_ERR_UNKNOWN_COMMAND .
+ */
+typedef struct {
+    mcpCmdId_t cmdId; /**< Command ID of the command */
+} commandHeader_t, *commandHeader_ptr;
+
+/** Response header.
+ * MobiCore will reply to every MCP command with an MCP response. Like the MCP command the response consists of a
+ * header followed by response data. The response is written to the same memory location as the MCP command.
+ */
+typedef struct {
+    uint32_t rspId;  /**< Command ID | FLAG_RESPONSE. */
+    mcpResult_t result; /**< Result informs about the execution result of the command associated with the response. */
+} responseHeader_t, *responseHeader_ptr;
+
+
+
+/** @defgroup CMD MCP Commands
+ * @{ */
+
+/** @defgroup ASMCMD Administrative Commands
+ * @{ */
+
+/** @defgroup MCPDONATERAM DONATE_RAM
+ * Donate NWd RAM to MobiCore.
+ * This is a debug feature that is not available in release version.
+ *
+ * @{ */
+
+/** Donate RAM Command */
+typedef struct {
+    commandHeader_t  cmdHeader; /**< Command header. */
+    ramType_t        ramType;            /**< Type of RAM used for memory pool */
+    uint32_t         adrBuffer;          /**< Physical address of the page range*/
+    uint32_t         numPages;          /**< Number of pages contained in the donation. */
+} mcpCmdDonateRam_t, *mcpCmdDonateRam_ptr;
+
+/** Donate RAM Command Response */
+typedef struct {
+    responseHeader_t  rspHeader; /**< Response header. */
+} mcpRspDonateRam_t, *mcpRspDonateRam_ptr;
+/** @} */// End MCPDONATERAM
+
+
+/** @defgroup MCPGETMOBICOREVERSION GET_MOBICORE_VERSION
+ * Get MobiCore version info.
+ *
+ * @{ */
+
+/** Get MobiCore Version Command. */
+typedef struct {
+    commandHeader_t cmdHeader;  /** Command header. */
+} mcpCmdGetMobiCoreVersion_t, *mcpCmdGetMobiCoreVersion_ptr;
+
+/** Get MobiCore Version Command Response. */
+typedef struct {
+    responseHeader_t rspHeader;   /** Response header. */
+    mcVersionInfo_t  versionInfo; /** MobiCore version info. */
+} mcpRspGetMobiCoreVersion_t, *mcpRspGetMobiCoreVersion_ptr;
+
+/** @} */// End MCPGETMOBICOREVERSION
+
+/** @} */// End ASMCMD
+
+
+/** @defgroup POWERCMD Power Management Commands
+ * @{ */
+
+/** @defgroup MCPSUSPEND SUSPEND
+ * Prepare MobiCore suspension.
+ * This command allows MobiCore and MobiCore drivers to release or clean resources and save device state.
+ *
+ * @{ */
+
+/** Suspend Command */
+typedef struct {
+    commandHeader_t  cmdHeader; /**< Command header. */
+} mcpCmdSuspend_t, *mcpCmdSuspend_ptr;
+
+/** Suspend Command Response */
+typedef struct {
+    responseHeader_t  rspHeader; /**< Response header. */
+} mcpRspSuspend_t, *mcpRspSuspend_ptr;
+/** @} */// End MCPSUSPEND
+
+
+/** @defgroup MCPRESUME RESUME
+ * Resume MobiCore from suspension.
+ * This command allows MobiCore and MobiCore drivers to reinitialize hardware affected by suspension.
+ *
+ * @{ */
+
+/** Resume Command */
+typedef struct {
+    commandHeader_t  cmdHeader; /**< Command header. */
+} mcpCmdResume_t, *mcpCmdResume_ptr;
+
+/** Resume Command Response */
+typedef struct {
+    responseHeader_t  rspHeader; /**< Response header. */
+} mcpRspResume_t, *mcpRspResume_ptr;
+
+/** @} */// End MCPRESUME
+
+/** @} */// End POWERCMD
+
+
+
+/** @defgroup SESSCMD Session Management Commands
+ * @{ */
+
+/** @defgroup MCPOPEN OPEN
+ * Load and open a session to a Trustlet.
+ * The OPEN command loads Trustlet data to the MobiCore context and opens a session to the Trustlet.
+ * If wsmTypeLoadData is WSM_INVALID MobiCore tries to start a pre-installed Trustlet
+ * associated with the uuid passed.
+ * The uuid passed must match the uuid contained in the load data (if available).
+ * On success, MobiCore returns the session ID which can be used for further communication.
+ * @{ */
+
+/** Open Command */
+typedef struct {
+    commandHeader_t   cmdHeader;        /**< Command header. */
+    mcUuid_t            uuid;             /**< Byte array containing the service UUID. */
+    wsmType_t         wsmTypeTci;       /**< Type of WSM used for the TCI */
+    uint32_t          adrTciBuffer;     /**< Physical address of the TCI */
+    uint32_t          ofsTciBuffer;     /**< Offset to the data. */
+    uint32_t          lenTciBuffer;     /**< Length of the TCI. */
+    wsmType_t         wsmTypeLoadData;  /**< Type of the memory containing the data to load. */
+    uint32_t          adrLoadData;      /**< Physical address of the data to load. */
+    uint32_t          ofsLoadData;      /**< Offset to the data. */
+    uint32_t          lenLoadData;      /**< Length of the data to load. */
+    mclfHeader_t      tlHeader;         /**< Service header. */
+} mcpCmdOpen_t, *mcpCmdOpen_ptr;
+
+/** Open Command Response */
+typedef struct {
+    responseHeader_t  rspHeader; /**< Response header. */
+    uint32_t          sessionId; /**< Session ID used for further communication. */
+} mcpRspOpen_t, *mcpRspOpen_ptr;
+
+/** @} */// End MCPOPEN
+
+
+/** @defgroup MCPCLOSE CLOSE
+ * Close an existing session to a Trustlet.
+ * The CLOSE command terminates a session and frees all resources in the MobiCore system which
+ * are currently occupied by the session. Before closing the session, the MobiCore runtime
+ * management waits until all pending operations, like calls to drivers, invoked by the Trustlet
+ * have been terminated.
+ * Mapped memory will automatically be unmapped from the MobiCore context. The NWd is responsible for
+ * processing the freed memory according to the Rich-OS needs.
+ *
+ * @{ */
+
+/** Close Command */
+typedef struct {
+    commandHeader_t  cmdHeader;  /**< Command header. */
+    uint32_t         sessionId;  /**< Session ID. */
+} mcpCmdClose_t, *mcpCmdClose_ptr;
+
+/** Close Command Response */
+typedef struct {
+    responseHeader_t  rspHeader; /**< Response header. */
+} mcpRspClose_t, *mcpRspClose_ptr;
+
+/** @} */// End MCPCLOSE
+
+
+/** @defgroup MCPMAP MAP
+ * Map a portion of memory to a session.
+ * The MAP command provides a block of memory to the context of a service.
+ * The memory then becomes world-shared memory (WSM).
+ * The WSM can either be normal anonymous memory from malloc() or be a
+ * block of page aligned, contiguous memory.
+ * The only allowed memory type here is WSM_L2.
+ * @{ */
+
+/** Map Command */
+typedef struct {
+    commandHeader_t  cmdHeader;     /**< Command header. */
+    uint32_t         sessionId;     /**< Session ID of a valid session */
+    wsmType_t        wsmType;       /**< Type of WSM used of the memory*/
+    uint32_t         adrBuffer;     /**< Physical address of the memory */
+    uint32_t         ofsBuffer;     /**< Offset to the payload. */
+    uint32_t         lenBuffer;     /**< Length of the buffer. */
+} mcpCmdMap_t, *mcpCmdMap_ptr;
+
+#define MCP_MAP_MAX         0x100000    /**< Maximum allowed length for MCP map. */
+
+/** Map Command Response */
+typedef struct {
+    responseHeader_t  rspHeader;        /**< Response header. */
+    uint32_t          secureVirtualAdr; /**< Virtual address in the context of the service the WSM is mapped to, already includes a possible offset! */
+} mcpRspMap_t, *mcpRspMap_ptr;
+
+/** @} *///End MCPMAP
+
+
+/** @defgroup MCPUNMAP UNMAP
+ * Unmap a portion of world-shared memory from a session.
+ * The UNMAP command is used to unmap a previously mapped block of
+ * world shared memory from the context of a session.
+ *
+ * Attention: The memory block will be immediately unmapped from the specified session.
+ * If the service is still accessing the memory, the service will trigger a segmentation fault.
+ * @{ */
+
+/** Unmap Command */
+typedef struct {
+    commandHeader_t  cmdHeader;         /**< Command header. */
+    uint32_t         sessionId;         /**< Session ID of a valid session */
+    wsmType_t        wsmType;           /**< Type of WSM used of the memory*/
+    uint32_t         secureVirtualAdr;  /**< Virtual address in the context of the service the WSM has been mapped to, already includes a possible offset! */
+    uint32_t         lenVirtualBuffer;  /**< Length of the virtual buffer. */
+} mcpCmdUnmap_t, *mcpCmdUnmap_ptr;
+
+/** Unmap Command Response */
+typedef struct {
+    responseHeader_t rspHeader; /**< Response header. */
+} mcpRspUnmap_t, *mcpRspUnmap_ptr;
+
+/** @} */// End MCPUNMAP
+
+/** @} */// End SESSCMD
+
+/** @} */// End CMD
+
+/** Structure of the MCP buffer. */
+typedef union {
+    commandHeader_t              cmdHeader;              /**< Command header. */
+    responseHeader_t             rspHeader;              /**< Response header. */
+    mcpCmdOpen_t                 cmdOpen;                /**< Load and open service. */
+    mcpRspOpen_t                 rspOpen;                /**< Response to load and open service. */
+    mcpCmdClose_t                cmdClose;               /**< Close command. */
+    mcpRspClose_t                rspClose;               /**< Response to close command. */
+    mcpCmdMap_t                  cmdMap;                 /**< Map WSM to service context. */
+    mcpRspMap_t                  rspMap;                 /**< Response to MAP command. */
+    mcpCmdUnmap_t                cmdUnmap;               /**< Unmap WSM from service context. */
+    mcpRspUnmap_t                rspUnmap;               /**< Response to UNMAP command. */
+    mcpCmdSuspend_t              cmdSuspend;             /**< Suspend MobiCore. */
+    mcpRspSuspend_t              rspSuspend;             /**< Response to SUSPEND command. */
+    mcpCmdResume_t               cmdResume;              /**< Resume MobiCore. */
+    mcpRspResume_t               rspResume;              /**< Response to RESUME command. */
+    mcpCmdDonateRam_t            cmdDonateRam;           /**< Donate RAM to MobiCore. */
+    mcpRspDonateRam_t            rspDonateRam;           /**< Response to DONATE_RAM command. */
+    mcpCmdGetMobiCoreVersion_t   cmdGetMobiCoreVersion;  /**< Get MobiCore Version command. */
+    mcpRspGetMobiCoreVersion_t   rspGetMobiCoreVersion;  /**< Response to GET_MOBICORE_VERSION command. */
+} mcpMessage_t, *mcpMessage_ptr;
+
+
+#define MIN_MCP_LEN         sizeof(mcpMessage_t)  /**< Minimum MCP buffer length (in bytes). */
+
+#define MC_FLAG_NO_SLEEP_REQ   0
+#define MC_FLAG_REQ_TO_SLEEP   1
+
+#define MC_STATE_NORMAL_EXECUTION 0
+#define MC_STATE_READY_TO_SLEEP   1
+
+typedef struct {
+    uint16_t  SleepReq;
+    uint16_t  ReadyToSleep;
+} mcSleepMod_t, *mcSleepMod_ptr;
+
+/** MobiCore status flags */
+typedef struct {
+    uint32_t      schedule;   /**< Scheduling hint: if <> MC_FLAG_SCHEDULE_IDLE, MobiCore should be scheduled by the NWd */
+    mcSleepMod_t  sleepMode;  /**<  */
+    uint32_t      RFU2;       /**< Reserved for future use: Must not be interpreted */
+    uint32_t      RFU3;       /**< Reserved for future use: Must not be interpreted */
+} mcFlags_t, *mcFlags_ptr;
+
+#define MC_FLAG_SCHEDULE_IDLE      0 /**< MobiCore is idle. No scheduling required. */
+#define MC_FLAG_SCHEDULE_NON_IDLE  1 /**< MobiCore is non idle, scheduling is required. */
+
+
+
+/** MCP buffer structure */
+typedef struct {
+    mcFlags_t     mcFlags;    /**< MobiCore Flags */
+    mcpMessage_t  mcpMessage; /**< MCP message buffer */
+} mcpBuffer_t, *mcpBuffer_ptr;
+
+/** @} */
+#endif /* MCP_H_ */
diff --git a/mobicore/common/MobiCore/inc/Mci/mcinq.h b/mobicore/common/MobiCore/inc/Mci/mcinq.h
new file mode 100644
index 0000000..ad2a763
--- /dev/null
+++ b/mobicore/common/MobiCore/inc/Mci/mcinq.h
@@ -0,0 +1,108 @@
+/** @addtogroup NQ
+ * @{
+ * Notifications inform the MobiCore runtime environment that information is pending in a WSM buffer.
+ * The Trustlet Connector (TLC) and the corresponding trustlet also utilize this buffer to notify
+ * each other about new data within the Trustlet Connector Interface (TCI).
+ *
+ * The buffer is set up as a queue, which means that more than one notification can be written to the buffer
+ * before the switch to the other world is performed. Each side therefore facilitates an incoming and an
+ * outgoing queue for communication with the other side.
+ *
+ * Notifications hold the session ID, which is used to reference the communication partner in the other world.
+ * So if, e.g., the TLC in the normal world wants to notify his trustlet about new data in the TLC buffer
+ *
+ * @file
+ * Notification queue declarations.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef NQ_H_
+#define NQ_H_
+
+/** \name NQ Size Defines
+ * Minimum and maximum count of elements in the notification queue.
+ * @{ */
+#define MIN_NQ_ELEM 1   /**< Minimum notification queue elements. */
+#define MAX_NQ_ELEM 64 /**< Maximum notification queue elements. */
+/** @} */
+
+/** \name NQ Length Defines
+ * Minimum and maximum notification queue length.
+ * @{ */
+#define MIN_NQ_LEN (MIN_NQ_ELEM * sizeof(notification_t))   /**< Minimum notification length (in bytes). */
+#define MAX_NQ_LEN (MAX_NQ_ELEM * sizeof(notification_t))   /**< Maximum notification length (in bytes). */
+/** @} */
+
+/** \name Session ID Defines
+ * Standard Session IDs.
+ * @{ */
+#define SID_MCP       0           /**< MCP session ID is used when directly communicating with the MobiCore (e.g. for starting and stopping of trustlets). */
+#define SID_INVALID   0xffffffff  /**< Invalid session id is returned in case of an error. */
+/** @} */
+
+/** Notification data structure. */
+typedef struct{
+    uint32_t sessionId; /**< Session ID. */
+    int32_t payload;    /**< Additional notification information. */
+} notification_t;
+
+/** Notification payload codes.
+ * 0 indicated a plain simple notification,
+ * a positive value is a termination reason from the task,
+ * a negative value is a termination reason from MobiCore.
+ * Possible negative values are given below.
+ */
+typedef enum {
+    ERR_INVALID_EXIT_CODE   = -1, /**< task terminated, but exit code is invalid */
+    ERR_SESSION_CLOSE       = -2, /**< task terminated due to session end, no exit code available */
+    ERR_INVALID_OPERATION   = -3, /**< task terminated due to invalid operation */
+    ERR_INVALID_SID         = -4, /**< session ID is unknown */
+    ERR_SID_NOT_ACTIVE      = -5 /**<  session is not active */
+} notificationPayload_t;
+
+/** Declaration of the notification queue header.
+ * layout as specified in the data structure specification.
+ */
+typedef struct {
+    uint32_t writeCnt;  /**< Write counter. */
+    uint32_t readCnt;   /**< Read counter. */
+    uint32_t queueSize; /**< Queue size. */
+} notificationQueueHeader_t;
+
+/** Queue struct which defines a queue object.
+ * The queue struct is accessed by the queue<operation> type of
+ * function. elementCnt must be a power of two and the power needs
+ * to be smaller than power of uint32_t (obviously 32).
+ */
+typedef struct {
+    notificationQueueHeader_t hdr;              /**< Queue header. */
+    notification_t notification[MIN_NQ_ELEM];   /**< Notification elements. */
+} notificationQueue_t;
+
+#endif /** NQ_H_ */
+
+/** @} */
diff --git a/mobicore/common/MobiCore/inc/Mci/version.h b/mobicore/common/MobiCore/inc/Mci/version.h
new file mode 100644
index 0000000..c1eab01
--- /dev/null
+++ b/mobicore/common/MobiCore/inc/Mci/version.h
@@ -0,0 +1,34 @@
+/**
+ * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef MCI_VERSION_H_
+#define MCI_VERSION_H_
+
+#define MCI_VERSION_MAJOR 0
+#define MCI_VERSION_MINOR 4
+
+#endif /** MCI_VERSION_H_ */
diff --git a/mobicore/common/MobiCore/inc/TlCm/cmp.h b/mobicore/common/MobiCore/inc/TlCm/cmp.h
new file mode 100644
index 0000000..2493669
--- /dev/null
+++ b/mobicore/common/MobiCore/inc/TlCm/cmp.h
@@ -0,0 +1,1624 @@
+/** @addtogroup CMP
+ * Content Management Protocol Definitions.
+ *
+ * The CMP (Content Management Protocol) is based on the TCI (Trustlet Control
+ * Interface) and defines commands/responses between the content management
+ * trustlet (CMTL) and the content management trustlet connector (CMTLC) and/or
+ * the remote backend.
+ *
+ * @{
+ *
+ * @file
+ * CMP global definitions.
+ * Various components need access to (sub-)structures defined and used by CMP;
+ * these common definitions are made available through this header file.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CMP_H_
+#define CMP_H_
+
+#include "mcContainer.h"
+#include "mcUuid.h"
+#include "mcVersionInfo.h"
+#include "version.h"
+
+typedef uint32_t cmpCommandId_t;
+typedef uint32_t cmpResponseId_t;
+typedef uint32_t cmpReturnCode_t;
+
+/** Responses have bit 31 set */
+#define RSP_ID_MASK (1U << 31)
+#define RSP_ID(cmdId) (((uint32_t)(cmdId)) | RSP_ID_MASK)
+#define IS_CMD(cmdId) ((((uint32_t)(cmdId)) & RSP_ID_MASK) == 0)
+#define IS_RSP(cmdId) ((((uint32_t)(cmdId)) & RSP_ID_MASK) == RSP_ID_MASK)
+
+/**
+ * CMP command header.
+ */
+typedef struct {
+    /** Command ID. */
+    cmpCommandId_t commandId; 
+} cmpCommandHeader_t;
+
+/**
+ * CMP response header.
+ */
+typedef struct{
+    /** Response ID (must be command ID | RSP_ID_MASK ). */
+    cmpResponseId_t     responseId; 
+    /** Return code of command. */
+    cmpReturnCode_t     returnCode; 
+} cmpResponseHeader_t;
+
+/** SHA256 checksum. */
+typedef struct {
+    uint8_t data[32];
+} cmpSha256_t;
+
+/** Key size of encryption algorithm used for secure messaging. */
+#define CMP_MSG_KEY_SIZE    32
+
+/** Block size of the encryption algorithm used for secure messaging. */
+#define CMP_MSG_CRYPTO_BLOCK_SIZE  16
+
+/** Total number of padding bytes required to encrypt data of given size. */
+#define CMP_ED_PADDING(netsize) (CMP_MSG_CRYPTO_BLOCK_SIZE - (netsize) % CMP_MSG_CRYPTO_BLOCK_SIZE)
+
+/** Total number of bytes used for message authentication code (MAC). */
+#define CMP_MAC_SIZE 32 // HMAC-SHA256
+
+/** Total number of bytes used for PSS signature in GENERATE AUTH TOKEN command. */
+#define CMP_GEN_AUTH_TOKEN_PSS_SIZE   256
+
+/** Message authentication code. */
+typedef struct {
+    uint8_t mac[CMP_MAC_SIZE];
+} cmpMac_t;
+
+/** 64-bit random number. */
+typedef struct {
+    uint8_t data[8];
+} cmpRnd8_t;
+
+/** 256-bit random number. */
+typedef struct {
+    uint8_t data[32];
+} cmpRnd32_t;
+
+/** Version tags. */
+typedef enum {
+    CMP_VERSION_TAG1 = 0x00000001, // Deprecated.
+    CMP_VERSION_TAG2 = 0x00000002,
+} cmpVersionTag_t;
+
+/** Version data for version tag 1. */
+typedef struct {
+    uint32_t number;
+} cmpVersionData1_t;
+
+/** Version data for version tag 2. */
+typedef struct {
+    mcVersionInfo_t versionInfo;
+} cmpVersionData2_t;
+
+/** Version data. */
+typedef union {
+    cmpVersionData1_t versionData1;
+    cmpVersionData2_t versionData2;
+} cmpVersionData_t;
+
+/** @defgroup MC_CMP_CMD_GET_VERSION
+* @{ */
+
+/** @defgroup MC_CMP_CMD_GET_VERSION_CMD Command
+* @{ */
+
+/** GetVersion command. */
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+} cmpCmdGetVersion_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_GET_VERSION_RSP Response
+* @{ */
+
+/** GetSuid response. */
+typedef struct {
+cmpResponseHeader_t rspHeader;
+    cmpVersionTag_t tag;
+    cmpVersionData_t data;
+} cmpRspGetVersion_t;
+
+/** @} */
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_GENERATE_AUTH_TOKEN
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_GENERATE_AUTH_TOKEN_CMD Command
+ * @{ */
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+    mcSuid_t suid;
+    mcSymmetricKey_t kSocAuth;
+    uint32_t kid;
+} cmpGenAuthTokenCmdSdata_t;
+
+typedef struct {
+    cmpGenAuthTokenCmdSdata_t sdata;
+    uint8_t pssSignature[CMP_GEN_AUTH_TOKEN_PSS_SIZE];
+} cmpGenAuthTokenCmd_t;
+
+/** GenAuthToken command. */
+typedef struct {
+    cmpGenAuthTokenCmd_t cmd;
+} cmpCmdGenAuthToken_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_GENERATE_AUTH_TOKEN_RSP Response
+ * @{ */
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    // No MAC.
+} cmpGenAuthTokenRsp_t;
+
+/** GenAuthToken response. */
+typedef struct {
+    cmpGenAuthTokenRsp_t rsp;
+    mcSoAuthTokenCont_t soAuthCont;
+} cmpRspGenAuthToken_t;
+
+/** @} */ 
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_BEGIN_SOC_AUTHENTICATION
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_BEGIN_SOC_AUTHENTICATION_CMD Command
+ * @{ */
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+} cmpBeginSocAuthenticationCmd_t;
+
+/** BeginSocAuthentication command. */
+typedef struct {
+    cmpBeginSocAuthenticationCmd_t cmd;
+    mcSoAuthTokenCont_t soAuthTokenCont;
+} cmpCmdBeginSocAuthentication_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_BEGIN_SOC_AUTHENTICATION_RSP Response
+ * @{ */
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    mcSuid_t suid;
+    cmpRnd8_t rnd1;
+} cmpBeginSocAuthenticationRspSdata_t;
+
+typedef struct {
+    cmpBeginSocAuthenticationRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpBeginSocAuthenticationRsp_t;
+
+/** BeginSocAuthentication response. */
+typedef struct {
+    cmpBeginSocAuthenticationRsp_t rsp;
+} cmpRspBeginSocAuthentication_t;
+
+/** @} */ 
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_BEGIN_ROOT_AUTHENTICATION
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_BEGIN_ROOT_AUTHENTICATION_CMD Command
+ * @{ */
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+} cmpBeginRootAuthenticationCmd_t;
+
+/** BeginRootAuthentication command. */
+typedef struct {
+    cmpBeginRootAuthenticationCmd_t cmd;
+    mcSoRootCont_t soRootCont;
+} cmpCmdBeginRootAuthentication_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_BEGIN_ROOT_AUTHENTICATION_RSP Response
+ * @{ */
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    mcSuid_t suid;
+    cmpRnd8_t rnd1;
+} cmpBeginRootAuthenticationRspSdata_t;
+
+typedef struct {
+    cmpBeginRootAuthenticationRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpBeginRootAuthenticationRsp_t;
+
+/** BeginRootAuthentication response. */
+typedef struct {
+    cmpBeginRootAuthenticationRsp_t rsp;
+} cmpRspBeginRootAuthentication_t;
+
+/** @} */ 
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_BEGIN_SP_AUTHENTICATION
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_BEGIN_SP_AUTHENTICATION_CMD Command
+ * @{ */
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+    mcSpid_t spid;
+} cmpBeginSpAuthenticationCmdSdata_t;
+
+typedef struct {
+    cmpBeginSpAuthenticationCmdSdata_t sdata;
+} cmpBeginSpAuthenticationCmd_t;
+
+/** BeginSpAuthentication command. */
+typedef struct {
+    cmpBeginSpAuthenticationCmd_t cmd;
+    mcSoRootCont_t soRootCont;
+    mcSoSpCont_t soSpCont;
+} cmpCmdBeginSpAuthentication_t;
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_BEGIN_SP_AUTHENTICATION_RSP Response
+ * @{ */
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    mcSuid_t suid;
+    mcSpid_t spid;
+    cmpRnd8_t rnd1;
+} cmpBeginSpAuthenticationRspSdata_t;
+
+typedef struct {
+    cmpBeginSpAuthenticationRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpBeginSpAuthenticationRsp_t;
+
+/** BeginSpAuthentication response. */
+typedef struct {
+    cmpBeginSpAuthenticationRsp_t rsp;
+} cmpRspBeginSpAuthentication_t;
+
+/** @} */ 
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_AUTHENTICATE 
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_AUTHENTICATE_CMD Command
+ * @{ */
+typedef struct {
+    mcSuid_t suid;
+    uint32_t entityId;
+    cmpRnd8_t rnd2;
+    cmpRnd8_t rnd1;
+    cmpRnd32_t k2;
+} cmpAuthMsgEdata_t;
+
+typedef struct {
+    cmpAuthMsgEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpAuthMsgEdata_t))];
+} cmpAuthCmdEd_t;
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+    cmpAuthCmdEd_t ed;
+} cmpAuthCmdSdata_t; 
+
+typedef struct {
+    cmpAuthCmdSdata_t sdata;
+    cmpMac_t mac;
+} cmpAuthenticateCmd_t;
+
+/** Authenticate command. */
+typedef struct {
+    cmpAuthenticateCmd_t cmd;
+} cmpCmdAuthenticate_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_AUTHENTICATE_RSP Response
+ * @{ */
+typedef struct {
+    mcSuid_t suid;
+    uint32_t entityId;
+    cmpRnd8_t rnd1;
+    cmpRnd8_t rnd2;
+    cmpRnd32_t k1;
+} cmpAuthRspEdata_t;
+
+typedef struct {
+    cmpAuthRspEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpAuthRspEdata_t))];
+} cmpAuthRspEd_t;
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    cmpAuthRspEd_t ed;
+} cmpAuthRspSdata_t;
+
+typedef struct {
+    cmpAuthRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpAuthenticateRsp_t;
+
+/** Authenticate response. */
+typedef struct {
+    cmpAuthenticateRsp_t rsp;
+} cmpRspAuthenticate_t;
+
+/** @} */ 
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_REGISTER_ACTIVATE 
+ * @{ */
+ 
+/** @defgroup MC_CMP_CMD_ROOT_CONT_REGISTER_ACTIVATE_CMD Command
+ * @{ */
+ 
+typedef struct {
+    mcSymmetricKey_t kRootAuth;
+} cmpRootRegActMsgEdata_t;
+
+typedef struct {
+    cmpRootRegActMsgEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpRootRegActMsgEdata_t))];
+} cmpRootRegActCmdEd_t;
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+    mcRootid_t rootid;
+    cmpRootRegActCmdEd_t ed;
+} cmpRootRegActCmdSdata_t;
+
+typedef struct {
+    cmpRootRegActCmdSdata_t sdata;
+    cmpMac_t mac;
+} cmpRootContRegisterActivateCmd_t;
+
+/** RootContRegisterActivate command. */
+typedef struct {
+    cmpRootContRegisterActivateCmd_t cmd;
+} cmpCmdRootContRegisterActivate_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_REGISTER_ACTIVATE_RSP Response
+ * @{ */
+ 
+typedef struct {
+    mcSoRootCont_t soRootCont;
+} cmpRootRegActRspEdata_t;
+
+typedef struct {
+    cmpRootRegActRspEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpRootRegActRspEdata_t))];
+} cmpRootRegActRspEd_t;
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    cmpRootRegActRspEd_t ed;
+} cmpRootRegActRspSdata_t;
+
+typedef struct {
+    cmpRootRegActRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpRootContRegisterActivateRsp_t;
+
+/** RooContRegisterActivate response. */
+typedef struct {
+    cmpRootContRegisterActivateRsp_t rsp;
+    mcSoRootCont_t soRootCont;
+} cmpRspRootContRegisterActivate_t;
+
+/** @} */
+
+/** @} */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_UNREGISTER 
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_UNREGISTER_CMD Command
+ * @{ */
+
+typedef struct {
+    mcSuid_t suid;
+    mcSoAuthTokenCont_t soAuthTokenCont;
+} cmpRootUnregMsgEdata_t;
+
+typedef struct {
+    cmpRootUnregMsgEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpRootUnregMsgEdata_t))];
+} cmpRootUnregCmdEd_t;
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+    cmpRootUnregCmdEd_t ed;
+} cmpRootUnregCmdSdata_t;
+
+typedef struct {
+    cmpRootUnregCmdSdata_t sdata;
+    cmpMac_t mac;
+} cmpRootContUnregisterCmd_t;
+
+/** RootContUnregister command. */
+typedef struct {
+    cmpRootContUnregisterCmd_t cmd;
+} cmpCmdRootContUnregister_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_UNREGISTER_RSP Response
+ * @{ */
+
+typedef struct {
+    mcSuid_t suid;
+} cmpRootUnregRspEdata_t;
+
+typedef struct {
+    cmpRootUnregRspEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpRootUnregRspEdata_t))];
+} cmpRootUnregRspEd_t;
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    cmpRootUnregRspEd_t ed;
+} cmpRootUnregRspSdata_t;
+
+typedef struct {
+    cmpRootUnregRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpRootContUnregisterRsp_t;
+
+/** RootContUnregister response. */
+typedef struct {
+    cmpRootContUnregisterRsp_t rsp;
+    mcSoAuthTokenCont_t soAuthTokenCont;
+} cmpRspRootContUnregister_t;
+
+/** @} */ 
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_LOCK_BY_ROOT
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_LOCK_BY_ROOT_CMD Command
+ * @{ */
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+} cmpRootLockByRootCmdSdata_t;
+
+typedef struct {
+    cmpRootLockByRootCmdSdata_t sdata;
+    cmpMac_t mac;
+} cmpRootContLockByRootCmd_t;
+
+/** RootContLockByRoot command. */
+typedef struct {
+    cmpRootContLockByRootCmd_t cmd;
+} cmpCmdRootContLockByRoot_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_LOCK_BY_ROOT_RSP Response
+ * @{ */
+
+typedef struct {
+    mcSoRootCont_t soRootCont;
+} cmpRootLockByRootRspEdata_t;
+
+typedef struct {
+    cmpRootLockByRootRspEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpRootLockByRootRspEdata_t))];
+} cmpRootLockByRootRspEd_t;
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    cmpRootLockByRootRspEd_t ed;
+} cmpRootLockByRootRspSdata_t;
+
+typedef struct {
+    cmpRootLockByRootRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpRootContLockByRootRsp_t;
+
+/** RootContLockByRoot response. */
+typedef struct {
+    cmpRootContLockByRootRsp_t rsp;
+    mcSoRootCont_t soRootCont;
+} cmpRspRootContLockByRoot_t;
+
+/** @} */ 
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_UNLOCK_BY_ROOT
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_UNLOCK_BY_ROOT_CMD Command
+ * @{ */
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+} cmpRootUnlockByRootCmdSdata_t;
+
+typedef struct {
+    cmpRootUnlockByRootCmdSdata_t sdata;
+    cmpMac_t mac;
+} cmpRootContUnlockByRootCmd_t;
+
+/** RootContUnlockByRoot command. */
+typedef struct {
+    cmpRootContUnlockByRootCmd_t cmd;
+} cmpCmdRootContUnlockByRoot_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_ROOT_CONT_UNLOCK_BY_ROOT_RSP Response
+ * @{ */
+
+typedef struct {
+    mcSoRootCont_t soRootCont;
+} cmpRootUnlockByRootRspEdata_t;
+
+typedef struct {
+    cmpRootUnlockByRootRspEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpRootUnlockByRootRspEdata_t))];
+} cmpRootUnlockByRootRspEd_t;
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    cmpRootUnlockByRootRspEd_t ed;
+} cmpRootUnlockByRootRspSdata_t;
+
+typedef struct {
+    cmpRootUnlockByRootRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpRootContUnlockByRootRsp_t;
+
+/** RootContUnlockByRoot response. */
+typedef struct {
+    cmpRootContUnlockByRootRsp_t rsp;
+    mcSoRootCont_t soRootCont;
+} cmpRspRootContUnlockByRoot_t;
+
+/** @} */ 
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER_ACTIVATE
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER_ACTIVATE_CMD Command
+ * @{ */
+
+typedef struct {
+    mcSymmetricKey_t kSpAuth;
+} cmpSpRegActMsgEdata_t;
+
+typedef struct {
+    cmpSpRegActMsgEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpRegActMsgEdata_t))];
+} cmpSpRegActCmdEd_t;
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+    mcSpid_t spid;
+    cmpSpRegActCmdEd_t ed;
+} cmpSpRegActCmdSdata_t;
+
+typedef struct {
+    cmpSpRegActCmdSdata_t sdata;
+    cmpMac_t mac;
+} cmpSpContRegisterActivateCmd_t;
+
+/** SpContRegisterActivate command. */
+typedef struct {
+    cmpSpContRegisterActivateCmd_t cmd;
+} cmpCmdSpContRegisterActivate_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER_ACTIVATE_RSP Response
+ * @{ */
+
+typedef struct {
+    mcSoRootCont_t soRootCont;
+    mcSoSpCont_t soSpCont;
+} cmpSpRegActRspEdata_t;
+
+typedef struct {
+    cmpSpRegActRspEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpRegActRspEdata_t))];
+} cmpSpRegActRspEd_t;
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    cmpSpRegActRspEd_t ed;
+} cmpSpRegActRspSdata_t;
+
+typedef struct {
+    cmpSpRegActRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpSpContRegisterActivateRsp_t;
+
+/** SpContRegisterActivate response. */
+typedef struct {
+    cmpSpContRegisterActivateRsp_t rsp;
+    mcSoRootCont_t soRootCont;
+    mcSoSpCont_t soSpCont;
+} cmpRspSpContRegisterActivate_t;
+
+/** @} */ 
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER_CMD Command
+ * @{ */
+
+typedef struct {
+    mcSymmetricKey_t kSpAuth;
+} cmpSpRegisterMsgEdata_t;
+
+typedef struct {
+    cmpSpRegisterMsgEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpRegisterMsgEdata_t))];
+} cmpSpRegisterCmdEd_t;
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+    mcSpid_t spid;
+    cmpSpRegisterCmdEd_t ed;
+} cmpSpRegisterCmdSdata_t;
+
+typedef struct {
+    cmpSpRegisterCmdSdata_t sdata;
+    cmpMac_t mac;
+} cmpSpContRegisterCmd_t;
+
+/** SpContRegister command. */
+typedef struct {
+    cmpSpContRegisterCmd_t cmd;
+} cmpCmdSpContRegister_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_SP_CONT_REGISTER_RSP Response
+ * @{ */
+
+typedef struct {
+    mcSoRootCont_t soRootCont;
+    mcSoSpCont_t soSpCont;
+} cmpSpRegisterRspEdata_t;
+
+typedef struct {
+    cmpSpRegisterRspEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpRegisterRspEdata_t))];
+} cmpSpRegisterRspEd_t;
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    cmpSpRegisterRspEd_t ed;
+} cmpSpRegisterRspSdata_t;
+
+typedef struct {
+    cmpSpRegisterRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpSpContRegisterRsp_t;
+
+/** SpContRegister response. */
+typedef struct {
+    cmpSpContRegisterRsp_t rsp;
+    mcSoRootCont_t soRootCont;
+    mcSoSpCont_t soSpCont;
+} cmpRspSpContRegister_t;
+
+/** @} */ 
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_SP_CONT_ACTIVATE
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_ACTIVATE_CMD Command
+ * @{ */
+
+typedef struct {
+    mcSymmetricKey_t kSpAuth;
+} cmpSpActivateMsgEdata_t;
+
+typedef struct {
+    cmpSpActivateMsgEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpActivateMsgEdata_t))];
+} cmpSpActivateCmdEd_t;
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+    mcSpid_t spid;
+    cmpSpActivateCmdEd_t ed;
+} cmpSpActivateCmdSdata_t;
+
+typedef struct {
+    cmpSpActivateCmdSdata_t sdata;
+    cmpMac_t mac;
+} cmpSpContActivateCmd_t;
+
+/** SpContActivate command. */
+typedef struct {
+    cmpSpContActivateCmd_t cmd;
+} cmpCmdSpContActivate_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_SP_CONT_ACTIVATE_RSP Response
+ * @{ */
+
+typedef struct {
+    mcSoSpCont_t soSpCont;
+} cmpSpActivateRspEdata_t;
+
+typedef struct {
+    cmpSpActivateRspEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpActivateRspEdata_t))];
+} cmpSpActivateRspEd_t;
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    cmpSpActivateRspEd_t ed;
+} cmpSpActivateRspSdata_t;
+
+typedef struct {
+    cmpSpActivateRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpSpContActivateRsp_t;
+
+/** SpContActivate response. */
+typedef struct {
+    cmpSpContActivateRsp_t rsp;
+    mcSoSpCont_t soSpCont;
+} cmpRspSpContActivate_t;
+
+/** @} */ 
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNREGISTER 
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNREGISTER_CMD Command
+ * @{ */
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+    mcSpid_t spid;
+} cmpSpContUnregCmdSdata_t;
+
+typedef struct {
+    cmpSpContUnregCmdSdata_t sdata;
+    cmpMac_t mac;
+} cmpSpContUnregisterCmd_t;
+
+/** SpContUnregister command. */
+typedef struct {
+    cmpSpContUnregisterCmd_t cmd;
+} cmpCmdSpContUnregister_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNREGISTER_RSP Response
+ * @{ */
+
+typedef struct {
+    mcSoRootCont_t soRootCont;
+} cmpSpUnregRspEdata_t;
+
+typedef struct {
+    cmpSpUnregRspEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpUnregRspEdata_t))];
+} cmpSpUnregRspEd_t;
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    cmpSpUnregRspEd_t ed;
+} cmpSpContUnregRspSdata_t;
+
+typedef struct {
+    cmpSpContUnregRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpSpContUnregisterRsp_t;
+
+/** SpContUnregister response. */
+typedef struct {
+    cmpSpContUnregisterRsp_t rsp;
+    mcSoRootCont_t soRootCont;
+} cmpRspSpContUnregister_t;
+
+/** @} */ 
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_ROOT 
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_ROOT_CMD Command
+ * @{ */
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader; 
+    mcSpid_t spid;
+} cmpSpLockByRootCmdSdata_t;
+
+typedef struct {
+    cmpSpLockByRootCmdSdata_t sdata;
+    cmpMac_t mac;
+} cmpSpContLockByRootCmd_t;
+
+/** SpContLockByRoot command. */
+typedef struct {
+    cmpSpContLockByRootCmd_t cmd;
+    mcSoSpCont_t soSpCont;
+} cmpCmdSpContLockByRoot_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_ROOT_RSP Response
+ * @{ */
+
+typedef struct {
+    mcSoSpCont_t soSpCont;
+} cmpSpLockByRootRspEdata_t;
+
+typedef struct {
+    cmpSpLockByRootRspEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpLockByRootRspEdata_t))];
+} cmpSpLockByRootRspEd_t;
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    cmpSpLockByRootRspEd_t ed;
+} cmpSpLockByRootRspSdata_t;
+
+typedef struct {
+    cmpSpLockByRootRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpSpContLockByRootRsp_t;
+
+/** SpContLockByRoot response. */
+typedef struct {
+    cmpSpContLockByRootRsp_t rsp;
+    mcSoSpCont_t soSpCont;
+} cmpRspSpContLockByRoot_t;
+
+/** @} */ 
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_ROOT 
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_ROOT_CMD Command
+ * @{ */
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader; 
+    mcSpid_t spid;
+} cmpSpUnlockByRootCmdSdata_t;
+
+typedef struct {
+    cmpSpUnlockByRootCmdSdata_t sdata;
+    cmpMac_t mac;
+} cmpSpContUnlockByRootCmd_t;
+
+/** SpContUnlockByRoot command. */
+typedef struct {
+    cmpSpContUnlockByRootCmd_t cmd;
+    mcSoSpCont_t soSpCont;
+} cmpCmdSpContUnlockByRoot_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_ROOT_RSP Response
+ * @{ */
+
+typedef struct {
+    mcSoSpCont_t soSpCont;
+} cmpSpUnlockByRootRspEdata_t;
+
+typedef struct {
+    cmpSpUnlockByRootRspEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpUnlockByRootRspEdata_t))];
+} cmpSpUnlockByRootRspEd_t;
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    cmpSpUnlockByRootRspEd_t ed;
+} cmpSpUnlockByRootRspSdata_t;
+
+typedef struct {
+    cmpSpUnlockByRootRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpSpContUnlockByRootRsp_t;
+
+/** SpContUnlockByRoot response. */
+typedef struct {
+    cmpSpContUnlockByRootRsp_t rsp;
+    mcSoSpCont_t soSpCont;
+} cmpRspSpContUnlockByRoot_t;
+
+/** @} */ 
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_SP
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_SP_CMD Command
+ * @{ */
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader; 
+    mcSpid_t spid;
+} cmpSpLockBySpCmdSdata_t;
+
+typedef struct {
+    cmpSpLockBySpCmdSdata_t sdata;
+    cmpMac_t mac;
+} cmpSpContLockBySpCmd_t;
+
+/** SpContLockBySp command. */
+typedef struct {
+    cmpSpContLockBySpCmd_t cmd;
+} cmpCmdSpContLockBySp_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_SP_CONT_LOCK_BY_SP_RSP Respose
+ * @{ */
+
+typedef struct {
+    mcSoSpCont_t soSpCont;
+} cmpSpLockBySpRspEdata_t;
+
+typedef struct {
+    cmpSpLockBySpRspEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpLockBySpRspEdata_t))];
+} cmpSpLockBySpRspEd_t;
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    cmpSpLockBySpRspEd_t ed;
+} cmpSpLockBySpRspSdata_t;
+
+typedef struct {
+    cmpSpLockBySpRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpSpContLockBySpRsp_t;
+
+/** SpContLockBySp response. */
+typedef struct {
+    cmpSpContLockBySpRsp_t rsp;
+    mcSoSpCont_t soSpCont;
+} cmpRspSpContLockBySp_t;
+
+/** @} */ 
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_SP
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_SP_CMD Command
+ * @{ */
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader; 
+    mcSpid_t spid;
+} cmpSpUnlockBySpCmdSdata_t;
+
+typedef struct {
+    cmpSpUnlockBySpCmdSdata_t sdata;
+    cmpMac_t mac;
+} cmpSpContUnlockBySpCmd_t;
+
+/** SpContUnlockBySp command. */
+typedef struct {
+    cmpSpContUnlockBySpCmd_t cmd;
+} cmpCmdSpContUnlockBySp_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_SP_CONT_UNLOCK_BY_SP_RSP Response
+ * @{ */
+
+typedef struct {
+    mcSoSpCont_t soSpCont;
+} cmpSpUnlockBySpRspEdata_t;
+
+typedef struct {
+    cmpSpUnlockBySpRspEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpSpUnlockBySpRspEdata_t))];
+} cmpSpUnlockBySpRspEd_t;
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    cmpSpUnlockBySpRspEd_t ed;
+} cmpSpUnlockBySpRspSdata_t;
+
+typedef struct {
+    cmpSpUnlockBySpRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpSpContUnlockBySpRsp_t;
+
+/** SpContUnlockBySp response. */
+typedef struct {
+    cmpSpContUnlockBySpRsp_t rsp;
+    mcSoSpCont_t soSpCont;
+} cmpRspSpContUnlockBySp_t;
+
+/** @} */ 
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER 
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER_CMD Command
+ * @{ */
+
+typedef struct {
+    mcSymmetricKey_t kSpTltEnc;
+} cmpTltRegMsgEdata_t;
+
+typedef struct {
+    cmpTltRegMsgEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltRegMsgEdata_t))];
+} cmpTltRegCmdEd_t;
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+    mcSpid_t spid;
+    mcUuid_t uuid;
+    cmpTltRegCmdEd_t ed;
+} cmpTltRegCmdSdata_t;
+
+typedef struct {
+    cmpTltRegCmdSdata_t sdata;
+    cmpMac_t mac;
+} cmpTltContRegisterCmd_t;
+
+/** TltContRegister command. */
+typedef struct {
+    cmpTltContRegisterCmd_t cmd;
+} cmpCmdTltContRegister_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER_RSP Response
+ * @{ */
+
+typedef struct {
+    mcSoSpCont_t soSpCont;
+    mcSoTltCont_t soTltCont;
+} cmpTltRegRspEdata_t;
+
+typedef struct {
+    cmpTltRegRspEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltRegRspEdata_t))];
+} cmpTltRegRspEd_t;
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    cmpTltRegRspEd_t ed;
+} cmpTltRegRspSdata_t;
+
+typedef struct {
+    cmpTltRegRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpTltContRegisterRsp_t;
+
+/** TltContRegister response. */
+typedef struct {
+    cmpTltContRegisterRsp_t rsp;
+    mcSoSpCont_t soSpCont;
+    mcSoTltCont_t soTltCont;
+} cmpRspTltContRegister_t;
+
+/** @} */ 
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_ACTIVATE 
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_ACTIVATE_CMD Command
+ * @{ */
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+    mcSpid_t spid;
+    mcUuid_t uuid;
+} cmpTltActCmdSdata_t;
+
+typedef struct {
+    cmpTltActCmdSdata_t sdata;
+    cmpMac_t mac;
+} cmpTltContActivateCmd_t;
+
+/** TltContActivate command. */
+typedef struct {
+    cmpTltContActivateCmd_t cmd;
+    mcSoTltCont_t soTltCont;
+} cmpCmdTltContActivate_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_ACTIVATE_RSP Response
+ * @{ */
+
+typedef struct {
+    mcSoTltCont_t soTltCont;
+} cmpTltActRspEdata_t;
+
+typedef struct {
+    cmpTltActRspEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltActRspEdata_t))];
+} cmpTltActRspEd_t;
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    cmpTltActRspEd_t ed;
+} cmpTltActRspSdata_t;
+
+typedef struct {
+    cmpTltActRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpTltContActivateRsp_t;
+
+/** TltContActivate response. */
+typedef struct {
+    cmpTltContActivateRsp_t rsp;
+    mcSoTltCont_t soTltCont;
+} cmpRspTltContActivate_t;
+
+/** @} */ 
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER_ACTIVATE 
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER_ACTIVATE_CMD Command
+ * @{ */
+
+typedef struct {
+    mcSymmetricKey_t kSpTltEnc;
+} cmpTltRegActMsgEdata_t;
+
+typedef struct {
+    cmpTltRegActMsgEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltRegActMsgEdata_t))];
+} cmpTltRegActCmdEd_t;
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+    mcSpid_t spid;
+    mcUuid_t uuid;
+    cmpTltRegActCmdEd_t ed;
+} cmpTltRegActCmdSdata_t;
+
+typedef struct {
+    cmpTltRegActCmdSdata_t sdata;
+    cmpMac_t mac;
+} cmpTltContRegisterActivateCmd_t;
+
+/** TltContRegisterActivate command. */
+typedef struct {
+    cmpTltContRegisterActivateCmd_t cmd;
+} cmpCmdTltContRegisterActivate_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_REGISTER_ACTIVATE_RSP Response
+ * @{ */
+
+typedef struct {
+    mcSoSpCont_t soSpCont;
+    mcSoTltCont_t soTltCont;
+} cmpTltRegActRspEdata_t;
+
+typedef struct {
+    cmpTltRegActRspEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltRegActRspEdata_t))];
+} cmpTltRegActRspEd_t;
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    cmpTltRegActRspEd_t ed;
+} cmpTltRegActRspSdata_t;
+
+typedef struct {
+    cmpTltRegActRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpTltContRegisterActivateRsp_t;
+
+/** TltContRegisterActivate response. */
+typedef struct {
+    cmpTltContRegisterActivateRsp_t rsp;
+    mcSoSpCont_t soSpCont;
+    mcSoTltCont_t soTltCont;
+} cmpRspTltContRegisterActivate_t;
+
+/** @} */ 
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_UNREGISTER
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_UNREGISTER_CMD Command
+ * @{ */
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+    mcSpid_t spid;
+    mcUuid_t uuid;
+} cmpTltUnregCmdSdata_t;
+
+typedef struct {
+    cmpTltUnregCmdSdata_t sdata;
+    cmpMac_t mac;
+} cmpTltContUnregisterCmd_t;
+
+/** TltContUnregister command. */
+typedef struct {
+    cmpTltContUnregisterCmd_t cmd;
+} cmpCmdTltContUnregister_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_UNREGISTER_RSP Response
+ * @{ */
+
+typedef struct {
+    mcSoSpCont_t soSpCont;
+} cmpTltUnregRspEdata_t;
+
+typedef struct {
+    cmpTltUnregRspEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltUnregRspEdata_t))];
+} cmpTltUnregRspEd_t;
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    cmpTltUnregRspEd_t ed;
+} cmpTltUnregRspSdata_t;
+
+typedef struct {
+    cmpTltUnregRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpTltContUnregisterRsp_t;
+
+/** TltContUnregister response. */
+typedef struct {
+    cmpTltContUnregisterRsp_t rsp;
+    mcSoSpCont_t soSpCont;
+} cmpRspTltContUnregister_t;
+
+/** @} */ 
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_LOCK_BY_SP 
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_LOCK_BY_SP_CMD Command
+ * @{ */
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+    mcSpid_t spid;
+    mcUuid_t uuid;
+} cmpTltLockBySpCmdSdata_t;
+
+typedef struct {
+    cmpTltLockBySpCmdSdata_t sdata;
+    cmpMac_t mac;
+} cmpTltContLockBySpCmd_t;
+
+/** TltContLockBySp command. */
+typedef struct {
+    cmpTltContLockBySpCmd_t cmd;
+    mcSoTltCont_t soTltCont;
+} cmpCmdTltContLockBySp_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_LOCK_BY_SP_RSP Response
+ * @{ */
+
+typedef struct {
+    mcSoTltCont_t soTltCont;
+} cmpTltLockBySpRspEdata_t;
+
+typedef struct {
+    cmpTltLockBySpRspEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltLockBySpRspEdata_t))];
+} cmpTltLockBySpRspEd_t;
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    cmpTltLockBySpRspEd_t ed;
+} cmpTltLockBySpRspSdata_t;
+
+typedef struct {
+    cmpTltLockBySpRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpTltContLockBySpRsp_t;
+
+/** TltContLockBySp response. */
+typedef struct {
+    cmpTltContLockBySpRsp_t rsp;
+    mcSoTltCont_t soTltCont;
+} cmpRspTltContLockBySp_t;
+
+/** @} */ 
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_UNLOCK_BY_SP 
+ * @{ */
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_UNLOCK_BY_SP_CMD Command
+ * @{ */
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+    mcSpid_t spid;
+    mcUuid_t uuid;
+} cmpTltUnlockBySpCmdSdata_t;
+
+typedef struct {
+    cmpTltUnlockBySpCmdSdata_t sdata;
+    cmpMac_t mac;
+} cmpTltContUnlockBySpCmd_t;
+
+/** TltContUnlockBySp command. */
+typedef struct {
+    cmpTltContUnlockBySpCmd_t cmd;
+    mcSoTltCont_t soTltCont;
+} cmpCmdTltContUnlockBySp_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_UNLOCK_BY_SP_RSP Response
+ * @{ */
+
+typedef struct {
+    mcSoTltCont_t soTltCont;
+} cmpTltUnlockBySpRspEdata_t;
+
+typedef struct {
+    cmpTltUnlockBySpRspEdata_t edata;
+    uint8_t padding[CMP_ED_PADDING(sizeof(cmpTltUnlockBySpRspEdata_t))];
+} cmpTltUnlockBySpRspEd_t;
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    cmpTltUnlockBySpRspEd_t ed;
+} cmpTltUnlockBySpRspSdata_t;
+
+typedef struct {
+    cmpTltUnlockBySpRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpTltContUnlockBySpRsp_t;
+
+/** TltContUnlockBySp response. */
+typedef struct {
+    cmpTltContUnlockBySpRsp_t rsp;
+    mcSoTltCont_t soTltCont;
+} cmpRspTltContUnlockBySp_t;
+
+/** @} */
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_GET_SUID
+* @{ */
+
+/** @defgroup MC_CMP_CMD_GET_SUID_CMD Command
+* @{ */
+
+/** GetSuid command. */
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+} cmpCmdGetSuid_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_GET_SUID_RSP Response
+* @{ */
+
+/** GetSuid response. */
+typedef struct {
+cmpResponseHeader_t rspHeader;
+    mcSuid_t suid;
+} cmpRspGetSuid_t;
+
+/** @} */
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_AUTHENTICATE_TERMINATE
+* @{ */
+
+/** @defgroup MC_CMP_CMD_AUTHENTICATE_TERMINATE_CMD Command
+* @{ */
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+} cmpAuthenticateTerminateCmdSdata_t;
+
+typedef struct {
+    cmpAuthenticateTerminateCmdSdata_t sdata;
+    cmpMac_t mac;
+} cmpAuthenticateTerminateCmd_t;
+
+/** AuthenticateTerminate command. */
+typedef struct {
+    cmpAuthenticateTerminateCmd_t cmd;
+} cmpCmdAuthenticateTerminate_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_AUTHENTICATE_TERMINATE_RSP Response
+* @{ */
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+} cmpAuthenticateTerminateRspSdata_t;
+
+typedef struct {
+    cmpAuthenticateTerminateRspSdata_t sdata;
+    cmpMac_t mac;
+} cmpTerminateAutenticateRsp_t;
+
+/** AuthenticateTerminate response. */
+typedef struct {
+    cmpTerminateAutenticateRsp_t rsp;
+} cmpRspAuthenticateTerminate_t;
+
+/** @} */
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_PERSONALIZE
+ * @{ */
+ 
+/** @defgroup MC_CMP_CMD_TLT_CONT_PERSONALIZE_CMD Command
+ * @{ */
+ 
+typedef struct {
+    mcPid_t pid;
+    mcCoDataCont_t persoData;
+} cmpTltContPersonalizeCmdEdata_t;
+
+typedef struct {
+    cmpTltContPersonalizeCmdEdata_t edata;
+    uint8_t padding_[CMP_ED_PADDING(sizeof(cmpTltContPersonalizeCmdEdata_t))];
+} cmpTltContPersonalizeCmdEd_t;
+
+typedef struct {
+    cmpCommandHeader_t cmdHeader;
+    mcSpid_t spid;
+    mcUuid_t uuid;
+    uint32_t edLen;
+    cmpTltContPersonalizeCmdEd_t ed;
+} cmpTltContPersonalizeCmdSdata_t;
+
+typedef struct {
+    cmpTltContPersonalizeCmdSdata_t sdata;
+    cmpMac_t mac_;
+} cmpTltContPersonalizeCmd_t;
+
+/** TltContPersonalize command. */
+typedef struct {
+    cmpTltContPersonalizeCmd_t cmd;
+    mcSoTltCont_t soTltCont_;
+} cmpCmdTltContPersonalize_t;
+
+/** @} */ 
+
+/** @defgroup MC_CMP_CMD_TLT_CONT_PERSONLIZE_RSP Response
+ * @{ */
+ 
+typedef struct {
+    mcSoDataCont_t soDataCont;
+} cmpTltContPersonalizeRspEdata_t;
+
+typedef struct {
+    cmpTltContPersonalizeRspEdata_t edata;
+    uint8_t padding_[CMP_ED_PADDING(sizeof(cmpTltContPersonalizeRspEdata_t))];
+} cmpTltContPersonalizeRspEd_t;
+
+typedef struct {
+    cmpResponseHeader_t rspHeader;
+    uint32_t edLen;
+    cmpTltContPersonalizeRspEd_t ed;
+} cmpTltContPersonalizeRspSdata_t;
+
+typedef struct {
+    cmpTltContPersonalizeRspSdata_t sdata;
+    cmpMac_t mac_;
+} cmpTltContPersonalizeRsp_t;
+
+/** TltContPersonalize response. */
+typedef struct {
+    cmpTltContPersonalizeRsp_t rsp;
+    mcSoDataCont_t soDataCont_;
+} cmpRspTltContPersonalize_t;
+
+
+/** @} */
+
+/** @} */
+
+
+#endif // CMP_H_
+
+/** @} */
+
diff --git a/mobicore/common/MobiCore/inc/TlCm/tlCmApi.h b/mobicore/common/MobiCore/inc/TlCm/tlCmApi.h
new file mode 100644
index 0000000..6428dd2
--- /dev/null
+++ b/mobicore/common/MobiCore/inc/TlCm/tlCmApi.h
@@ -0,0 +1,184 @@
+/** @addtogroup CMP
+ * @{
+ * @file
+ * Interface to content management trustlet definitions.
+ *
+ * The TlCm (Content Management Trustlet) is responsible for implementing
+ * CMP commands and generating approriate CMP responses.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TLCMAPI_H_
+#define TLCMAPI_H_
+
+#include "cmp.h"
+#include "tlCmError.h"
+
+/** TlCm command ids.
+ * List of all commands supported by TlCm.
+ * @note All command ids must be in range 0 to 0x7FFFFFFF.
+ */
+//lint -esym(756, cmpCommands_t) cmpCommands_t type by itself not used.
+typedef enum cmpCommands_t {
+    MC_CMP_CMD_AUTHENTICATE = 0,
+    MC_CMP_CMD_BEGIN_ROOT_AUTHENTICATION = 1,
+    MC_CMP_CMD_BEGIN_SOC_AUTHENTICATION = 2,
+    MC_CMP_CMD_BEGIN_SP_AUTHENTICATION = 3, 
+    MC_CMP_CMD_GENERATE_AUTH_TOKEN = 4,
+    MC_CMP_CMD_GET_VERSION = 5,
+//  MC_CMP_CMD_ROOT_CONT_ACTIVATE = 6,
+    MC_CMP_CMD_ROOT_CONT_LOCK_BY_ROOT = 7,
+//  MC_CMP_CMD_ROOT_CONT_REGISTER = 8,
+    MC_CMP_CMD_ROOT_CONT_REGISTER_ACTIVATE = 9,
+    MC_CMP_CMD_ROOT_CONT_UNLOCK_BY_ROOT = 10,
+    MC_CMP_CMD_ROOT_CONT_UNREGISTER = 11,
+    MC_CMP_CMD_SP_CONT_ACTIVATE = 12,
+    MC_CMP_CMD_SP_CONT_LOCK_BY_ROOT = 13,
+    MC_CMP_CMD_SP_CONT_LOCK_BY_SP = 14,
+    MC_CMP_CMD_SP_CONT_REGISTER = 15,
+    MC_CMP_CMD_SP_CONT_REGISTER_ACTIVATE = 16,
+    MC_CMP_CMD_SP_CONT_UNLOCK_BY_ROOT = 17,
+    MC_CMP_CMD_SP_CONT_UNLOCK_BY_SP = 18,
+    MC_CMP_CMD_SP_CONT_UNREGISTER = 19,
+    MC_CMP_CMD_TLT_CONT_ACTIVATE = 20,
+    MC_CMP_CMD_TLT_CONT_LOCK_BY_SP = 21,
+    MC_CMP_CMD_TLT_CONT_PERSONALIZE = 22,
+    MC_CMP_CMD_TLT_CONT_REGISTER = 23,
+    MC_CMP_CMD_TLT_CONT_REGISTER_ACTIVATE = 24,
+    MC_CMP_CMD_TLT_CONT_UNLOCK_BY_SP = 25,
+    MC_CMP_CMD_TLT_CONT_UNREGISTER = 26,
+    MC_CMP_CMD_GET_SUID = 27,
+    MC_CMP_CMD_AUTHENTICATE_TERMINATE = 28,
+    MC_CMP_CMD_LAST_ = MC_CMP_CMD_AUTHENTICATE_TERMINATE,
+} cmpCommands_t;
+
+/**
+ * CMP Content Manager message data.
+ */
+typedef union {
+    cmpCommandHeader_t commandHeader;
+    cmpResponseHeader_t responseHeader;
+
+    cmpCmdGetVersion_t cmpCmdGetVersion;
+    cmpRspGetVersion_t cmpRspGetVersion;
+
+    cmpCmdBeginSocAuthentication_t cmpCmdBeginSocAuthentication;
+    cmpRspBeginSocAuthentication_t cmpRspBeginSocAuthentication;
+
+    cmpCmdBeginRootAuthentication_t cmpCmdBeginRootAuthentication;
+    cmpRspBeginRootAuthentication_t cmpRspBeginRootAuthentication;
+
+    cmpCmdBeginSpAuthentication_t cmpCmdBeginSpAuthentication;
+    cmpRspBeginSpAuthentication_t cmpRspBeginSpAuthentication;
+
+    cmpCmdAuthenticate_t cmpCmdAuthenticate;
+    cmpRspAuthenticate_t cmpRspAuthenticate;
+
+    cmpCmdGenAuthToken_t cmpCmdGenAuthToken;
+    cmpRspGenAuthToken_t cmpRspGenAuthToken;
+
+    cmpCmdRootContRegisterActivate_t cmpCmdRootContRegisterActivate;
+    cmpRspRootContRegisterActivate_t cmpRspRootContRegisterActivate;
+
+    cmpCmdRootContUnregister_t cmpCmdRootContUnregister;
+    cmpRspRootContUnregister_t cmpRspRootContUnregister;
+
+    cmpCmdRootContLockByRoot_t cmpCmdRootContLockByRoot;
+    cmpRspRootContLockByRoot_t cmpRspRootContLockByRoot;
+
+    cmpCmdRootContUnlockByRoot_t cmpCmdRootContUnlockByRoot;
+    cmpRspRootContUnlockByRoot_t cmpRspRootContUnlockByRoot;
+
+    cmpCmdSpContRegisterActivate_t cmpCmdSpContRegisterActivate;
+    cmpRspSpContRegisterActivate_t cmpRspSpContRegisterActivate;
+
+    cmpCmdSpContUnregister_t cmpCmdSpContUnregister;
+    cmpRspSpContUnregister_t cmpRspSpContUnregister;
+
+    cmpCmdSpContLockByRoot_t cmpCmdSpContLockByRoot;
+    cmpRspSpContLockByRoot_t cmpRspSpContLockByRoot;
+
+    cmpCmdSpContUnlockByRoot_t cmpCmdSpContUnlockByRoot;
+    cmpRspSpContUnlockByRoot_t cmpRspSpContUnlockByRoot;
+
+    cmpCmdSpContLockBySp_t cmpCmdSpContLockBySp;
+    cmpRspSpContLockBySp_t cmpRspSpContLockBySp;
+
+    cmpCmdSpContUnlockBySp_t cmpCmdSpContUnlockBySp;
+    cmpRspSpContUnlockBySp_t cmpRspSpContUnlockBySp;
+
+    cmpCmdTltContRegister_t cmpCmdTltContRegister;
+    cmpRspTltContRegister_t cmpRspTltContRegister;
+
+    cmpCmdTltContActivate_t cmpCmdTltContActivate;
+    cmpRspTltContActivate_t cmpRspTltContActivate;
+
+    cmpCmdTltContRegisterActivate_t cmpCmdTltContRegisterActivate;
+    cmpRspTltContRegisterActivate_t cmpRspTltContRegisterActivate;
+
+    cmpCmdTltContLockBySp_t cmpCmdTltContLockBySp;
+    cmpRspTltContLockBySp_t cmpRspTltContLockBySp;
+
+    cmpCmdTltContUnlockBySp_t cmpCmdTltContUnlockBySp;
+    cmpRspTltContUnlockBySp_t cmpRspTltContUnlockBySp;
+
+    cmpCmdTltContUnregister_t cmpCmdTltContUnregister;
+    cmpRspTltContUnregister_t cmpRspTltContUnregister;
+
+    cmpCmdGetSuid_t cmpCmdGetSuid;
+    cmpRspGetSuid_t cmpRspGetSuid;
+
+    cmpCmdAuthenticateTerminate_t cmpCmdAuthenticateTerminate;
+    cmpRspAuthenticateTerminate_t cmpRspAuthenticateTerminate;
+
+    cmpCmdTltContPersonalize_t cmpCmdTltContPersonalize;
+    cmpRspTltContPersonalize_t cmpRspTltContPersonalize;
+
+    cmpCmdSpContRegister_t cmpCmdSpContRegister;
+    cmpRspSpContRegister_t cmpRspSpContRegister;
+
+    cmpCmdSpContActivate_t cmpCmdSpContActivate;
+    cmpRspSpContActivate_t cmpRspSpContActivate;
+} cmpMessage_t;
+
+/**
+ * Overall CMP structure.
+ */
+typedef struct {
+    /** CMP message. */
+    cmpMessage_t msg;
+} cmp_t;
+
+/**
+ * TlCm exit code: TlCm exited with error.
+ */
+#define EXIT_ERROR  ((uint32_t)(-1))
+
+#endif // TLCMAPI_H_
+
+/** @} */
diff --git a/mobicore/common/MobiCore/inc/TlCm/tlCmError.h b/mobicore/common/MobiCore/inc/TlCm/tlCmError.h
new file mode 100644
index 0000000..ed1fe24
--- /dev/null
+++ b/mobicore/common/MobiCore/inc/TlCm/tlCmError.h
@@ -0,0 +1,62 @@
+/** @addtogroup CMP
+ * @{
+ *
+ * @file
+ * TlCm error return code definitions.
+ * Definition of all possible TlCm rror return codes.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TLCMERROR_H_
+#define TLCMERROR_H_
+
+#define  SUCCESSFUL                                  0x00000000
+
+#define RET_ERR_EXT_UNKNOWN_COMMAND                  0xE0000000
+#define RET_ERR_EXT_SECURITY_STATUS_NOT_SATISFIED    0xE0000010
+#define RET_ERR_EXT_SECURE_MESSAGING_FAILED          0xE0000020
+#define RET_ERR_EXT_INCORRECT_PARAMETERS             0xE0000030
+#define RET_ERR_EXT_REFERENCED_DATA_INVALID          0xE0000040
+#define RET_ERR_EXT_REFERENCED_DATA_NOT_FOUND        0xE0000050
+#define RET_ERR_EXT_METHOD_BLOCKED                   0xE0000060
+#define RET_ERR_EXT_CONDITIONS_OF_USE_NOT_SATISFIED  0xE0000070
+#define RET_ERR_EXT_DEVICE_ALREADY_BOUND             0xE0000080
+#define RET_ERR_EXT_ALREADY_REGISTERED               0xE0000090
+#define RET_ERR_EXT_ALREADY_ACTIVATED                0xE00000A0
+#define RET_ERR_EXT_NOT_REGISTERED                   0xE00000B0
+#define RET_ERR_EXT_NOT_ACTIVATED                    0xE00000C0
+#define RET_ERR_EXT_CONTAINER_FULL                   0xE00000D0
+#define RET_ERR_EXT_INTERNAL_ERROR                   0xE0001000
+
+#define RET_ERR_EXT_UNSPECIFIED                      0xEEEEEEEE
+
+#endif // TLCMERROR_H_
+
+/** @} */
+
+
diff --git a/mobicore/common/MobiCore/inc/TlCm/tlCmUuid.h b/mobicore/common/MobiCore/inc/TlCm/tlCmUuid.h
new file mode 100644
index 0000000..6e17afd
--- /dev/null
+++ b/mobicore/common/MobiCore/inc/TlCm/tlCmUuid.h
@@ -0,0 +1,42 @@
+/** @addtogroup CMP
+ * @{
+ * @file
+ * Content management trustlet UUID definitions.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TLCMUUID_H
+#define TLCMUUID_H
+
+/** UUID of content management trustlet. */
+#define TL_CM_UUID { { 7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
+
+#endif // TLCMUUID_H
+
+/** @} */
+
diff --git a/mobicore/common/MobiCore/inc/TlCm/version.h b/mobicore/common/MobiCore/inc/TlCm/version.h
new file mode 100644
index 0000000..0719dcb
--- /dev/null
+++ b/mobicore/common/MobiCore/inc/TlCm/version.h
@@ -0,0 +1,36 @@
+/** @addtogroup CMP
+ * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef CMP_VERSION_H_
+#define CMP_VERSION_H_
+
+#define CMP_VERSION_MAJOR   2
+#define CMP_VERSION_MINOR   0
+
+#endif /** CMP_VERSION_H_ */
+
+
diff --git a/mobicore/common/MobiCore/inc/mcContainer.h b/mobicore/common/MobiCore/inc/mcContainer.h
new file mode 100644
index 0000000..a1ad57a
--- /dev/null
+++ b/mobicore/common/MobiCore/inc/mcContainer.h
@@ -0,0 +1,275 @@
+/** @addtogroup MC_CONTAINER mcContainer - Containers for MobiCore Content Management.
+ * @ingroup  MC_DATA_TYPES
+ * @{
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef MC_CONTAINER_H_
+#define MC_CONTAINER_H_
+
+#include <stdint.h>
+
+#include "mcRootid.h"
+#include "mcSpid.h"
+#include "mcUuid.h"
+#include "mcSo.h"
+#include "mcSuid.h"
+
+#define CONTAINER_VERSION_MAJOR   2
+#define CONTAINER_VERSION_MINOR   0
+
+#define MC_CONT_SYMMETRIC_KEY_SIZE      32 
+#define MC_CONT_PUBLIC_KEY_SIZE         320
+#define MC_CONT_CHILDREN_COUNT          16
+#define MC_DATA_CONT_MAX_DATA_SIZE      2048
+#define MC_TLT_CODE_HASH_SIZE           32
+
+#define MC_BYTES_TO_WORDS(bytes)       ( (bytes) / sizeof(uint32_t) )
+#define MC_ENUM_32BIT_SPACER           ((int32_t)-1)
+
+typedef uint32_t mcContVersion_t;
+
+/** Personalization Data ID. */
+typedef struct {
+    uint32_t data;
+} mcPid_t;
+
+typedef struct {
+    uint32_t keydata[MC_BYTES_TO_WORDS(MC_CONT_SYMMETRIC_KEY_SIZE)];
+} mcSymmetricKey_t;
+
+typedef struct {
+    uint32_t keydata[MC_BYTES_TO_WORDS(MC_CONT_PUBLIC_KEY_SIZE)];
+} mcPublicKey_t;
+
+typedef mcSpid_t spChild_t[MC_CONT_CHILDREN_COUNT];
+
+typedef mcUuid_t mcUuidChild_t[MC_CONT_CHILDREN_COUNT];
+
+/** Content management container states.
+ */
+typedef enum {
+     /** Container state unregistered. */
+     MC_CONT_STATE_UNREGISTERED = 0,
+     /** Container is registered. */
+     MC_CONT_STATE_REGISTERED = 1,
+     /** Container  is activated. */
+     MC_CONT_STATE_ACTIVATED = 2,
+     /** Container is locked by root. */
+     MC_CONT_STATE_ROOT_LOCKED = 3,
+     /** Container is locked by service provider. */
+     MC_CONT_STATE_SP_LOCKED = 4,
+     /** Container is locked by root and service provider. */
+     MC_CONT_STATE_ROOT_SP_LOCKED = 5,
+     /** Dummy: ensure that enum is 32 bits wide. */
+     MC_CONT_ATTRIB_SPACER = MC_ENUM_32BIT_SPACER
+} mcContainerState_t;
+
+/** Content management container attributes.
+ */
+typedef struct {
+    mcContainerState_t state;
+} mcContainerAttribs_t;
+
+/** Container types. */
+typedef enum {
+    /** SOC container. */
+    CONT_TYPE_SOC = 0,
+    /** Root container. */
+    CONT_TYPE_ROOT,
+    /** Service provider container. */
+    CONT_TYPE_SP,
+    /** Trustlet container. */
+    CONT_TYPE_TLCON,
+    /** Service provider data. */
+    CONT_TYPE_SPDATA,
+    /** Trustlet data. */
+    CONT_TYPE_TLDATA
+} contType_t;
+
+
+/** @defgroup MC_CONTAINER_CRYPTO_OBJECTS Container secrets.
+ * Data that is stored encrypted within the container.
+ * @{ */
+
+/** SoC secret */
+typedef struct {
+    mcSymmetricKey_t kSocAuth;
+} mcCoSocCont_t;
+
+/** */
+typedef struct {
+    mcSymmetricKey_t kRootAuth;
+} mcCoRootCont_t;
+
+/** */
+typedef struct {
+    mcSymmetricKey_t kSpAuth;
+} mcCoSpCont_t;
+
+/** */
+typedef struct {
+    mcSymmetricKey_t kTl;
+} mcCoTltCont_t;
+
+/** */
+typedef struct {
+    uint8_t data[MC_DATA_CONT_MAX_DATA_SIZE];
+} mcCoDataCont_t;
+
+/** */
+typedef union {
+    mcSpid_t spid;
+    mcUuid_t uuid;
+} mcCid_t;
+
+/** @} */
+
+/** @defgroup MC_CONTAINER_CONTAINER_OBJECTS Container definitions.
+ * Container type definitions.
+ * @{ */
+
+/** SoC Container */
+typedef struct {
+    contType_t type;
+    uint32_t version;
+    mcContainerAttribs_t attribs;
+    mcSuid_t suid;
+    // Secrets.
+    mcCoSocCont_t co;
+} mcSocCont_t;
+
+/** */
+typedef struct {
+    contType_t type;
+    uint32_t version;
+    mcContainerAttribs_t attribs;
+    mcSuid_t suid;
+    mcRootid_t rootid;
+    spChild_t children;
+    // Secrets.
+    mcCoRootCont_t co;
+} mcRootCont_t; 
+
+/** */
+typedef struct {
+    contType_t type;
+    uint32_t version;
+    mcContainerAttribs_t attribs;
+    mcSpid_t spid;
+    mcUuidChild_t children;
+    // Secrets.
+    mcCoSpCont_t co;
+} mcSpCont_t;
+
+/** */
+typedef struct {
+    contType_t type;
+    uint32_t version;
+    mcContainerAttribs_t attribs;
+    mcSpid_t parent;
+    mcUuid_t uuid;
+    // Secrets.
+    mcCoTltCont_t co;
+} mcTltCont_t;
+
+/** */
+typedef struct {
+    contType_t type;
+    uint32_t version;
+    mcUuid_t uuid;
+    mcPid_t pid;
+    // Secrets.
+    mcCoDataCont_t co;
+} mcDataCont_t;
+
+/** @} */
+
+/** Calculates the total size of the secure object hash and padding for a given
+ * container.
+ * @param contTotalSize Total size of the container (sum of plain and encrypted
+ * parts).
+ * @param contCoSize Size/length of the encrypted container part ("crypto
+ * object").
+ * @return Total size of hash and padding for given container.
+ */
+#define SO_CONT_HASH_AND_PAD_SIZE(contTotalSize, contCoSize) ( \
+    MC_SO_SIZE((contTotalSize) - (contCoSize), (contCoSize)) \
+        - sizeof(mcSoHeader_t) \
+        - (contTotalSize) )
+
+/** @defgroup MC_CONTAINER_SECURE_OBJECTS Containers in secure objects.
+ * Secure objects wrapping different containers.
+ * @{ */
+
+/** Authentication token */
+typedef struct {
+    mcSoHeader_t soHeader;
+    mcSocCont_t coSoc;
+    uint8_t hashAndPad[SO_CONT_HASH_AND_PAD_SIZE(sizeof(mcSocCont_t), sizeof(mcCoSocCont_t))];
+} mcSoAuthTokenCont_t;
+
+/** Root container */
+typedef struct {
+    mcSoHeader_t soHeader;
+    mcRootCont_t cont; 
+    uint8_t hashAndPad[SO_CONT_HASH_AND_PAD_SIZE(sizeof(mcRootCont_t), sizeof(mcCoRootCont_t))];
+} mcSoRootCont_t;
+
+/** */
+typedef struct {
+    mcSoHeader_t soHeader;
+    mcSpCont_t cont;
+    uint8_t hashAndPad[SO_CONT_HASH_AND_PAD_SIZE(sizeof(mcSpCont_t), sizeof(mcCoSpCont_t))];
+} mcSoSpCont_t;
+
+/** */
+typedef struct {
+    mcSoHeader_t soHeader;
+    mcTltCont_t cont;
+    uint8_t hashAndPad[SO_CONT_HASH_AND_PAD_SIZE(sizeof(mcTltCont_t), sizeof(mcCoTltCont_t))];
+} mcSoTltCont_t;
+
+/** */
+typedef struct {
+    mcSoHeader_t soHeader;
+    mcDataCont_t cont;
+    uint8_t hashAndPad[SO_CONT_HASH_AND_PAD_SIZE(sizeof(mcDataCont_t), sizeof(mcCoDataCont_t))];
+} mcSoDataCont_t; 
+
+/** */
+typedef struct {
+    mcSoRootCont_t soRoot;
+    mcSoSpCont_t soSp;
+    mcSoTltCont_t soTlt;
+} mcSoContainerPath_t;
+
+/** @} */
+
+#endif // MC_CONTAINER_H_
+
+/** @} */
diff --git a/mobicore/common/MobiCore/inc/mcDriverId.h b/mobicore/common/MobiCore/inc/mcDriverId.h
new file mode 100644
index 0000000..e4e6a39
--- /dev/null
+++ b/mobicore/common/MobiCore/inc/mcDriverId.h
@@ -0,0 +1,64 @@
+/**
+ * @file
+ * Driver ID definition.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2011-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RTMDRVID_H_
+#define RTMDRVID_H_
+
+#define MC_DRV_VENDOR_ID_SHIFT     (16)
+#define MC_DRV_VENDOR_ID_MASK      (0xFFFF << MC_DRV_VENDOR_ID_SHIFT)
+#define MC_DRV_NUMBER_MASK         (0x0000FFFF)
+
+/** MobiCore vendor IDs. */
+typedef enum {
+    MC_DRV_VENDOR_ID_GD   = 0 << MC_DRV_VENDOR_ID_SHIFT,
+} mcDrvVendorId_t;
+
+/** MobiCore GD driver numbers. */
+typedef enum {
+	MC_DRV_NUMBER_INVALID = 0,
+	MC_DRV_NUMBER_CRYPTO  = 1,
+    MC_DRV_NUMBER_KEYPAD  = 2,
+    /** Last GD driver number reserved for pre-installed drivers. 
+     * GD driver numbers up to this constant may not be used for loadable drivers. */
+    MC_DRV_NUMBER_LAST_PRE_INSTALLED = 100,
+} mcDrvNumber_t;
+
+/** MobiCore driver IDs for Trustlets. */
+typedef enum {
+	MC_DRV_ID_INVALID = MC_DRV_VENDOR_ID_GD | MC_DRV_NUMBER_INVALID,
+	MC_DRV_ID_CRYPTO  = MC_DRV_VENDOR_ID_GD | MC_DRV_NUMBER_CRYPTO,
+    MC_DRV_ID_KEYPAD  = MC_DRV_VENDOR_ID_GD | MC_DRV_NUMBER_KEYPAD,
+    /** Last GD driver ID reserved for pre-installed drivers. 
+     * GD driver IDs up to this constant may not be used for loadable drivers. */
+    MC_DRV_ID_LAST_PRE_INSTALLED = MC_DRV_VENDOR_ID_GD | MC_DRV_NUMBER_LAST_PRE_INSTALLED,
+} mcDriverId_t;
+
+#endif /* RTMDRVID_H_ */
diff --git a/mobicore/common/MobiCore/inc/mcLoadFormat.h b/mobicore/common/MobiCore/inc/mcLoadFormat.h
new file mode 100644
index 0000000..eca9962
--- /dev/null
+++ b/mobicore/common/MobiCore/inc/mcLoadFormat.h
@@ -0,0 +1,194 @@
+/**
+ * @defgroup MCLF   MobiCore Load Format
+ *
+ * @defgroup MCLF_VER    MCLF Versions
+ * @ingroup MCLF
+ *
+ * @addtogroup MCLF
+ * @{
+ *
+ * MobiCore Load Format declarations.
+ *
+ * Holds the definitions for the layout of MobiCore Trustlet Blob.
+ * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef MCLOADFORMAT_H_
+#define MCLOADFORMAT_H_
+
+#include "mcUuid.h"
+#include "mcDriverId.h"
+
+#define MCLF_VERSION_MAJOR   2
+#define MCLF_VERSION_MINOR   1
+
+#define MC_SERVICE_HEADER_MAGIC_BE         ((uint32_t)('M'|('C'<<8)|('L'<<16)|('F'<<24))) /**< "MCLF" in big endian integer representation */
+#define MC_SERVICE_HEADER_MAGIC_LE         ((uint32_t)(('M'<<24)|('C'<<16)|('L'<<8)|'F')) /**< "MCLF" in little endian integer representation */
+#define MC_SERVICE_HEADER_MAGIC_STR         "MCLF"                                        /**< "MCLF" as string */
+
+/** @name MCLF flags */
+/*@{*/
+#define MC_SERVICE_HEADER_FLAGS_PERMANENT               (1U << 0) /**< Loaded service cannot be unloaded from MobiCore. */
+#define MC_SERVICE_HEADER_FLAGS_NO_CONTROL_INTERFACE    (1U << 1) /**< Service has no WSM control interface. */
+#define MC_SERVICE_HEADER_FLAGS_DEBUGGABLE              (1U << 2) /**< Service can be debugged. */
+/*@}*/
+
+#if !defined(ADDR_T_DEFINED)
+#define ADDR_T_DEFINED
+typedef void*    addr_t;                /**< an address, can be physical or virtual */
+#endif // !defined(ADDR_T_DEFINED)
+
+/** Service type.
+ * The service type defines the type of executable.
+ */
+typedef enum {
+    SERVICE_TYPE_ILLEGAL    = 0,        /**< Service type is invalid. */
+    SERVICE_TYPE_DRIVER     = 1,        /**< Service is a driver. */
+    SERVICE_TYPE_SP_TRUSTLET   = 2,     /**< Service is a Trustlet. */
+    SERVICE_TYPE_SYSTEM_TRUSTLET = 3    /**< Service is a system Trustlet. */
+} serviceType_t;
+
+/**
+ * Memory types.
+ */
+typedef enum {
+    MCLF_MEM_TYPE_INTERNAL_PREFERRED = 0, /**< If available use internal memory; otherwise external memory. */
+    MCLF_MEM_TYPE_INTERNAL = 1, /**< Internal memory must be used for executing the service. */
+    MCLF_MEM_TYPE_EXTERNAL = 2, /**< External memory must be used for executing the service. */
+} memType_t;
+
+/**
+ * Descriptor for a memory segment.
+ */
+typedef struct {
+    addr_t      start;  /**< Virtual start address. */
+    uint32_t    len;    /**< Length of the segment in bytes. */
+} segmentDescriptor_t, *segmentDescriptor_ptr;
+
+/**
+ * MCLF intro for data structure identification.
+ * Must be the first element of a valid MCLF file.
+ */
+typedef struct {
+    uint32_t        magic;      /**< Header magic value ASCII "MCLF". */
+    uint32_t        version;    /**< Version of the MCLF header structure. */
+} mclfIntro_t, *mclfIntro_ptr;
+
+/** @} */
+
+
+// Version 1 /////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * @defgroup MCLF_VER_V1   MCLF Version 1
+ * @ingroup MCLF_VER
+ *
+ * @addtogroup MCLF_VER_V1
+ * @{
+ */
+
+/**
+ * Version 1 MCLF header.
+ */
+typedef struct {
+    mclfIntro_t             intro;           /**< MCLF header start with the mandatory intro. */
+    uint32_t                flags;           /**< Service flags. */
+    memType_t               memType;         /**< Type of memory the service must be executed from. */
+    serviceType_t           serviceType;     /**< Type of service. */
+
+    uint32_t                numInstances;    /**< Number of instances which can be run simultaneously. */
+    mcUuid_t                uuid;            /**< Loadable service unique identifier (UUID). */
+    mcDriverId_t            driverId;        /**< If the serviceType is SERVICE_TYPE_DRIVER the Driver ID is used. */
+    uint32_t                numThreads;      /**<
+                                              * <pre>
+                                              * <br>Number of threads (N) in a service depending on service type.<br>
+                                              *
+                                              *   SERVICE_TYPE_SP_TRUSTLET: N = 1
+                                              *   SERVICE_TYPE_SYSTEM_TRUSTLET: N = 1
+                                              *   SERVICE_TYPE_DRIVER: N >= 1
+                                              * </pre>
+                                              */
+    segmentDescriptor_t     text;           /**< Virtual text segment. */
+    segmentDescriptor_t     data;           /**< Virtual data segment. */
+    uint32_t                bssLen;         /**< Length of the BSS segment in bytes. MUST be at least 8 byte. */
+    addr_t                  entry;          /**< Virtual start address of service code. */
+} mclfHeaderV1_t, *mclfHeaderV1_ptr;
+/** @} */
+
+// Version 2 /////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * @defgroup MCLF_VER_V2   MCLF Version 2
+ * @ingroup MCLF_VER
+ *
+ * @addtogroup MCLF_VER_V2
+ * @{
+ */
+
+/**
+ * Version 2 MCLF header.
+ */
+typedef struct {
+    mclfIntro_t             intro;           /**< MCLF header start with the mandatory intro. */
+    uint32_t                flags;           /**< Service flags. */
+    memType_t               memType;         /**< Type of memory the service must be executed from. */
+    serviceType_t           serviceType;     /**< Type of service. */
+
+    uint32_t                numInstances;    /**< Number of instances which can be run simultaneously. */
+    mcUuid_t                uuid;            /**< Loadable service unique identifier (UUID). */
+    mcDriverId_t            driverId;        /**< If the serviceType is SERVICE_TYPE_DRIVER the Driver ID is used. */
+    uint32_t                numThreads;      /**<
+                                              * <pre>
+                                              * <br>Number of threads (N) in a service depending on service type.<br>
+                                              *
+                                              *   SERVICE_TYPE_SP_TRUSTLET: N = 1
+                                              *   SERVICE_TYPE_SYSTEM_TRUSTLET: N = 1
+                                              *   SERVICE_TYPE_DRIVER: N >= 1
+                                              * </pre>
+                                              */
+    segmentDescriptor_t     text;           /**< Virtual text segment. */
+    segmentDescriptor_t     data;           /**< Virtual data segment. */
+    uint32_t                bssLen;         /**< Length of the BSS segment in bytes. MUST be at least 8 byte. */
+    addr_t                  entry;          /**< Virtual start address of service code. */
+    uint32_t                serviceVersion; /**< Version of the interface the driver exports. */
+} mclfHeaderV2_t, *mclfHeaderV2_ptr;
+/** @} */
+
+
+// Version 1 and 2 ///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * @addtogroup MCLF
+ * @{
+ */
+
+/** MCLF header */
+typedef union {
+    mclfIntro_t    intro;           /**< Intro for data structure identification. */
+    mclfHeaderV1_t mclfHeaderV1;    /**< Version 1 header */
+    mclfHeaderV2_t mclfHeaderV2;    /**< Version 2 header */
+} mclfHeader_t, *mclfHeader_ptr;
+
+#endif /* MCLOADFORMAT_H_ */
+
+/** @} */
diff --git a/mobicore/common/MobiCore/inc/mcRootid.h b/mobicore/common/MobiCore/inc/mcRootid.h
new file mode 100644
index 0000000..9b88e1d
--- /dev/null
+++ b/mobicore/common/MobiCore/inc/mcRootid.h
@@ -0,0 +1,54 @@
+/**
+ * @addtogroup MC_ROOTID mcRootid - Root container id.
+ *
+ * Global definition of root ID.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2011-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @ingroup  MC_DATA_TYPES
+ * @{
+ */
+
+#ifndef MC_ROOTID_H_
+#define MC_ROOTID_H_
+
+/** Root Identifier type. */
+typedef uint32_t mcRootid_t;
+
+/** Reserved root id value 1. */
+static const mcRootid_t MC_ROOTID_RESERVED1 = 0;
+
+/** Reserved root id value 2. */
+static const mcRootid_t MC_ROOTID_RESERVED2 = 0xFFFFFFFF;
+
+/** Root id for system applications. */
+static const mcRootid_t MC_ROOTID_SYSTEM = 0xFFFFFFFE;
+
+#endif // MC_ROOTID_H_
+
+/** @} */
+
diff --git a/mobicore/common/MobiCore/inc/mcSo.h b/mobicore/common/MobiCore/inc/mcSo.h
new file mode 100644
index 0000000..cf1f4ae
--- /dev/null
+++ b/mobicore/common/MobiCore/inc/mcSo.h
@@ -0,0 +1,164 @@
+/**
+ * @defgroup MC_DATA_TYPES MobiCore generic data types
+ *
+ * @addtogroup MC_SO mcSo - Secure objects definitions.
+ * <!-- Copyright Giesecke & Devrient GmbH 2011-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @ingroup  MC_DATA_TYPES
+ * @{
+ *
+ */
+
+#ifndef MC_SO_H_
+#define MC_SO_H_
+
+#include "mcUuid.h"
+#include "mcSpid.h"
+
+#define SO_VERSION_MAJOR   2
+#define SO_VERSION_MINOR   0
+
+#define MC_ENUM_32BIT_SPACER           ((int32_t)-1)
+
+/** Secure object type. */
+typedef enum {
+    /** Regular secure object. */
+    MC_SO_TYPE_REGULAR = 0x00000001,
+    /** Dummy to ensure that enum is 32 bit wide. */
+    MC_SO_TYPE_DUMMY = MC_ENUM_32BIT_SPACER,
+} mcSoType_t;
+
+
+/** Secure object context.
+ * A context defines which key to use to encrypt/decrypt a secure object.
+ */
+typedef enum {
+    /** Trustlet context. */
+    MC_SO_CONTEXT_TLT = 0x00000001,
+     /** Service provider context. */
+    MC_SO_CONTEXT_SP = 0x00000002,
+     /** Device context. */
+    MC_SO_CONTEXT_DEVICE = 0x00000003,
+    /** Dummy to ensure that enum is 32 bit wide. */
+    MC_SO_CONTEXT_DUMMY = MC_ENUM_32BIT_SPACER,
+} mcSoContext_t;
+
+/** Secure object lifetime.
+ * A lifetime defines how long a secure object is valid.
+ */
+typedef enum {
+    /** SO does not expire. */
+    MC_SO_LIFETIME_PERMANENT = 0x00000000,
+    /** SO expires on reboot (coldboot). */
+    MC_SO_LIFETIME_POWERCYCLE = 0x00000001,
+    /** SO expires when Trustlet is closed. */
+    MC_SO_LIFETIME_SESSION = 0x00000002,
+    /** Dummy to ensure that enum is 32 bit wide. */
+    MC_SO_LIFETIME_DUMMY = MC_ENUM_32BIT_SPACER,
+} mcSoLifeTime_t;
+
+/** Service provider Trustlet id.
+ * The combination of service provider id and Trustlet UUID forms a unique
+ * Trustlet identifier.
+ */
+typedef struct {
+    /** Service provider id. */
+    mcSpid_t spid;
+    /** Trustlet UUID. */
+    mcUuid_t uuid;
+} tlApiSpTrustletId_t;
+
+/** Secure object header.
+ * A secure object header introduces a secure object.
+ * Layout of a secure object:
+ * <pre>
+ * <code>
+ *
+ *     +--------+------------------+------------------+--------+---------+
+ *     | Header |   plain-data     |  encrypted-data  |  hash  | padding |
+ *     +--------+------------------+------------------+--------+---------+
+ *
+ *     /--------/---- plainLen ----/-- encryptedLen --/-- 32 --/- 1..16 -/
+ *
+ *     /----------------- toBeHashedLen --------------/
+ *
+ *                                 /---------- toBeEncryptedLen ---------/
+ *
+ *     /--------------------------- totalSoSize -------------------------/
+ *
+ * </code>
+ * </pre>
+ */
+typedef struct {
+    /** Type of secure object. */
+    uint32_t type;
+    /** Secure object version. */
+    uint32_t version;
+    /** Secure object context. */
+    mcSoContext_t context;
+    /** Secure object lifetime. */
+    mcSoLifeTime_t lifetime;
+    /** Producer Trustlet id. */
+    tlApiSpTrustletId_t producer;
+    /** Length of unencrypted user data (after the header). */
+    uint32_t plainLen;
+    /** Length of encrypted user data (after unencrypted data, excl. checksum
+     * and excl. padding bytes). */
+    uint32_t encryptedLen;
+} mcSoHeader_t;
+
+/** Maximum size of the payload (plain length + encrypted length) of a secure object. */
+#define MC_SO_PAYLOAD_MAX_SIZE      1000000
+
+/** Block size of encryption algorithm used for secure objects. */
+#define MC_SO_ENCRYPT_BLOCK_SIZE    16
+
+/** Maximum number of ISO padding bytes. */
+#define MC_SO_MAX_PADDING_SIZE (MC_SO_ENCRYPT_BLOCK_SIZE)
+
+/** Size of hash used for secure objects. */
+#define MC_SO_HASH_SIZE             32
+
+/** Calculates gross size of cryptogram within secure object including ISO padding bytes. */
+#define MC_SO_ENCRYPT_PADDED_SIZE(netsize) ( (netsize) + \
+    MC_SO_MAX_PADDING_SIZE - (netsize) % MC_SO_MAX_PADDING_SIZE )
+
+/** Calculates the total size of a secure object.
+ * @param plainLen Length of plain text part within secure object.
+ * @param encryptedLen Length of encrypted part within secure object (excl.
+ * hash, padding).
+ * @return Total (gross) size of the secure object or 0 if given parameters are
+ * illegal or would lead to a secure object of invalid size.
+ */
+#define MC_SO_SIZE(plainLen, encryptedLen) ( \
+    ((plainLen) + (encryptedLen) < (encryptedLen) || (plainLen) + (encryptedLen) > MC_SO_PAYLOAD_MAX_SIZE) ? 0 : \
+    sizeof(mcSoHeader_t) + (plainLen) + MC_SO_ENCRYPT_PADDED_SIZE((encryptedLen) + MC_SO_HASH_SIZE) \
+)
+
+#endif // MC_SO_H_
+
+/** @} */
diff --git a/mobicore/common/MobiCore/inc/mcSpid.h b/mobicore/common/MobiCore/inc/mcSpid.h
new file mode 100644
index 0000000..2e8f80c
--- /dev/null
+++ b/mobicore/common/MobiCore/inc/mcSpid.h
@@ -0,0 +1,53 @@
+/**
+ * @addtogroup MC_SPID mcSpid - service provider ID.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2011-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * @ingroup  MC_DATA_TYPES
+ * @{
+ */
+
+#ifndef MC_SPID_H_
+#define MC_SPID_H_
+
+/** Service provider Identifier type. */
+typedef uint32_t mcSpid_t;
+
+/** SPID value used as free marker in root containers. */
+static const mcSpid_t MC_SPID_FREE = 0xFFFFFFFF;
+
+/** Reserved SPID value. */
+static const mcSpid_t MC_SPID_RESERVED = 0;
+
+/** SPID for system applications. */
+static const mcSpid_t MC_SPID_SYSTEM = 0xFFFFFFFE;
+
+#endif // MC_SPID_H_
+
+/** @} */
+
+
+
diff --git a/mobicore/common/MobiCore/inc/mcSuid.h b/mobicore/common/MobiCore/inc/mcSuid.h
new file mode 100644
index 0000000..55afa98
--- /dev/null
+++ b/mobicore/common/MobiCore/inc/mcSuid.h
@@ -0,0 +1,53 @@
+/**
+ * @addtogroup MC_SUID mcSuid - SoC unique ID.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2011-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @ingroup  MC_DATA_TYPES
+ * @{
+ */
+
+#ifndef MC_SUID_H_
+#define MC_SUID_H_
+
+/** Length of SUID. */
+#define MC_SUID_LEN    16
+
+/** Platform specific device identifier (serial number of the chip). */
+typedef struct {
+    uint8_t data[MC_SUID_LEN - sizeof(uint32_t)];
+} suidData_t;
+
+/** Soc unique identifier type. */
+typedef struct {
+    uint32_t    sipId;  /**< Silicon Provider ID to be set during build. */
+    suidData_t  suidData;
+} mcSuid_t;
+
+#endif // MC_SUID_H_
+
+/** @} */
diff --git a/mobicore/common/MobiCore/inc/mcUuid.h b/mobicore/common/MobiCore/inc/mcUuid.h
new file mode 100644
index 0000000..a1d2a0b
--- /dev/null
+++ b/mobicore/common/MobiCore/inc/mcUuid.h
@@ -0,0 +1,74 @@
+/**
+ * @addtogroup MC_UUID mcUuid - Universally Unique Identifier.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2011-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @ingroup  MC_DATA_TYPES
+ * @{
+ */
+
+#ifndef MC_UUID_H_
+#define MC_UUID_H_
+
+#define UUID_TYPE
+
+/** Universally Unique Identifier (UUID) according to ISO/IEC 11578. */
+typedef struct {
+    uint8_t value[16]; /**< Value of the UUID. */
+} mcUuid_t, *mcUuid_ptr;
+
+/** UUID value used as free marker in service provider containers. */
+#define MC_UUID_FREE_DEFINE \
+    { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }
+
+static const mcUuid_t MC_UUID_FREE = {
+    MC_UUID_FREE_DEFINE
+};
+
+/** Reserved UUID. */
+#define MC_UUID_RESERVED_DEFINE \
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+
+static const mcUuid_t MC_UUID_RESERVED = {
+    MC_UUID_RESERVED_DEFINE
+};
+
+/** UUID for system applications. */
+#define MC_UUID_SYSTEM_DEFINE \
+    { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
+      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE }
+
+static const mcUuid_t MC_UUID_SYSTEM = {
+    MC_UUID_SYSTEM_DEFINE
+};
+
+#endif // MC_UUID_H_
+
+/** @} */
+
diff --git a/mobicore/common/MobiCore/inc/mcVersionHelper.h b/mobicore/common/MobiCore/inc/mcVersionHelper.h
new file mode 100644
index 0000000..87e33b5
--- /dev/null
+++ b/mobicore/common/MobiCore/inc/mcVersionHelper.h
@@ -0,0 +1,194 @@
+/** @addtogroup MC_RTM
+ * @{
+ * MobiCore Version Helper Macros
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+
+//lint -emacro(*,MC_CHECK_VERSION) Disable all warnings for this macro.
+//lint -emacro(*,MC_MAKE_VERSION) Disable all warnings for this macro.
+//lint -emacro(*,MC_GET_MAJOR_VERSION) Disable all warnings for this macro.
+//lint -emacro(*,MC_GET_MINOR_VERSION) Disable all warnings for this macro.
+//lint -emacro(*,MC_GET_MINOR_VERSION) Disable all warnings for this macro.
+//lint -emacro(*,ASSERT_VERSION_IMPLEMENTATION) Disable all warnings for this macro.
+//lint -esym(*,Actual_*) Disable all warnings for these functions.
+
+/** Create a version number given major and minor numbers. */
+#define MC_MAKE_VERSION(major,minor) \
+    (   (((major) & 0xffff) << 16) |\
+        ((minor) & 0xffff))
+
+/** Get major version number from complete version. */
+#define MC_GET_MAJOR_VERSION(version) ((version) >> 16)
+
+/** Get minor version number from complete version. */
+#define MC_GET_MINOR_VERSION(version) ((version) & 0xffff)
+
+// Asserts expression at compile-time (to be used outside a function body).
+#define ASSERT_VERSION_IMPLEMENTATION(comp, versionpart, requiredV, actualV, expression) \
+    extern int Actual_##comp##_##versionpart##_VERSION_##actualV##_does_not_match_required_version_##requiredV[(expression) ? 0:-1]
+
+#define ASSERT_VERSION_EVALUATOR(comp, versionpart, requiredV, actualV, expression) \
+        ASSERT_VERSION_IMPLEMENTATION(comp, versionpart, requiredV, actualV, expression)
+
+#define ASSERT_VERSION(required, comparator, comp, versionpart) \
+    ASSERT_VERSION_EVALUATOR(comp, versionpart, required, comp ##_VERSION_## versionpart, required comparator comp ##_VERSION_## versionpart)
+
+/** Checks at compile-time that an interface version provided by component
+ * 'comp' is identical to the required version of a component using this interface.
+ * Note! This check is useful for components that IMPLEMENT a particular
+ * interface to be alerted of changes to the interface which are likely to
+ * require adaptations in the implementation. */
+#define MC_CHECK_VERSION_EQUALS(comp, major, minor) \
+    ASSERT_VERSION(major, ==, comp, MAJOR); \
+    ASSERT_VERSION(minor, ==, comp, MINOR);
+
+/** Checks at compile-time that an interface version provided by component 'comp' meets the
+ * required version of a component using this interface. */
+#define MC_CHECK_VERSION_STATIC(comp, majorRequired, minorRequired) \
+    ASSERT_VERSION(majorRequired, ==, comp, MAJOR); \
+    ASSERT_VERSION(minorRequired, <=, comp, MINOR);
+
+/** Version check helper macro for an interface consumer against an interface
+ * provider.
+ * @param comp          Name of Interface to check.
+ * @param majorRequired Required major version of interface provider.
+ * @param minorRequired Required minor version of interface provider.
+ * Performs a compile-time interface version check that comp_VERSION_MAJOR
+ * equals majorRequired and that comp_VERSION_MINOR is at least minorRequired.
+ * On success, compilation goes through.
+ * On error, compilation breaks, telling the component that did not match in the
+ * error message.
+ *
+ * Additionally, a function is created:
+ *
+ * checkVersionOk##component(uint32_t version, char** errmsg)
+ *
+ * Compares version against majorRequired and minorRequired.
+ * Additionally, it creates a message string that can be printed out using printf("%s", errmsg).
+ * It returns either only the actual version, or on mismatch, actual and required version.
+ *
+ * @param version[in] component version as returned by layer-specific getVersion.
+ * @param errmsg[out] a message string that contains a log.
+ *
+ */
+#if !defined(NDEBUG)
+#define MC_CHECK_VERSION(comp, majorRequired, minorRequired) \
+    MC_CHECK_VERSION_STATIC(comp, majorRequired, minorRequired) \
+    static uint32_t checkVersionOk##comp(uint32_t version, char** errmsg) { \
+        static char msgBuf[100]; \
+        uint32_t major = MC_GET_MAJOR_VERSION(version); \
+        uint32_t minor = MC_GET_MINOR_VERSION(version); \
+        uint32_t ret = 0; \
+        *errmsg = msgBuf; \
+        if ((major == majorRequired) && (minor >= minorRequired)) { \
+            snprintf(msgBuf, sizeof(msgBuf), \
+                #comp " version is %u.%u", major, minor); \
+            ret = 1; \
+        } else { \
+            snprintf(msgBuf, sizeof(msgBuf), \
+                #comp " version error. Got: %u.%u, want >= %u.%u", major, minor, majorRequired, minorRequired); \
+        } \
+        msgBuf[sizeof(msgBuf) - 1] = '\0'; \
+        return ret; \
+    } 
+#else
+#define MC_CHECK_VERSION(comp, majorRequired, minorRequired) \
+    MC_CHECK_VERSION_STATIC(comp, majorRequired, minorRequired) \
+    static uint32_t checkVersionOk##comp(uint32_t version, char** errmsg) { \
+        uint32_t major = MC_GET_MAJOR_VERSION(version); \
+        uint32_t minor = MC_GET_MINOR_VERSION(version); \
+        *errmsg = NULL; \
+        if ((major == majorRequired) && (minor >= minorRequired)) { \
+            return 1; \
+        }; \
+        return 0; \
+    } 
+#endif
+
+/** Version check helper macro for version checks of a data object version
+ * against an data object consumer.
+ * 
+ * @param comp           Name of Interface to check.
+ * @param majorRequired Major data object version supported by component.
+ * @param minorRequired Minor data object version supported by component.
+ * Performs a compile-time interface version check that comp_VERSION_MAJOR
+ * equals majorRequired and that comp_VERSION_MINOR is at least minorRequired.
+ * On success, compilation goes through.
+ * On error, compilation breaks, telling the component that did not match in the
+ * error message.
+ *
+ * Additionally, the following function is created:
+ *
+ * checkVersionOkDataObject##component(uint32_t version, char** errmsg)
+ *
+ * This function checks that the data object version is compatible with the
+ * interface version; that is, the major version of the data object must match
+ * exactly and the minor version of the data object MUST BE LESS OR EQUAL to the
+ * required interface version.
+ * Additionally, it creates a message string that can be printed out using printf("%s", errmsg).
+ * It returns either only the actual version, or on mismatch, actual and
+ * provided version.
+ *
+ * @param version[in] Data object version of data object.
+ * @param errmsg[out] a message string that contains a log.
+ *
+ */
+#if !defined(NDEBUG)
+#define MC_CHECK_DATA_OBJECT_VERSION(comp, majorRequired, minorRequired) \
+    MC_CHECK_VERSION_STATIC(comp, majorRequired, minorRequired) \
+    static uint32_t checkVersionOkDataObject##comp(uint32_t version, char** errmsg) { \
+        static char msgBuf[100]; \
+        uint32_t major = MC_GET_MAJOR_VERSION(version); \
+        uint32_t minor = MC_GET_MINOR_VERSION(version); \
+        uint32_t ret = 0; \
+        *errmsg = msgBuf; \
+        if ((major == majorRequired) && (minor <= minorRequired)) { \
+            snprintf(msgBuf, sizeof(msgBuf), \
+                #comp " version is %u.%u", major, minor); \
+            ret = 1; \
+        } else { \
+            snprintf(msgBuf, sizeof(msgBuf), \
+                #comp " version error. Got: %u.%u, want <= %u.%u", major, minor, majorRequired, minorRequired); \
+        } \
+        msgBuf[sizeof(msgBuf) - 1] = '\0'; \
+        return ret; \
+    } 
+#else
+#define MC_CHECK_DATA_OBJECT_VERSION(comp, majorRequired, minorRequired) \
+    MC_CHECK_VERSION_STATIC(comp, majorRequired, minorRequired) \
+    static uint32_t checkVersionOkDataObject##comp(uint32_t version, char** errmsg) { \
+        uint32_t major = MC_GET_MAJOR_VERSION(version); \
+        uint32_t minor = MC_GET_MINOR_VERSION(version); \
+        *errmsg = NULL; \
+        if ((major == majorRequired) && (minor <= minorRequired)) { \
+            return 1; \
+        }; \
+        return 0; \
+    } 
+#endif
diff --git a/mobicore/common/MobiCore/inc/mcVersionInfo.h b/mobicore/common/MobiCore/inc/mcVersionInfo.h
new file mode 100644
index 0000000..1464e73
--- /dev/null
+++ b/mobicore/common/MobiCore/inc/mcVersionInfo.h
@@ -0,0 +1,52 @@
+/** @addtogroup MC_RTM
+ * @{
+ * MobiCore Version Information
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MCVERSIONINFO_H_
+#define MCVERSIONINFO_H_
+
+/** Length of MobiCore product ID string. */
+#define MC_PRODUCT_ID_LEN 64
+
+/** Global MobiCore Version Information.
+ */
+typedef struct {
+    char productId[MC_PRODUCT_ID_LEN]; /** < Product ID of Mobicore; zero-terminated */
+    uint32_t versionMci;               /** < Version of Mobicore Control Interface */
+    uint32_t versionSo;                /** < Version of Secure Objects */
+    uint32_t versionMclf;              /** < Version of MobiCore Load Format */
+    uint32_t versionContainer;         /** < Version of MobiCore Container Format */
+    uint32_t versionMcConfig;          /** < Version of MobiCore Configuration Block Format */
+    uint32_t versionTlApi;             /** < Version of MobiCore Trustlet API Implementation */
+    uint32_t versionDrApi;             /** < Version of MobiCore Driver API Implementation */
+    uint32_t versionCmp;               /** < Version of Content Management Protocol */
+} mcVersionInfo_t;
+
+#endif /** MCVERSIONINFO_H_ */
diff --git a/mobicore/daemon/Android.mk b/mobicore/daemon/Android.mk
new file mode 100644
index 0000000..37a3fe3
--- /dev/null
+++ b/mobicore/daemon/Android.mk
@@ -0,0 +1,8 @@
+# =============================================================================
+#
+# Makefile pointing to all makefiles within the project.
+#
+# =============================================================================
+APP_PROJECT_PATH := $(call my-dir)
+# Including all Android.mk files from subdirectories
+include $(call all-subdir-makefiles)
diff --git a/mobicore/daemon/Application.mk b/mobicore/daemon/Application.mk
new file mode 100644
index 0000000..c88edd4
--- /dev/null
+++ b/mobicore/daemon/Application.mk
@@ -0,0 +1,17 @@
+# =============================================================================
+#
+# Main build file defining the project modules and their global variables.
+#
+# =============================================================================
+
+# Don't remove this - mandatory
+APP_PROJECT_PATH := $(call my-dir)
+
+# The only STL implementation currently working with exceptions
+APP_STL := stlport_static
+
+# Don't optimize for better debugging
+APP_OPTIM := debug
+
+# Show all warnings
+APP_CFLAGS := -Wall
diff --git a/mobicore/daemon/ClientLib/Android.mk b/mobicore/daemon/ClientLib/Android.mk
new file mode 100644
index 0000000..c2bf7e9
--- /dev/null
+++ b/mobicore/daemon/ClientLib/Android.mk
@@ -0,0 +1,47 @@
+# =============================================================================
+#
+# Module: libMcClient.so
+# 
+# C(version) Client Lib for Linux TLCs
+#
+# =============================================================================
+
+LOCAL_PATH	:= $(call my-dir)
+MY_CLIENTLIB_PATH	:= $(LOCAL_PATH)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE	:= libMcClient
+LOCAL_MODULE_TAGS := eng
+LOCAL_PRELINK_MODULE := false
+
+# External include files
+LOCAL_C_INCLUDES += bionic \
+	external/stlport/stlport
+
+# Add new folders with header files here
+LOCAL_C_INCLUDES +=\
+	$(LOCAL_PATH)/public \
+	$(APP_PROJECT_PATH) \
+	$(APP_PROJECT_PATH)/Daemon/public \
+	$(APP_PROJECT_PATH)/Kernel \
+	$(APP_PROJECT_PATH)/Kernel/Platforms/Generic \
+	$(APP_PROJECT_PATH)/Common
+
+# Add new folders with header files here
+LOCAL_C_INCLUDES +=\
+	$(COMP_PATH_MobiCore)/inc \
+	$(COMP_PATH_MobiCoreDriverMod)/Public
+
+# Add new source files here
+LOCAL_SRC_FILES +=\
+    Device.cpp\
+    ClientLib.cpp\
+    Session.cpp
+
+LOCAL_STATIC_LIBRARIES =  libstlport_static libMcKernel libMcCommon
+
+LOCAL_CPPFLAGS += -fno-rtti -fno-exceptions
+include $(COMP_PATH_Logwrapper)/Android.mk
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/mobicore/daemon/ClientLib/ClientLib.cpp b/mobicore/daemon/ClientLib/ClientLib.cpp
new file mode 100644
index 0000000..9b6c5df
--- /dev/null
+++ b/mobicore/daemon/ClientLib/ClientLib.cpp
@@ -0,0 +1,1278 @@
+/** @addtogroup MCD_IMPL_LIB
+ * @{
+ * @file
+ *
+ * MobiCore Driver API.
+ *
+ * Functions for accessing MobiCore functionality from the normal world.
+ * Handles sessions and notifications via MCI buffer.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdint.h>
+#include <stdbool.h>
+#include <list>
+#include <cassert>
+
+#include "public/MobiCoreDriverApi.h"
+
+#include "mc_drv_module_api.h"
+#include "Connection.h"
+#include "CMutex.h"
+#include "Device.h"
+#include "mcVersionHelper.h"
+
+#include "Daemon/public/MobiCoreDriverCmd.h"
+#include "Daemon/public/mcVersion.h"
+
+#define LOG_TAG	"McClient"
+#include "log.h"
+
+MC_CHECK_VERSION(DAEMON, 0, 2);
+
+/** Notification data structure. */
+typedef struct {
+	uint32_t sessionId; /**< Session ID. */
+	int32_t payload; /**< Additional notification information. */
+} notification_t;
+
+using namespace std;
+
+list<Device*> devices;
+
+// Forward declarations.
+static uint32_t getDaemonVersion(Connection* devCon);
+
+//------------------------------------------------------------------------------
+static Device *resolveDeviceId(
+    uint32_t deviceId
+) {
+    Device *ret = NULL;
+
+    // Get Session for sessionId
+    for (list<Device*>::iterator  iterator = devices.begin();
+         iterator != devices.end();
+         ++iterator)
+    {
+        Device  *device = (*iterator);
+
+        if (device->deviceId == deviceId)
+        {
+            ret = device;
+            break;
+        }
+    }
+    return ret;
+}
+
+
+//------------------------------------------------------------------------------
+static void addDevice(
+    Device *device
+) {
+    devices.push_back(device);
+}
+
+
+//------------------------------------------------------------------------------
+static bool removeDevice(
+    uint32_t deviceId
+) {
+    bool ret = false;
+
+    for (list<Device*>::iterator iterator = devices.begin();
+         iterator != devices.end();
+         ++iterator)
+    {
+        Device  *device = (*iterator);
+
+        if (device->deviceId == deviceId)
+        {
+            devices.erase(iterator);
+            delete device;
+            ret = true;
+            break;
+        }
+    }
+    return ret;
+}
+
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcOpenDevice(
+    uint32_t deviceId
+) {
+    mcResult_t mcResult = MC_DRV_OK;
+    static CMutex mutex;
+    Connection *devCon = NULL;
+
+    mutex.lock(); // Enter critical section
+
+    do
+    {
+        Device *device = resolveDeviceId(deviceId);
+        if (NULL != device)
+        {
+            LOG_E("mcOpenDevice(): Device %d already opened", deviceId);
+            mcResult = MC_DRV_ERR_INVALID_OPERATION;
+            break;
+        }
+
+        // Open new connection to device
+        devCon = new Connection();
+        if (!devCon->connect(SOCK_PATH))
+        {
+            LOG_E("mcOpenDevice(): Could not connect to %s", SOCK_PATH);
+            mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE;
+            break;
+        }
+
+        // Runtime check of Daemon version.
+        char* errmsg;
+        if (!checkVersionOkDAEMON(getDaemonVersion(devCon), &errmsg)) {
+            LOG_E("%s", errmsg);
+            mcResult = MC_DRV_ERR_DAEMON_VERSION;
+            break;
+        }
+        LOG_I("%s", errmsg);
+
+        // Forward device open to the daemon and read result
+        mcDrvCmdOpenDevice_t mcDrvCmdOpenDevice = {
+            // C++ does not support C99 designated initializers
+                /* .header = */ {
+                    /* .commandId = */ MC_DRV_CMD_OPEN_DEVICE
+                },
+                /* .payload = */ {
+                    /* .deviceId = */ deviceId
+                }
+            };
+
+        int len = devCon->writeData(
+                            &mcDrvCmdOpenDevice,
+                            sizeof(mcDrvCmdOpenDevice));
+        if (len < 0)
+        {
+            LOG_E("mcOpenDevice(): CMD_OPEN_DEVICE writeCmd failed, ret=%d", len);
+            mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE;
+            break;
+        }
+
+        mcDrvResponseHeader_t  rspHeader;
+        len = devCon->readData(
+                        &rspHeader,
+                        sizeof(rspHeader));
+        if (len != sizeof(rspHeader))
+        {
+            LOG_E("mcOpenDevice(): CMD_OPEN_DEVICE readRsp failed, ret=%d", len);
+            mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE;
+            break;
+        }
+        if (MC_DRV_RSP_OK != rspHeader.responseId)
+        {
+            LOG_E("mcOpenDevice(): CMD_OPEN_DEVICE failed, respId=%d", rspHeader.responseId);
+            switch(rspHeader.responseId)
+            {
+            case MC_DRV_RSP_PAYLOAD_LENGTH_ERROR:
+            	mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE;
+            	break;
+            case MC_DRV_INVALID_DEVICE_NAME:
+            	mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            	break;
+            case MC_DRV_RSP_DEVICE_ALREADY_OPENED:
+            default:
+            	mcResult = MC_DRV_ERR_INVALID_OPERATION;
+            	break;
+            }
+            break;
+        }
+
+        // there is no payload to read
+
+        device = new Device(deviceId, devCon);
+        if (!device->open(MC_DRV_MOD_DEVNODE_FULLPATH))
+        {
+            delete device;
+            // devCon is freed in the Device destructor
+            devCon = NULL;
+            LOG_E("mcOpenDevice(): could not open device file: %s", MC_DRV_MOD_DEVNODE_FULLPATH);
+            mcResult = MC_DRV_ERR_INVALID_DEVICE_FILE;
+            break;
+        }
+
+        addDevice(device);
+
+    } while (false);
+    
+    if (mcResult != MC_DRV_OK && devCon != NULL)
+    {
+        delete devCon;
+    }
+
+    mutex.unlock(); // Exit critical section
+
+    return mcResult;
+}
+
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcCloseDevice(
+    uint32_t deviceId
+) {
+    mcResult_t mcResult = MC_DRV_OK;
+    static CMutex mutex;
+
+    mutex.lock(); // Enter critical section
+    do
+    {
+        Device *device = resolveDeviceId(deviceId);
+        if (NULL == device)
+        {
+            LOG_E("mcCloseDevice(): Device not found");
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+        Connection *devCon = device->connection;
+
+        // Return if not all sessions have been closed
+        if (device->hasSessions())
+        {
+            LOG_E("mcCloseDevice(): cannot close with sessions still pending");
+            mcResult = MC_DRV_ERR_SESSION_PENDING;
+            break;
+        }
+
+        mcDrvCmdCloseDevice_t mcDrvCmdCloseDevice = {
+            // C++ does not support C99 designated initializers
+                /* .header = */ {
+                    /* .commandId = */ MC_DRV_CMD_CLOSE_DEVICE
+                }
+            };
+        int len = devCon->writeData(
+                    &mcDrvCmdCloseDevice,
+                    sizeof(mcDrvCmdCloseDevice));
+        // ignore error, but log details
+        if (len < 0)
+        {
+            LOG_E("mcCloseDevice(): CMD_CLOSE_DEVICE writeCmd failed, ret=%d", len);
+            mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE;
+        }
+
+        mcDrvResponseHeader_t  rspHeader;
+        len = devCon->readData(
+                        &rspHeader,
+                        sizeof(rspHeader));
+        if (len != sizeof(rspHeader))
+        {
+            LOG_E("mcCloseDevice(): CMD_CLOSE_DEVICE readResp failed, ret=%d", len);
+            mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE;
+            break;
+        }
+
+        if (MC_DRV_RSP_OK != rspHeader.responseId)
+        {
+            LOG_E("mcCloseDevice(): CMD_CLOSE_DEVICE failed, respId=%d", rspHeader.responseId);
+            mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE;
+            break;
+        }
+
+        removeDevice(deviceId);
+
+    } while (false);
+
+    mutex.unlock(); // Exit critical section
+
+    return mcResult;
+}
+
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcOpenSession(
+    mcSessionHandle_t  *session,
+    const mcUuid_t     *uuid,
+    uint8_t            *tci,
+    uint32_t           len
+) {
+    mcResult_t mcResult = MC_DRV_OK;
+    static CMutex mutex;
+
+    mutex.lock(); // Enter critical section
+
+    do
+    {
+        if (NULL == session)
+        {
+            LOG_E("mcOpenSession(): Session is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+        if (NULL == uuid)
+        {
+            LOG_E("mcOpenSession(): UUID is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+        if (NULL == tci)
+        {
+            LOG_E("mcOpenSession(): TCI is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+        if (len > MC_MAX_TCI_LEN)
+        {
+            LOG_E("mcOpenSession(): TCI length is longer than %d", MC_MAX_TCI_LEN);
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+
+        // Get the device associated with the given session
+        Device *device = resolveDeviceId(session->deviceId);
+        if (NULL == device)
+        {
+            LOG_E("mcOpenSession(): Device not found");
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+        Connection *devCon = device->connection;
+
+        // Get the physical address of the given TCI
+        CWsm_ptr pWsm = device->findContiguousWsm(tci);
+        if (NULL == pWsm)
+        {
+            LOG_E("mcOpenSession(): Could not resolve physical address of TCI");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+
+        if (pWsm->len < len)
+        {
+            LOG_E("mcOpenSession(): length is more than allocated TCI");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+
+        // Prepare open session command
+        mcDrvCmdOpenSession_t cmdOpenSession = {
+                // C++ does not support C99 designated initializers
+                    /* .header = */ {
+                        /* .commandId = */ MC_DRV_CMD_OPEN_SESSION
+                    },
+                    /* .payload = */ {
+                        /* .deviceId = */ session->deviceId,
+                        /* .uuid = */ *uuid,
+                        /* .tci = */ (uint32_t)pWsm->physAddr,
+                        /* .len = */ len
+                    }
+                };
+
+        // Transmit command data
+
+        int len = devCon->writeData(
+                            &cmdOpenSession,
+                            sizeof(cmdOpenSession));
+        if (sizeof(cmdOpenSession) != len)
+        {
+            LOG_E("mcOpenSession(): CMD_OPEN_SESSION writeData failed, ret=%d", len);
+            mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE;
+            break;
+        }
+
+        // Read command response
+
+        // read header first
+        mcDrvResponseHeader_t rspHeader;
+        len = devCon->readData(
+                        &rspHeader,
+                        sizeof(rspHeader));
+        if (sizeof(rspHeader) != len)
+        {
+            LOG_E("mcOpenSession(): CMD_OPEN_SESSION readResp failed, ret=%d", len);
+            mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE;
+            break;
+        }
+
+        if (MC_DRV_RSP_OK != rspHeader.responseId)
+        {
+            LOG_E("mcOpenSession(): CMD_OPEN_SESSION failed, respId=%d", rspHeader.responseId);
+            switch(rspHeader.responseId)
+            {
+            case MC_DRV_RSP_WRONG_PUBLIC_KEY:
+                mcResult = MC_DRV_ERR_WRONG_PUBLIC_KEY;
+                break;
+            case MC_DRV_RSP_CONTAINER_TYPE_MISMATCH:
+                mcResult = MC_DRV_ERR_CONTAINER_TYPE_MISMATCH;
+                break;
+            case MC_DRV_RSP_CONTAINER_LOCKED:
+                mcResult = MC_DRV_ERR_CONTAINER_LOCKED;
+                break;
+            case MC_DRV_RSP_SP_NO_CHILD:
+                mcResult = MC_DRV_ERR_SP_NO_CHILD;
+                break;
+            case MC_DRV_RSP_TL_NO_CHILD:
+                mcResult = MC_DRV_ERR_TL_NO_CHILD;
+                break;
+            case MC_DRV_RSP_UNWRAP_ROOT_FAILED:
+                mcResult = MC_DRV_ERR_UNWRAP_ROOT_FAILED;
+                break;
+            case MC_DRV_RSP_UNWRAP_SP_FAILED:
+                mcResult = MC_DRV_ERR_UNWRAP_SP_FAILED;
+                break;
+            case MC_DRV_RSP_UNWRAP_TRUSTLET_FAILED:
+                mcResult = MC_DRV_ERR_UNWRAP_TRUSTLET_FAILED;
+                break;
+            case MC_DRV_RSP_TRUSTLET_NOT_FOUND:
+            	mcResult = MC_DRV_ERR_INVALID_DEVICE_FILE;
+            	break;
+            case MC_DRV_RSP_PAYLOAD_LENGTH_ERROR:
+            case MC_DRV_RSP_DEVICE_NOT_OPENED:
+            case MC_DRV_RSP_FAILED:
+            default:
+            	mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE;
+            	break;
+            }
+
+            break;
+        }
+
+        // read payload
+        mcDrvRspOpenSessionPayload_t rspOpenSessionPayload;
+        len = devCon->readData(
+                        &rspOpenSessionPayload,
+                        sizeof(rspOpenSessionPayload));
+        if (sizeof(rspOpenSessionPayload) != len)
+        {
+            LOG_E("mcOpenSession(): CMD_OPEN_SESSION readPayload failed, ret=%d", len);
+            mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE;
+            break;
+        }
+
+        // Register session with handle
+        session->sessionId = rspOpenSessionPayload.sessionId;
+
+        // Set up second channel for notifications
+        Connection *sessionConnection = new Connection();
+        if (!sessionConnection->connect(SOCK_PATH))
+        {
+            LOG_E("mcOpenSession(): Could not connect to %s", SOCK_PATH);
+            delete sessionConnection;
+            mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE;
+            break;
+        }
+
+        //TODO CONTINOUE HERE !!!! FIX RW RETURN HANDLING!!!!
+
+        // Write command to use channel for notifications
+        mcDrvCmdNqConnect_t cmdNqConnect = {
+                // C++ does not support C99 designated initializers
+                    /* .header = */ {
+                        /* .commandId = */ MC_DRV_CMD_NQ_CONNECT
+                    },
+                    /* .payload = */ {
+                            /* .deviceId =  */ session->deviceId,
+                            /* .sessionId = */ session->sessionId,
+                            /* .deviceSessionId = */ rspOpenSessionPayload.deviceSessionId,
+                            /* .sessionMagic = */ rspOpenSessionPayload.sessionMagic
+                    }
+                };
+        sessionConnection->writeData(
+                                &cmdNqConnect,
+                                sizeof(cmdNqConnect));
+
+
+        // Read command response, header first
+        len = sessionConnection->readData(
+                                    &rspHeader,
+                                    sizeof(rspHeader));
+        if (sizeof(rspHeader) != len)
+        {
+            LOG_E("mcOpenSession(): CMD_NQ_CONNECT readRsp failed, ret=%d", len);
+            delete sessionConnection;
+            mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE;
+            break;
+        }
+
+        if (MC_DRV_RSP_OK != rspHeader.responseId)
+        {
+            LOG_E("mcOpenSession(): CMD_NQ_CONNECT failed, respId=%d", rspHeader.responseId);
+            delete sessionConnection;
+            mcResult = MC_DRV_ERR_NQ_FAILED;
+            break;
+        }
+
+        // there is no payload.
+
+        // Session has been established, new session object must be created
+        device->createNewSession(
+                    session->sessionId,
+                    sessionConnection);
+
+    } while (false);
+
+    mutex.unlock(); // Exit critical section
+
+    return mcResult;
+}
+
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcCloseSession(
+    mcSessionHandle_t *session
+) {
+    mcResult_t mcResult = MC_DRV_OK;
+    static CMutex mutex;
+
+    mutex.lock(); // Enter critical section
+
+    do
+    {
+        if (NULL == session)
+        {
+            LOG_E("mcCloseSession(): Session is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+
+        Device  *device = resolveDeviceId(session->deviceId);
+        if (NULL == device)
+        {
+            LOG_E("mcCloseSession(): Device not found");
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+        Connection  *devCon = device->connection;
+
+        Session  *nqSession = device->resolveSessionId(session->sessionId);
+        if (NULL == nqSession)
+        {
+            LOG_E("mcCloseSession(): Session not found");
+            mcResult = MC_DRV_ERR_UNKNOWN_SESSION;
+            break;
+        }
+
+        // Write close session command
+        mcDrvCmdCloseSession_t cmdCloseSession = {
+                // C++ does not support C99 designated initializers
+                    /* .header = */ {
+                        /* .commandId = */ MC_DRV_CMD_CLOSE_SESSION
+                    },
+                    /* .payload = */ {
+                            /* .sessionId = */ session->sessionId,
+                    }
+                };
+        devCon->writeData(
+                            &cmdCloseSession,
+                            sizeof(cmdCloseSession));
+
+        // Read command response
+        mcDrvResponseHeader_t rspHeader;
+        int len = devCon->readData(
+                        &rspHeader,
+                        sizeof(rspHeader));
+        if (sizeof(rspHeader) != len)
+        {
+            LOG_E("mcCloseSession(): CMD_CLOSE_SESSION readRsp failed, ret=%d", len);
+            mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE;
+            break;
+        }
+
+        if (MC_DRV_RSP_OK != rspHeader.responseId)
+        {
+            LOG_E("mcCloseSession(): CMD_CLOSE_SESSION failed, respId=%d", rspHeader.responseId);
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+
+        bool r = device->removeSession(session->sessionId);
+        assert(r == true);
+        mcResult = MC_DRV_OK;
+
+    } while (false);
+
+    mutex.unlock(); // Exit critical section
+
+    return mcResult;
+}
+
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcNotify(
+    mcSessionHandle_t	*session
+) {
+    mcResult_t mcResult = MC_DRV_OK;
+    
+    LOG_I("===%s()===", __func__);
+
+    do
+    {
+        if (NULL == session)
+        {
+            LOG_E("mcNotify(): Session is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+
+        Device *device = resolveDeviceId(session->deviceId);
+        if (NULL == device)
+        {
+            LOG_E("mcNotify(): Device not found");
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+        Connection  *devCon = device->connection;
+
+        Session  *nqsession = device->resolveSessionId(session->sessionId);
+        if (NULL == nqsession)
+        {
+            LOG_E("mcNotify(): Session not found");
+            mcResult = MC_DRV_ERR_UNKNOWN_SESSION;
+            break;
+        }
+
+        mcDrvCmdNotify_t cmdNotify = {
+                // C++ does not support C99 designated initializers
+                    /* .header = */ {
+                        /* .commandId = */ MC_DRV_CMD_NOTIFY
+                    },
+                    /* .payload = */ {
+                            /* .sessionId = */ session->sessionId,
+                    }
+                };
+
+        devCon->writeData(
+                    &cmdNotify,
+                    sizeof(cmdNotify));
+
+        // Daemon will not return a response
+
+    } while(false);
+
+    return mcResult;
+}
+
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcWaitNotification(
+    mcSessionHandle_t  *session,
+    int32_t            timeout
+) {
+    mcResult_t mcResult = MC_DRV_OK;
+    
+    LOG_I("===%s()===", __func__);
+
+    do
+    {
+        if (NULL == session)
+        {
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+
+        Device  *device = resolveDeviceId(session->deviceId);
+        if (NULL == device)
+        {
+            LOG_E("mcWaitNotification(): Device not found");
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+
+        Session  *nqSession = device->resolveSessionId(session->sessionId);
+        if (NULL == nqSession)
+        {
+            LOG_E("mcWaitNotification(): Session not found");
+            mcResult = MC_DRV_ERR_UNKNOWN_SESSION;
+            break;
+        }
+
+        Connection * nqconnection = nqSession->notificationConnection;
+        uint32_t count = 0;
+
+        // Read notification queue till it's empty
+        for(;;)
+        {
+            notification_t notification;
+            ssize_t numRead = nqconnection->readData(
+                                        &notification,
+                                        sizeof(notification_t),
+                                        timeout);
+            //Exit on timeout in first run
+            //Later runs have timeout set to 0. -2 means, there is no more data.
+            if (0 == count && -2 == numRead)
+            {
+                LOG_E("mcWaitNotification(): read timeout");
+                mcResult = MC_DRV_ERR_TIMEOUT;
+                break;
+            }
+            // After first notification the queue will be drained, Thus we set
+            // no timeout for the following reads
+            timeout = 0;
+
+            if (numRead != sizeof(notification_t))
+            {
+            	if (0 == count)
+                {
+                	//failure in first read, notify it
+                    mcResult = MC_DRV_ERR_NOTIFICATION;
+                    LOG_E("mcWaitNotification(): read notification failed, %i bytes received", (int)numRead);
+                    break;
+                }
+            	else
+            	{
+					// Read of the n-th notification failed/timeout. We don't tell the
+					// caller, as we got valid notifications before.
+					mcResult = MC_DRV_OK;
+					break;
+                }
+            }
+
+            count++;
+            LOG_I("mcWaitNotification(): readNq count=%d, SessionID=%d, Payload=%d",
+                   count, notification.sessionId, notification.payload);
+
+            if (0 != notification.payload)
+            {
+                // Session end point died -> store exit code
+                nqSession->setErrorInfo(notification.payload);
+
+                mcResult = MC_DRV_INFO_NOTIFICATION;
+                break;
+            }
+        } // for(;;)
+
+    } while (false);
+
+    return mcResult;
+}
+
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcMallocWsm(
+    uint32_t	deviceId,
+    uint32_t	align,
+    uint32_t	len,
+    uint8_t		**wsm,
+    uint32_t	wsmFlags
+) {
+    mcResult_t mcResult = MC_DRV_ERR_UNKNOWN;
+    static CMutex mutex;
+
+	LOG_I("===%s()===", __func__);
+
+    mutex.lock(); // Enter critical section
+
+    do
+    {
+        Device *device = resolveDeviceId(deviceId);
+        if (NULL == device)
+        {
+            LOG_E("mcMallocWsm(): Device not found");
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+        if(NULL == wsm)
+        {
+        	mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+        	break;
+        }
+
+        CWsm_ptr pWsm =  device->allocateContiguousWsm(len);
+        if (NULL == pWsm)
+        {
+            LOG_E("mcMallocWsm(): Allocation of WSM failed");
+            mcResult = MC_DRV_ERR_NO_FREE_MEMORY;
+            break;
+        }
+
+        *wsm = (uint8_t*)pWsm->virtAddr;
+        mcResult = MC_DRV_OK;
+
+    } while (false);
+
+    mutex.unlock(); // Exit critical section
+
+    return mcResult;
+}
+
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcFreeWsm(
+    uint32_t	deviceId,
+    uint8_t		*wsm
+) {
+    mcResult_t mcResult = MC_DRV_ERR_UNKNOWN;
+    Device *device;
+
+    static CMutex mutex;
+
+    LOG_I("===%s()===", __func__);
+
+    mutex.lock(); // Enter critical section
+
+    do {
+
+        // Get the device associated wit the given session
+        device = resolveDeviceId(deviceId);
+        if (NULL == device)
+        {
+            LOG_E("mcFreeWsm(): Device not found");
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+
+        // find WSM object
+        CWsm_ptr pWsm = device->findContiguousWsm(wsm);
+        if (NULL == pWsm)
+        {
+            LOG_E("mcFreeWsm(): unknown address");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+
+        // Free the given virtual address
+        if (!device->freeContiguousWsm(pWsm))
+        {
+            LOG_E("mcFreeWsm(): Free of virtual address failed");
+            mcResult = MC_DRV_ERR_FREE_MEMORY_FAILED;
+            break;
+        }
+        mcResult = MC_DRV_OK;
+
+    } while (false);
+
+    mutex.unlock(); // Exit critical section
+
+    return mcResult;
+}
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcMap(
+    mcSessionHandle_t  *sessionHandle,
+    void               *buf,
+    uint32_t           bufLen,
+    mcBulkMap_t        *mapInfo
+) {
+    mcResult_t mcResult = MC_DRV_ERR_UNKNOWN;
+    static CMutex mutex;
+
+    mutex.lock(); // Enter critical section
+
+    do
+    {
+        if (NULL == sessionHandle)
+        {
+            LOG_E("mcMap(): sessionHandle is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+        if (NULL == mapInfo)
+        {
+            LOG_E("mcMap(): mapInfo is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+        if (NULL == buf)
+        {
+            LOG_E("mcMap(): buf is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+
+        // Determine device the session belongs to
+        Device  *device = resolveDeviceId(sessionHandle->deviceId);
+        if (NULL == device) {
+            LOG_E("mcMap(): Device not found");
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+        Connection *devCon = device->connection;
+
+        // Get session
+        Session  *session = device->resolveSessionId(sessionHandle->sessionId);
+        if (NULL == session)
+        {
+            LOG_E("mcMap(): Session not found");
+            mcResult = MC_DRV_ERR_UNKNOWN_SESSION;
+            break;
+        }
+
+		// Workaround Linux memory handling
+		if (NULL != buf)
+		{
+			for (uint32_t i = 0; i < bufLen; i += 4096) {
+				volatile uint8_t x = ((uint8_t *) buf)[i]; x = x;
+			}
+		}
+
+        // Register mapped bulk buffer to Kernel Module and keep mapped bulk buffer in mind
+        BulkBufferDescriptor *bulkBuf = session->addBulkBuf(buf, bufLen);
+        if (NULL == bulkBuf)
+        {
+            LOG_E("mcMap(): Error mapping bulk buffer");
+            mcResult = MC_DRV_ERR_BULK_MAPPING;
+            break;
+        }
+
+
+        // Prepare map command
+        mcDrvCmdMapBulkMem_t mcDrvCmdMapBulkMem = {
+                // C++ does not support C99 designated initializers
+                    /* .header = */ {
+                        /* .commandId = */ MC_DRV_CMD_MAP_BULK_BUF
+                    },
+                    /* .payload = */ {
+                        /* .sessionId = */ session->sessionId,
+                        /* .pAddrL2 = */ (uint32_t)bulkBuf->physAddrWsmL2,
+                        /* .offsetPayload = */ (uint32_t)(bulkBuf->virtAddr) & 0xFFF,
+                        /* .lenBulkMem = */ bulkBuf->len
+                    }
+                };
+
+        // Transmit map command to MobiCore device
+        devCon->writeData(
+                    &mcDrvCmdMapBulkMem,
+                    sizeof(mcDrvCmdMapBulkMem));
+
+        // Read command response
+        mcDrvResponseHeader_t rspHeader;
+        int len = devCon->readData(
+                        &rspHeader,
+                        sizeof(rspHeader));
+        if (sizeof(rspHeader) != len)
+        {
+            LOG_E("mcMap(): CMD_MAP_BULK_BUF readRsp failed, ret=%d", len);
+            mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE;
+            break;
+        }
+
+        if (MC_DRV_RSP_OK != rspHeader.responseId)
+        {
+            LOG_E("mcMap(): CMD_MAP_BULK_BUF failed, respId=%d", rspHeader.responseId);
+            // REV We ignore Daemon Error code because client cannot handle it anyhow.
+            mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE;
+
+            // Unregister mapped bulk buffer from Kernel Module and remove mapped
+            // bulk buffer from session maintenance
+            if (!session->removeBulkBuf(buf))
+            {
+                // Removing of bulk buffer not possible
+                LOG_E("mcMap(): Unregistering of bulk memory from Kernel Module failed");
+            }
+            break;
+        }
+
+        mcDrvRspMapBulkMemPayload_t rspMapBulkMemPayload;
+        devCon->readData(
+                    &rspMapBulkMemPayload,
+                    sizeof(rspMapBulkMemPayload));
+
+        // Set mapping info for Trustlet
+        mapInfo->sVirtualAddr = (void *) (rspMapBulkMemPayload.secureVirtualAdr);
+        mapInfo->sVirtualLen = bufLen;
+        mcResult = MC_DRV_OK;
+
+    } while (false);
+
+    mutex.unlock(); // Exit critical section
+
+    return mcResult;
+}
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcUnmap(
+    mcSessionHandle_t  *sessionHandle,
+    void               *buf,
+    mcBulkMap_t        *mapInfo
+) {
+    mcResult_t mcResult = MC_DRV_ERR_UNKNOWN;
+    static CMutex mutex;
+
+    LOG_I("===%s()===", __func__);
+
+    mutex.lock(); // Enter critical section
+
+    do
+    {
+        if (NULL == sessionHandle)
+        {
+            LOG_E("mcUnmap(): sessionHandle is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+        if (NULL == mapInfo)
+        {
+            LOG_E("mcUnmap(): mapInfo is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+        if (NULL == buf)
+        {
+            LOG_E("mcUnmap(): buf is null");
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+
+        // Determine device the session belongs to
+        Device  *device = resolveDeviceId(sessionHandle->deviceId);
+        if (NULL == device)
+        {
+            LOG_E("mcUnmap(): Device not found");
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+        Connection  *devCon = device->connection;
+
+        // Get session
+        Session  *session = device->resolveSessionId(sessionHandle->sessionId);
+        if (NULL == session)
+        {
+            LOG_E("mcUnmap(): Session not found");
+            mcResult = MC_DRV_ERR_UNKNOWN_SESSION;
+            break;
+        }
+
+        // Prepare unmap command
+        mcDrvCmdUnmapBulkMem_t cmdUnmapBulkMem = {
+                // C++ does not support C99 designated initializers
+                    /* .header = */ {
+                        /* .commandId = */ MC_DRV_CMD_UNMAP_BULK_BUF
+                    },
+                    /* .payload = */ {
+                        /* .sessionId = */ session->sessionId,
+                        /* .secureVirtualAdr = */ (uint32_t)(mapInfo->sVirtualAddr),
+                        /* .lenBulkMem = mapInfo->sVirtualLen*/
+                    }
+                };
+
+        devCon->writeData(
+                    &cmdUnmapBulkMem,
+                    sizeof(cmdUnmapBulkMem));
+
+        // Read command response
+        mcDrvResponseHeader_t rspHeader;
+        int len = devCon->readData(
+                        &rspHeader,
+                        sizeof(rspHeader));
+        if (sizeof(rspHeader) != len)
+        {
+            LOG_E("mcUnmap(): CMD_UNMAP_BULK_BUF readRsp failed, ret=%d", len);
+            mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE;
+            break;
+        }
+
+        if (MC_DRV_RSP_OK != rspHeader.responseId)
+        {
+            LOG_E("mcUnmap(): CMD_UNMAP_BULK_BUF failed, respId=%d", rspHeader.responseId);
+            // REV We ignore Daemon Error code because client cannot handle it anyhow.
+            mcResult = MC_DRV_ERR_DAEMON_UNREACHABLE;
+            break;
+        }
+
+        mcDrvRspUnmapBulkMemPayload_t rspUnmapBulkMemPayload;
+        devCon->readData(
+                    &rspUnmapBulkMemPayload,
+                    sizeof(rspUnmapBulkMemPayload));
+
+        // REV axh: what about check the payload?
+
+        // Unregister mapped bulk buffer from Kernel Module and remove mapped
+        // bulk buffer from session maintenance
+        if (!session->removeBulkBuf(buf))
+        {
+            // Removing of bulk buffer not possible
+            LOG_E("mcUnmap(): Unregistering of bulk memory from Kernel Module failed");
+            mcResult = MC_DRV_ERR_BULK_UNMAPPING;
+            break;
+        }
+
+        mcResult = MC_DRV_OK;
+
+    } while (false);
+
+    mutex.unlock(); // Exit critical section
+
+    return mcResult;
+}
+
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcGetSessionErrorCode(
+    mcSessionHandle_t	*session,
+    int32_t				*lastErr
+) {
+    mcResult_t mcResult = MC_DRV_OK;
+    
+    LOG_I("===%s()===", __func__);
+
+    do
+    {
+        if (NULL == session || NULL == lastErr)
+        {
+            mcResult = MC_DRV_ERR_INVALID_PARAMETER;
+            break;
+        }
+
+        // Get device
+        Device *device = resolveDeviceId(session->deviceId);
+        if (NULL == device)
+        {
+            LOG_E("mcGetSessionErrorCode(): Device not found");
+            mcResult = MC_DRV_ERR_UNKNOWN_DEVICE;
+            break;
+        }
+
+        // Get session
+        Session *nqsession = device->resolveSessionId(session->sessionId);
+        if (NULL == nqsession)
+        {
+            LOG_E("mcGetSessionErrorCode(): Session not found");
+            mcResult = MC_DRV_ERR_UNKNOWN_SESSION;
+            break;
+        }
+
+        // get session error code from session
+        *lastErr = nqsession->getLastErr();
+
+    } while (false);
+
+    return mcResult;
+}
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcDriverCtrl(
+    mcDriverCtrl_t  param,
+    uint8_t         *data,
+    uint32_t        len
+) {
+    LOG_W("mcDriverCtrl(): not implemented");
+    return MC_DRV_ERR_NOT_IMPLEMENTED;
+}
+
+//------------------------------------------------------------------------------
+__MC_CLIENT_LIB_API mcResult_t mcGetMobiCoreVersion(
+    uint32_t  deviceId,
+    mcVersionInfo_t* versionInfo
+) {
+    mcResult_t mcResult = MC_DRV_OK;
+
+    Device* device = resolveDeviceId(deviceId);
+    if (NULL == device) {
+        LOG_E("mcGetMobiCoreVersion(): Device not found");
+        return MC_DRV_ERR_UNKNOWN_DEVICE;
+    }
+
+    if (NULL == versionInfo) {
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+
+    Connection* devCon = device->connection;
+
+    mcDrvCmdGetMobiCoreVersion_t mcDrvCmdGetMobiCoreVersion = {
+        {
+            MC_DRV_CMD_GET_MOBICORE_VERSION,
+        }
+    };
+    int len = devCon->writeData(
+        &mcDrvCmdGetMobiCoreVersion,
+        sizeof(mcDrvCmdGetMobiCoreVersion));
+
+    if (len < 0) {
+        LOG_E("mcGetMobiCoreVersion(): MC_DRV_CMD_GET_MOBICORE_VERSION writeCmd failed, ret=%d", len);
+        return MC_DRV_ERR_DAEMON_UNREACHABLE;
+    }
+
+    // Read GET MOBICORE VERSION response.
+
+    // Read header first.
+    mcDrvResponseHeader_t rspHeader;
+    len = devCon->readData(&rspHeader, sizeof(rspHeader));
+    if (sizeof(rspHeader) != len) {
+        LOG_E("mcGetMobiCoreVersion(): MC_DRV_CMD_GET_MOBICORE_VERSION failed to respond, ret=%d", len);
+        return MC_DRV_ERR_DAEMON_UNREACHABLE;
+    }
+
+    if (MC_DRV_RSP_OK != rspHeader.responseId) {
+        LOG_E("mcGetMobiCoreVersion(): MC_DRV_CMD_GET_MOBICORE_VERSION bad response, respId=%d", rspHeader.responseId);
+        return MC_DRV_ERR_DAEMON_UNREACHABLE;
+    }
+
+    // Read payload.
+    mcDrvRspGetMobiCoreVersionPayload_t rspGetMobiCoreVersionPayload;
+    len = devCon->readData(&rspGetMobiCoreVersionPayload, sizeof(rspGetMobiCoreVersionPayload));
+    if (sizeof(rspGetMobiCoreVersionPayload) != len) {
+        LOG_E("mcGetMobiCoreVersion(): MC_DRV_CMD_GET_MOBICORE_VERSION readPayload failed, ret=%d", len);
+        return MC_DRV_ERR_DAEMON_UNREACHABLE;
+    }
+
+    *versionInfo = rspGetMobiCoreVersionPayload.versionInfo;
+
+    return mcResult;
+}
+
+
+//------------------------------------------------------------------------------
+static uint32_t getDaemonVersion(
+    Connection* devCon
+) {
+    assert(devCon != NULL);
+
+    // Send GET VERSION command to daemon.
+    mcDrvCmdGetVersion_t cmdGetVersion = {
+        {
+            MC_DRV_CMD_GET_VERSION,
+        },
+    };
+    int len = devCon->writeData(&cmdGetVersion, sizeof(cmdGetVersion));
+    if (sizeof(cmdGetVersion) != len) {
+        LOG_E("getDaemonVersion(): MC_DRV_CMD_GET_VERSION failed, ret=%d", len);
+        return 0;
+    }
+
+    // Read GET VERSION response.
+
+    // Read header first.
+    mcDrvResponseHeader_t rspHeader;
+    len = devCon->readData(&rspHeader, sizeof(rspHeader));
+    if (sizeof(rspHeader) != len) {
+        LOG_E("getDaemonVersion(): MC_DRV_CMD_GET_VERSION failed to respond, ret=%d", len);
+        return 0;
+    }
+
+    if (MC_DRV_RSP_OK != rspHeader.responseId) {
+        LOG_E("getDaemonVersion(): MC_DRV_CMD_GET_VERSION bad response, respId=%d", rspHeader.responseId);
+        return 0;
+    }
+
+    // Read payload.
+    mcDrvRspGetVersionPayload_t rspGetVersionPayload;
+    len = devCon->readData(&rspGetVersionPayload, sizeof(rspGetVersionPayload));
+    if (sizeof(rspGetVersionPayload) != len) {
+        LOG_E("getDaemonVersion(): MC_DRV_CMD_GET_VERSION readPayload failed, ret=%d", len);
+        return 0;
+    }
+
+    return rspGetVersionPayload.version;
+}
+
+/** @} */
diff --git a/mobicore/daemon/ClientLib/Device.cpp b/mobicore/daemon/ClientLib/Device.cpp
new file mode 100644
index 0000000..bde0a08
--- /dev/null
+++ b/mobicore/daemon/ClientLib/Device.cpp
@@ -0,0 +1,259 @@
+/** @addtogroup MCD_IMPL_LIB
+ * @{
+ * @file
+ *
+ * Client library device management.
+ *
+ * Device and Trustlet Session management Funtions.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdint.h>
+#include <vector>
+
+#include "mc_drv_module_api.h"
+
+#include "Device.h"
+
+#define LOG_TAG	"McClientLib_Device"
+#include "log.h"
+
+
+//------------------------------------------------------------------------------
+Device::Device(
+    uint32_t    deviceId,
+    Connection  *connection
+) {
+	this->deviceId = deviceId;
+	this->connection = connection;
+
+	pMcKMod = new CMcKMod();
+}
+
+
+//------------------------------------------------------------------------------
+Device::~Device(
+    void
+) {
+	/* Delete all session objects. Usually this should not be needed as closeDevice()
+	 * requires that all sessions have been closed before.
+	 */
+	sessionIterator_t  sessionIterator = sessionList.begin();
+	while(sessionIterator != sessionList.end())
+	{
+		delete (*sessionIterator);
+		sessionIterator = sessionList.erase(sessionIterator);
+	}
+
+	// Free all allocated WSM descriptors
+	wsmIterator_t  wsmIterator = wsmL2List.begin();
+	while(wsmIterator != wsmL2List.end())
+	{
+	    CWsm_ptr pWsm = *wsmIterator;
+
+	    // ignore return code
+	    pMcKMod->free(pWsm->handle);
+
+	    delete (*wsmIterator);
+		wsmIterator = wsmL2List.erase(wsmIterator);
+	}
+	delete connection;
+	delete pMcKMod;
+}
+
+
+//------------------------------------------------------------------------------
+bool Device::open(
+    const char * deviceName
+) {
+	return pMcKMod->open(deviceName);
+}
+
+
+//------------------------------------------------------------------------------
+void Device::close(
+    void
+) {
+	pMcKMod->close();
+}
+
+
+//------------------------------------------------------------------------------
+bool Device::hasSessions(
+    void
+) {
+	return sessionList.size() > 0;
+}
+
+
+//------------------------------------------------------------------------------
+void Device::createNewSession(
+    uint32_t    sessionId,
+    Connection  *connection
+) {
+	Session *session = new Session(sessionId, pMcKMod, connection);
+	sessionList.push_back(session);
+}
+
+
+//------------------------------------------------------------------------------
+bool Device::removeSession(
+    uint32_t sessionId
+) {
+	bool ret = false;
+
+	sessionIterator_t interator = sessionList.begin();
+	while(interator != sessionList.end())
+	{
+		if ((*interator)->sessionId == sessionId)
+		{
+			delete (*interator);
+			interator = sessionList.erase(interator);
+			ret = true;
+			break;
+		}
+		else
+		{
+		    interator++;
+		}
+	}
+	return ret;
+}
+
+
+//------------------------------------------------------------------------------
+Session *Device::resolveSessionId(
+    uint32_t sessionId
+) {
+	Session  *ret = NULL;
+
+	// Get Session for sessionId
+	for ( sessionIterator_t interator = sessionList.begin();
+	      interator != sessionList.end();
+	      ++interator)
+    {
+		if ((*interator)->sessionId == sessionId) {
+			ret = (*interator);
+			break;
+		}
+	}
+	return ret;
+}
+
+
+//------------------------------------------------------------------------------
+CWsm_ptr Device::allocateContiguousWsm(
+    uint32_t len
+) {
+    CWsm_ptr  pWsm = NULL;
+	do
+	{
+	    if (0 == len)
+	    {
+		    break;
+	    }
+	    
+		// Allocate shared memory
+		addr_t    virtAddr;
+		uint32_t  handle;
+		addr_t    physAddr;
+		bool      mciReuse = false;
+		int ret = pMcKMod->mmap(
+							len,
+							&handle,
+							&virtAddr,
+							&physAddr,
+							&mciReuse);
+		if (0 != ret)
+		{
+			break;
+		}
+
+		// Register (vaddr,paddr) with device
+		pWsm = new CWsm(virtAddr,len,handle,physAddr);
+
+		wsmL2List.push_back(pWsm);
+		
+	} while(0);
+
+	// Return pointer to the allocated memory
+	return pWsm;
+}
+
+
+//------------------------------------------------------------------------------
+bool Device::freeContiguousWsm(
+    CWsm_ptr  pWsm
+) {
+	bool ret = false;
+	wsmIterator_t iterator;
+
+	for (iterator=wsmL2List.begin(); iterator!=wsmL2List.end(); ++iterator)
+	{
+	    if (pWsm == *iterator)
+	    {
+	        ret = true;
+	        break;
+	    }
+	}
+
+	if(ret) {
+		LOG_I("freeWsm virtAddr=0x%p, handle=%d",
+				pWsm->virtAddr,pWsm->handle);
+
+		// ignore return code
+		pMcKMod->free(pWsm->handle);
+
+		iterator = wsmL2List.erase(iterator);
+		delete pWsm;
+	}
+	return ret;
+}
+
+
+//------------------------------------------------------------------------------
+CWsm_ptr Device::findContiguousWsm(
+    addr_t  virtAddr
+) {
+    CWsm_ptr pWsm = NULL;
+
+	for( wsmIterator_t iterator=wsmL2List.begin();
+	     iterator!=wsmL2List.end();
+	     ++iterator)
+	{
+		CWsm_ptr pTmpWsm = *iterator;
+	    if (virtAddr == pTmpWsm->virtAddr)
+		{
+			pWsm = pTmpWsm;
+			break;
+		}
+	}
+
+	return pWsm;
+}
+
+/** @} */
diff --git a/mobicore/daemon/ClientLib/Device.h b/mobicore/daemon/ClientLib/Device.h
new file mode 100644
index 0000000..56d8fff
--- /dev/null
+++ b/mobicore/daemon/ClientLib/Device.h
@@ -0,0 +1,151 @@
+/** @addtogroup MCD_IMPL_LIB
+ * @{
+ * @file
+ *
+ * Client library device management.
+ *
+ * Device and Trustlet Session management Functions.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef DEVICE_H_
+#define DEVICE_H_
+
+#include <stdint.h>
+#include <vector>
+
+#include "Session.h"
+#include "CWsm.h"
+
+
+class Device {
+
+private:
+	sessionList_t   sessionList; /**< MobiCore Trustlet session associated with the device */
+    wsmList_t       wsmL2List; /**< WSM L2 Table  */
+
+
+public:
+	uint32_t     deviceId; /**< Device identifier */
+	Connection   *connection; /**< The device connection */
+	CMcKMod_ptr  pMcKMod;
+
+	Device(
+	    uint32_t    deviceId,
+	    Connection  *connection
+	);
+
+	virtual ~Device(
+	    void
+	);
+
+	/**
+	 * Open the device.
+	 * @param deviceName Name of the kernel modules device file.
+	 * @return true if the device has been opened successfully
+	 */
+	bool open(
+	    const char * deviceName
+	);
+
+    /**
+     * Closes the device.
+     */
+    void close(
+        void
+    );
+
+	/**
+	 * Check if the device has open sessions.
+	 * @return true if the device has one or more open sessions.
+	 */
+	bool hasSessions(
+	    void
+	);
+
+	/**
+	 * Add a session to the device.
+	 * @param sessionId session ID
+	 * @param connection session connection
+	 */
+	void createNewSession(
+	    uint32_t    sessionId,
+	    Connection  *connection
+	);
+
+	/**
+	 * Remove the specified session from the device.
+	 * The session object will be destroyed and all resources associated with it will be freed.
+	 *
+	 * @param sessionId Session of the session to remove.
+	 * @return true if a session has been found and removed.
+	 */
+	bool removeSession(
+	    uint32_t sessionId
+	);
+
+	/**
+	 * Get as session object for a given session ID.
+	 * @param sessionId Identified of a previously opened session.
+	 * @return Session object if available or NULL if no session has been found.
+	 */
+	Session *resolveSessionId(
+	    uint32_t sessionId
+	);
+
+	/**
+	 * Allocate a block of contiguous WSM.
+	 * @param len The virtual address to be registered.
+	 * @return The virtual address of the allocated memory or NULL if no memory is available.
+	 */
+	CWsm_ptr allocateContiguousWsm(
+	    uint32_t len
+	);
+
+	/**
+	 * Unregister a vaddr from a device.
+	 * @param vaddr The virtual address to be registered.
+	 * @param paddr The physical address to be registered.
+	 */
+	bool freeContiguousWsm(
+	    CWsm_ptr  pWsm
+	);
+
+	/**
+	 * Get a WSM object for a given virtual address.
+	 * @param vaddr The virtual address which has been allocate with mcMallocWsm() in advance.
+	 * @return the WSM object or NULL if no address has been found.
+	 */
+	CWsm_ptr findContiguousWsm(
+	    addr_t  virtAddr
+	);
+
+};
+
+#endif /* DEVICE_H_ */
+
+/** @} */
diff --git a/mobicore/daemon/ClientLib/Session.cpp b/mobicore/daemon/ClientLib/Session.cpp
new file mode 100644
index 0000000..85e1398
--- /dev/null
+++ b/mobicore/daemon/ClientLib/Session.cpp
@@ -0,0 +1,207 @@
+/** @addtogroup MCD_IMPL_LIB
+ * @{
+ * @file
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdint.h>
+#include <vector>
+
+#include "mc_drv_module_api.h"
+
+#include "Session.h"
+
+#define LOG_TAG	"McClient"
+#include "log.h"
+
+
+//------------------------------------------------------------------------------
+Session::Session(
+    uint32_t    sessionId,
+    CMcKMod     *mcKMod,
+    Connection  *connection
+) {
+    this->sessionId = sessionId;
+    this->mcKMod = mcKMod;
+    this->notificationConnection = connection;
+
+    sessionInfo.lastErr = SESSION_ERR_NO;
+    sessionInfo.state = SESSION_STATE_INITIAL;
+}
+
+
+//------------------------------------------------------------------------------
+Session::~Session(
+    void
+) {
+    BulkBufferDescriptor  *pBlkBufDescr;
+
+    // Unmap still mapped buffers
+    for ( bulkBufferDescrIterator_t iterator = bulkBufferDescriptors.begin();
+          iterator != bulkBufferDescriptors.end();
+          ++iterator)
+    {
+        pBlkBufDescr = *iterator;
+
+        LOG_I("removeBulkBuf - Physical Address of L2 Table = 0x%X, handle= %d",
+                (unsigned int)pBlkBufDescr->physAddrWsmL2,
+                pBlkBufDescr->handle);
+
+        // ignore any error, as we cannot do anything in this case.
+        int ret = mcKMod->unregisterWsmL2(pBlkBufDescr->handle);
+        if (0 != ret)
+        {
+            LOG_E("removeBulkBuf(): mcKModUnregisterWsmL2 failed: %d",ret);
+        }
+
+        //iterator = bulkBufferDescriptors.erase(iterator);
+        delete(pBlkBufDescr);
+    }
+
+    // Finally delete notification connection
+    delete notificationConnection;
+}
+
+
+//------------------------------------------------------------------------------
+void Session::setErrorInfo(
+    int32_t err
+) {
+    sessionInfo.lastErr = err;
+}
+
+
+//------------------------------------------------------------------------------
+int32_t Session::getLastErr(
+    void
+) {
+    return sessionInfo.lastErr;
+}
+
+
+//------------------------------------------------------------------------------
+BulkBufferDescriptor* Session::addBulkBuf(
+    addr_t		buf,
+    uint32_t	len
+) {
+    BulkBufferDescriptor* blkBufDescr = NULL;
+
+    // Search bulk buffer descriptors for existing vAddr
+    // At the moment a virtual address can only be added one time
+    for ( bulkBufferDescrIterator_t iterator = bulkBufferDescriptors.begin();
+          iterator != bulkBufferDescriptors.end();
+          ++iterator
+    ) {
+        if ((*iterator)->virtAddr == buf)
+        {
+            return NULL;
+        }
+    }
+
+    do
+    {
+        // Prepare the interface structure for memory registration in Kernel Module
+        addr_t    pPhysWsmL2;
+        uint32_t  handle;
+
+        int ret = mcKMod->registerWsmL2(
+                    buf,
+                    len,
+                    0,
+                    &handle,
+                    &pPhysWsmL2);
+
+        if (0 != ret) {
+            LOG_E("mcKModRegisterWsmL2 failed, ret=%d",ret);
+            break;
+        }
+
+        LOG_I("addBulkBuf - Physical Address of L2 Table = 0x%X, handle=%d",
+                (unsigned int)pPhysWsmL2,
+                handle);
+
+        // Create new descriptor
+        blkBufDescr = new BulkBufferDescriptor(
+                            buf,
+                            len,
+                            handle,
+                            pPhysWsmL2);
+
+        // Add to vector of descriptors
+        bulkBufferDescriptors.push_back(blkBufDescr);
+    } while(0);
+
+    return blkBufDescr;
+}
+
+
+//------------------------------------------------------------------------------
+bool Session::removeBulkBuf(
+	addr_t	virtAddr
+) {
+    bool ret = true;
+    BulkBufferDescriptor  *pBlkBufDescr = NULL;
+
+    LOG_I("removeBulkBuf(): Virtual Address = 0x%X", (unsigned int) virtAddr);
+
+    // Search and remove bulk buffer descriptor
+    for ( bulkBufferDescrIterator_t iterator = bulkBufferDescriptors.begin();
+          iterator != bulkBufferDescriptors.end();
+          ++iterator
+    ) {
+
+        if ((*iterator)->virtAddr == virtAddr)
+        {
+            pBlkBufDescr = *iterator;
+            iterator = bulkBufferDescriptors.erase(iterator);
+            break;
+        }
+    }
+
+    if (NULL == pBlkBufDescr)
+    {
+        LOG_E("removeBulkBuf - Virtual Address not found");
+        ret = false;
+    }
+    else
+    {
+        LOG_I("removeBulkBuf(): WsmL2 phys=0x%X, handle=%d",
+        		(unsigned int)pBlkBufDescr->physAddrWsmL2, pBlkBufDescr->handle);
+
+        // ignore any error, as we cannot do anything
+        int ret = mcKMod->unregisterWsmL2(pBlkBufDescr->handle);
+        if (0 != ret)
+        {
+            LOG_E("removeBulkBuf(): mcKModUnregisterWsmL2 failed: %d",ret);
+        }
+
+        delete (pBlkBufDescr);
+    }
+
+    return ret;
+}
+
+/** @} */
diff --git a/mobicore/daemon/ClientLib/Session.h b/mobicore/daemon/ClientLib/Session.h
new file mode 100644
index 0000000..8d609a8
--- /dev/null
+++ b/mobicore/daemon/ClientLib/Session.h
@@ -0,0 +1,167 @@
+/** @addtogroup MCD_IMPL_LIB
+ * @{
+ * @file
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef SESSION_H_
+#define SESSION_H_
+
+#include <stdint.h>
+#include <list>
+
+#include "mc_drv_module_api.h"
+#include "Connection.h"
+#include "CMcKMod.h"
+
+
+class BulkBufferDescriptor{
+
+public:
+    addr_t    virtAddr; /**< The virtual address of the Bulk buffer*/
+    uint32_t  len; /**< Length of the Bulk buffer*/
+    uint32_t  handle;
+    addr_t    physAddrWsmL2; /**< The physical address of the L2 table of the Bulk buffer*/
+
+    BulkBufferDescriptor(
+        addr_t    virtAddr,
+        uint32_t  len,
+        uint32_t  handle,
+        addr_t    physAddrWsmL2
+    ) :
+        virtAddr(virtAddr),
+        len(len),
+        handle(handle),
+    physAddrWsmL2(physAddrWsmL2)
+    {};
+
+};
+
+typedef std::list<BulkBufferDescriptor*>  bulkBufferDescrList_t;
+typedef bulkBufferDescrList_t::iterator   bulkBufferDescrIterator_t;
+
+
+/** Session states.
+ * At the moment not used !!.
+ */
+typedef enum
+{
+	SESSION_STATE_INITIAL,
+	SESSION_STATE_OPEN,
+    SESSION_STATE_TRUSTLET_DEAD
+} sessionState_t;
+
+#define SESSION_ERR_NO      0 /**< No session error */
+
+/** Session information structure.
+ * The information structure is used to hold the state of the session, which will limit further actions for the session.
+ * Also the last error code will be stored till it's read.
+ */
+typedef struct {
+    sessionState_t state;       /**< Session state */
+	int32_t        lastErr;     /**< Last error of session */
+} sessionInformation_t;
+
+
+class Session {
+
+private:
+
+    CMcKMod                  *mcKMod;
+    bulkBufferDescrList_t    bulkBufferDescriptors; /**< Descriptors of additional bulk buffer of a session */
+	sessionInformation_t     sessionInfo; /**< Informations about session */
+
+public:
+
+	uint32_t    sessionId;
+	Connection  *notificationConnection;
+
+	Session(
+	    uint32_t     sessionId,
+	    CMcKMod      *mcKMod,
+	    Connection   *connection
+	);
+
+	virtual ~Session(
+	    void
+	);
+
+	/**
+	 * Add address information of additional bulk buffer memory to session and
+	 * register virtual memory in kernel module.
+	 *
+	 * @attention The virtual address can only be added one time. If the virtual address already exist, NULL is returned.
+	 *
+	 * @param buf The virtual address of bulk buffer.
+	 * @param len Length of bulk buffer.
+	 *
+	 * @return On success the actual Bulk buffer descriptor with all address information is retured, NULL if an error occurs.
+	 */
+	BulkBufferDescriptor * addBulkBuf(
+	    addr_t    buf,
+	    uint32_t  len
+	);
+
+	/**
+	 * Remove address information of additional bulk buffer memory from session and
+	 * unregister virtual memory in kernel module
+	 *
+	 * @param buf The virtual address of the bulk buffer.
+	 *
+	 * @return true on success.
+	 */
+	bool removeBulkBuf(
+	    addr_t	buf
+	);
+
+	/**
+	 * Set additional error information of the last error that occured.
+	 *
+	 * @param errorCode The actual error.
+	 */
+	void setErrorInfo(
+	    int32_t	err
+	);
+
+	/**
+	 * Get additional error information of the last error that occured.
+	 *
+	 * @attention After request the information is set to SESSION_ERR_NO.
+	 *
+	 * @return Last stored error code or SESSION_ERR_NO.
+	 */
+	int32_t getLastErr(
+	    void
+	);
+
+};
+
+typedef std::list<Session*>            sessionList_t;
+typedef sessionList_t::iterator        sessionIterator_t;
+
+#endif /* SESSION_H_ */
+
+/** @} */
diff --git a/mobicore/daemon/ClientLib/public/MobiCoreDriverApi.h b/mobicore/daemon/ClientLib/public/MobiCoreDriverApi.h
new file mode 100644
index 0000000..85997e6
--- /dev/null
+++ b/mobicore/daemon/ClientLib/public/MobiCoreDriverApi.h
@@ -0,0 +1,428 @@
+/**
+ * @defgroup MCD_API                    MobiCore Driver API
+ * @addtogroup MCD_API
+ * @{
+ *
+ * @if DOXYGEN_MCDRV_API
+ *   @mainpage MobiCore Driver API.
+ * @endif
+ *
+ * MobiCore Driver API.
+ *
+ * The MobiCore (MC) Driver API provides access functions to the MobiCore runtime environment and the contained Trustlets.
+ *
+ * @image html DoxyOverviewDrvApi500x.png
+ * @image latex DoxyOverviewDrvApi500x.png "MobiCore Overview" width=12cm
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef MCDRIVER_H_
+#define MCDRIVER_H_
+
+#if (!defined(__MC_CLIENT_LIB_API)) && __cplusplus
+  #define __MC_CLIENT_LIB_API       extern "C"
+#else
+  #define __MC_CLIENT_LIB_API
+#endif // __cplusplus
+
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "mcUuid.h"
+#include "mcVersionInfo.h"
+
+/**
+ * Return values of MobiCore driver functions.
+ */
+typedef enum
+{
+    MC_DRV_OK                                   =  0, /**< Function call succeeded. */
+    MC_DRV_NO_NOTIFICATION                      =  1, /**< No notification available. */
+    MC_DRV_ERR_NOTIFICATION                     =  2, /**< Error during notification on communication level. */
+    MC_DRV_ERR_NOT_IMPLEMENTED                  =  3, /**< Function not implemented. */
+    MC_DRV_ERR_OUT_OF_RESOURCES                 =  4, /**< No more resources available. */
+    MC_DRV_ERR_INIT                             =  5, /**< Driver initialization failed. */
+    MC_DRV_ERR_UNKNOWN                          =  6, /**< Unknown error. */
+    MC_DRV_ERR_UNKNOWN_DEVICE                   =  7, /**< The specified device is unknown. */
+    MC_DRV_ERR_UNKNOWN_SESSION                  =  8, /**< The specified session is unknown. */
+    MC_DRV_ERR_INVALID_OPERATION                =  9, /**< The specified operation is not allowed. */
+    MC_DRV_ERR_INVALID_RESPONSE                 = 10, /**< The response header from the MC is invalid. */
+    MC_DRV_ERR_TIMEOUT                          = 11, /**< Function call timed out. */
+    MC_DRV_ERR_NO_FREE_MEMORY                   = 12, /**< Can not allocate additional memory. */
+    MC_DRV_ERR_FREE_MEMORY_FAILED               = 13, /**< Free memory failed. */
+    MC_DRV_ERR_SESSION_PENDING                  = 14, /**< Still some open sessions pending. */
+    MC_DRV_ERR_DAEMON_UNREACHABLE               = 15, /**< MC daemon not reachable */
+    MC_DRV_ERR_INVALID_DEVICE_FILE              = 16, /**< The device file of the kernel module could not be opened. */
+    MC_DRV_ERR_INVALID_PARAMETER                = 17, /**< Invalid parameter. */
+    MC_DRV_ERR_KERNEL_MODULE                    = 18, /**< Unspecified error from Kernel Module*/
+    MC_DRV_ERR_BULK_MAPPING                     = 19, /**< Error during mapping of additional bulk memory to session. */
+    MC_DRV_ERR_BULK_UNMAPPING                   = 20, /**< Error during unmapping of additional bulk memory to session. */
+    MC_DRV_INFO_NOTIFICATION                    = 21, /**< Notification received, exit code available. */
+    MC_DRV_ERR_NQ_FAILED                        = 22, /**< Set up of NWd connection failed. */
+    MC_DRV_ERR_DAEMON_VERSION                   = 23, /**< Wrong daemon version. */
+    MC_DRV_ERR_CONTAINER_VERSION                = 24, /**< Wrong container version. */
+    MC_DRV_ERR_WRONG_PUBLIC_KEY                 = 25, /**< System Trustlet public key is wrong. */
+    MC_DRV_ERR_CONTAINER_TYPE_MISMATCH          = 26, /**< Wrong containter type(s). */
+    MC_DRV_ERR_CONTAINER_LOCKED                 = 27, /**< Container is locked (or not activated). */
+    MC_DRV_ERR_SP_NO_CHILD                      = 28, /**< SPID is not registered with root container. */
+    MC_DRV_ERR_TL_NO_CHILD                      = 29, /**< UUID is not registered with sp container. */
+    MC_DRV_ERR_UNWRAP_ROOT_FAILED               = 30, /**< Unwrapping of root container failed. */
+    MC_DRV_ERR_UNWRAP_SP_FAILED                 = 31, /**< Unwrapping of service provider container failed. */
+    MC_DRV_ERR_UNWRAP_TRUSTLET_FAILED           = 32, /**< Unwrapping of Trustlet container failed. */
+} mcResult_t;
+
+
+/**
+ * Driver control command.
+ */
+typedef enum {
+    MC_CTRL_DUMMY = 1 /**< Dummy. */
+} mcDriverCtrl_t;
+
+
+/** Structure of Session Handle, includes the Session ID and the Device ID the Session belongs to.
+ * The session handle will be used for session-based MobiCore communication.
+ * It will be passed to calls which address a communication end point in the MobiCore environment.
+ */
+typedef struct {
+	uint32_t sessionId; /**< MobiCore session ID */
+	uint32_t deviceId; /**< Device ID the session belongs to */
+} mcSessionHandle_t;
+
+/** Information structure about additional mapped Bulk buffer between the Trustlet Connector (Nwd) and
+ * the Trustlet (Swd). This structure is initialized from a Trustlet Connector by calling mcMap().
+ * In order to use the memory within a Trustlet the Trustlet Connector has to inform the Trustlet with
+ * the content of this structure via the TCI.
+ */
+typedef struct {
+	void *sVirtualAddr;       	/**< The virtual address of the Bulk buffer regarding the address space of the Trustlet, already includes a possible offset! */
+	uint32_t sVirtualLen;     	/**< Length of the mapped Bulk buffer */
+} mcBulkMap_t;
+
+
+#define MC_DEVICE_ID_DEFAULT       0 /**< The default device ID */
+#define MC_INFINITE_TIMEOUT        ((int32_t)(-1)) /**< Wait infinite for a response of the MC. */
+#define MC_NO_TIMEOUT              0   /**< Do not wait for a response of the MC. */
+#define MC_MAX_TCI_LEN             0x100000 /**< TCI/DCI must not exceed 1MiB */
+
+/* Mark only the following functions for export */
+#pragma GCC visibility push(default)
+
+/** Open a new connection to a MobiCore device.
+ *
+ * mcOpenDevice() initializes all device specific resources required to communicate
+ * with an MobiCore instance located on the specified device in the system. If the device
+ * does not exist the function will return MC_DRV_ERR_UNKNOWN_DEVICE.
+ *
+ * @param [in] deviceId Identifier for the MobiCore device to be used. MC_DEVICE_ID_DEFAULT refers to the default device.
+ *
+ * @return MC_DRV_OK if operation has been successfully completed.
+ * @return MC_DRV_ERR_INVALID_OPERATION if device already opened.
+ * @return MC_DRV_ERR_DAEMON_UNREACHABLE when problems with daemon occur.
+ * @return MC_DRV_ERR_UNKNOWN_DEVICE when deviceId is unknown.
+ * @return MC_DRV_ERR_INVALID_DEVICE_FILE if kernel module under /dev/mobicore cannot be opened
+ *
+ * Uses a Mutex.
+ */
+__MC_CLIENT_LIB_API mcResult_t mcOpenDevice(
+    uint32_t deviceId
+);
+
+/** Close the connection to a MobiCore device.
+ * When closing a device, active sessions have to be closed beforehand.
+ * Resources associated with the device will be released.
+ * The device may be opened again after it has been closed.
+ *
+ * @param [in] deviceId Identifier for the MobiCore device. MC_DEVICE_ID_DEFAULT refers to the default device.
+ *
+ * @return MC_DRV_OK if operation has been successfully completed.
+ * @return MC_DRV_ERR_UNKNOWN_DEVICE when device id is invalid.
+ * @return MC_DRV_ERR_SESSION_PENDING when a session is still open.
+ * @return MC_DRV_ERR_DAEMON_UNREACHABLE when problems with daemon occur.
+ *
+ * Uses a Mutex.
+ */
+__MC_CLIENT_LIB_API mcResult_t mcCloseDevice(
+    uint32_t deviceId
+);
+
+/** Open a new session to a Trustlet. The trustlet with the given UUID has to be available in the flash filesystem.
+ *
+ * Write MCP open message to buffer and notify MobiCore about the availability of a new command.
+ * Waits till the MobiCore responses with the new session ID (stored in the MCP buffer).
+ *
+ * @param [in,out] session On success, the session data will be returned. Note that session.deviceId has to be the device id of an opened device.
+ * @param [in] uuid UUID of the Trustlet to be opened.
+ * @param [in] tci TCI buffer for communicating with the trustlet.
+ * @param [in] tciLen Length of the TCI buffer. Maximum allowed value is MC_MAX_TCI_LEN.
+ *
+ * @return MC_DRV_OK if operation has been successfully completed.
+ * @return MC_DRV_INVALID_PARAMETER if session parameter is invalid.
+ * @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.
+ *
+ * Uses a Mutex.
+ */
+__MC_CLIENT_LIB_API mcResult_t mcOpenSession(
+    mcSessionHandle_t  *session,
+    const mcUuid_t       *uuid,
+    uint8_t            *tci,
+    uint32_t           tciLen
+);
+
+/** Close a Trustlet session.
+ *
+ * Closes the specified MobiCore session. The call will block until the session has been closed.
+ *
+ * @pre Device deviceId has to be opened in advance.
+ *
+ * @param [in] session Session to be closed.
+ *
+ * @return MC_DRV_OK if operation has been successfully completed.
+ * @return MC_DRV_INVALID_PARAMETER if session parameter is invalid.
+ * @return MC_DRV_ERR_UNKNOWN_SESSION when session id is invalid.
+ * @return MC_DRV_ERR_UNKNOWN_DEVICE when device id of session is invalid.
+ * @return MC_DRV_ERR_DAEMON_UNREACHABLE when problems with daemon occur.
+ * @return MC_DRV_ERR_INVALID_DEVICE_FILE when daemon cannot open trustlet file.
+ *
+ * Uses a Mutex.
+ */
+__MC_CLIENT_LIB_API mcResult_t mcCloseSession(
+    mcSessionHandle_t *session
+);
+
+/** Notify a session.
+ * Notifies the session end point about available message data.
+ * If the session parameter is correct, notify will always succeed.
+ * Corresponding errors can only be received by mcWaitNotification().
+ * @pre A session has to be opened in advance.
+ *
+ * @param session The session to be notified.
+ *
+ * @return MC_DRV_OK if operation has been successfully completed.
+ * @return MC_DRV_INVALID_PARAMETER if session parameter is invalid.
+ * @return MC_DRV_ERR_UNKNOWN_SESSION when session id is invalid.
+ * @return MC_DRV_ERR_UNKNOWN_DEVICE when device id of session is invalid.
+ */
+__MC_CLIENT_LIB_API mcResult_t mcNotify(
+    mcSessionHandle_t *session
+);
+
+/** Wait for a notification.
+ *
+ * Wait for a notification issued by the MobiCore for a specific session.
+ * The timeout parameter specifies the number of milliseconds the call will wait for a notification.
+ * If the caller passes 0 as timeout value the call will immediately return. If timeout value is below 0 the call will block
+ * until a notification for the session has been received.
+ *
+ * @attention if timeout is below 0, call will block:
+ * Caller has to trust the other side to send a notification to wake him up again.
+ *
+ * @param [in] session The session the notification should correspond to.
+ * @param [in] timeout Time in milliseconds to wait (MC_NO_TIMEOUT : direct return, > 0 : milliseconds, MC_INFINITE_TIMEOUT : wait infinitely)
+ *
+ * @return MC_DRV_OK if notification is available.
+ * @return MC_DRV_ERR_TIMEOUT if no notification arrived in time.
+ * @return MC_DRV_INFO_NOTIFICATION if a problem with the session was encountered. Get more details with mcGetSessionErrorCode().
+ * @return MC_DRV_ERR_NOTIFICATION if a problem with the socket occurred.
+ * @return MC_DRV_INVALID_PARAMETER if a parameter is invalid.
+ * @return MC_DRV_ERR_UNKNOWN_SESSION when session id is invalid.
+ * @return MC_DRV_ERR_UNKNOWN_DEVICE when device id of session is invalid.
+ */
+__MC_CLIENT_LIB_API mcResult_t mcWaitNotification(
+    mcSessionHandle_t  *session,
+    int32_t            timeout
+);
+
+/**
+ * Allocate a block of world shared memory (WSM).
+ * The MC driver allocates a contiguous block of memory which can be used as WSM.
+ * This implicates that the allocated memory is aligned according to the alignment parameter.
+ * Always returns a buffer of size WSM_SIZE aligned to 4K.
+ *
+ * @param [in]  deviceId The ID of an opened device to retrieve the WSM from.
+ * @param [in]  align The alignment (number of pages) of the memory block (e.g. 0x00000001 for 4kb).
+ * @param [in]  len	Length of the block in bytes.
+ * @param [out] wsm Virtual address of the world shared memory block.
+ * @param [in]  wsmFlags Platform specific flags describing the memory to be allocated.
+ *
+ * @attention: align and wsmFlags are currently ignored
+ *
+ * @return MC_DRV_OK if operation has been successfully completed.
+ * @return MC_DRV_INVALID_PARAMETER if a parameter is invalid.
+ * @return MC_DRV_ERR_UNKNOWN_DEVICE when device id is invalid.
+ * @return MC_DRV_ERR_NO_FREE_MEMORY if no more contiguous memory is available in this size or for this process.
+ *
+ * Uses a Mutex.
+ */
+__MC_CLIENT_LIB_API mcResult_t mcMallocWsm(
+    uint32_t  deviceId,
+    uint32_t  align,
+    uint32_t  len,
+    uint8_t   **wsm,
+    uint32_t  wsmFlags
+);
+
+/**
+ * Free a block of world shared memory (WSM).
+ * The MC driver will free a block of world shared memory (WSM) previously allocated with
+ * mcMallocWsm(). The caller has to assure that the address handed over to the driver
+ * is a valid WSM address.
+ *
+ * @param [in] deviceId The ID to which the given address belongs.
+ * @param [in] wsm Address of WSM block to be freed.
+ *
+ * @return MC_DRV_OK if operation has been successfully completed.
+ * @return MC_DRV_INVALID_PARAMETER if a parameter is invalid.
+ * @return MC_DRV_ERR_UNKNOWN_DEVICE when device id is invalid.
+ * @return MC_DRV_ERR_FREE_MEMORY_FAILED on failures.
+ *
+ * Uses a Mutex.
+ */
+__MC_CLIENT_LIB_API mcResult_t mcFreeWsm(
+    uint32_t  deviceId,
+    uint8_t   *wsm
+);
+
+/**
+ * Map additional bulk buffer between a Trustlet Connector (TLC) and the Trustlet (TL) for a session.
+ * Memory allocated in user space of the TLC can be mapped as additional communication channel
+ * (besides TCI) to the Trustlet. Limitation of the Trustlet memory structure apply: only 6 chunks can be mapped
+ * with a maximum chunk size of 1 MiB each.
+ *
+ * @attention It is up to the application layer (TLC) to inform the Trustlet about the additional mapped bulk memory.
+ *
+ * @param [in] session Session handle with information of the deviceId and the sessionId. The
+ * given buffer is mapped to the session specified in the sessionHandle.
+ * @param [in] buf Virtual address of a memory portion (relative to TLC) to be shared with the Trustlet, already includes a possible offset!
+ * @param [in] len length of buffer block in bytes.
+ * @param [out] mapInfo Information structure about the mapped Bulk buffer between the TLC (Nwd) and
+ * the TL (Swd).
+ *
+ * @return MC_DRV_OK if operation has been successfully completed.
+ * @return MC_DRV_INVALID_PARAMETER if a parameter is invalid.
+ * @return MC_DRV_ERR_UNKNOWN_SESSION when session id is invalid.
+ * @return MC_DRV_ERR_UNKNOWN_DEVICE when device id of session is invalid.
+ * @return MC_DRV_ERR_DAEMON_UNREACHABLE when problems with daemon occur.
+ * @return MC_DRV_ERR_BULK_MAPPING when buf is already uses as bulk buffer or when registering the buffer failed.
+ *
+ * Uses a Mutex.
+ */
+__MC_CLIENT_LIB_API mcResult_t mcMap(
+    mcSessionHandle_t  *session,
+    void               *buf,
+    uint32_t           len,
+    mcBulkMap_t        *mapInfo
+);
+
+/**
+ * Remove additional mapped bulk buffer between Trustlet Connector (TLC) and the Trustlet (TL) for a session.
+ *
+ * @attention The bulk buffer will immediately be unmapped from the session context.
+ * @attention The application layer (TLC) must inform the TL about unmapping of the additional bulk memory before calling mcUnmap!
+ *
+ * @param [in] session Session handle with information of the deviceId and the sessionId. The
+ * given buffer is unmapped from the session specified in the sessionHandle.
+ * @param [in] buf Virtual address of a memory portion (relative to TLC) shared with the TL, already includes a possible offset!
+ * @param [in] mapInfo Information structure about the mapped Bulk buffer between the TLC (Nwd) and
+ * the TL (Swd).
+ * @attention The clientlib currently ignores the len field in mapInfo.
+ *
+ * @return MC_DRV_OK if operation has been successfully completed.
+ * @return MC_DRV_INVALID_PARAMETER if a parameter is invalid.
+ * @return MC_DRV_ERR_UNKNOWN_SESSION when session id is invalid.
+ * @return MC_DRV_ERR_UNKNOWN_DEVICE when device id of session is invalid.
+ * @return MC_DRV_ERR_DAEMON_UNREACHABLE when problems with daemon occur.
+ * @return MC_DRV_ERR_BULK_UNMAPPING when buf was not registered earlier or when unregistering failed.
+ *
+ * Uses a Mutex.
+ */
+__MC_CLIENT_LIB_API mcResult_t mcUnmap(
+    mcSessionHandle_t  *session,
+    void               *buf,
+    mcBulkMap_t        *mapInfo
+);
+
+
+/**
+ * @attention: Not implemented.
+ * Execute driver specific command.
+ * mcDriverCtrl() can be used to execute driver specific commands.
+ * Besides the control command MC_CTRL_GET_VERSION commands are implementation specific.
+ * Please refer to the corresponding specification of the driver manufacturer.
+ *
+ * @param [in] param Command ID of the command to be executed.
+ * @param [in, out] data  Command data and response depending on command.
+ * @param [in] len Length of the data block.
+ *
+ * @return MC_DRV_ERR_NOT_IMPLEMENTED.
+ */
+__MC_CLIENT_LIB_API mcResult_t mcDriverCtrl(
+    mcDriverCtrl_t  param,
+    uint8_t         *data,
+    uint32_t        len
+);
+
+/**
+ * Get additional error information of the last error that occured on a session.
+ * After the request the stored error code will be deleted.
+ *
+ * @param [in] session Session handle with information of the deviceId and the sessionId.
+ * @param [out] lastErr >0 Trustlet has terminated itself with this value, <0 Trustlet is dead because of an error within the MobiCore (e.g. Kernel exception).
+ * See also MCI definition.
+ *
+ * @return MC_DRV_OK if operation has been successfully completed.
+ * @return MC_DRV_INVALID_PARAMETER if a parameter is invalid.
+ * @return MC_DRV_ERR_UNKNOWN_SESSION when session id is invalid.
+ * @return MC_DRV_ERR_UNKNOWN_DEVICE when device id of session is invalid.
+ */
+__MC_CLIENT_LIB_API mcResult_t mcGetSessionErrorCode(
+    mcSessionHandle_t  *session,
+    int32_t            *lastErr
+);
+
+/**
+ * Get MobiCore version information of a device.
+ *
+ * @param [in] deviceId of an open device.
+ * @param [out] versionInfo MobiCore version info.
+ *
+ * @return MC_DRV_OK if operation has been successfully completed.
+ * @return MC_DRV_ERR_UNKNOWN_DEVICE when device is not open.
+ * @return MC_DRV_INVALID_PARAMETER if a parameter is invalid.
+ * @return MC_DRV_ERR_DAEMON_UNREACHABLE when problems with daemon occur.
+ */
+__MC_CLIENT_LIB_API mcResult_t mcGetMobiCoreVersion(
+    uint32_t  deviceId,
+    mcVersionInfo_t* versionInfo
+);
+#pragma GCC visibility pop
+#endif /** MCDRIVER_H_ */
+
+/** @} */
diff --git a/mobicore/daemon/Common/Android.mk b/mobicore/daemon/Common/Android.mk
new file mode 100644
index 0000000..1b6520c
--- /dev/null
+++ b/mobicore/daemon/Common/Android.mk
@@ -0,0 +1,33 @@
+# =============================================================================
+#
+# Module: libCommon.a - classes shared by various modules
+#
+# =============================================================================
+
+LOCAL_PATH	:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE	:= libMcCommon
+LOCAL_MODULE_TAGS := eng
+
+# Add new source files here
+LOCAL_SRC_FILES +=\
+	CMutex.cpp\
+	Connection.cpp\
+    NetlinkConnection.cpp\
+	CSemaphore.cpp\
+	CThread.cpp
+
+# Header files required by components including this module
+LOCAL_EXPORT_C_INCLUDES	:= $(LOCAL_PATH)
+LOCAL_EXPORT_CPPFLAGS += -fno-rtti -fno-exceptions
+
+LOCAL_C_INCLUDES += bionic \
+	external/stlport/stlport
+
+LOCAL_CPPFLAGS += -fno-rtti -fno-exceptions
+
+include $(COMP_PATH_Logwrapper)/Android.mk
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/mobicore/daemon/Common/CMutex.cpp b/mobicore/daemon/Common/CMutex.cpp
new file mode 100644
index 0000000..0ae95c8
--- /dev/null
+++ b/mobicore/daemon/Common/CMutex.cpp
@@ -0,0 +1,77 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_SRV
+ * @{
+ * @file
+ *
+ * Mutex implementation (pthread wrapper).
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "CMutex.h"
+
+
+//------------------------------------------------------------------------------
+CMutex::CMutex(
+	void
+) {
+	pthread_mutex_init(&m_mutex, NULL);
+	pthread_cond_init(&m_cond, NULL);
+}
+
+
+//------------------------------------------------------------------------------
+CMutex::~CMutex(
+	void
+) {
+	pthread_mutex_destroy(&m_mutex);
+	pthread_cond_destroy(&m_cond);
+}
+
+
+//------------------------------------------------------------------------------
+int32_t CMutex::lock(
+	void
+) {
+	return pthread_mutex_lock(&m_mutex);
+}
+
+
+//------------------------------------------------------------------------------
+int32_t CMutex::trylock(
+	void
+) {
+    return pthread_mutex_trylock(&m_mutex);
+}
+
+
+//------------------------------------------------------------------------------
+int32_t CMutex::unlock(
+	void
+) {
+    return pthread_mutex_unlock(&m_mutex);
+}
+
+/** @} */
diff --git a/mobicore/daemon/Common/CMutex.h b/mobicore/daemon/Common/CMutex.h
new file mode 100644
index 0000000..c6c1bc4
--- /dev/null
+++ b/mobicore/daemon/Common/CMutex.h
@@ -0,0 +1,63 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_SRV
+ * @{
+ * @file
+ *
+ * Mutex implementation (pthread wrapper).
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef CMUTEX_H_
+#define CMUTEX_H_
+
+#include <inttypes.h>
+#include "pthread.h"
+
+
+class CMutex {
+
+public:
+
+	CMutex(void);
+
+	~CMutex(void);
+
+	int32_t lock(void);
+
+	int32_t trylock(void);
+
+	int32_t unlock(void);
+
+private:
+
+	pthread_mutex_t m_mutex;
+	pthread_cond_t m_cond;
+
+};
+
+#endif /* CMUTEX_H_ */
+
+/** @} */
diff --git a/mobicore/daemon/Common/CSemaphore.cpp b/mobicore/daemon/Common/CSemaphore.cpp
new file mode 100644
index 0000000..2e7deea
--- /dev/null
+++ b/mobicore/daemon/Common/CSemaphore.cpp
@@ -0,0 +1,113 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_SRV
+ * @{
+ * @file
+ *
+ * Semaphore implementation (pthread wrapper).
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <time.h>
+#include <limits.h>
+#include "CSemaphore.h"
+#include <stdio.h>
+
+//------------------------------------------------------------------------------
+CSemaphore::CSemaphore(int size) : m_waiters_count(0), m_count(size)  
+{
+	pthread_mutex_init(&m_mutex, NULL);
+	pthread_cond_init(&m_cond, NULL);
+}
+
+
+//------------------------------------------------------------------------------
+CSemaphore::~CSemaphore()
+{
+	pthread_mutex_destroy(&m_mutex);
+	pthread_cond_destroy(&m_cond);
+}
+
+
+//------------------------------------------------------------------------------
+void CSemaphore::wait()
+{
+	pthread_mutex_lock(&m_mutex);
+	m_waiters_count ++;
+	while( m_count == 0 )
+		pthread_cond_wait(&m_cond, &m_mutex);
+	m_waiters_count --;
+	m_count --;
+	pthread_mutex_unlock(&m_mutex);
+}
+
+//------------------------------------------------------------------------------
+bool CSemaphore::wait(int sec)
+{
+	int rc = 0;
+	struct timespec tm;
+	if(sec < 0)
+		sec = LONG_MAX;
+	clock_gettime(CLOCK_REALTIME, &tm);
+	tm.tv_sec += sec;
+	
+	pthread_mutex_lock(&m_mutex);
+	m_waiters_count ++;
+	if( m_count == 0 ) {
+		rc = pthread_cond_timedwait(&m_cond, &m_mutex, &tm);
+	}
+	m_waiters_count --;
+	// Decrement only if waiting actually succeeded, otherwise we
+	// just timed out
+	if (!rc)
+		m_count --;
+	pthread_mutex_unlock(&m_mutex);
+	return (rc == 0);
+}
+
+
+//------------------------------------------------------------------------------
+bool CSemaphore::wouldWait()
+{
+	bool ret = false;
+	pthread_mutex_lock(&m_mutex);
+	if( m_count == 0 )
+		ret = true;
+	pthread_mutex_unlock(&m_mutex);
+	return ret;
+}
+
+
+//------------------------------------------------------------------------------
+void CSemaphore::signal()
+{
+	pthread_mutex_lock(&m_mutex);
+	if( m_waiters_count > 0 )
+		pthread_cond_signal(&m_cond);
+	m_count ++;
+	pthread_mutex_unlock(&m_mutex);
+}
+
+/** @} */
diff --git a/mobicore/daemon/Common/CSemaphore.h b/mobicore/daemon/Common/CSemaphore.h
new file mode 100644
index 0000000..0739430
--- /dev/null
+++ b/mobicore/daemon/Common/CSemaphore.h
@@ -0,0 +1,70 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_SRV
+ * @{
+ * @file
+ *
+ * Semaphore implementation (pthread wrapper).
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef CSEMAPHORE_H_
+#define CSEMAPHORE_H_
+
+#include "pthread.h"
+
+/**
+ * Could inherit from CMutex, or use CMutex internally.
+ * Semaphore is a mutex with a counter. Constructor and destructor
+ * code is the same.
+ */
+
+class CSemaphore {
+
+public:
+
+	CSemaphore(int size = 0);
+
+	~CSemaphore(void);
+
+	void wait(void);
+	bool wait(int sec);
+
+	bool wouldWait(void);
+
+	void signal(void);
+
+private:
+
+	pthread_mutex_t m_mutex;
+	pthread_cond_t m_cond;
+	int m_waiters_count;
+	int m_count;
+
+};
+
+#endif /*CSEMAPHORE_H_*/
+
+/** @} */
diff --git a/mobicore/daemon/Common/CThread.cpp b/mobicore/daemon/Common/CThread.cpp
new file mode 100644
index 0000000..1508c13
--- /dev/null
+++ b/mobicore/daemon/Common/CThread.cpp
@@ -0,0 +1,143 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_SRV
+ * @{
+ * @file
+ *
+ * Thread implementation (pthread abstraction).
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "CThread.h"
+
+#define LOG_TAG	"McDaemon"
+#include "log.h"
+
+
+//------------------------------------------------------------------------------
+CThread::CThread(void) :
+	m_terminate(false), m_isExiting(false)
+{
+	m_sem = new CSemaphore();
+}
+
+
+//------------------------------------------------------------------------------
+CThread::~CThread(
+	void
+) {
+	delete m_sem;
+}
+
+
+//------------------------------------------------------------------------------
+void CThread::terminate(
+	void
+) {
+	m_terminate = true;
+}
+
+
+//------------------------------------------------------------------------------
+bool CThread::isExiting(
+	void
+) {
+    return m_isExiting;
+}
+
+
+//------------------------------------------------------------------------------
+void CThread::setExiting(
+	void
+) {
+    m_isExiting = true;
+}
+
+
+//------------------------------------------------------------------------------
+void CThread::exit(
+	int32_t exitcode
+) {
+    setExiting();
+    pthread_exit((void *)exitcode);
+}
+
+
+//------------------------------------------------------------------------------
+bool CThread::shouldTerminate(
+	void
+) {
+	return m_terminate;
+}
+
+
+//------------------------------------------------------------------------------
+void CThread::start(
+	void
+) {
+	int ret;
+	ret = pthread_create(&m_thread, NULL, CThreadStartup, this);
+	if (0 != ret)
+		LOG_E("pthread_create failed with error code %d", ret);
+}
+
+
+//------------------------------------------------------------------------------
+void CThread::join(
+	void
+) {
+	int ret;
+	ret = pthread_join(m_thread, NULL);
+	if (0 != ret)
+		LOG_E("pthread_join failed with error code %d", ret);
+}
+
+
+//------------------------------------------------------------------------------
+void CThread::sleep(
+	void
+) {
+	m_sem->wait();
+}
+
+
+//------------------------------------------------------------------------------
+void CThread::wakeup(
+	void
+) {
+	m_sem->signal();
+}
+
+
+//------------------------------------------------------------------------------
+void *CThreadStartup(
+	void *_tgtObject
+) {
+	CThread *tgtObject = (CThread *) _tgtObject;
+	tgtObject->run();
+	return NULL;
+}
+
+/** @} */
diff --git a/mobicore/daemon/Common/CThread.h b/mobicore/daemon/Common/CThread.h
new file mode 100644
index 0000000..be053bf
--- /dev/null
+++ b/mobicore/daemon/Common/CThread.h
@@ -0,0 +1,86 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_SRV
+ * @{
+ * @file
+ *
+ * Thread implementation (pthread abstraction).
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef CTHREAD_H_
+#define CTHREAD_H_
+
+#include <inttypes.h>
+#include "CSemaphore.h"
+#include "pthread.h"
+
+using namespace std;
+
+
+class CThread {
+
+public:
+
+	CThread(void);
+
+	virtual ~CThread(void);
+
+	virtual void run(void)=0;
+
+	void start(void);
+
+	void join(void);
+
+	void sleep(void);
+
+	void wakeup(void);
+
+	void terminate(void);
+
+	bool isExiting(void);
+
+	void setExiting(void);
+
+protected:
+
+	bool shouldTerminate(void);
+
+	void exit(int32_t exitcode);
+
+private:
+
+	CSemaphore *m_sem;
+	pthread_t m_thread;
+	bool m_terminate;
+	bool m_isExiting;
+
+};
+
+extern "C" void *CThreadStartup(void *);
+
+#endif /*CTHREAD_H_*/
+
+/** @} */
diff --git a/mobicore/daemon/Common/CWsm.h b/mobicore/daemon/Common/CWsm.h
new file mode 100644
index 0000000..d95dc73
--- /dev/null
+++ b/mobicore/daemon/Common/CWsm.h
@@ -0,0 +1,70 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_SRV
+ * @{
+ * @file
+ *
+ * World shared memory definitions.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef CWSM_H_
+#define CWSM_H_
+
+#include <stdint.h>
+#include <list>
+#include "McTypes.h"
+
+
+class CWsm {
+
+public:
+
+	addr_t virtAddr;
+	uint32_t len;
+	uint32_t handle;
+	addr_t physAddr;
+
+    CWsm(
+        addr_t    virtAddr,
+        uint32_t  len,
+        uint32_t  handle,
+        addr_t    physAddr = NULL // this may be unknown, so is can be omitted.
+    ) :
+        virtAddr(virtAddr),
+        len(len),
+        handle(handle),
+        physAddr(physAddr)
+    { };
+
+};
+
+typedef CWsm                   *CWsm_ptr;
+typedef std::list<CWsm_ptr>  wsmList_t;
+typedef wsmList_t::iterator  wsmIterator_t;
+
+#endif /* CWSM_H_ */
+
+/** @} */
diff --git a/mobicore/daemon/Common/Connection.cpp b/mobicore/daemon/Common/Connection.cpp
new file mode 100644
index 0000000..d9b012b
--- /dev/null
+++ b/mobicore/daemon/Common/Connection.cpp
@@ -0,0 +1,200 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_SRV
+ * @{
+ * @file
+ *
+ * Connection data.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <unistd.h>
+#include <assert.h>
+#include <cstring>
+#include <errno.h>
+
+#include "Connection.h"
+
+#define LOG_TAG	"McClient"
+#include "log.h"
+
+
+//------------------------------------------------------------------------------
+Connection::Connection(
+    void
+) {
+	connectionData = NULL;
+	// Set invalid socketDescriptor
+	socketDescriptor = -1;
+}
+
+
+//------------------------------------------------------------------------------
+Connection::Connection(
+    int           socketDescriptor,
+    sockaddr_un   *remote
+) {
+	assert(NULL != remote);
+	assert(-1 != socketDescriptor);
+
+	this->socketDescriptor = socketDescriptor;
+	this->remote = *remote;
+	connectionData = NULL;
+}
+
+
+//------------------------------------------------------------------------------
+Connection::~Connection(
+    void
+) {
+	LOG_I("%s: Connection closed!", __func__);
+    if (socketDescriptor != -1)
+        close(socketDescriptor);
+}
+
+
+//------------------------------------------------------------------------------
+bool Connection::connect(
+    const char *dest
+) {
+	bool ret = false;
+	int32_t len;
+
+	assert(NULL != dest);
+
+	LOG_I("connect(): Connecting to %s", dest);
+	do {
+		remote.sun_family = AF_UNIX;
+		strncpy(remote.sun_path, dest, sizeof(remote.sun_path) - 1);
+		if ((socketDescriptor = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+			LOG_E("Can't open stream socket - errno: %d", errno);
+			break;
+		}
+		len = strlen(remote.sun_path) + sizeof(remote.sun_family);
+		// The Daemon socket is in the Abstract Domain(LINUX ONLY!)
+		remote.sun_path[0] = 0;
+		if (::connect(socketDescriptor, (struct sockaddr *) &remote, len) < 0) {
+			LOG_E("connect() failed - errno: %d", errno);
+			break;
+		}
+		ret = true;
+	} while (false);
+
+	return ret;
+}
+
+
+//------------------------------------------------------------------------------
+size_t Connection::readData(
+    void *buffer,
+    uint32_t len
+) {
+    return readData(buffer, len, -1);
+}
+
+
+//------------------------------------------------------------------------------
+size_t Connection::readData(
+    void      *buffer,
+    uint32_t  len,
+    int32_t   timeout
+) {
+	size_t ret;
+	struct timeval tv;
+	struct timeval *ptv = NULL;
+    fd_set readfds;
+
+    assert(NULL != buffer);
+	assert(-1 != socketDescriptor);
+
+    do{
+
+        if(timeout >= 0){
+            // Calculate timeout value
+            tv.tv_sec = timeout/1000;
+            tv.tv_usec = (timeout - (tv.tv_sec * 1000)) * 1000;
+            ptv = &tv;
+        }
+
+        FD_ZERO(&readfds);
+        FD_SET(socketDescriptor, &readfds);
+        ret = select(socketDescriptor + 1, &readfds, NULL, NULL, ptv);
+
+        // check for read error
+        if (-1 == (int)ret) {
+            LOG_E("readData(): select() failed, ret=%d, errno=%d", ret,errno);
+            break;
+        }
+
+        // Handle case of no descriptor ready
+        if (0 == ret) {
+            LOG_W("readData(): select() timed out");
+            ret = -2;
+            break;
+        }
+
+        // one or more descriptors are ready 
+
+        // finally check if fd has been selected -> must socketDescriptor
+        if (!FD_ISSET(socketDescriptor, &readfds))
+        {
+            LOG_E("readData(): failure, errno=%d", errno);
+            break;
+        }
+
+        ret = recv(socketDescriptor, buffer, len, MSG_WAITALL);
+        if(0 == ret)
+        {
+            LOG_I("readData(): peer orderly closed connection.");
+            break;
+        }
+
+    }while(false);
+
+	return ret;
+}
+
+
+//------------------------------------------------------------------------------
+size_t Connection::writeData(
+    void *buffer,
+    uint32_t len
+) {
+	size_t ret;
+
+	assert(NULL != buffer);
+	assert(-1 != socketDescriptor);
+
+    ret = send(socketDescriptor, buffer, len, 0);
+    if (ret != len)
+    {
+        LOG_E( "writeData(): could no send all data, ret=%d, errno: %d", ret,errno);
+        ret = -1;
+    }
+
+    return ret;
+}
+
+/** @} */
diff --git a/mobicore/daemon/Common/Connection.h b/mobicore/daemon/Common/Connection.h
new file mode 100644
index 0000000..81e8dd8
--- /dev/null
+++ b/mobicore/daemon/Common/Connection.h
@@ -0,0 +1,125 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_SRV
+ * @{
+ * @file
+ *
+ * Connection data.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef CONNECTION_H_
+#define CONNECTION_H_
+
+#include <list>
+#include <exception>
+
+#include <inttypes.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+
+class Connection {
+
+public:
+    struct sockaddr_un remote; /**< Remote address */
+    int32_t socketDescriptor; /**< Local socket descriptor */
+    void *connectionData; /**< reference to data related with the connection */
+    bool detached; /**< Connection state */
+
+    Connection(
+        void
+    );
+
+    Connection(
+        int          socketDescriptor,
+        sockaddr_un  *remote
+    );
+
+    virtual ~Connection(
+        void
+    );
+
+    /**
+     * Connect to destination.
+     *
+     * @param Destination pointer.
+     * @return true on success.
+     */
+    virtual bool connect(
+        const char *dest
+    );
+
+    /**
+     * Read bytes from the connection.
+     *
+     * @param buffer	Pointer to destination buffer.
+     * @param len       Number of bytes to read.
+     * @param timeout   Timeout in milliseconds
+     * @return Number of bytes read.
+     * @return -1 if select() failed (returned -1)
+     * @return -2 if no data available, i.e. timeout
+     */
+    virtual size_t readData(
+        void      *buffer,
+        uint32_t  len,
+        int32_t   timeout
+    );
+
+    /**
+     * Read bytes from the connection.
+     *
+     * @param buffer    Pointer to destination buffer.
+     * @param len       Number of bytes to read.
+     * @return Number of bytes read.
+     */
+    virtual size_t readData(
+        void      * buffer,
+        uint32_t  len
+    );
+
+    /**
+     * Write bytes to the connection.
+     *
+     * @param buffer	Pointer to source buffer.
+     * @param len		Number of bytes to read.
+     * @return Number of bytes written.
+     */
+    virtual size_t writeData(
+        void      *buffer,
+        uint32_t  len
+    );
+
+};
+
+typedef std::list<Connection*>         connectionList_t;
+typedef connectionList_t::iterator     connectionIterator_t;
+
+
+#endif /* CONNECTION_H_ */
+
+/** @} */
diff --git a/mobicore/daemon/Common/McTypes.h b/mobicore/daemon/Common/McTypes.h
new file mode 100644
index 0000000..a4f8f4f
--- /dev/null
+++ b/mobicore/daemon/Common/McTypes.h
@@ -0,0 +1,40 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_SRV
+ * @{
+ * @file
+ *
+ * MobiCore types redefinition.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef MCTYPES_H_
+#define MCTYPES_H_
+
+typedef void    *addr_t;
+
+#endif /* MCTYPES_H_ */
+
+/** @} */
diff --git a/mobicore/daemon/Common/NetlinkConnection.cpp b/mobicore/daemon/Common/NetlinkConnection.cpp
new file mode 100644
index 0000000..81b394b
--- /dev/null
+++ b/mobicore/daemon/Common/NetlinkConnection.cpp
@@ -0,0 +1,289 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_SRV
+ * @{
+ * @file
+ *
+ * Connection data.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include <cstring>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+
+#include "NetlinkConnection.h"
+
+#define LOG_TAG	"McDaemon"
+#include "log.h"
+
+
+uint64_t hashConnection(
+	pid_t pid,
+	uint32_t seq
+)
+{
+	return (((uint64_t)seq) << 32) | (uint64_t)pid;
+}
+
+
+//------------------------------------------------------------------------------
+NetlinkConnection::NetlinkConnection(
+    void
+) :Connection(), 
+    dataLeft(0),
+    manager(NULL)
+{
+	detached = false;
+	dataMsg = NULL;
+	dataStart = NULL;
+	dataLen = 0;
+    
+	
+	selfPid = getpid();
+	peerPid = 0;
+	sequenceMagic = 0;
+	hash = hashConnection(peerPid, sequenceMagic);
+}
+
+
+//------------------------------------------------------------------------------
+NetlinkConnection::NetlinkConnection(
+    NetlinkConnectionManager	*manager,
+    int							socketDescriptor,
+	uint32_t 					pid,
+    uint32_t					seq
+): Connection(), 
+    dataLeft(0),
+    manager(manager)
+{
+	detached = false;
+	dataMsg = NULL;
+	dataStart = NULL;
+	dataLen = 0;
+    
+	this->socketDescriptor = socketDescriptor;
+	selfPid = getpid();
+	peerPid = pid;
+	sequenceMagic = seq;
+	hash = hashConnection(pid, seq);
+}
+
+
+//------------------------------------------------------------------------------
+NetlinkConnection::~NetlinkConnection(
+    void
+) {
+    LOG_I("%s: destroy connection for PID 0x%X", __func__, peerPid);
+    socketDescriptor = -1;
+    free(dataMsg);
+    
+    if (manager) {
+		manager->removeConnection(hash);
+    }
+}
+
+
+//------------------------------------------------------------------------------
+bool NetlinkConnection::connect(
+    const char *dest
+) {
+    struct sockaddr_nl addr;
+    bool ret = false;
+
+	assert(NULL != dest);
+
+    LOG_I("%s: Connecting to SEQ 0x%X", __func__, MC_DAEMON_PID);
+    do {
+		if ((socketDescriptor = socket(PF_NETLINK, SOCK_DGRAM, MC_DAEMON_NETLINK)) < 0) {
+            LOG_E("%s: Can't open netlink socket - errno: %d(%s)", 
+                  __func__, errno, strerror(errno));
+            break;
+        }
+        memset(&addr, 0, sizeof(addr));
+        addr.nl_family = AF_NETLINK;
+        addr.nl_pid = selfPid;  /* self pid */
+        addr.nl_groups = 0;  /* not in mcast groups */
+        
+        if (bind(socketDescriptor, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
+            LOG_E("%s: bind() failed - errno: %d(%s)", __func__, errno, strerror(errno));
+            close(socketDescriptor);
+            
+            // Set invalid socketDescriptor
+            socketDescriptor = -1;
+            break;
+        }
+        ret = true;
+    
+        
+    } while (false);
+
+	return ret;
+}
+
+
+//------------------------------------------------------------------------------
+void NetlinkConnection::handleMessage(
+    struct nlmsghdr *nlh
+) {
+	dataMutex.lock();
+    /* Takeover the buffer */
+    dataMsg = nlh;
+    dataLen = NLMSG_PAYLOAD(dataMsg, 0);
+	dataStart = static_cast<uint8_t *>(NLMSG_DATA(dataMsg));
+	dataMutex.unlock();
+	dataLeft.signal();
+}
+
+//------------------------------------------------------------------------------
+size_t NetlinkConnection::readData(
+    void *buffer,
+    uint32_t len
+) {
+    return readData(buffer, len, -1);
+}
+
+
+//------------------------------------------------------------------------------
+size_t NetlinkConnection::readData(
+    void      *buffer,
+    uint32_t  len,
+    int32_t   timeout
+) {
+    size_t ret = -1;
+    assert(NULL != buffer);
+
+	if(!dataLeft.wait(timeout)){
+		return -2;
+	}
+	dataMutex.lock();
+    // No data left?? Could we get this far?
+    if (dataLen <= 0)
+    {
+		dataMutex.unlock();
+		return -2;
+	}
+
+    //LOG_I("%s: reading connection data %u, connection data left %u", 
+    //      __func__, len, dataLen);
+    
+    assert(dataStart != NULL);
+    
+    // trying to read more than the left data
+    if (len > dataLen)
+    {
+        ret = dataLen;
+        memcpy(buffer, dataStart, dataLen);
+        dataLen = 0;
+    }
+    else
+    {
+        ret = len;
+        memcpy(buffer, dataStart, len);
+        dataLen -= len;
+        dataStart += len;
+    }
+    
+    if (dataLen == 0)
+    {
+        dataStart = NULL;
+        free(dataMsg);
+        dataMsg = NULL;
+    }
+    else{
+		// Still some data left
+		dataLeft.signal();
+	}
+    dataMutex.unlock();
+    
+    //LOG_I("%s: read %u", __func__, ret);
+    return ret;
+}
+
+//------------------------------------------------------------------------------
+size_t NetlinkConnection::writeData(
+    void *buffer,
+    uint32_t len
+) {
+    size_t ret;
+    struct sockaddr_nl dest_addr;
+    struct nlmsghdr *nlh = NULL;
+    struct iovec iov;
+    struct msghdr msg;
+
+    assert(NULL != buffer);
+    assert(-1 != socketDescriptor);
+    
+    //LOG_I("%s: send data %u to PID %u", __func__, len, sequenceMagic);
+
+    memset(&dest_addr, 0, sizeof(dest_addr));
+    dest_addr.nl_family = AF_NETLINK;
+    dest_addr.nl_pid = peerPid;
+    dest_addr.nl_groups = 0; /* unicast */
+    
+    nlh=(struct nlmsghdr *)malloc(
+        NLMSG_SPACE(len));
+    /* Fill the netlink message header */
+    nlh->nlmsg_len = NLMSG_SPACE(len);
+    nlh->nlmsg_pid = selfPid;
+    nlh->nlmsg_flags = NLM_F_REQUEST;
+    nlh->nlmsg_seq = sequenceMagic;
+    
+    /* Fill in the netlink message payload */
+    memcpy(NLMSG_DATA(nlh), buffer, len);
+    
+    iov.iov_base = (void *)nlh;
+    iov.iov_len = nlh->nlmsg_len;
+    msg.msg_name = (void *)&dest_addr;
+    msg.msg_namelen = sizeof(dest_addr);
+    msg.msg_iov = &iov;
+    msg.msg_iovlen = 1;
+    msg.msg_control = NULL;
+    msg.msg_controllen = 0;
+    
+    ret = sendmsg(socketDescriptor, &msg, 0);
+    if (ret != NLMSG_SPACE(len))
+    {
+        LOG_E( "%s: could no send all data, ret=%d, errno: %d(%s)", 
+               __func__, ret, errno, strerror(errno));
+        ret = -1;
+    }
+    else{
+        /* The whole message sent also includes the header, so make sure to 
+		 * return only the number of payload data sent, not everything */
+        ret = len;
+    }
+    
+    free(nlh);
+
+    return ret;
+}
+
+/** @} */
diff --git a/mobicore/daemon/Common/NetlinkConnection.h b/mobicore/daemon/Common/NetlinkConnection.h
new file mode 100644
index 0000000..7121919
--- /dev/null
+++ b/mobicore/daemon/Common/NetlinkConnection.h
@@ -0,0 +1,218 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_SRV
+ * @{
+ * @file
+ *
+ * Connection data.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef NETLINKCONNECTION_H_
+#define NETLINKCONNECTION_H_
+
+#include <unistd.h>
+#include <map>
+#include <exception>
+#include <inttypes.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include "Connection.h"
+#include "CMutex.h"
+#include "CSemaphore.h"
+
+/** PID(address) of MC daemon.  */
+#define MC_DAEMON_PID 0xFFFFFFFF
+/** Maximum Netlink payload size 
+ * TODO: figure out the best value for this */
+#define MAX_PAYLOAD 1024
+
+#define MC_DAEMON_NETLINK  17
+
+
+class NetlinkConnection;
+
+/**
+ * Hash function for unique ID of a connection.
+ *
+ * @param pid Connection PID
+ * @param seq Connection sequenceMagic
+ * 
+ * @return Unique identifier of the connection
+ */
+uint64_t hashConnection(pid_t pid, uint32_t seq);
+
+/** Netlink connection manager interface.
+ * This inteface has to be implemented by the handling server
+ * to ensure connection will be removed from accounting when destroied. */
+class NetlinkConnectionManager {
+public:
+    virtual ~NetlinkConnectionManager(){};
+    /**
+	 * Retreive connection based on a unique hash.
+	 * Search the peer connections hashmap for a hash and return 
+	 * the associated Connection object
+     *
+	 * @param hash The hash to search
+     * @return The NetlinkConnection object if found or NULL if not found
+     */
+    virtual NetlinkConnection* findConnection(
+		uint64_t hash
+    ) = 0;
+    
+    /**
+     * Insert a connection in connection lisst
+     * Insert a new connection in the peer connections list. If there 
+	 * is already such a connection
+     * it will be overriden!
+     *
+	 * @param hash The hash to use
+     * @param connection The connection object to insert
+     */
+    virtual void insertConnection(
+		uint64_t hash,
+        NetlinkConnection *connection
+    ) = 0;
+    
+    /**
+     * Remove a connection from the peer connections
+     * Remove the connection associated with seq from the peer list. 
+	 * This doesn't actually free the connection object!
+	 * If the hash is invalid nothing happens.
+     *
+	 * @param hash The hash hash use
+     */
+    virtual void removeConnection(
+		uint64_t hash
+    ) = 0;
+};
+
+class NetlinkConnection: public Connection {
+public:
+    pid_t selfPid; /**< Which PID to use to identify when writing data */
+    pid_t peerPid; /**< Destination PID for sending data */
+    uint32_t sequenceMagic; /**< Random? magic to match requests/answers */
+    uint64_t hash; /**< Unique connection ID, see hashConnection */
+    
+    NetlinkConnection(
+        void
+    );
+
+	/**
+	 * Connection main constructor
+	 *
+	 * @param manager Connection manager pointer.
+	 * @param socketDescriptor Socket descriptor to use for writing
+	 * @param pid Connection PID
+	 * @param seq Connection sequence magic number
+	 */
+    NetlinkConnection(
+        NetlinkConnectionManager *manager,
+        int   socketDescriptor,
+		uint32_t pid,
+		uint32_t seq
+    );
+
+    virtual ~NetlinkConnection(
+        void
+    );
+
+    /**
+     * Connect to destination.
+     *
+     * @param Destination pointer.
+     * @return true on success.
+     */
+    virtual bool connect(
+        const char *dest
+    );
+
+    /**
+     * Read bytes from the connection(compatiblity method).
+     *
+     * @param buffer	Pointer to destination buffer.
+     * @param len       Number of bytes to read.
+     * @param timeout   Timeout in milliseconds(ignored)
+     * @return Number of bytes read.
+     * @return -1 if select() failed (returned -1)
+     * @return -2 if no data available, i.e. timeout
+     */
+    virtual size_t readData(
+        void      *buffer,
+        uint32_t  len,
+        int32_t   timeout
+    );
+
+    /**
+     * Read bytes from the connection.
+     *
+     * @param buffer    Pointer to destination buffer.
+     * @param len       Number of bytes to read.
+     * @return Number of bytes read.
+     */
+    virtual size_t readData(
+        void      * buffer,
+        uint32_t  len
+    );
+
+    /**
+     * Write bytes to the connection.
+     *
+     * @param buffer	Pointer to source buffer.
+     * @param len		Number of bytes to read.
+     * @return Number of bytes written.
+     */
+    virtual size_t writeData(
+        void      *buffer,
+        uint32_t  len
+    );
+    
+    /**
+     * Set the internal data connection.
+     * This method is called by the 
+     *
+     * @param nlh    Netlink structure pointing to data.
+     */
+    void handleMessage(
+        struct nlmsghdr *nlh
+    );
+
+private:
+	CMutex dataMutex;
+	CSemaphore dataLeft;
+    struct nlmsghdr *dataMsg; /**< Last message received */
+    uint32_t dataLen; /**< How much connection data is left */
+    uint8_t *dataStart; /**< Start pointer of remaining data */
+    NetlinkConnectionManager *manager; /**< Netlink connection manager(eg. NetlinkServer) */
+};
+
+typedef std::map<uint64_t, NetlinkConnection*>  connectionMap_t;
+
+#endif /* NETLINKCONNECTION_H_ */
+
+/** @} */
diff --git a/mobicore/daemon/Daemon/Android.mk b/mobicore/daemon/Daemon/Android.mk
new file mode 100644
index 0000000..149305a
--- /dev/null
+++ b/mobicore/daemon/Daemon/Android.mk
@@ -0,0 +1,43 @@
+# =============================================================================
+#
+# Module: mcDriverDaemon
+#
+# =============================================================================
+LOCAL_PATH := $(call my-dir)
+MY_MCDRIVER_PATH := $(LOCAL_PATH)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE	:= mcDriverDaemon
+LOCAL_MODULE_TAGS := eng
+
+# Add new subdirectories containing code here
+include $(LOCAL_PATH)/Device/Android.mk
+include $(LOCAL_PATH)/Server/Android.mk
+
+LOCAL_C_INCLUDES += bionic \
+	external/stlport/stlport
+
+# Add new folders with header files here
+LOCAL_C_INCLUDES += \
+	$(COMP_PATH_MobiCore)/inc \
+	$(COMP_PATH_MobiCoreDriverMod)/Public \
+	$(APP_PROJECT_PATH)/ClientLib/public \
+	$(APP_PROJECT_PATH)/Kernel \
+	$(APP_PROJECT_PATH)/Kernel/Platforms/Generic \
+	$(APP_PROJECT_PATH)/Common \
+	$(APP_PROJECT_PATH)/Registry/Public \
+	$(MY_MCDRIVER_PATH)/public
+
+# Add new source files here
+LOCAL_SRC_FILES += \
+	MobiCoreDriverDaemon.cpp
+
+LOCAL_CPPFLAGS += -fno-rtti -fno-exceptions
+# Modules this one depnds on (depending ones first)
+LOCAL_STATIC_LIBRARIES = libstlport_static libMcKernel libMcCommon libMcRegistry
+
+include $(COMP_PATH_Logwrapper)/Android.mk
+
+include $(BUILD_EXECUTABLE)
+
diff --git a/mobicore/daemon/Daemon/Device/Android.mk b/mobicore/daemon/Daemon/Device/Android.mk
new file mode 100644
index 0000000..5ae55d8
--- /dev/null
+++ b/mobicore/daemon/Daemon/Device/Android.mk
@@ -0,0 +1,26 @@
+# =============================================================================
+#
+# MC driver device files
+#
+# =============================================================================
+
+# This is not a separate module.
+# Only for inclusion by other modules.
+
+MY_MCDRV_DEVICE_PATH	:= $(call my-dir)
+MY_MCDRV_DEVICE_PATH_REL	:= Device
+
+include $(MY_MCDRV_DEVICE_PATH)/Platforms/Android.mk
+
+# Add new folders with header files here
+LOCAL_C_INCLUDES +=\
+	$(MY_MCDRV_DEVICE_PATH)\
+	$(MY_MCDRV_DEVICE_PATH)/public
+
+# Add new source files here
+LOCAL_SRC_FILES +=\
+	$(MY_MCDRV_DEVICE_PATH_REL)/DeviceIrqHandler.cpp\
+	$(MY_MCDRV_DEVICE_PATH_REL)/DeviceScheduler.cpp\
+	$(MY_MCDRV_DEVICE_PATH_REL)/MobiCoreDevice.cpp\
+	$(MY_MCDRV_DEVICE_PATH_REL)/NotificationQueue.cpp\
+	$(MY_MCDRV_DEVICE_PATH_REL)/TrustletSession.cpp\
diff --git a/mobicore/daemon/Daemon/Device/DeviceIrqHandler.cpp b/mobicore/daemon/Daemon/Device/DeviceIrqHandler.cpp
new file mode 100644
index 0000000..e941c88
--- /dev/null
+++ b/mobicore/daemon/Daemon/Device/DeviceIrqHandler.cpp
@@ -0,0 +1,44 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_DEV
+ * @{
+ * @file
+ *
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "DeviceIrqHandler.h"
+
+
+//------------------------------------------------------------------------------
+void DeviceIrqHandler::run(
+	void
+) {
+	handleIrq();
+	this->exit(-1);
+}
+
+/** @} */
diff --git a/mobicore/daemon/Daemon/Device/DeviceIrqHandler.h b/mobicore/daemon/Daemon/Device/DeviceIrqHandler.h
new file mode 100644
index 0000000..957db40
--- /dev/null
+++ b/mobicore/daemon/Daemon/Device/DeviceIrqHandler.h
@@ -0,0 +1,51 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_DEV
+ * @{
+ * @file
+ *
+ * IRQ handler thread.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DEVICEIRQHANDLER_H_
+#define DEVICEIRQHANDLER_H_
+
+#include "CThread.h"
+
+
+class DeviceIrqHandler: public CThread {
+
+public:
+
+	virtual void handleIrq() =0;
+
+	void run();
+};
+
+#endif /* DEVICEIRQHANDLER_H_ */
+
+/** @} */
diff --git a/mobicore/daemon/Daemon/Device/DeviceScheduler.cpp b/mobicore/daemon/Daemon/Device/DeviceScheduler.cpp
new file mode 100644
index 0000000..30024fb
--- /dev/null
+++ b/mobicore/daemon/Daemon/Device/DeviceScheduler.cpp
@@ -0,0 +1,44 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_DEV
+ * @{
+ * @file
+ *
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "DeviceScheduler.h"
+
+
+//------------------------------------------------------------------------------
+void DeviceScheduler::run(
+	void
+) {
+    schedule();
+	exit(-1);
+}
+
+/** @} */
diff --git a/mobicore/daemon/Daemon/Device/DeviceScheduler.h b/mobicore/daemon/Daemon/Device/DeviceScheduler.h
new file mode 100644
index 0000000..5698f68
--- /dev/null
+++ b/mobicore/daemon/Daemon/Device/DeviceScheduler.h
@@ -0,0 +1,52 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_DEV
+ * @{
+ * @file
+ *
+ * Scheduler thread
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DEVICESCHEDULER_H_
+#define DEVICESCHEDULER_H_
+
+#include "CThread.h"
+
+
+class DeviceScheduler: public CThread {
+
+public:
+
+	virtual void schedule() =0;
+
+	void run();
+
+};
+
+#endif /* DEVICESCHEDULER_H_ */
+
+/** @} */
diff --git a/mobicore/daemon/Daemon/Device/MobiCoreDevice.cpp b/mobicore/daemon/Daemon/Device/MobiCoreDevice.cpp
new file mode 100644
index 0000000..a5cfa71
--- /dev/null
+++ b/mobicore/daemon/Daemon/Device/MobiCoreDevice.cpp
@@ -0,0 +1,626 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_DEV
+ * @{
+ * @file
+ *
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <cstdlib>
+#include <pthread.h>
+#include "McTypes.h"
+
+#include "DeviceScheduler.h"
+#include "DeviceIrqHandler.h"
+#include "ExcDevice.h"
+#include "Connection.h"
+#include "TrustletSession.h"
+
+#include "MobiCoreDevice.h"
+#include "Mci/mci.h"
+#include "mcLoadFormat.h"
+
+
+#define LOG_TAG	"McDaemon"
+#include "log.h"
+#include "public/MobiCoreDevice.h"
+
+
+//------------------------------------------------------------------------------
+MobiCoreDevice::MobiCoreDevice() {
+	mcFault = false;
+}
+
+//------------------------------------------------------------------------------
+MobiCoreDevice::~MobiCoreDevice() {
+	delete mcVersionInfo;
+	mcVersionInfo = NULL;
+}
+
+//------------------------------------------------------------------------------
+TrustletSession* MobiCoreDevice::getTrustletSession(
+    uint32_t sessionId
+) {
+	TrustletSession* ts = NULL;
+
+	for (trustletSessionIterator_t session = trustletSessions.begin();
+			session != trustletSessions.end();
+			++session) {
+		TrustletSession* tsTmp = *session;
+		if (tsTmp->sessionId == sessionId)
+		{
+			ts = tsTmp;
+			break;
+		}
+	}
+	return ts;
+}
+
+
+//------------------------------------------------------------------------------
+Connection * MobiCoreDevice::getSessionConnection(
+	uint32_t sessionId,
+	notification_t *notification	
+) {
+	Connection *con = NULL;
+	TrustletSession* ts = NULL;
+
+	ts = getTrustletSession(sessionId);
+	if (NULL == ts) {
+		return NULL;
+	}
+
+	con = ts->notificationConnection;
+	if(NULL == con) {
+		ts->queueNotification(notification);
+		return NULL;
+	}
+
+	return con;
+}
+
+
+//------------------------------------------------------------------------------
+bool MobiCoreDevice::open(
+    Connection *connection
+) {
+	// Link this device to the connection
+	connection->connectionData = this;
+	return true;
+}
+
+
+//------------------------------------------------------------------------------
+/**
+ * Close device.
+ *
+ * Removes all sessions to a connection. Though, clientLib rejects the closeDevice()
+ * command if still sessions connected to the device, this is needed to clean up all
+ * sessions if client dies.
+ */
+void MobiCoreDevice::close(
+    Connection *connection
+) {
+	trustletSessionList_t::reverse_iterator interator;
+	static CMutex mutex;
+	// 1. Iterate through device session to find connection
+	// 2. Decide what to do with open Trustlet sessions
+	// 3. Remove & delete deviceSession from vector
+
+	// Enter critical section
+	mutex.lock();
+	for (interator = trustletSessions.rbegin();
+		interator != trustletSessions.rend();
+		interator++) {
+		TrustletSession* ts = *interator;
+
+		if (ts->deviceConnection == connection) {
+			closeSession(connection, ts->sessionId);
+		}
+	}
+	// Leave critical section
+	mutex.unlock();
+
+	connection->connectionData = NULL;
+}
+
+
+//------------------------------------------------------------------------------
+void MobiCoreDevice::start(
+    void
+) {
+	// Call the device specific initialization
+	//	initDevice();
+
+	LOG_I("Starting DeviceIrqHandler...");
+	// Start the irq handling thread
+	DeviceIrqHandler::start();
+
+	if (schedulerAvailable()) {
+		LOG_I("Starting DeviceScheduler...");
+		// Start the scheduling handling thread
+		DeviceScheduler::start();
+	} else {
+		LOG_I("No DeviceScheduler available.");
+	}
+}
+
+
+//------------------------------------------------------------------------------
+void MobiCoreDevice::signalMcpNotification(
+    void
+) {
+	mcpSessionNotification.signal();
+}
+
+
+//------------------------------------------------------------------------------
+bool MobiCoreDevice::waitMcpNotification(
+    void
+) {
+	int counter = 5;
+	while (1) {
+		// In case of fault just return, nothing to do here
+		if (mcFault) {
+			return false;
+		}
+		// Wait 10 seconds for notification
+		if (mcpSessionNotification.wait(10) == false) {
+			// No MCP answer received and mobicore halted, dump mobicore status 
+			// then throw exception
+			LOG_I("No MCP answer received in 2 seconds.");
+			if (getMobicoreStatus() == MC_STATUS_HALT) {
+				dumpMobicoreStatus();
+				mcFault = true;
+				return false;
+			} else {
+				counter--;
+				if (counter < 1) {
+					mcFault = true;
+					return false;
+				} 
+			}
+		} else {
+				break;
+		}
+	}
+
+	// Check healthiness state of the device
+	if (DeviceIrqHandler::isExiting()) {
+		LOG_I("waitMcpNotification(): IrqHandler thread died! Joining");
+		DeviceIrqHandler::join();
+		LOG_I("waitMcpNotification(): Joined");
+		LOG_E("IrqHandler thread died!");
+		return false;
+	}
+
+	if (DeviceScheduler::isExiting()) {
+		LOG_I("waitMcpNotification(): Scheduler thread died! Joining");
+		DeviceScheduler::join();
+		LOG_I("waitMcpNotification(): Joined");
+		LOG_E("Scheduler thread died!");
+		return false;
+	}
+	return true;
+}
+
+
+//------------------------------------------------------------------------------
+void MobiCoreDevice::openSession(
+	Connection                      *deviceConnection,
+	loadDataOpenSession_ptr         pLoadDataOpenSession,
+	mcDrvCmdOpenSessionPayload_ptr  pCmdOpenSessionPayload,
+	mcDrvRspOpenSessionPayload_ptr  pRspOpenSessionPayload
+) {
+
+	do {
+		// Write MCP open message to buffer
+		mcpMessage->cmdOpen.cmdHeader.cmdId = MC_MCP_CMD_OPEN_SESSION;
+		mcpMessage->cmdOpen.uuid = pCmdOpenSessionPayload->uuid;
+		mcpMessage->cmdOpen.wsmTypeTci = WSM_CONTIGUOUS;
+		mcpMessage->cmdOpen.adrTciBuffer = (uint32_t)(pCmdOpenSessionPayload->tci);
+		mcpMessage->cmdOpen.ofsTciBuffer = 0;
+		mcpMessage->cmdOpen.lenTciBuffer = pCmdOpenSessionPayload->len;
+
+		LOG_I("%s(): tciPhys=%p, len=%d,", __FUNCTION__,
+				(addr_t)(pCmdOpenSessionPayload->tci),
+				pCmdOpenSessionPayload->len);
+
+		// check if load data is provided
+		if(NULL == pLoadDataOpenSession)
+		{
+			// Preinstalled trustlet shall be loaded
+			mcpMessage->cmdOpen.wsmTypeLoadData = WSM_INVALID;
+		}
+		else
+		{
+			mcpMessage->cmdOpen.wsmTypeLoadData = WSM_L2;
+			mcpMessage->cmdOpen.adrLoadData = (uint32_t)pLoadDataOpenSession->baseAddr;
+			mcpMessage->cmdOpen.ofsLoadData = pLoadDataOpenSession->offs;
+			mcpMessage->cmdOpen.lenLoadData = pLoadDataOpenSession->len;
+			memcpy(&mcpMessage->cmdOpen.tlHeader, pLoadDataOpenSession->tlHeader, sizeof(*pLoadDataOpenSession->tlHeader));
+		}
+
+		// Clear the notifications queue. We asume the race condition we have
+		// seen in openSession never happens elsewhere
+		notifications = std::queue<notification_t>();
+		// Notify MC about a new command inside the MCP buffer
+		notify(SID_MCP);
+
+		// Wait till response from MC is available
+		if(!waitMcpNotification()) {
+			break;
+		}
+
+		// Check if the command response ID is correct
+		if ((MC_MCP_CMD_OPEN_SESSION | FLAG_RESPONSE) != mcpMessage->rspHeader.rspId)
+		{
+			LOG_E("%s(): CMD_OPEN_SESSION got invalid MCP command response(0x%X)",
+				  __FUNCTION__, mcpMessage->rspHeader.rspId);
+			break;
+		}
+
+		uint32_t mcRet = mcpMessage->rspOpen.rspHeader.result;
+		pRspOpenSessionPayload->mcResult = mcRet;
+
+		if(MC_MCP_RET_OK != mcRet)
+		{
+			LOG_E("%s: CMD_OPEN_SESSION error %d", __FUNCTION__, mcRet);
+			break;
+		}
+
+		LOG_I("%s: We have %d queued notifications after open session", 
+			  __FUNCTION__, notifications.size());
+		// Read MC answer from MCP buffer
+		TrustletSession *trustletSession = new TrustletSession(
+													deviceConnection,
+													mcpMessage->rspOpen.sessionId);
+
+		pRspOpenSessionPayload->deviceId = pCmdOpenSessionPayload->deviceId;
+		pRspOpenSessionPayload->sessionId = trustletSession->sessionId;
+		pRspOpenSessionPayload->deviceSessionId = (uint32_t)trustletSession;
+		pRspOpenSessionPayload->sessionMagic = trustletSession->sessionMagic;
+
+		trustletSessions.push_back(trustletSession);
+		// We have some queued notifications and we need to send them to them
+		// trustlet session
+		while (!notifications.empty()) {
+			trustletSession->queueNotification(&notifications.front());
+			notifications.pop();
+		}
+
+	} while(0);
+}
+
+
+//------------------------------------------------------------------------------
+TrustletSession *MobiCoreDevice::registerTrustletConnection(
+	Connection                    *connection,
+	mcDrvCmdNqConnectPayload_ptr  pCmdNqConnectPayload
+) {
+	LOG_I("%s(): searching sessionMagic %d and sessionId %d", __FUNCTION__,
+		pCmdNqConnectPayload->sessionMagic,
+		pCmdNqConnectPayload->sessionId);
+
+	for (trustletSessionIterator_t iterator = trustletSessions.begin();
+			iterator != trustletSessions.end();
+			++iterator) {
+		TrustletSession *ts = *iterator;
+
+		if (ts != (TrustletSession*) (pCmdNqConnectPayload->deviceSessionId)) {
+			continue;
+		}
+
+		if ( (ts->sessionMagic != pCmdNqConnectPayload->sessionMagic)
+				|| (ts->sessionId != pCmdNqConnectPayload->sessionId)) {
+			continue;
+		}
+
+		LOG_I("%s(): found connection", __FUNCTION__);
+
+		ts->notificationConnection = connection;
+		return ts;
+	}
+
+	LOG_I("registerTrustletConnection(): search failed");
+	return NULL;
+}
+
+
+//------------------------------------------------------------------------------
+/**
+ * Need connection as well as according session ID, so that a client can not
+ * close sessions not belonging to him.
+ */
+bool MobiCoreDevice::closeSession(
+    Connection  *deviceConnection,
+	uint32_t    sessionId
+) {
+	bool ret = true;
+
+	do {
+		TrustletSession *ts = NULL;
+		trustletSessionIterator_t iterator;
+
+		// Search object to session id
+		for (iterator = trustletSessions.begin();
+				iterator != trustletSessions.end();
+				++iterator)
+		{
+			TrustletSession  *tsTmp = *iterator;
+			if ( (tsTmp->sessionId == sessionId)
+					&& (tsTmp->deviceConnection == deviceConnection))
+			{
+				ts = tsTmp;
+				break;
+			}
+		}
+		if (NULL == ts)
+		{
+			LOG_I("closeSession(): no session found with id=%d",sessionId);
+			ret = false;
+			break;
+		}
+
+		LOG_I("closeSession(): Write MCP close message to buffer and notify, wait");
+
+		// Write MCP close message to buffer
+		mcpMessage->cmdClose.cmdHeader.cmdId = MC_MCP_CMD_CLOSE_SESSION;
+		mcpMessage->cmdClose.sessionId = sessionId;
+
+		// Notify MC about the availability of a new command inside the MCP buffer
+		notify(SID_MCP);
+
+		// Wait till response from MSH is available
+		if(!waitMcpNotification()) {
+			ret = false;
+			break;
+		}
+
+		// Check if the command response ID is correct
+		if ((MC_MCP_CMD_CLOSE_SESSION | FLAG_RESPONSE) != mcpMessage->rspHeader.rspId) {
+			LOG_E("closeSession(): CMD_CLOSE_SESSION got invalid MCP response");
+			ret = false;
+			break;
+		}
+
+		// Read MC answer from MCP buffer
+		uint32_t mcRet = mcpMessage->rspOpen.rspHeader.result;
+
+		if( MC_MCP_RET_OK != mcRet) {
+			LOG_E("closeSession(): CMD_CLOSE_SESSION error %d",mcRet);
+			ret = false;
+			break;
+		}
+
+		// remove objects
+		trustletSessions.erase(iterator);
+		delete ts;
+
+	} while(0);
+
+	return ret;
+}
+
+
+//------------------------------------------------------------------------------
+void MobiCoreDevice::mapBulk(
+    Connection                     *deviceConnection,
+    mcDrvCmdMapBulkMemPayload_ptr  pCmdMapBulkMemPayload,
+    mcDrvRspMapBulkMemPayload_ptr  pRspMapBulkMemPayload
+) {
+	do
+	{
+
+		// Write MCP map message to buffer
+		mcpMessage->cmdMap.cmdHeader.cmdId = MC_MCP_CMD_MAP;
+		mcpMessage->cmdMap.sessionId = pCmdMapBulkMemPayload->sessionId;
+		mcpMessage->cmdMap.wsmType = WSM_L2;
+		mcpMessage->cmdMap.adrBuffer = (uint32_t)(pCmdMapBulkMemPayload->pAddrL2);
+		mcpMessage->cmdMap.ofsBuffer = pCmdMapBulkMemPayload->offsetPayload;
+		mcpMessage->cmdMap.lenBuffer = pCmdMapBulkMemPayload->lenBulkMem;
+
+		// Notify MC about the availability of a new command inside the MCP buffer
+		notify(SID_MCP);
+
+		// Wait till response from MC is available
+		if(!waitMcpNotification()) {
+			break;
+		}
+
+		// Check if the command response ID is correct
+		if ((MC_MCP_CMD_MAP | FLAG_RESPONSE) != mcpMessage->rspHeader.rspId) {
+			LOG_E("mapBulk(): CMD_MAP got invalid MCP response");
+			break;
+		}
+
+		uint32_t mcRet = mcpMessage->rspMap.rspHeader.result;
+		pRspMapBulkMemPayload->mcResult = mcRet;
+		pRspMapBulkMemPayload->sessionId = pCmdMapBulkMemPayload->sessionId;
+
+		if(MC_MCP_RET_OK != mcRet) {
+			LOG_E("mapBulk(): CMD_MAP error %d",mcRet);
+			break;
+		}
+
+		pRspMapBulkMemPayload->secureVirtualAdr = mcpMessage->rspMap.secureVirtualAdr;
+
+	} while(0);
+}
+
+
+//------------------------------------------------------------------------------
+void MobiCoreDevice::unmapBulk(
+    Connection                       *deviceConnection,
+    mcDrvCmdUnmapBulkMemPayload_ptr  pCmdUnmapBulkMemPayload,
+    mcDrvRspUnmapBulkMemPayload_ptr  pRspUnmapBulkMemPayload
+) {
+	do {
+		// Write MCP unmap command to buffer
+		mcpMessage->cmdUnmap.cmdHeader.cmdId = MC_MCP_CMD_UNMAP;
+		mcpMessage->cmdUnmap.sessionId = pCmdUnmapBulkMemPayload->sessionId;
+		mcpMessage->cmdUnmap.wsmType = WSM_L2;
+		mcpMessage->cmdUnmap.secureVirtualAdr = pCmdUnmapBulkMemPayload->secureVirtualAdr;
+		mcpMessage->cmdUnmap.lenVirtualBuffer = pCmdUnmapBulkMemPayload->lenBulkMem;
+
+		// Notify MC about the availability of a new command inside the MCP buffer
+		notify(SID_MCP);
+
+		// Wait till response from MC is available
+		if(!waitMcpNotification()) {
+			break;
+		}
+
+		// Check if the command response ID is correct
+		if ((MC_MCP_CMD_UNMAP | FLAG_RESPONSE) != mcpMessage->rspHeader.rspId)
+		{
+			LOG_E("unmapBulk(): CMD_OPEN_SESSION got invalid MCP response");
+			break;
+		}
+
+		uint32_t  mcRet = mcpMessage->rspUnmap.rspHeader.result;
+		pRspUnmapBulkMemPayload->mcResult = mcRet;
+		pRspUnmapBulkMemPayload->sessionId = pCmdUnmapBulkMemPayload->sessionId;
+
+		if(MC_MCP_RET_OK != mcRet)
+		{
+			LOG_E("unmapBulk(): MC_MCP_CMD_UNMAP error %d",mcRet);
+			break;
+		}
+
+	} while(0);
+}
+
+
+//------------------------------------------------------------------------------
+void MobiCoreDevice::donateRam(
+	const uint32_t	donationSize
+) {
+	// Donate additional RAM to the MobiCore
+	CWsm_ptr ram = allocateContiguousPersistentWsm(donationSize);
+	if (NULL == ram) {
+		LOG_E("Allocation of additional RAM failed");
+		return;
+	}
+	ramType_t ramType = RAM_GENERIC;
+	addr_t adrBuffer = ram->physAddr;
+	const uint32_t numPages = donationSize / (4 * 1024);
+
+
+	LOG_I("donateRam(): adrBuffer=%p, numPages=%d, ramType=%d",
+			adrBuffer,
+			numPages,
+			ramType);
+
+	do {
+		// Write MCP open message to buffer
+		mcpMessage->cmdDonateRam.cmdHeader.cmdId = MC_MCP_CMD_DONATE_RAM;
+		mcpMessage->cmdDonateRam.adrBuffer = (uint32_t) adrBuffer;
+		mcpMessage->cmdDonateRam.numPages = numPages;
+		mcpMessage->cmdDonateRam.ramType = ramType;
+
+		// Notify MC about a new command inside the MCP buffer
+		notify(SID_MCP);
+
+		// Wait till response from MC is available
+		if(!waitMcpNotification()) {
+			break;
+		}
+
+		// Check if the command response ID is correct
+		if ((MC_MCP_CMD_DONATE_RAM | FLAG_RESPONSE) != mcpMessage->rspHeader.rspId)
+		{
+			LOG_E("donateRam(): CMD_DONATE_RAM got invalid MCP response - rspId is: %d",
+					mcpMessage->rspHeader.rspId);
+			break;
+		}
+
+		uint32_t mcRet = mcpMessage->rspDonateRam.rspHeader.result;
+		if(MC_MCP_RET_OK != mcRet)
+		{
+			LOG_E("donateRam(): CMD_DONATE_RAM error %d", mcRet);
+			break;
+		}
+
+		LOG_I("donateRam() succeeded.");
+
+	} while(0);
+}
+
+//------------------------------------------------------------------------------
+void MobiCoreDevice::getMobiCoreVersion(
+    mcDrvRspGetMobiCoreVersionPayload_ptr pRspGetMobiCoreVersionPayload
+) {
+	// If MobiCore version info already fetched.
+	if (mcVersionInfo != NULL) {
+		pRspGetMobiCoreVersionPayload->mcResult = MC_MCP_RET_OK;
+		pRspGetMobiCoreVersionPayload->versionInfo = *mcVersionInfo;
+	// Otherwise, fetch it via MCP.
+	} else {
+		pRspGetMobiCoreVersionPayload->mcResult = MC_MCP_RET_ERR_UNKNOWN;
+
+		// Write MCP unmap command to buffer
+		mcpMessage->cmdGetMobiCoreVersion.cmdHeader.cmdId = MC_MCP_CMD_GET_MOBICORE_VERSION;
+
+		// Notify MC about the availability of a new command inside the MCP buffer
+		notify(SID_MCP);
+
+		// Wait till response from MC is available
+		if(!waitMcpNotification()) {
+			return;
+		}
+
+		// Check if the command response ID is correct
+		if ((MC_MCP_CMD_GET_MOBICORE_VERSION | FLAG_RESPONSE) != mcpMessage->rspHeader.rspId) {
+			LOG_E("getMobiCoreVersion(): MC_MCP_CMD_GET_MOBICORE_VERSION got invalid MCP response");
+			return;
+		}
+
+		uint32_t  mcRet = mcpMessage->rspGetMobiCoreVersion.rspHeader.result;
+		pRspGetMobiCoreVersionPayload->mcResult = mcRet;
+
+		if(MC_MCP_RET_OK != mcRet) {
+			LOG_E("getMobiCoreVersion(): MC_MCP_CMD_GET_MOBICORE_VERSION error %d",mcRet);
+			return;
+		}
+
+		pRspGetMobiCoreVersionPayload->versionInfo = mcpMessage->rspGetMobiCoreVersion.versionInfo;
+
+		// Store MobiCore info for future reference.
+		mcVersionInfo = new mcVersionInfo_t();
+		*mcVersionInfo = pRspGetMobiCoreVersionPayload->versionInfo;
+	}
+}
+
+//------------------------------------------------------------------------------
+void MobiCoreDevice::queueUnknownNotification(
+	notification_t notification
+) {
+	notifications.push(notification);
+}
+
+/** @} */
diff --git a/mobicore/daemon/Daemon/Device/NotificationQueue.cpp b/mobicore/daemon/Daemon/Device/NotificationQueue.cpp
new file mode 100644
index 0000000..c9a79ff
--- /dev/null
+++ b/mobicore/daemon/Daemon/Device/NotificationQueue.cpp
@@ -0,0 +1,77 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_DEV
+ * @{
+ * @file
+ *
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "NotificationQueue.h"
+#include <stddef.h>
+
+#define LOG_TAG	"McDaemon"
+#include "log.h"
+
+//------------------------------------------------------------------------------
+NotificationQueue::NotificationQueue(
+	notificationQueue_t *i,
+	notificationQueue_t *o,
+	uint32_t size
+) : in(i), out(o) {
+	in->hdr.queueSize = size;
+	out->hdr.queueSize = size;
+}
+
+
+//------------------------------------------------------------------------------
+void NotificationQueue::putNotification(
+	notification_t *notification
+) {
+	mutex.lock();
+	if ((out->hdr.writeCnt - out->hdr.readCnt) < out->hdr.queueSize) {
+		out->notification[out->hdr.writeCnt & (out->hdr.queueSize - 1)]
+				= *notification;
+		out->hdr.writeCnt++;
+	}
+	mutex.unlock();
+}
+
+
+//------------------------------------------------------------------------------
+notification_t *NotificationQueue::getNotification(
+	void
+) {
+	notification_t *ret = NULL;
+	mutex.lock();
+	if ((in->hdr.writeCnt - in->hdr.readCnt) > 0) {
+		ret = &(in->notification[in->hdr.readCnt & (in->hdr.queueSize - 1)]);
+		in->hdr.readCnt++;
+	}
+	mutex.unlock();
+	return ret;
+}
+
+/** @} */
diff --git a/mobicore/daemon/Daemon/Device/NotificationQueue.h b/mobicore/daemon/Daemon/Device/NotificationQueue.h
new file mode 100644
index 0000000..c3f60bf
--- /dev/null
+++ b/mobicore/daemon/Daemon/Device/NotificationQueue.h
@@ -0,0 +1,86 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_DEV
+ * @{
+ * @file
+ *
+ * MobiCore Notification Queue handling.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef NOTIFICATIONQUEUE_H_
+#define NOTIFICATIONQUEUE_H_
+
+#include <inttypes.h> //C99 data
+#include "Mci/mcinq.h"
+#include "CMutex.h"
+
+
+class NotificationQueue {
+
+public:
+
+	/** NQ Constructor, initializes the NQ component.
+	 *
+	 * makes the given queue object usable with the queue<Command> type of functions
+	 *
+	 * @param in queue to initialize
+	 * @param out beginning of queue header
+	 * @param queueSize Size of the queue
+	 */
+	NotificationQueue(
+		notificationQueue_t *in,
+		notificationQueue_t *out,
+		uint32_t size
+	);
+
+	/** Places an element to the outgoing queue.
+	 *
+	 * @param notification Data to be placed in queue.
+	 */
+	void putNotification(
+		notification_t *notification
+	);
+
+	/** Retrieves the first element from the queue.
+	 *
+	 * @return first notification Queue element.
+	 * @return NULL if the queue is empty.
+	 */
+	notification_t *getNotification(
+		void
+	);
+
+private:
+
+	notificationQueue_t *in;
+	notificationQueue_t *out;
+	CMutex mutex;
+
+};
+
+#endif /* NOTIFICATIONQUEUE_H_ */
+
+/** @} */
diff --git a/mobicore/daemon/Daemon/Device/Platforms/Android.mk b/mobicore/daemon/Daemon/Device/Platforms/Android.mk
new file mode 100644
index 0000000..c367952
--- /dev/null
+++ b/mobicore/daemon/Daemon/Device/Platforms/Android.mk
@@ -0,0 +1,15 @@
+# =============================================================================
+#
+# Makefile pointing to the platform specific makefile.
+#
+# =============================================================================
+
+PLATFORMS_PATH := $(call my-dir)
+
+# Always include the Generic code
+include $(PLATFORMS_PATH)/Generic/Android.mk
+
+ifneq ($(filter-out Generic,$(PLATFORM)),)
+  $(info PLATFORM: $(PLATFORM))
+  include $(PLATFORMS_PATH)/$(PLATFORM)/Android.mk
+endif
diff --git a/mobicore/daemon/Daemon/Device/Platforms/Generic/Android.mk b/mobicore/daemon/Daemon/Device/Platforms/Generic/Android.mk
new file mode 100644
index 0000000..50cf589
--- /dev/null
+++ b/mobicore/daemon/Daemon/Device/Platforms/Generic/Android.mk
@@ -0,0 +1,17 @@
+# =============================================================================
+#
+# Generic TrustZone device includes
+#
+# =============================================================================
+
+# This is not a separate module.
+# Only for inclusion by other modules.
+
+GENERIC_PATH		:= $(call my-dir)
+GENERIC_PATH_REL	:= Device/Platforms/Generic
+
+# Add new source files here
+LOCAL_SRC_FILES +=$(GENERIC_PATH_REL)/TrustZoneDevice.cpp
+
+# Header files for components including this module
+LOCAL_C_INCLUDES += $(call my-dir)
diff --git a/mobicore/daemon/Daemon/Device/Platforms/Generic/TrustZoneDevice.cpp b/mobicore/daemon/Daemon/Device/Platforms/Generic/TrustZoneDevice.cpp
new file mode 100644
index 0000000..51dfb69
--- /dev/null
+++ b/mobicore/daemon/Daemon/Device/Platforms/Generic/TrustZoneDevice.cpp
@@ -0,0 +1,698 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_DEV
+ * @{
+ * @file
+ *
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <cstdlib>
+#include <fstream>
+#include <inttypes.h>
+#include <list>
+
+#include "McTypes.h"
+#include "mc_drv_module_api.h"
+#include "Mci/mci.h"
+#include "mcVersionHelper.h"
+
+#include "CSemaphore.h"
+#include "CMcKMod.h"
+
+#include "MobiCoreDevice.h"
+#include "TrustZoneDevice.h"
+#include "NotificationQueue.h"
+
+#define LOG_TAG	"McDaemon"
+#include "log.h"
+
+
+#define NQ_NUM_ELEMS      (16)
+#define NQ_BUFFER_SIZE    (2 * (sizeof(notificationQueueHeader_t)+  NQ_NUM_ELEMS * sizeof(notification_t)))
+#define MCP_BUFFER_SIZE   (sizeof(mcpBuffer_t))
+#define MCI_BUFFER_SIZE   (NQ_BUFFER_SIZE + MCP_BUFFER_SIZE)
+
+//------------------------------------------------------------------------------
+MC_CHECK_VERSION(MCI,0,2);
+
+//------------------------------------------------------------------------------
+__attribute__ ((weak)) MobiCoreDevice* getDeviceInstance(
+	void
+) {
+	return new TrustZoneDevice();
+}
+
+
+//------------------------------------------------------------------------------
+TrustZoneDevice::TrustZoneDevice(
+    void
+) {
+    // nothing to do
+}
+
+
+//------------------------------------------------------------------------------
+TrustZoneDevice::~TrustZoneDevice(
+    void
+) {
+    delete pMcKMod;
+	delete pWsmMcp;
+    delete nq;
+}
+
+
+//------------------------------------------------------------------------------
+static int loadMobiCoreImage(
+	addr_t	virtAddr,
+	int32_t size,
+	const char*	mobicorePath
+) {
+
+    LOG_I("MobiCore path: %s", mobicorePath);
+
+    int ret = 1;
+
+    do {
+        // Open MobiCore binary for reading only
+        fstream fs(mobicorePath, ios_base::in | ios_base::binary);
+        if (!fs) {
+            LOG_E("MobiCore not found: %s", mobicorePath);
+            break;
+        }
+
+        // Get the MobiCore file size
+        fs.seekg(0, ios::end);
+        int32_t fileSize = fs.tellg();
+        fs.seekg(0, ios::beg);
+        LOG_I("File size: %i", fileSize);
+        // Check if file is too big
+        if (fileSize > size) {
+            LOG_E("MobiCore size exceeds expectations. Size is: %i", fileSize);
+            break;
+        }
+
+        fs.read((char*)virtAddr, fileSize);
+
+        //Create an visible line with different content at the end
+        memset((void*)((uint32_t)virtAddr+fileSize),0xff,4096);
+
+        // Close file
+        fs.close();
+        ret = 0;
+    } while (false);
+
+    return ret;
+}
+
+
+#define SIZE_DDRAM              (256 * 1024)
+#define MOBICORE_BINARY_PATH    "/data/app/mobicore.img"
+//------------------------------------------------------------------------------
+/**
+ * Set up MCI and wait till MC is initialized
+ * @return true if mobicore is already initialized
+ */
+bool TrustZoneDevice::initDevice(
+	const char	*devFile,
+	bool		loadMobiCore,
+	const char  *mobicoreImage,
+	bool		enableScheduler
+) throw (ExcDevice) {
+
+    notificationQueue_t* nqStartOut;
+	notificationQueue_t* nqStartIn;
+	addr_t mciBuffer;
+
+    pMcKMod = new CMcKMod();
+    if (!pMcKMod->open(devFile))
+    {
+        LOG_E("open() kernel module device failed");
+        return false;
+    }
+    if (!pMcKMod->checkKmodVersionOk())
+    {
+        LOG_E("kernel module version mismatch");
+        return false;
+    }
+
+    // Start MobiCore from DDRAM
+    if (loadMobiCore) {
+        // 1. Allocate DDRAM as pseudo IRAM
+        mobicoreInDDR = allocateContiguousPersistentWsm(SIZE_DDRAM);
+        if (NULL == mobicoreInDDR) {
+            LOG_E("Allocation of additional RAM failed");
+            return false;
+        }
+        memset(mobicoreInDDR->virtAddr,0xCC,SIZE_DDRAM);
+
+        int ret = loadMobiCoreImage(mobicoreInDDR->virtAddr, SIZE_DDRAM,
+					mobicoreImage);
+        if (0 != ret) {
+            LOG_E("loading Mobicore file failed: %d", ret);
+            return false;
+        }
+
+        ret = pMcKMod->fcExecute(
+                mobicoreInDDR->physAddr,
+                MCP_BUFFER_SIZE);
+        if (0 != ret) {
+            LOG_E("pMcKMod->fcExecute() failed : %d", ret);
+            return false;
+        }
+    }
+    this->schedulerEnabled = enableScheduler;
+
+    // Init MC with NQ and MCP buffer addresses
+
+	// Set up MCI buffer
+	if(!getMciInstance(MCI_BUFFER_SIZE, &pWsmMcp, &mciReused)) {
+		return false;
+	}
+	mciBuffer = pWsmMcp->virtAddr;
+
+	if(!checkMciVersion()) {
+		return false;
+	}
+
+	// Only do a fastcall if MCI has not been reused (MC already initialized)
+	if (!mciReused)
+	{
+		// Wipe memory before first usage
+		bzero(mciBuffer, MCI_BUFFER_SIZE);
+
+		// Init MC with NQ and MCP buffer addresses
+		int ret = pMcKMod->fcInit(
+							pWsmMcp->physAddr,
+							0,
+							NQ_BUFFER_SIZE,
+							NQ_BUFFER_SIZE,
+							MCP_BUFFER_SIZE);
+		if (0 != ret)
+		{
+			LOG_E("pMcKMod->fcInit() failed");
+			return false;
+		}
+
+		// First empty N-SIQ which results in set up of the MCI structure
+		if(!nsiq()) {
+			return false;
+		}
+
+		// Wait until MobiCore state switches to MC_STATUS_INITIALIZED
+		// It is assumed that MobiCore always switches state at a certain point in time.
+		while(1)
+		{
+			uint32_t status = getMobicoreStatus();
+			
+			if (MC_STATUS_INITIALIZED == status)
+			{
+				break;
+			}
+			else if (MC_STATUS_NOT_INITIALIZED == status)
+			{
+				// Switch to MobiCore to give it more CPU time.
+				if(!yield()) {
+					return false;
+				}
+			}
+			else if (MC_STATUS_HALT == status)
+			{
+				dumpMobicoreStatus();
+				LOG_E("MobiCore halted during init !!!, state is 0x%x", status);
+				return false;
+			}
+			else // MC_STATUS_BAD_INIT or anything else
+			{
+				LOG_E("MCI buffer init failed, state is 0x%x", status);
+				return false;
+			}
+		}
+	}
+
+	nqStartOut = (notificationQueue_t *) mciBuffer;
+	nqStartIn = (notificationQueue_t *) ((uint8_t *) nqStartOut
+			+ sizeof(notificationQueueHeader_t) + NQ_NUM_ELEMS
+			* sizeof(notification_t));
+
+	// Set up the NWd NQ
+	nq = new NotificationQueue(nqStartIn, nqStartOut, NQ_NUM_ELEMS);
+
+	mcpBuffer_t *mcpBuf = (mcpBuffer_t*) ((uint8_t *) mciBuffer + NQ_BUFFER_SIZE);
+
+	// Set up the MC flags
+	mcFlags = &(mcpBuf->mcFlags);
+
+	// Set up the MCP message
+	mcpMessage = &(mcpBuf->mcpMessage);
+
+	// convert virtual address of mapping to physical address for the init.
+	LOG_I("MCP: virt=%p, phys=%p, reused=%s",
+			pWsmMcp->virtAddr,
+			pWsmMcp->physAddr,
+			mciReused ? "true" : "false");
+	return true;
+}
+
+
+//------------------------------------------------------------------------------
+void TrustZoneDevice::initDeviceStep2(
+    void
+) {
+	// not needed
+}
+
+
+//------------------------------------------------------------------------------
+bool TrustZoneDevice::yield(
+    void
+) {
+    int32_t ret = pMcKMod->fcYield();
+    if (ret != 0) {
+        LOG_E("pMcKMod->fcYield() failed: %d", ret);
+    }
+    return ret == 0;
+}
+
+
+//------------------------------------------------------------------------------
+bool TrustZoneDevice::nsiq(
+    void
+) {
+    // There is no need to set the NON-IDLE flag here. Sending an N-SIQ will 
+    // make the MobiCore run until it could set itself to a state where it 
+    // set the flag itself. IRQs and FIQs are disbaled for this period, so 
+    // there is no way the NWd can interrupt here. 
+
+    // not needed: mcFlags->schedule = MC_FLAG_SCHEDULE_NON_IDLE;
+
+    int32_t ret = pMcKMod->fcNSIQ();
+    if (ret != 0) {
+        LOG_E("pMcKMod->fcNSIQ() failed : %d", ret);
+        return false;
+    }
+    // now we have to wake the scheduler, so MobiCore gets CPU time.
+    schedSync.signal();
+    return true;
+}
+
+
+//------------------------------------------------------------------------------
+void TrustZoneDevice::notify(
+    uint32_t sessionId
+) {
+	do
+	{
+        // Check if it is MCP session - handle openSession() command
+        if (SID_MCP != sessionId)
+        {
+            // Check if session ID exists to avoid flooding of nq by clients
+            TrustletSession* ts = getTrustletSession(sessionId);
+            if (NULL == ts)
+            {
+                LOG_E("notify(): no session with id=%d", sessionId);
+                break;
+            }
+        }
+
+		LOG_I("notify(): Send notification for id=%d", sessionId);
+        // Notify MobiCore about new data
+
+        notification_t notification = {
+                // C++ does not support C99 designated initializers
+                    /* .sessionId = */ sessionId,
+                    /* .payload = */ 0
+                };
+
+        nq->putNotification(&notification);
+        //IMPROVEMENT-2012-03-07-maneaval What happens when/if nsiq fails?
+        //In the old days an exception would be thrown but it was uncertain
+        //where it was handled, some server(sock or Netlink). In that case
+        //the server would just die but never actually signaled to the client
+        //any error condition
+		nsiq();
+
+	} while(0);
+}
+
+//------------------------------------------------------------------------------
+uint32_t TrustZoneDevice::getMobicoreStatus(
+	void
+) {
+	uint32_t status;
+	//IMPROVEMENT-2012-03-07-maneaval Can fcInfo ever fail? Before it threw an
+	//exception but the handler depended on the context.
+	pMcKMod->fcInfo(0, &status, NULL);
+	
+	return status;
+}
+
+//------------------------------------------------------------------------------
+bool TrustZoneDevice::checkMciVersion(
+    void
+) {
+    int ret;
+    uint32_t version = 0;
+
+    ret = pMcKMod->fcInfo(MC_EXT_INFO_ID_MCI_VERSION, NULL, &version);
+    if (ret != 0) {
+        LOG_E("pMcKMod->fcInfo() failed with %d", ret);
+        return false;
+    }
+
+    // Run-time check.
+    char* errmsg;
+    if (!checkVersionOkMCI(version, &errmsg)) {
+        LOG_E("%s", errmsg);
+        return false;
+    }
+    LOG_I("%s", errmsg);
+    return true;
+}
+
+//------------------------------------------------------------------------------
+void TrustZoneDevice::dumpMobicoreStatus(
+	void
+) {
+	int ret;
+	uint32_t status, info;
+	// read additional info about exception-point and print
+	LOG_E("MobiCore halted !!!");
+	ret = pMcKMod->fcInfo(1, &status, &info);		
+	LOG_W("MC_HALT: flags               : 0x%8x", info);
+	ret = pMcKMod->fcInfo(2, &status, &info);		
+	LOG_W("MC_HALT: haltCode            : 0x%8x", info);
+	ret = pMcKMod->fcInfo(3, &status, &info);		
+	LOG_W("MC_HALT: haltIp              : 0x%8x", info);
+	ret = pMcKMod->fcInfo(4, &status, &info);		
+	LOG_W("MC_HALT: faultRec.cnt        : 0x%8x", info);
+	ret = pMcKMod->fcInfo(5, &status, &info);		
+	LOG_W("MC_HALT: faultRec.cause      : 0x%8x", info);
+	ret = pMcKMod->fcInfo(6, &status, &info);		
+	LOG_W("MC_HALT: faultRec.meta       : 0x%8x", info);
+	ret = pMcKMod->fcInfo(7, &status, &info);		
+	LOG_W("MC_HALT: faultRec.thread     : 0x%8x", info);
+	ret = pMcKMod->fcInfo(8, &status, &info);		
+	LOG_W("MC_HALT: faultRec.ip         : 0x%8x", info);
+	ret = pMcKMod->fcInfo(9, &status, &info);		
+	LOG_W("MC_HALT: faultRec.sp         : 0x%8x", info);
+	ret = pMcKMod->fcInfo(10, &status, &info);		
+	LOG_W("MC_HALT: faultRec.arch.dfsr  : 0x%8x", info);
+	ret = pMcKMod->fcInfo(11, &status, &info);		
+	LOG_W("MC_HALT: faultRec.arch.adfsr : 0x%8x", info);
+	ret = pMcKMod->fcInfo(12, &status, &info);		
+	LOG_W("MC_HALT: faultRec.arch.dfar  : 0x%8x", info);
+	ret = pMcKMod->fcInfo(13, &status, &info);		
+	LOG_W("MC_HALT: faultRec.arch.ifsr  : 0x%8x", info);
+	ret = pMcKMod->fcInfo(14, &status, &info);		
+	LOG_W("MC_HALT: faultRec.arch.aifsr : 0x%8x", info);
+	ret = pMcKMod->fcInfo(15, &status, &info);		
+	LOG_W("MC_HALT: faultRec.arch.ifar  : 0x%8x", info);
+	ret = pMcKMod->fcInfo(16, &status, &info);		
+	LOG_W("MC_HALT: mcData.flags        : 0x%8x", info);
+    ret = pMcKMod->fcInfo(19, &status, &info);
+    LOG_W("MC_HALT: mcExcep.partner     : 0x%8x", info);
+    ret = pMcKMod->fcInfo(20, &status, &info);
+    LOG_W("MC_HALT: mcExcep.peer        : 0x%8x", info);
+    ret = pMcKMod->fcInfo(21, &status, &info);
+    LOG_W("MC_HALT: mcExcep.message     : 0x%8x", info);
+    ret = pMcKMod->fcInfo(22, &status, &info);
+    LOG_W("MC_HALT: mcExcep.data        : 0x%8x", info);
+}
+
+//------------------------------------------------------------------------------
+bool TrustZoneDevice::waitSsiq(
+    void
+) {
+    uint32_t cnt;
+    if (!pMcKMod->waitSSIQ(&cnt))
+    {
+        LOG_E("pMcKMod->SSIQ() failed");
+        return false;
+    }
+    LOG_I("SSIQ Received, COUNTER = %u", cnt);
+    return true;
+}
+
+
+//------------------------------------------------------------------------------
+bool TrustZoneDevice::getMciInstance(
+    uint32_t  len,
+    CWsm_ptr  *mci,
+    bool	  *reused
+) {
+    addr_t    virtAddr;
+    uint32_t  handle;
+    addr_t    physAddr;
+    bool	  isMci = true;
+    if (0 == len)
+    {
+        LOG_E("allocateWsm() length is 0");
+        return false;
+    }
+
+    int ret = pMcKMod->mmap(
+                        len,
+                        &handle,
+                        &virtAddr,
+                        &physAddr,
+                        &isMci);
+    if (0 != ret)
+    {
+        LOG_E("pMcKMod->mmap() failed: %d", ret);
+        return false;
+    }
+    *mci = new CWsm(virtAddr, len, handle, physAddr);
+    // isMci will be set to true if buffer has been reused
+    *reused = isMci;
+    return true;
+}
+
+
+//------------------------------------------------------------------------------
+bool TrustZoneDevice::freeWsm(
+    CWsm_ptr  pWsm
+) {
+
+    int ret = pMcKMod->free(pWsm->handle);
+    if (ret != 0)
+    {
+        LOG_E("pMcKMod->free() failed: %d", ret);
+        return false;
+    }
+    delete pWsm;
+    return true;
+}
+
+
+//------------------------------------------------------------------------------
+CWsm_ptr TrustZoneDevice::registerWsmL2(
+    addr_t    buffer,
+    uint32_t  len,
+    uint32_t  pid
+) {
+    addr_t    physAddr;
+    uint32_t  handle;
+
+    int ret = pMcKMod->registerWsmL2(
+                        buffer,
+                        len,
+                        pid,
+                        &handle,
+                        &physAddr);
+    if (ret != 0)
+    {
+        LOG_E("ipMcKMod->registerWsmL2() failed: %d", ret);
+        return NULL;
+    }
+
+    return new CWsm(buffer,len,handle,physAddr);
+}
+
+
+//------------------------------------------------------------------------------
+CWsm_ptr TrustZoneDevice::allocateContiguousPersistentWsm(
+    uint32_t len
+) {
+    CWsm_ptr  pWsm = NULL;
+	do
+	{
+	    if (0 == len)
+	    {
+		    break;
+	    }
+
+	    // Allocate shared memory
+	    addr_t    virtAddr;
+	    uint32_t  handle;
+	    addr_t    physAddr;
+	    int ret = pMcKMod->mapPersistent(
+	                     len,
+	                     &handle,
+	                     &virtAddr,
+	                     &physAddr);
+    	if (0 != ret)
+    	{
+    		break;
+    	}
+
+    	// Register (vaddr,paddr) with device
+        pWsm = new CWsm(virtAddr,len,handle,physAddr);
+
+    } while(0);
+
+	// Return pointer to the allocated memory
+	return pWsm;
+}
+
+
+//------------------------------------------------------------------------------
+bool TrustZoneDevice::unregisterWsmL2(
+    CWsm_ptr  pWsm
+) {
+    int ret = pMcKMod->unregisterWsmL2(pWsm->handle);
+    if (ret != 0) {
+        LOG_E("pMcKMod->unregisterWsmL2 failed: %d", ret);
+        //IMPROVEMENT-2012-03-07 maneaval Make sure we don't leak objects
+        return false;
+    }
+    delete pWsm;
+    return true;
+}
+
+// REV add unregister (used after OPEN_SESSION)
+
+//------------------------------------------------------------------------------
+bool TrustZoneDevice::schedulerAvailable(
+	void
+){
+    return schedulerEnabled;
+}
+
+//------------------------------------------------------------------------------
+//TODO Schedulerthread to be switched off if MC is idle. Will be woken up when
+//     driver is called again.
+void TrustZoneDevice::schedule(
+    void
+) {
+    uint32_t timeslice = SCHEDULING_FREQ;
+	// loop forever
+	for (;;)
+	{
+		// Scheduling decision
+		if (MC_FLAG_SCHEDULE_IDLE == mcFlags->schedule)
+		{
+			// MobiCore is IDLE
+
+			// Prevent unnecessary consumption of CPU cycles -> Wait until S-SIQ received
+			schedSync.wait();
+
+		} else {
+			// MobiCore is not IDLE (anymore)
+
+			// Check timeslice
+			if (0 == timeslice)
+			{
+				// Slice expired, so force MC internal scheduling decision
+				timeslice = SCHEDULING_FREQ;
+				if(!nsiq()) {
+					break;
+				}
+			} else {
+				// Slice not used up, simply hand over control to the MC
+				timeslice--;
+				if(!yield()) {
+					break;
+				}
+			}
+		}
+	}
+}
+//------------------------------------------------------------------------------
+void TrustZoneDevice::handleIrq(
+	void
+	) {
+	LOG_I("Starting NQ IRQ handler...");
+	for (;;)
+	{
+		LOG_I("NQ empty now");
+		if(!waitSsiq()) {
+			LOG_E("Waiting for SSIQ failed");
+			break;
+		}
+		LOG_I("S-SIQ received");
+
+		// Save all the
+		for (;;)
+		{
+			notification_t *notification = nq->getNotification();
+			if (NULL == notification) {
+				break;
+			}
+			LOG_I("Received notification, sessionId=%d, payload=%d",
+			notification->sessionId, notification->payload);
+			
+			// check if the notification belongs to the MCP session
+			if (notification->sessionId == SID_MCP) {
+				// Signal main thread of the driver to continue after MCP
+				// command has been processed by the MC
+				signalMcpNotification();
+			}
+			else
+			{
+				// Get the NQ connection for the session ID
+				Connection *connection = getSessionConnection(notification->sessionId, notification);
+				if (connection == NULL) {
+					/* Couldn't find the session for this notifications
+					 * In practice this only means one thing: there is
+					 * a race condition between RTM and the Daemon and
+					 * RTM won. But we shouldn't drop the notification
+					 * right away we should just queue it in the device
+					 */
+					LOG_W("Notification for unknown session ID");
+					queueUnknownNotification(*notification);
+				}
+				else
+				{
+					LOG_I("Write notification!");
+					// Forward session ID and additional payload of
+					// notification to the TLC/Application layer
+					connection->writeData((void *)notification,
+								sizeof(notification_t));
+				}
+			}
+		}
+
+		// Wake up scheduler
+		schedSync.signal();
+	}
+	LOG_E("S-SIQ exception");
+	// Tell main thread that "something happened"
+	// MSH thread MUST not block!
+	DeviceIrqHandler::setExiting();
+	signalMcpNotification();
+}
+/** @} */
diff --git a/mobicore/daemon/Daemon/Device/Platforms/Generic/TrustZoneDevice.h b/mobicore/daemon/Daemon/Device/Platforms/Generic/TrustZoneDevice.h
new file mode 100644
index 0000000..58d0cbf
--- /dev/null
+++ b/mobicore/daemon/Daemon/Device/Platforms/Generic/TrustZoneDevice.h
@@ -0,0 +1,172 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_DEV
+ * @{
+ * @file
+ *
+ * Class for TrustZone Devices.
+ * TrustZone device implements communication functions needed for
+ * accessing MobiCore located in an TrustZone environment.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef TRUSTZONEDEVICE_H_
+#define TRUSTZONEDEVICE_H_
+
+
+#include <stdint.h>
+
+#include "McTypes.h"
+
+#include "CSemaphore.h"
+#include "CMcKMod.h"
+#include "CWsm.h"
+
+#include "ExcDevice.h"
+#include "MobiCoreDevice.h"
+
+
+#define SCHEDULING_FREQ     5   /**< N-SIQ every n-th time */
+
+class TrustZoneDevice : public MobiCoreDevice {
+
+protected:
+	bool         schedulerEnabled; /**< NQ IRQ Scheduler enabling */
+	CSemaphore   schedSync; /**< Semaphore to synchronize S-SIQs with scheduler thread */
+	CMcKMod_ptr  pMcKMod; /**< kernel module */
+    CWsm_ptr     pWsmMcp; /**< WSM use for MCP */
+    CWsm_ptr     mobicoreInDDR;  /**< WSM used for Mobicore binary */
+    bool         mciReused;
+
+	/** Access functions to the MC Linux kernel module
+	 */
+	bool yield(
+	    void
+	);
+
+	bool nsiq(
+	    void
+	);
+
+	bool waitSsiq(
+	    void
+	);
+
+public:
+
+	TrustZoneDevice(
+	    void
+	);
+
+	virtual ~TrustZoneDevice(
+	    void
+	);
+
+//	static MobiCoreDevice* getDeviceInstance(
+//		void
+//	);
+	/** Set up MCI and wait till MC is initialized
+	 * 
+	 * @param devFile the device node to speak to.
+	 * @param loadMobiCore
+	 * @param mobicoreImage
+	 * @param enableScheduler
+	 *
+	 * @return true if mobicore is initialized
+	 * @trows ExcDevice
+	 */
+	bool initDevice(
+		const char	*devFile,
+		bool		loadMobiCore,
+		const char  *mobicoreImage,
+		bool		enableScheduler
+	);
+
+	void initDeviceStep2(
+		void
+    );
+
+	void notify(
+	    uint32_t sessionId
+	);
+	
+	void dumpMobicoreStatus(
+		void
+	);
+	
+	uint32_t getMobicoreStatus(
+		void
+	);
+
+	bool checkMciVersion(
+	    void
+	);
+
+	/** Memory allocation functions
+	 */
+    // TODO xgal: move memory registration from TzDevice to Device class
+	bool getMciInstance(
+        uint32_t  len,
+        CWsm_ptr  *mci,
+        bool	  *reused
+    );
+
+    bool freeWsm(
+        CWsm_ptr  pWsm
+    );
+
+    CWsm_ptr registerWsmL2(
+        addr_t    buffer,
+        uint32_t  len,
+        uint32_t  pid
+    );
+
+    bool unregisterWsmL2(
+        CWsm_ptr  pWsm
+    );
+
+    /**
+     * Allocates persistent WSM memory for TL (won't be fried when TLC exits).
+     */
+    CWsm_ptr allocateContiguousPersistentWsm(
+        uint32_t len
+    );
+
+	bool schedulerAvailable(
+	    void
+	);
+
+	void schedule(
+	    void
+	);
+
+	void handleIrq(
+	    void
+	);
+};
+
+#endif /* TRUSTZONEDEVICE_H_ */
+
+/** @} */
diff --git a/mobicore/daemon/Daemon/Device/TrustletSession.cpp b/mobicore/daemon/Daemon/Device/TrustletSession.cpp
new file mode 100644
index 0000000..c0dfe4e
--- /dev/null
+++ b/mobicore/daemon/Daemon/Device/TrustletSession.cpp
@@ -0,0 +1,83 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_DEV
+ * @{
+ * @file
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "TrustletSession.h"
+#include <cstdlib>
+
+#define LOG_TAG	"McDaemon"
+#include "log.h"
+
+
+//------------------------------------------------------------------------------
+TrustletSession::TrustletSession(
+	Connection *deviceConnection,
+	uint32_t sessionId
+) {
+	this->deviceConnection = deviceConnection;
+	this->notificationConnection = NULL;
+	this->sessionId = sessionId;
+	sessionMagic = rand();
+}
+
+
+//------------------------------------------------------------------------------
+TrustletSession::~TrustletSession(
+	void
+) {
+	delete notificationConnection;
+}
+
+//------------------------------------------------------------------------------
+void TrustletSession::queueNotification(
+	notification_t *notification
+) {
+	notifications.push(*notification);
+}
+
+//------------------------------------------------------------------------------
+void TrustletSession::processQueuedNotifications(
+	void
+) {
+	// Nothing to do here!
+	if(notificationConnection == NULL)
+		return;
+
+	while (!notifications.empty())
+	{
+		// Forward session ID and additional payload of
+		// notification to the just established connection
+		notificationConnection->writeData((void *)&notifications.front(),
+							  sizeof(notification_t));
+		notifications.pop();
+	}
+}
+
+/** @} */
diff --git a/mobicore/daemon/Daemon/Device/TrustletSession.h b/mobicore/daemon/Daemon/Device/TrustletSession.h
new file mode 100644
index 0000000..026f78b
--- /dev/null
+++ b/mobicore/daemon/Daemon/Device/TrustletSession.h
@@ -0,0 +1,74 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_DEV
+ * @{
+ * @file
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef TRUSTLETSESSION_H_
+#define TRUSTLETSESSION_H_
+
+#include "NotificationQueue.h"
+
+#include "Connection.h"
+#include <queue>
+
+
+class TrustletSession {
+
+public:
+
+	TrustletSession(
+		Connection *deviceConnection,
+		uint32_t sessionId
+	);
+
+	~TrustletSession(
+		void
+	);
+	
+	void queueNotification(
+		notification_t *notification
+	);
+	
+	void processQueuedNotifications(
+		void
+	);
+
+	uint32_t sessionId;
+	uint32_t sessionMagic; // Random data
+	Connection *deviceConnection;
+	Connection *notificationConnection;
+private:
+	std::queue<notification_t> notifications;
+};
+
+typedef std::list<TrustletSession*> trustletSessionList_t;
+typedef trustletSessionList_t::iterator trustletSessionIterator_t;
+
+#endif /* TRUSTLETSESSION_H_ */
+
+/** @} */
diff --git a/mobicore/daemon/Daemon/Device/public/ExcDevice.h b/mobicore/daemon/Daemon/Device/public/ExcDevice.h
new file mode 100644
index 0000000..cb55352
--- /dev/null
+++ b/mobicore/daemon/Daemon/Device/public/ExcDevice.h
@@ -0,0 +1,68 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_DEV
+ * @{
+ * @file
+ *
+ * Device exceptions.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef EXCDEVICE_H_
+#define EXCDEVICE_H_
+
+#include <stdint.h>
+#include <exception>
+#include <cstdio>
+#include <cstdlib>
+
+#define ERROR_MCI_VERSION_MISMATCH  ((int)(-2))
+#define ERROR_KMOD_VERSION_MISMATCH  ((int)(-3))
+
+class ExcDevice: public std::exception {
+
+public:
+
+	ExcDevice(const char *description, int cause) :
+		cause(cause), description(description) {
+	}
+
+	virtual int getCause() const throw () {
+		return cause;
+	}
+
+	virtual const char *getDescription() const throw () {
+		return description;
+	}
+
+private:
+
+	int cause;
+	const char *description;
+};
+
+#endif /* EXCDEVICE_H_ */
+
+/** @} */
diff --git a/mobicore/daemon/Daemon/Device/public/MobiCoreDevice.h b/mobicore/daemon/Daemon/Device/public/MobiCoreDevice.h
new file mode 100644
index 0000000..1ac2dda
--- /dev/null
+++ b/mobicore/daemon/Daemon/Device/public/MobiCoreDevice.h
@@ -0,0 +1,259 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_DEV
+ * @{
+ * @file
+ *
+ * MobiCore device.
+ * The MobiCore device class handles the MCP processing within the driver.
+ * Concrete devices implementing the communication behavior for the platforms have to be derived
+ * from this.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef MOBICOREDEVICE_H_
+#define MOBICOREDEVICE_H_
+
+#include <stdint.h>
+#include <vector>
+
+#include "McTypes.h"
+
+#include "Mci/mcimcp.h"
+#include "mcLoadFormat.h"
+#include "MobiCoreDriverCmd.h"
+
+#include "Connection.h"
+#include "CWsm.h"
+
+#include "ExcDevice.h"
+#include "DeviceScheduler.h"
+#include "DeviceIrqHandler.h"
+#include "NotificationQueue.h"
+#include "TrustletSession.h"
+#include "mcVersionInfo.h"
+
+
+class MobiCoreDevice;
+
+typedef struct {
+	addr_t baseAddr;	/**< Physical address of the data to load. */
+	uint32_t offs;		/**< Offset to the data. */
+	uint32_t len;		/**< Length of the data to load. */
+	mclfHeader_ptr tlHeader; /**< Pointer to trustlet header. */
+} loadDataOpenSession_t, *loadDataOpenSession_ptr;
+
+/**
+ * Factory method to return the platform specific MobiCore device.
+ * Implemented in the platform specific *Device.cpp
+ */
+extern MobiCoreDevice* getDeviceInstance(void);
+
+class MobiCoreDevice : public DeviceScheduler, public DeviceIrqHandler {
+
+protected:
+
+	NotificationQueue	*nq;	/**< Pointer to the notification queue within the MCI buffer */
+	mcFlags_t			*mcFlags; /**< Pointer to the MC flags within the MCI buffer */
+	mcpMessage_t		*mcpMessage; /**< Pointer to the MCP message structure within the MCI buffer */
+	CSemaphore			mcpSessionNotification; /**< Semaphore to synchronize incoming notifications for the MCP session */
+
+	trustletSessionList_t trustletSessions; /**< Available Trustlet Sessions */
+	mcVersionInfo_t		*mcVersionInfo; /**< MobiCore version info. */
+	bool				mcFault; /**< Signal RTM fault */
+
+	/* In a special case a trustlet can create a race condition in the daemon.
+	 * If at trustlet start it detects an error of some sort and calls the
+	 * exit function before waiting for any notifications from NWD then the daemon
+	 * will receive the openSession notification from RTM and the error notification
+	 * from the trustlet at the same time but because the internal objects in
+	 * the daemon are not yet completely setup then the error notification will
+	 * never be sent to the TLC!
+	 * 
+	 * This queue holds notifications received between the time the daemon
+	 * puts the MCP command for open session until the internal session objects
+	 * are setup corectly.
+	 */
+	std::queue<notification_t> notifications; /**<  Notifications queue for open session notification */
+
+	MobiCoreDevice();
+
+	void signalMcpNotification(
+		void
+	);
+
+	bool waitMcpNotification(
+		void
+	);
+
+private:
+
+	virtual bool yield(
+		void
+	) =0;
+
+	virtual bool nsiq(
+		void
+	) =0;
+
+	virtual bool waitSsiq(
+		void
+	) =0;
+
+public:
+
+	virtual ~MobiCoreDevice();
+
+	TrustletSession* getTrustletSession(
+		uint32_t sessionId
+	);
+
+	Connection* getSessionConnection(
+		uint32_t  sessionId,
+		notification_t *notification
+	);
+
+	bool open(
+		Connection  *connection);
+
+	void close(
+		Connection  *connection);
+
+	void openSession(
+		Connection                      *deviceConnection,
+		loadDataOpenSession_ptr         pLoadDataOpenSession,
+		mcDrvCmdOpenSessionPayload_ptr  pCmdOpenSessionPayload,
+		mcDrvRspOpenSessionPayload_ptr  pRspOpenSessionPayload);
+
+	TrustletSession *registerTrustletConnection(
+		Connection                    *connection,
+		mcDrvCmdNqConnectPayload_ptr  pCmdNqConnectPayload);
+
+	bool closeSession(
+		Connection  *deviceConnection,
+		uint32_t    sessionId);
+
+	virtual void notify(
+		uint32_t  sessionId
+	) = 0;
+
+	void mapBulk(
+		Connection                     *deviceConnection,
+		mcDrvCmdMapBulkMemPayload_ptr  pCmdMapBulkMemPayload,
+		mcDrvRspMapBulkMemPayload_ptr  pRspMapBulkMemPayload);
+
+	void unmapBulk(
+		Connection                       *deviceConnection,
+		mcDrvCmdUnmapBulkMemPayload_ptr  pCmdUnmapBulkMemPayload,
+		mcDrvRspUnmapBulkMemPayload_ptr  pRspUnmapBulkMemPayload);
+
+	void start();
+
+	void donateRam(
+			const uint32_t	donationSize
+	);
+
+	void getMobiCoreVersion(
+		mcDrvRspGetMobiCoreVersionPayload_ptr pRspGetMobiCoreVersionPayload
+	);
+	
+	bool getMcFault() { return mcFault; }
+	
+	void queueUnknownNotification(
+		notification_t notification
+	);
+
+	virtual void dumpMobicoreStatus(
+			void
+	) = 0;
+
+	virtual uint32_t getMobicoreStatus(
+		void
+	) = 0;
+
+	virtual bool schedulerAvailable(
+		void
+	) = 0;
+
+	virtual void schedule(
+		void
+	) = 0;
+
+	virtual void handleIrq(
+		void
+	) = 0;
+
+	virtual bool freeWsm(
+		CWsm_ptr  pWsm
+	) = 0;
+
+	/**
+	 * Initialize MobiCore.
+	 *
+	 * @param devFile the device node to speak to.
+	 * @param loadMobiCore
+	 * @param mobicoreImage
+	 * @param enableScheduler
+	 *
+	 * @returns true if MobiCore is already initialized.
+	 * */
+	virtual bool initDevice(
+		const char	*devFile,
+		bool		loadMobiCore,
+		const char  *mobicoreImage,
+		bool		enableScheduler
+	) = 0;
+
+	virtual void initDeviceStep2(
+		void
+	) = 0;
+
+	virtual bool getMciInstance(
+		uint32_t  len,
+		CWsm_ptr  *mci,
+		bool	  *reused
+	) = 0;
+
+	virtual CWsm_ptr registerWsmL2(
+		addr_t    buffer,
+		uint32_t  len,
+		uint32_t  pid
+	) = 0;
+
+	virtual bool unregisterWsmL2(
+		CWsm_ptr  pWsm
+	) = 0;
+
+	/**
+		* Allocates persistent WSM memory for TL (won't be released when TLC exits).
+		*/
+	virtual CWsm_ptr allocateContiguousPersistentWsm(
+		uint32_t len
+	) = 0;
+};
+
+#endif /* MOBICOREDEVICE_H_ */
+
+/** @} */
diff --git a/mobicore/daemon/Daemon/MobiCoreDriverDaemon.cpp b/mobicore/daemon/Daemon/MobiCoreDriverDaemon.cpp
new file mode 100644
index 0000000..bde00f3
--- /dev/null
+++ b/mobicore/daemon/Daemon/MobiCoreDriverDaemon.cpp
@@ -0,0 +1,1110 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_CONHDLR
+ * @{
+ * @file
+ *
+ * Entry of the MobiCore Driver.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <cstdlib>
+#include <signal.h>
+#include <fcntl.h>
+#include <fstream>
+#include <cassert>
+
+#include "MobiCoreDriverCmd.h"
+#include "mcVersion.h"
+#include "mcVersionHelper.h"
+#include "mc_drv_module_api.h"
+
+#include "MobiCoreDriverDaemon.h"
+#include "MobiCoreRegistry.h"
+#include "MobiCoreDevice.h"
+
+#include "NetlinkServer.h"
+
+#define LOG_TAG	"McDaemon"
+#include "log.h"
+
+#define DRIVER_TCI_LEN 100
+
+#include "Mci/mci.h"
+
+MC_CHECK_VERSION(MCI, 0, 2);
+MC_CHECK_VERSION(SO, 2, 0);
+MC_CHECK_VERSION(MCLF, 2, 0);
+MC_CHECK_VERSION(CONTAINER, 2, 0); 
+
+static void checkMobiCoreVersion(MobiCoreDevice* mobiCoreDevice);
+
+//------------------------------------------------------------------------------
+MobiCoreDriverDaemon::MobiCoreDriverDaemon(
+	bool enableScheduler,
+	bool loadMobicore,
+	std::string mobicoreImage,
+	unsigned int donateRamSize,
+	bool loadDriver,
+	std::string driverPath
+) {
+	mobiCoreDevice = NULL;
+
+	this->enableScheduler = enableScheduler;
+	this->loadMobicore = loadMobicore;
+	this->mobicoreImage = mobicoreImage;
+	this->donateRamSize = donateRamSize;
+	this->loadDriver = loadDriver;
+	this->driverPath = driverPath;
+
+	for (int i = 0; i < MAX_SERVERS; i++) {
+		servers[i] = NULL;
+	}
+}
+
+//------------------------------------------------------------------------------
+MobiCoreDriverDaemon::~MobiCoreDriverDaemon(
+    void
+) {
+	// Unload any device drivers might have been loaded
+	driverResourcesList_t::iterator it;
+	for(it = driverResources.begin(); it != driverResources.end(); it++) {
+		MobicoreDriverResources *res = *it;
+		mobiCoreDevice->closeSession(res->conn, res->sessionId);
+		mobiCoreDevice->unregisterWsmL2(res->pTciWsm);
+	}
+	delete mobiCoreDevice;
+	for (int i = 0; i < MAX_SERVERS; i++) {
+		delete servers[i];
+		servers[i] = NULL;
+	}
+}
+
+
+//------------------------------------------------------------------------------
+void MobiCoreDriverDaemon::run(
+	void
+) {
+	LOG_I("Daemon starting up...");
+	LOG_I("Socket interface version is %u.%u", DAEMON_VERSION_MAJOR, DAEMON_VERSION_MINOR);
+#ifdef MOBICORE_COMPONENT_BUILD_TAG
+	LOG_I("%s", MOBICORE_COMPONENT_BUILD_TAG);
+#else
+	#warning "MOBICORE_COMPONENT_BUILD_TAG is not defined!"
+#endif
+	LOG_I("Build timestamp is %s %s", __DATE__, __TIME__);
+
+	int i;
+
+	mobiCoreDevice = getDeviceInstance();
+
+	LOG_I("Daemon scheduler is %s", enableScheduler? "enabled" : "disabled");
+	if(!mobiCoreDevice->initDevice(
+		MC_DRV_MOD_DEVNODE_FULLPATH,
+		loadMobicore,
+		mobicoreImage.c_str(),
+		enableScheduler)) {
+		LOG_E("%s: Failed to initialize MobiCore!", __FUNCTION__);
+		return;
+	}
+	mobiCoreDevice->start();
+
+	checkMobiCoreVersion(mobiCoreDevice);
+
+	if (donateRamSize > 0) {
+		// Donate additional RAM to MC
+		LOG_I("Donating %u Kbytes to Mobicore", donateRamSize / 1024);
+		mobiCoreDevice->donateRam(donateRamSize);
+	}
+
+	// Load device driver if requested
+	if (loadDriver) {
+		loadDeviceDriver(driverPath);
+	}
+
+	LOG_I("Servers will be created!");
+	// Start listening for incoming TLC connections
+	servers[0] = new NetlinkServer(this);
+	servers[1] = new Server(this, SOCK_PATH);
+	LOG_I("Servers created!");
+
+	// Start all the servers
+	for (i = 0; i < MAX_SERVERS; i++) {
+		servers[i]->start();
+	}
+
+	// then wait for them to exit
+	for (i = 0; i < MAX_SERVERS; i++) {
+		servers[i]->join();
+	}
+}
+
+
+//------------------------------------------------------------------------------
+MobiCoreDevice *MobiCoreDriverDaemon::getDevice(
+    uint32_t deviceId
+) {
+	// Always return the trustZoneDevice as it is currently the only one supported
+	if(MC_DEVICE_ID_DEFAULT != deviceId)
+		return NULL;
+	return mobiCoreDevice;
+}
+
+
+//------------------------------------------------------------------------------
+void MobiCoreDriverDaemon::dropConnection(
+    Connection *connection
+) {
+	// Check if a Device has already been registered with the connection
+	MobiCoreDevice *device = (MobiCoreDevice *) (connection->connectionData);
+
+	if (device != NULL) {
+		LOG_I("dropConnection(): closing still open device.");
+		// A connection has been found and has to be closed
+		device->close(connection);
+	}
+}
+
+
+//------------------------------------------------------------------------------
+size_t MobiCoreDriverDaemon::writeResult(
+    Connection	*connection,
+    mcDrvRsp_t  code
+) {
+	if (0 != code) {
+		LOG_E("writeResult(): set error code %d",code);
+	}
+	return connection->writeData(&code, sizeof(mcDrvRsp_t));
+}
+
+//------------------------------------------------------------------------------
+bool MobiCoreDriverDaemon::loadDeviceDriver(
+	std::string driverPath
+) {
+	bool ret = false;
+	CWsm_ptr pWsm = NULL, pTciWsm = NULL;
+	regObject_t *regObj = NULL;
+	Connection *conn = NULL;
+	uint8_t *tci = NULL;
+	mcDrvRspOpenSession_t rspOpenSession;
+	
+	do
+	{
+		//mobiCoreDevice
+		ifstream fs(driverPath.c_str(), ios_base::binary);
+		if (!fs) {
+			LOG_E("%s: failed: cannot open %s", __func__, driverPath.c_str());
+			break;
+		}
+		
+		LOG_I("%s: loading %s", __func__, driverPath.c_str());
+		
+		regObj = mcRegistryGetDriverBlob(driverPath.c_str());
+		if (regObj == NULL) {
+			break;;
+		}
+
+		LOG_I("registering L2 in kmod, p=%p, len=%i",
+				regObj->value, regObj->len);
+		
+		// Prepare the interface structure for memory registration, then
+		// register virtual memory in kernel module, create L2 table
+		// TODO xgal: refactor naming of datatypes and WSM handling
+		pWsm = mobiCoreDevice->registerWsmL2(
+			(addr_t)(regObj->value), regObj->len, 0);
+		if (pWsm == NULL)
+		{
+			LOG_E("allocating WSM for Trustlet failed");
+			break;
+		}
+		// Initialize information data of open session command
+		loadDataOpenSession_t loadDataOpenSession;
+		loadDataOpenSession.baseAddr = pWsm->physAddr;
+		loadDataOpenSession.offs = ((uint32_t) regObj->value) & 0xFFF;
+		loadDataOpenSession.len = regObj->len;
+		loadDataOpenSession.tlHeader = (mclfHeader_ptr) regObj->value;
+		
+		mcDrvCmdOpenSessionPayload_t  openSessionPayload;
+		tci = (uint8_t*)malloc(DRIVER_TCI_LEN);
+		pTciWsm = mobiCoreDevice->registerWsmL2(
+			(addr_t)tci, DRIVER_TCI_LEN, 0);
+		if (pTciWsm == NULL)
+		{
+			LOG_E("allocating WSM TCI for Trustlet failed");
+			break;
+		}
+		openSessionPayload.deviceId = MC_DEVICE_ID_DEFAULT;
+		openSessionPayload.tci = (uint32_t)pTciWsm->physAddr;
+		openSessionPayload.len = DRIVER_TCI_LEN;
+
+		conn = new Connection();
+		mobiCoreDevice->openSession(
+			conn,
+			&loadDataOpenSession,
+			&openSessionPayload,
+			&(rspOpenSession.payload));
+		
+		// Unregister physical memory from kernel module.
+		// This will also destroy the WSM object.
+		mobiCoreDevice->unregisterWsmL2(pWsm);
+		pWsm = NULL;
+		
+		// Free memory occupied by Trustlet data
+		free(regObj);
+		regObj = NULL;
+		
+		if (rspOpenSession.payload.mcResult != MC_MCP_RET_OK)
+		{
+			LOG_E("%s: rspOpenSession mcResult %d", __func__, 
+				  rspOpenSession.payload.mcResult);
+			break;
+		}
+		
+		ret = true;
+	} while (false);
+	// Free all allocated resources
+	if (ret == false) {
+		LOG_I("%s: Freeing previously allocated resources!", __func__);
+		if (pWsm != NULL) {
+			if(!mobiCoreDevice->unregisterWsmL2(pWsm)) {
+				// At least make sure we don't leak the WSM object
+				delete pWsm;
+			}
+		}
+		// No matter if we free NULL objects
+		free(regObj);
+		
+		if (conn != NULL) {
+			delete conn;
+		}
+	} else if (conn != NULL) {
+		driverResources.push_back(new MobicoreDriverResources(
+			conn, tci, pTciWsm, rspOpenSession.payload.sessionId));
+	}
+	
+	return ret;
+}
+
+//------------------------------------------------------------------------------
+void MobiCoreDriverDaemon::processOpenDevice(
+    Connection	*connection
+) {
+	do
+	{
+		// Read entire command data
+		mcDrvCmdOpenDevicePayload_t cmdOpenDevicePayload;
+		uint32_t rlen = connection->readData(
+							&(cmdOpenDevicePayload),
+							sizeof(cmdOpenDevicePayload));
+		if (rlen != sizeof(cmdOpenDevicePayload))
+		{
+			LOG_E("processOpenDevice(): OpenSession length error: %d", rlen);
+			writeResult(connection, MC_DRV_RSP_PAYLOAD_LENGTH_ERROR);
+			break;
+		}
+
+		// Check if device has been registered to the connection
+		MobiCoreDevice *device = (MobiCoreDevice *) (connection->connectionData);
+		if (NULL != device)
+		{
+			LOG_E("processOpenDevice(): device already set");
+			writeResult(connection, MC_DRV_RSP_DEVICE_ALREADY_OPENED);
+			break;
+		}
+
+		LOG_I("processOpenDevice(): deviceId is %d",
+				cmdOpenDevicePayload.deviceId);
+
+		// Get device for device ID
+		device = getDevice(cmdOpenDevicePayload.deviceId);
+
+		// Check if a device for the given name has been found
+		if (NULL == device)
+		{
+			LOG_E("invalid deviceId");
+			writeResult(connection, MC_DRV_INVALID_DEVICE_NAME);
+			break;
+		}
+
+		// Register device object with connection
+		if (false == device->open(connection))
+		{
+			LOG_E("processOpenDevice(): device->open() failed");
+			writeResult(connection, MC_DRV_RSP_FAILED);
+			break;
+		}
+
+		// Return result code to client lib (no payload)
+		writeResult(connection, MC_DRV_RSP_OK);
+
+	} while (false);
+}
+
+
+//------------------------------------------------------------------------------
+void MobiCoreDriverDaemon::processCloseDevice(
+    Connection  *connection
+) {
+	do
+	{
+		// there is no payload to read
+
+		// Device required
+		MobiCoreDevice *device = (MobiCoreDevice *) (connection->connectionData);
+		if (NULL == device)
+		{
+			LOG_E("processCloseDevice(): no device");
+			writeResult(connection, MC_DRV_RSP_DEVICE_NOT_OPENED);
+			break;
+		}
+
+		// No command data will be read
+		// Unregister device object with connection
+		device->close(connection);
+
+		// there is no payload
+		writeResult(connection, MC_DRV_RSP_OK);
+
+	} while (false);
+}
+
+
+//------------------------------------------------------------------------------
+void MobiCoreDriverDaemon::processOpenSession(
+    Connection  *connection
+) {
+	do
+	{
+		// Read entire command data
+		mcDrvCmdOpenSessionPayload_t  cmdOpenSessionPayload;
+		uint32_t rlen = connection->readData(
+							&cmdOpenSessionPayload,
+							sizeof(cmdOpenSessionPayload));
+		if (rlen != sizeof(cmdOpenSessionPayload))
+		{
+			LOG_E("processOpenSession(): OpenSession length error: %d", rlen);
+			writeResult(connection, MC_DRV_RSP_PAYLOAD_LENGTH_ERROR);
+			break;
+		}
+
+		// Device required
+		MobiCoreDevice  *device = (MobiCoreDevice *) (connection->connectionData);
+		if (NULL == device)
+		{
+			writeResult(connection, MC_DRV_RSP_DEVICE_NOT_OPENED);
+			break;
+		}
+
+		// Get service blob from registry
+		regObject_t *regObj = mcRegistryGetServiceBlob(
+				(mcUuid_t*) &(cmdOpenSessionPayload.uuid));
+
+		// Call preinstalled variant of method
+		mcDrvRspOpenSession_t rspOpenSession;
+		if (NULL == regObj)
+		{
+			writeResult(connection, MC_DRV_RSP_TRUSTLET_NOT_FOUND);
+			break;
+		}
+		if (0 == regObj->len)
+		{
+			free(regObj);
+			writeResult(connection, MC_DRV_RSP_TRUSTLET_NOT_FOUND);
+			break;
+		}
+		else
+		{
+			// Trustlet retrieved from registry
+
+			LOG_I("registering L2 in kmod, p=%p, len=%i",
+					regObj->value,
+					regObj->len);
+
+			// Prepare the interface structure for memory registration, then
+			// register virtual memory in kernel module, create L2 table
+			// TODO xgal: refactor naming of datatypes and WSM handling
+			CWsm_ptr pWsm = device->registerWsmL2(
+				(addr_t)(regObj->value),
+				regObj->len,
+				0);
+			if (NULL == pWsm)
+			{
+				LOG_E("allocating WSM for Trustlet failed");
+				writeResult(connection, MC_DRV_RSP_FAILED);
+				break;
+			}
+			// Initialize information data of open session command
+			loadDataOpenSession_t loadDataOpenSession;
+			loadDataOpenSession.baseAddr = pWsm->physAddr;
+			loadDataOpenSession.offs = ((uint32_t) regObj->value) & 0xFFF;
+			loadDataOpenSession.len = regObj->len;
+			loadDataOpenSession.tlHeader = (mclfHeader_ptr) regObj->value;
+			
+			device->openSession(
+						connection,
+						&loadDataOpenSession,
+						&cmdOpenSessionPayload,
+						&(rspOpenSession.payload));
+
+			// Unregister physical memory from kernel module.
+			// This will also destroy the WSM object.
+			if(!device->unregisterWsmL2(pWsm)) {
+				writeResult(connection, MC_DRV_RSP_FAILED);
+				break;
+			}
+
+			// Free memory occupied by Trustlet data
+			free(regObj);
+		}
+
+		uint32_t mcResult = rspOpenSession.payload.mcResult;
+
+        mcDrvRsp_t responseId = MC_DRV_RSP_FAILED;
+
+        switch (mcResult) 
+        {
+        case MC_MCP_RET_OK:
+            responseId = MC_DRV_RSP_OK;
+            break;
+        case MC_MCP_RET_ERR_WRONG_PUBLIC_KEY:
+            responseId = MC_DRV_RSP_WRONG_PUBLIC_KEY;
+            break;
+        case MC_MCP_RET_ERR_CONTAINER_TYPE_MISMATCH:
+            responseId = MC_DRV_RSP_CONTAINER_TYPE_MISMATCH;
+            break;
+        case MC_MCP_RET_ERR_CONTAINER_LOCKED:
+            responseId = MC_DRV_RSP_CONTAINER_LOCKED;
+            break;
+        case MC_MCP_RET_ERR_SP_NO_CHILD:
+            responseId = MC_DRV_RSP_SP_NO_CHILD;
+            break;
+        case MC_MCP_RET_ERR_TL_NO_CHILD:
+            responseId = MC_DRV_RSP_TL_NO_CHILD;
+            break;
+        case MC_MCP_RET_ERR_UNWRAP_ROOT_FAILED:
+            responseId = MC_DRV_RSP_UNWRAP_ROOT_FAILED;
+            break;
+        case MC_MCP_RET_ERR_UNWRAP_SP_FAILED:
+            responseId = MC_DRV_RSP_UNWRAP_SP_FAILED;
+            break;
+        case MC_MCP_RET_ERR_UNWRAP_TRUSTLET_FAILED:
+            responseId = MC_DRV_RSP_UNWRAP_TRUSTLET_FAILED;
+            break;
+        }
+
+		if (MC_MCP_RET_OK != mcResult)
+		{
+			LOG_E("rspOpenSession mcResult %d", mcResult);
+			writeResult(connection, responseId);
+			break;
+		}
+
+		rspOpenSession.header.responseId = responseId;
+		connection->writeData(
+						&rspOpenSession,
+						sizeof(rspOpenSession));
+
+	} while (false);
+}
+
+
+//------------------------------------------------------------------------------
+void MobiCoreDriverDaemon::processCloseSession(
+    Connection  *connection
+) {
+	do
+	{
+		// Read entire command data
+		mcDrvCmdCloseSessionPayload_t  cmdCloseSessionPayload;
+		uint32_t rlen = connection->readData(
+							&cmdCloseSessionPayload,
+							sizeof(cmdCloseSessionPayload));
+		if (rlen != sizeof(cmdCloseSessionPayload))
+		{
+			LOG_E("processCloseSession(): CloseSessionPayload length error: %d",rlen);
+			writeResult(connection, MC_DRV_RSP_PAYLOAD_LENGTH_ERROR);
+			break;
+		}
+
+		// Device required
+		MobiCoreDevice *device = (MobiCoreDevice *) (connection->connectionData);
+		if (NULL == device)
+		{
+			LOG_E("processCloseSession(): device is NULL");
+			writeResult(connection, MC_DRV_RSP_DEVICE_NOT_OPENED);
+			break;
+		}
+
+		device->closeSession(
+					connection,
+					cmdCloseSessionPayload.sessionId);
+
+		// there is no payload
+		writeResult(connection, MC_DRV_RSP_OK);
+
+	} while (false);
+}
+
+
+//------------------------------------------------------------------------------
+void MobiCoreDriverDaemon::processNqConnect(
+    Connection  *connection
+) {
+	do
+	{
+		// Set up the channel for sending SWd notifications to the client
+		// MC_DRV_CMD_NQ_CONNECT is only allowed on new connections not
+		// associated with a device. If a device is registered to the
+		// connection NQ_CONNECT is not allowed.
+
+		// Read entire command data
+		mcDrvCmdNqConnectPayload_t  cmdNqConnectPayload;
+		size_t rlen = connection->readData(
+										&(cmdNqConnectPayload),
+										sizeof(cmdNqConnectPayload));
+		if (rlen != sizeof(cmdNqConnectPayload))
+		{
+			LOG_E("processNqConnect(): NqConnect length error: %d",rlen);
+			writeResult(connection,MC_DRV_RSP_PAYLOAD_LENGTH_ERROR);
+			break;
+		}
+
+		// device must be empty
+		MobiCoreDevice *device = (MobiCoreDevice *)(connection->connectionData);
+		if (NULL != device)
+		{
+			LOG_E("processNqConnect(): device already set\n");
+			writeResult(connection,MC_DRV_RSP_COMMAND_NOT_ALLOWED);
+			break;
+		}
+
+		// Remove the connection from the list of known client connections
+		for (int i = 0; i < MAX_SERVERS; i++) {
+			servers[i]->detachConnection(connection);
+		}
+
+		device = getDevice(cmdNqConnectPayload.deviceId);
+		if (NULL == device)
+		{
+			//TODO xgal: how about ...NO_SUCH_DEVICE
+			LOG_E("processNqConnect(): no device found\n");
+			writeResult(connection, MC_DRV_RSP_FAILED);
+			break;
+		}
+
+		TrustletSession* ts = device->registerTrustletConnection(
+								connection,
+								&cmdNqConnectPayload);
+		if (!ts) {
+			LOG_E("processNqConnect(): registerTrustletConnection() failed!");
+			writeResult(connection, MC_DRV_RSP_FAILED);
+			break;
+		}
+
+		writeResult(connection, MC_DRV_RSP_OK);
+		ts->processQueuedNotifications();
+		
+
+	} while (false);
+}
+
+
+//------------------------------------------------------------------------------
+void MobiCoreDriverDaemon::processNotify(
+    Connection  *connection
+) {
+	do
+	{
+		// Read entire command data
+		mcDrvCmdNotifyPayload_t  cmdNotifyPayload;
+		uint32_t rlen = connection->readData(
+							&cmdNotifyPayload,
+							sizeof(cmdNotifyPayload));
+		if (sizeof(cmdNotifyPayload) != rlen)
+		{
+			LOG_E("processNotify(): NotifyPayload length error: %d", rlen);
+			// NOTE: notify fails silently
+			// writeResult(connection,MC_DRV_RSP_PAYLOAD_LENGTH_ERROR);
+			break;
+		}
+
+		// Device required
+		MobiCoreDevice *device = (MobiCoreDevice *) (connection->connectionData);
+		if (NULL == device)
+		{
+			LOG_E("processNotify(): device is NULL");
+			// NOTE: notify fails silently
+			// writeResult(connection,MC_DRV_RSP_DEVICE_NOT_OPENED);
+			break;
+		}
+
+		// REV axh: we cannot trust the clientLib to give us a valid
+		//          sessionId here. Thus we have to check that it belongs to
+		//          the clientLib's process.
+
+		device->notify(cmdNotifyPayload.sessionId);
+		// NOTE: for notifications there is no response at all
+	} while(0);
+}
+
+
+//------------------------------------------------------------------------------
+void MobiCoreDriverDaemon::processMapBulkBuf(
+    Connection  *connection
+) {
+	do
+	{
+		// Read entire command data
+		mcDrvCmdMapBulkMemPayload_t  cmdMapBulkMemPayload;
+		uint32_t rlen = connection->readData(
+								&cmdMapBulkMemPayload,
+								sizeof(cmdMapBulkMemPayload));
+		if (rlen != sizeof(cmdMapBulkMemPayload))
+		{
+			LOG_E("processMapBulkBuf(): MapBulkMemPayload length error: %d", rlen);
+			writeResult(connection, MC_DRV_RSP_PAYLOAD_LENGTH_ERROR);
+			break;
+		}
+
+		// Device required
+		MobiCoreDevice *device = (MobiCoreDevice *) (connection->connectionData);
+		if (NULL == device)
+		{
+			LOG_E("processMapBulkBuf(): device is NULL");
+			writeResult(connection, MC_DRV_RSP_DEVICE_NOT_OPENED);
+			break;
+		}
+
+		// Map bulk memory to secure world
+		mcDrvRspMapBulkMem_t rspMapBulk;
+		device->mapBulk(
+					connection,
+					&cmdMapBulkMemPayload,
+					&(rspMapBulk.payload));
+
+		uint32_t mcResult = rspMapBulk.payload.mcResult;
+		if (MC_MCP_RET_OK != mcResult)
+		{
+			LOG_E("processMapBulkBuf(): rspMapBulk.mcResult=%d", mcResult);
+			writeResult(connection, MC_DRV_RSP_FAILED);
+			break;
+		}
+
+		rspMapBulk.header.responseId = MC_DRV_RSP_OK;
+		connection->writeData(&rspMapBulk, sizeof(rspMapBulk));
+
+	} while (false);
+}
+
+
+//------------------------------------------------------------------------------
+void MobiCoreDriverDaemon::processUnmapBulkBuf(
+    Connection  *connection
+) {
+	do
+	{
+		// Read entire command data
+		mcDrvCmdUnmapBulkMemPayload_t cmdUnmapBulkMemPayload;
+		uint32_t rlen = connection->readData(
+							&cmdUnmapBulkMemPayload,
+							sizeof(cmdUnmapBulkMemPayload));
+		if (rlen != sizeof(cmdUnmapBulkMemPayload))
+		{
+			LOG_E("processMapBulkBuf(): UnmapBulkMem length error: %d", rlen);
+			writeResult(connection, MC_DRV_RSP_PAYLOAD_LENGTH_ERROR);
+			break;
+		}
+
+		// Device required
+		MobiCoreDevice *device = (MobiCoreDevice *) (connection->connectionData);
+		if (NULL == device)
+		{
+			writeResult(connection, MC_DRV_RSP_DEVICE_NOT_OPENED);
+			break;
+		}
+
+		// Unmap bulk memory from secure world
+		mcDrvRspUnmapBulkMem_t rspUnmpaBulk;
+
+		device->unmapBulk(
+					connection,
+					&cmdUnmapBulkMemPayload,
+					&(rspUnmpaBulk.payload));
+
+		uint32_t mcResult = rspUnmpaBulk.payload.mcResult;
+		if (MC_MCP_RET_OK != mcResult)
+		{
+			LOG_E("processUnmapBulkBuf(): rspUnmpaBulk mcResult %d", mcResult);
+			writeResult(connection, MC_DRV_RSP_FAILED);
+			break;
+		}
+
+		rspUnmpaBulk.header.responseId = MC_DRV_RSP_OK;
+		connection->writeData(
+						&rspUnmpaBulk,
+						sizeof(rspUnmpaBulk));
+
+	} while (false);
+}
+
+
+//------------------------------------------------------------------------------
+void MobiCoreDriverDaemon::processGetVersion(
+    Connection  *connection
+) {
+	mcDrvRspGetVersion_t rspGetVersion;
+	rspGetVersion.payload.version = MC_MAKE_VERSION(DAEMON_VERSION_MAJOR, DAEMON_VERSION_MINOR);
+
+	rspGetVersion.header.responseId = MC_DRV_RSP_OK;
+	connection->writeData(
+		&rspGetVersion,
+		sizeof(rspGetVersion));
+}
+
+//------------------------------------------------------------------------------
+void MobiCoreDriverDaemon::processGetMobiCoreVersion(
+    Connection  *connection
+) {
+	// Device required
+	MobiCoreDevice *device = (MobiCoreDevice *) (connection->connectionData);
+	if (NULL == device) {
+		writeResult(connection, MC_DRV_RSP_DEVICE_NOT_OPENED);
+		return;
+	}
+
+	// Get MobiCore version info from secure world.
+	mcDrvRspGetMobiCoreVersion_t rspGetMobiCoreVersion;
+
+	device->getMobiCoreVersion(
+		&rspGetMobiCoreVersion.payload);
+
+	uint32_t mcResult = rspGetMobiCoreVersion.payload.mcResult;
+	if (MC_MCP_RET_OK != mcResult) {
+		LOG_E("processGetMobiCoreVersion(): rspGetMobiCoreVersion mcResult %d", mcResult);
+		writeResult(connection, MC_DRV_RSP_FAILED);
+		return;
+	}
+
+	rspGetMobiCoreVersion.header.responseId = MC_DRV_RSP_OK;
+	connection->writeData(
+		&rspGetMobiCoreVersion,
+		sizeof(rspGetMobiCoreVersion));
+}
+
+
+//------------------------------------------------------------------------------
+bool MobiCoreDriverDaemon::handleConnection(
+    Connection *connection
+) {
+    bool ret = false;
+	static CMutex mutex;
+	
+	/* In case of RTM fault do not try to signal anything to MobiCore
+	 * just answer NO to all incoming connections! */
+	if (mobiCoreDevice->getMcFault()) {
+		return false;
+	}
+
+	mutex.lock();
+	do
+	{
+		// Read header
+		mcDrvCommandHeader_t mcDrvCommandHeader;
+		uint32_t rlen = connection->readData(
+							&(mcDrvCommandHeader),
+							sizeof(mcDrvCommandHeader));
+
+		if (0 == rlen)
+		{
+			LOG_I("handleConnection(): Connection closed.");
+			break;
+		}
+		if (sizeof(mcDrvCommandHeader) != rlen)
+		{
+			LOG_E("handleConnection(): Header length error: %d", rlen);
+			break;
+		}
+		ret = true;
+
+		switch (mcDrvCommandHeader.commandId)
+		{
+			//-----------------------------------------
+			case MC_DRV_CMD_OPEN_DEVICE:
+				processOpenDevice(connection);
+				break;
+			//-----------------------------------------
+			case MC_DRV_CMD_CLOSE_DEVICE:
+				processCloseDevice(connection);
+				break;
+			//-----------------------------------------
+			case MC_DRV_CMD_OPEN_SESSION:
+				processOpenSession(connection);
+				break;
+			//-----------------------------------------
+			case MC_DRV_CMD_CLOSE_SESSION:
+				processCloseSession(connection);
+				break;
+			//-----------------------------------------
+			case MC_DRV_CMD_NQ_CONNECT:
+				processNqConnect(connection);
+				break;
+			//-----------------------------------------
+			case MC_DRV_CMD_NOTIFY:
+				processNotify(connection);
+				break;
+			//-----------------------------------------
+			case MC_DRV_CMD_MAP_BULK_BUF:
+				processMapBulkBuf(connection);
+				break;
+			//-----------------------------------------
+			case MC_DRV_CMD_UNMAP_BULK_BUF:
+				processUnmapBulkBuf(connection);
+				break;
+			//-----------------------------------------
+			case MC_DRV_CMD_GET_VERSION:
+				processGetVersion(connection);
+				break;
+			//-----------------------------------------
+			case MC_DRV_CMD_GET_MOBICORE_VERSION:
+				processGetMobiCoreVersion(connection);
+				break;
+			//-----------------------------------------
+
+			default:
+				LOG_E("handleConnection(): unknown command: %d=0x%x",
+						mcDrvCommandHeader.commandId,
+						mcDrvCommandHeader.commandId);
+				ret = false;
+				break;
+		}
+	} while(0);
+	mutex.unlock();
+
+	return ret;
+}
+
+//------------------------------------------------------------------------------
+/**
+ * Print daemon command line options
+ */
+
+void printUsage(
+	int argc,
+	char *args[]
+) {
+	fprintf(stderr, "usage: %s [-mdsbh]\n", args[0]);
+	fprintf(stderr, "Start MobiCore Daemon\n\n");
+	fprintf(stderr, "-h\t\tshow this help\n");
+	fprintf(stderr, "-b\t\tfork to background\n");
+	fprintf(stderr, "-m IMAGE\tload mobicore from IMAGE to DDR\n");
+	fprintf(stderr, "-s\t\tdisable daemon scheduler(default enabled)\n");
+	fprintf(stderr, "-d SIZE\t\tdonate SIZE bytes to mobicore(disabled on most platforms)\n");
+	fprintf(stderr, "-r DRIVER\t\tMobiCore driver to load at start-up\n");
+}
+
+//------------------------------------------------------------------------------
+/**
+ * Signal handler for daemon termination
+ * Using this handler instead of the standard libc one ensures the daemon
+ * can cleanup everything -> read() on a FD will now return EINTR
+ */
+void terminateDaemon(
+	int signum
+) {
+	LOG_E("Signal %d received\n", signum);
+}
+
+//------------------------------------------------------------------------------
+/**
+ * Main entry of the MobiCore Driver Daemon.
+ */
+int main(
+    int argc,
+    char *args[]
+) {
+    // Create the MobiCore Driver Singleton
+    MobiCoreDriverDaemon *mobiCoreDriverDaemon = NULL;
+	// Process signal action
+    struct sigaction action;
+	
+	// Read the Command line options
+	extern char *optarg;
+	extern int optopt;
+	int c, errFlag = 0;
+	// Scheduler enabled by default
+	int schedulerFlag = 1;
+	// Mobicore loading disable by default
+	int mobicoreFlag = 0;
+	// Autoload driver at start-up
+	int driverLoadFlag = 0;
+	std::string mobicoreImage, driverPath;
+	// Ram donation disabled by default
+	int donationSize = 0;
+	// By default don't fork
+	bool forkDaemon = false;
+	while ((c = getopt(argc, args, "m:d:r:sbh")) != -1) {
+		switch(c) {
+			case 'h': /* Help */
+				errFlag++;
+				break;
+			case 's': /* Disable Scheduler */
+				schedulerFlag = 0;
+				break;
+			case 'd': /* Ram Donation size */
+				donationSize = atoi(optarg);
+				break;
+			case 'm': /* Load mobicore image */
+				mobicoreFlag = 1;
+				mobicoreImage = optarg;
+				break;
+			case 'b': /* Fork to background */
+				forkDaemon = true;
+				break;
+			case 'r': /* Load mobicore driver at start-up */
+				driverLoadFlag = 1;
+				driverPath = optarg;
+				break;
+			case ':':       /* -d or -m without operand */
+				fprintf(stderr, "Option -%c requires an operand\n", optopt);
+				errFlag++;
+				break;
+			case '?':
+				fprintf(stderr,
+						"Unrecognized option: -%c\n", optopt);
+				errFlag++;
+		}
+	}
+	if (errFlag) {
+		printUsage(argc, args);
+		exit(2);
+	}
+
+	// We should fork the daemon to background
+	if (forkDaemon == true) {
+		int i = fork();
+		if (i < 0) {
+			exit(1);
+		}
+		// Parent
+		else if (i > 0) {
+			exit(0);
+		}
+	
+		// obtain a new process group */
+		setsid();
+		/* close all descriptors */
+		for (i = getdtablesize();i >= 0; --i) {
+			close(i);
+		}
+		// STDIN, STDOUT and STDERR should all point to /dev/null */
+		i = open("/dev/null",O_RDWR); 
+		dup(i);
+		dup(i);
+		/* ignore tty signals */
+		signal(SIGTSTP,SIG_IGN);
+		signal(SIGTTOU,SIG_IGN);
+		signal(SIGTTIN,SIG_IGN);
+	}
+
+	// Set up the structure to specify the new action.
+	action.sa_handler = terminateDaemon;
+	sigemptyset (&action.sa_mask);
+	action.sa_flags = 0;
+	sigaction (SIGINT, &action, NULL);
+	sigaction (SIGHUP, &action, NULL);
+	sigaction (SIGTERM, &action, NULL);
+	signal(SIGPIPE, SIG_IGN);
+	
+	mobiCoreDriverDaemon = new MobiCoreDriverDaemon(
+		/* Scheduler status */
+		schedulerFlag,
+		/* Mobicore loading to DDR */
+		mobicoreFlag,
+		mobicoreImage,
+		/* Ram Donation */
+		donationSize,
+		/* Auto Driver loading */
+		driverLoadFlag,
+		driverPath);
+
+	// Start the driver
+	mobiCoreDriverDaemon->run();
+
+	delete mobiCoreDriverDaemon;
+
+	// This should not happen
+	LOG_E("Exiting MobiCoreDaemon");
+
+	return EXIT_FAILURE;
+}
+
+//------------------------------------------------------------------------------
+static void checkMobiCoreVersion(
+	MobiCoreDevice* mobiCoreDevice
+) {
+	bool failed = false;
+
+	// Get MobiCore version info.
+	mcDrvRspGetMobiCoreVersionPayload_t versionPayload;
+	mobiCoreDevice->getMobiCoreVersion(&versionPayload);
+
+	if (versionPayload.mcResult != MC_MCP_RET_OK) {
+		LOG_E("Failed to obtain MobiCore version info. MCP return code: %u", versionPayload.mcResult);
+		failed = true;
+
+	} else {
+		LOG_I("Product ID is %s", versionPayload.versionInfo.productId);
+
+		// Check MobiCore version info.
+		char* msg;
+		if (!checkVersionOkMCI(versionPayload.versionInfo.versionMci, &msg)) {
+			LOG_E("%s", msg);
+			failed = true;
+		}
+		LOG_I("%s", msg);
+		if (!checkVersionOkSO(versionPayload.versionInfo.versionSo, &msg)) {
+			LOG_E("%s", msg);
+			failed = true;
+		}
+		LOG_I("%s", msg);
+		if (!checkVersionOkMCLF(versionPayload.versionInfo.versionMclf, &msg)) {
+			LOG_E("%s", msg);
+			failed = true;
+		}
+		LOG_I("%s", msg);
+		if (!checkVersionOkCONTAINER(versionPayload.versionInfo.versionContainer, &msg)) {
+			LOG_E("%s", msg);
+			failed = true;
+		}
+		LOG_I("%s", msg);
+	}
+
+	if (failed) {
+		exit(1);
+	}
+}
+
+/** @} */
diff --git a/mobicore/daemon/Daemon/MobiCoreDriverDaemon.h b/mobicore/daemon/Daemon/MobiCoreDriverDaemon.h
new file mode 100644
index 0000000..a6ad2aa
--- /dev/null
+++ b/mobicore/daemon/Daemon/MobiCoreDriverDaemon.h
@@ -0,0 +1,193 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_CONHDLR
+ * @{
+ * @file
+ *
+ * MobiCore driver class.
+ * The MobiCore driver class implements the ConnectionHandler interface.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef MOBICOREDRIVER_H_
+#define MOBICOREDRIVER_H_
+
+#include "Server/public/ConnectionHandler.h"
+#include "Server/public/Server.h"
+
+#include "MobiCoreDevice.h"
+#include <string>
+#include <list>
+
+
+#define MAX_SERVERS 2
+
+class MobicoreDriverResources {
+public:
+	Connection *conn;
+	CWsm* pTciWsm;
+	uint8_t *tci;
+	uint32_t sessionId;
+	
+	MobicoreDriverResources(
+		Connection *conn,
+		uint8_t* tci,
+		CWsm* pTciWsm,
+		uint32_t sessionId
+	) {
+		this->conn = conn;
+		this->pTciWsm = pTciWsm;
+		this->sessionId = sessionId;
+	};
+};
+
+typedef std::list<MobicoreDriverResources*> driverResourcesList_t;
+
+class MobiCoreDriverDaemon : ConnectionHandler {
+
+public:
+
+	/**
+	 * Create daemon object
+	 *
+	 * @param enableScheduler Enable NQ IRQ scheduler
+	 * @param loadMobicore Load mobicore image to DDR
+	 * @param mobicoreImage Mobicore image path
+	 * @param donateRamSize Ram donation size in bytes
+	 */
+	MobiCoreDriverDaemon(
+		bool enableScheduler,
+		/**< Mobicore loading to DDR */
+		bool loadMobicore,
+		std::string mobicoreImage,
+		unsigned int donateRamSize,
+		/**< Mobicore driver loading at start-up */
+		bool loadDriver,
+		std::string driverPath
+	);
+
+	virtual ~MobiCoreDriverDaemon(
+	    void
+	);
+
+	void dropConnection(
+	    Connection *connection
+	);
+
+	bool handleConnection(
+	    Connection *connection
+	);
+
+	void run(
+		void
+	);
+
+private:
+
+	MobiCoreDevice *mobiCoreDevice;
+	/**< Flag to start/stop the scheduler */
+	bool enableScheduler;
+	/**< Flag to load mobicore image to DDR */
+	bool loadMobicore;
+	/**< Mobicore image location */
+	std::string mobicoreImage;
+	/**< Ram size to donate */
+	unsigned int donateRamSize;
+	bool loadDriver;
+	std::string driverPath;
+	/**< List of resources for the loaded drivers */
+	driverResourcesList_t driverResources;
+	/**< List of servers processing connections */	
+	Server *servers[MAX_SERVERS];
+
+	size_t writeResult(
+		Connection  *connection,
+		mcDrvRsp_t  code
+	);
+
+	/**
+		* Resolve a device ID to a MobiCore device.
+		*
+		* @param deviceId Device identifier of the device.
+		* @return Reference to the device or NULL if device could not be found.
+		*/
+	MobiCoreDevice *getDevice(
+		uint32_t deviceId
+	);
+	
+	/**
+	 * Load Device driver
+	 *
+	 * @param driverPath Path to the driver file
+	 * @return True for success/false for failure
+	 */
+	bool loadDeviceDriver(
+		std::string driverPath
+	);
+
+	void processOpenDevice(
+		Connection *connection
+	);
+
+	void processOpenSession(
+		Connection *connection
+	);
+
+	void processNqConnect(
+		Connection *connection
+	);
+
+	void processCloseDevice(
+		Connection *connection
+	);
+
+	void processNotify(
+		Connection *connection
+	);
+
+	void processCloseSession(
+		Connection *connection
+	);
+
+	void processMapBulkBuf(
+		Connection *connection
+	);
+
+	void processUnmapBulkBuf(
+		Connection *connection
+	);
+
+	void processGetVersion(
+		Connection *connection
+	);
+
+	void processGetMobiCoreVersion(
+		Connection *connection
+	);
+};
+
+#endif /* MOBICOREDRIVER_H_ */
+
+/** @} */
diff --git a/mobicore/daemon/Daemon/Server/Android.mk b/mobicore/daemon/Daemon/Server/Android.mk
new file mode 100644
index 0000000..1831793
--- /dev/null
+++ b/mobicore/daemon/Daemon/Server/Android.mk
@@ -0,0 +1,18 @@
+# =============================================================================
+#
+# MC driver server files
+#
+# =============================================================================
+
+# This is not a separate module.
+# Only for inclusion by other modules.
+
+MY_MCDRV_SERVER_PATH := $(call my-dir)
+MY_MCDRV_SERVER_PATH_REL := Server
+
+# Add new folders with header files here
+LOCAL_C_INCLUDES += $(MY_MCDRV_SERVER_PATH)/public
+
+# Add new source files here
+LOCAL_SRC_FILES += $(MY_MCDRV_SERVER_PATH_REL)/Server.cpp \
+		$(MY_MCDRV_SERVER_PATH_REL)/NetlinkServer.cpp
diff --git a/mobicore/daemon/Daemon/Server/NetlinkServer.cpp b/mobicore/daemon/Daemon/Server/NetlinkServer.cpp
new file mode 100644
index 0000000..3e12dc8
--- /dev/null
+++ b/mobicore/daemon/Daemon/Server/NetlinkServer.cpp
@@ -0,0 +1,273 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_SRV
+ * @{
+ * @file
+ *
+ * Connection server.
+ *
+ * Handles incoming socket connections from clients using the MobiCore driver.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "public/NetlinkServer.h"
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <linux/netlink.h>
+
+#include <stdlib.h>
+#include "NetlinkConnection.h"
+#include <signal.h>
+
+#define LOG_TAG	"McDaemon"
+#include "log.h"
+
+//------------------------------------------------------------------------------
+NetlinkServer::NetlinkServer(
+    ConnectionHandler * connectionHandler
+):Server(connectionHandler, "dummy") {
+}
+
+
+//------------------------------------------------------------------------------
+void NetlinkServer::run(
+) {
+	do
+	{
+		LOG_I("%s: start listening on netlink bus", __func__);
+		
+		// Open a socket
+		serverSock = socket(PF_NETLINK, SOCK_DGRAM,  MC_DAEMON_NETLINK);
+		if (serverSock < 0)
+		{
+			LOG_E("run(): can't open socket, errno=%d", errno);
+			break;
+		}
+
+		// Fill in address structure and bind to socket
+		struct sockaddr_nl src_addr;
+		struct nlmsghdr *nlh = NULL;
+		struct iovec iov;
+		struct msghdr msg;
+		uint32_t len;
+		
+		memset(&src_addr, 0, sizeof(src_addr));
+		src_addr.nl_family = AF_NETLINK;
+		src_addr.nl_pid = MC_DAEMON_PID;  /* daemon pid */
+		src_addr.nl_groups = 0;  /* not in mcast groups */
+		if(bind(serverSock, (struct sockaddr*)&src_addr, sizeof(src_addr)) < 0){
+			LOG_E("bind() to server socket failed, errno=%d(%s)", 
+					errno, strerror(errno));
+			close(serverSock);
+			break;
+		}
+
+		// Start reading the socket
+		LOG_I("\n********* successfully initialized *********\n");
+
+		for (;;)
+		{
+			// This buffer will be taken over by the connection it was routed to
+			nlh=(struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
+			memset(&msg, 0, sizeof(msg));
+			iov.iov_base = (void *)nlh;
+			iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);
+			msg.msg_iov = &iov;
+			msg.msg_iovlen = 1;
+			msg.msg_name = &src_addr;
+			msg.msg_namelen = sizeof(src_addr);
+			
+			memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
+			
+			// Read the incomming message and route it to the connection based
+			// on the incomming PID
+			if ((len = recvmsg(serverSock, &msg, 0)) < 0) {
+				LOG_E("%s: recvmsg() failed, errno=%d(%s)", 
+						__func__, errno, strerror(errno));
+				break;
+			}
+			
+            if (NLMSG_OK(nlh, len)) {
+				handleMessage(nlh);
+			} else {
+				break;
+			}
+		}
+	} while(false);
+
+    LOG_E("%s: exiting due to error, errno=%d(%s)",
+		  __func__, errno, strerror(errno));
+}
+
+//------------------------------------------------------------------------------
+void NetlinkServer::handleMessage(
+    struct nlmsghdr *nlh
+) {
+	uint32_t seq = nlh->nlmsg_seq;
+	uint32_t pid = nlh->nlmsg_pid;
+	//LOG_I("%s: Handling NQ message for pid %u seq %u...", __func__, pid, seq);
+	uint64_t hash = hashConnection(pid, seq);
+	/* First cleanup the connection list */
+	cleanupConnections();
+
+	NetlinkConnection *connection = findConnection(hash);
+	// This is a message from a new client
+	if (connection == NULL) {
+		//LOG_I("%s: Cound't find the connection, creating a new one", __func__);
+		connection = new NetlinkConnection(this, serverSock, pid, seq);
+		// Add the new connection
+		insertConnection(hash, connection);
+	}
+
+	connection->handleMessage(nlh);
+
+	// Only handle connections which have not been detached
+	if(connection->detached == false)
+	{
+		if (!connectionHandler->handleConnection(connection))
+		{
+			LOG_I("%s: No command processed.", __func__);
+			connection->socketDescriptor = -1;
+			//Inform the driver
+			connectionHandler->dropConnection(connection);
+			
+			// Remove connection from list
+			removeConnection(hash);
+			connection->socketDescriptor = -1;
+			delete connection;
+		}
+		// If connection data is set to NULL then device close has been called 
+		// so we must remove all connections associated with this hash
+		else if (connection->connectionData == NULL && 
+			connection->detached == false)
+		{
+			delete connection;
+		}
+	}
+}
+
+
+//------------------------------------------------------------------------------
+void NetlinkServer::detachConnection(
+    Connection *connection
+) {
+	connection->detached = true;
+}
+
+
+//------------------------------------------------------------------------------
+NetlinkServer::~NetlinkServer(
+	void
+) {
+	connectionMap_t::iterator i;
+	// Shut down the server socket
+	close(serverSock);
+
+	// Destroy all client connections
+	for (i = peerConnections.begin(); i != peerConnections.end(); i++) {
+		if (i->second->detached == false) {
+			delete i->second;
+		}
+	}
+	peerConnections.clear();
+}
+
+
+//------------------------------------------------------------------------------
+NetlinkConnection* NetlinkServer::findConnection(
+    uint64_t hash
+) {
+	connectionMap_t::iterator i = peerConnections.find(hash);
+	if (i != peerConnections.end()) {
+		return i->second;
+	}
+
+	return NULL;
+}
+
+
+//------------------------------------------------------------------------------
+void NetlinkServer::insertConnection(
+	uint64_t hash,
+    NetlinkConnection *connection
+) {
+	peerConnections[hash] = connection;
+}
+
+/* This is called from multiple threads! */
+//------------------------------------------------------------------------------
+void NetlinkServer::removeConnection(
+	uint64_t hash
+) {
+	connectionMap_t::iterator i = peerConnections.find(hash);
+	if (i != peerConnections.end()){
+		peerConnections.erase(i);
+	}
+}
+
+//------------------------------------------------------------------------------
+void NetlinkServer::cleanupConnections(
+	void
+) {
+	connectionMap_t::reverse_iterator i;
+	pid_t pid;
+	NetlinkConnection *connection = NULL;
+	// Destroy all client connections
+	for (i = peerConnections.rbegin(); i != peerConnections.rend(); ++i) {
+		connection = i->second;
+		// Only 16 bits are for the actual PID, the rest is session magic
+		pid = connection->peerPid & 0xFFFF;
+		//LOG_I("%s: checking PID %u", __func__, pid);
+		// Check if the peer pid is still alive
+		if (pid == 0) {
+			continue;
+		}
+		if (kill(pid, 0)) {
+			bool detached = connection->detached;
+			LOG_I("%s: PID %u has died, cleaning up session 0x%X", 
+				  __func__, pid, connection->peerPid);
+			
+			connection->socketDescriptor = -1;
+			//Inform the driver
+			connectionHandler->dropConnection(connection);
+			
+			// We aren't handling this connection anymore no matter what
+			removeConnection(connection->hash);
+			
+			// Remove connection from list only if detached, the detached
+			// connections are managed by the device
+			if (detached == false) {
+				delete connection;
+			}
+			if (peerConnections.size() == 0) {
+				break;
+			}
+			i = peerConnections.rbegin();
+		}
+	}
+}
+
+/** @} */
diff --git a/mobicore/daemon/Daemon/Server/Server.cpp b/mobicore/daemon/Daemon/Server/Server.cpp
new file mode 100644
index 0000000..e61a8b2
--- /dev/null
+++ b/mobicore/daemon/Daemon/Server/Server.cpp
@@ -0,0 +1,251 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_SRV
+ * @{
+ * @file
+ *
+ * Connection server.
+ *
+ * Handles incoming socket connections from clients using the MobiCore driver.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "public/Server.h"
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#define LOG_TAG	"McDaemon"
+#include "log.h"
+
+
+//------------------------------------------------------------------------------
+Server::Server(
+    ConnectionHandler * connectionHandler,
+    const char *localAddr
+) :socketAddr(localAddr)
+{
+	this->connectionHandler = connectionHandler;
+}
+
+
+//------------------------------------------------------------------------------
+void Server::run(
+	void
+) {
+    do
+    {
+		LOG_I("run(): start listening on socket %s", socketAddr.c_str());
+
+		// Open a socket (a UNIX domain stream socket)
+		serverSock = socket(AF_UNIX, SOCK_STREAM, 0);
+		if (serverSock < 0)
+		{
+			LOG_E("run(): can't open stream socket, errno=%d", errno);
+			break;
+		}
+
+		// Fill in address structure and bind to socket
+		struct sockaddr_un  serverAddr;
+		serverAddr.sun_family = AF_UNIX;
+		strncpy(serverAddr.sun_path, socketAddr.c_str(), sizeof(serverAddr.sun_path) - 1);
+
+		uint32_t len = strlen(serverAddr.sun_path) + sizeof(serverAddr.sun_family);
+		// Make the socket in the Abstract Domain(no path but everyone can connect)
+		serverAddr.sun_path[0] = 0;
+		if (bind(serverSock, (struct sockaddr *) &serverAddr, len) < 0)
+		{
+			LOG_E("bind() to server socket failed, errno=%d", errno);
+		}
+
+		// Start listening on the socket
+		if (listen(serverSock, LISTEN_QUEUE_LEN) < 0)
+		{
+			LOG_E("run(): listen() failed, errno=%d", errno);
+			break;
+		}
+
+		LOG_I("\n********* successfully initialized *********\n");
+
+		for (;;)
+		{
+			fd_set fdReadSockets;
+
+		    // Clear FD for select()
+			FD_ZERO(&fdReadSockets);
+
+			// Select server socket descriptor
+			FD_SET(serverSock, &fdReadSockets);
+			int maxSocketDescriptor = serverSock;
+
+			// Select socket descriptor of all connections
+			for (connectionIterator_t iterator = peerConnections.begin();
+			     iterator != peerConnections.end();
+			     ++iterator)
+			{
+			    Connection *connection = (*iterator);
+			    int peerSocket = connection->socketDescriptor;
+				FD_SET(peerSocket, &fdReadSockets);
+				if (peerSocket > maxSocketDescriptor)
+				{
+					maxSocketDescriptor = peerSocket;
+				}
+			}
+
+			// Wait for activities, select() returns the number of sockets
+			// which require processing
+			LOG_I("run(): waiting on sockets");
+			int numSockets = select(
+			                    maxSocketDescriptor + 1,
+			                    &fdReadSockets,
+			                    NULL, NULL, NULL);
+
+			// Check if select failed
+			if (numSockets < 0)
+			{
+				LOG_E("run(): select() failed, errno=%d", errno);
+				break;
+			}
+
+            // actually, this should not happen.
+			if (0 == numSockets)
+            {
+			    LOG_W("run(): select() returned 0, spurious event?.");
+			    continue;
+            }
+
+			LOG_I("run(): events on %d socket(s).", numSockets);
+
+			// Check if a new client connected to the server socket
+			if (FD_ISSET(serverSock, &fdReadSockets))
+			{
+				do
+				{
+					LOG_I("run(): new connection");
+					numSockets--;
+
+					struct sockaddr_un clientAddr;
+					socklen_t clientSockLen = sizeof(clientAddr);
+					int clientSock = accept(
+										serverSock,
+										(struct sockaddr*) &clientAddr,
+										&clientSockLen);
+
+					if (clientSock <= 0)
+					{
+						LOG_E("run(): accept() failed, errno=%d", errno);
+						break;
+					}
+
+					Connection *connection = new Connection(clientSock, &clientAddr);
+					peerConnections.push_back(connection);
+					LOG_I("run(): added new connection");
+				} while (false);
+
+				// we can ignore any errors from accepting a new connection.
+				// If this fail, the client has to deal with it, we are done
+				// and nothing has changed.
+			}
+
+			// Handle traffic on existing client connections
+			connectionIterator_t iterator = peerConnections.begin();
+			while ( (iterator != peerConnections.end())
+			        && (numSockets > 0) )
+            {
+				Connection *connection = (*iterator);
+				int peerSocket = connection->socketDescriptor;
+
+				if (!FD_ISSET(peerSocket, &fdReadSockets))
+				{
+				    ++iterator;
+				    continue;
+				}
+
+				numSockets--;
+
+				// the connection will be terminated if command processing
+				// fails
+				if (!connectionHandler->handleConnection(connection))
+				{
+					LOG_I("run(): No command processed.");
+
+					//Inform the driver
+					connectionHandler->dropConnection(connection);
+
+					// Remove connection from list
+					delete connection;
+					iterator = peerConnections.erase(iterator);
+					continue;
+				}
+
+				++iterator;
+			}
+		}
+
+	} while (false);
+
+    LOG_E("run(): exiting due to error, errno=%d", errno);
+}
+
+
+//------------------------------------------------------------------------------
+void Server::detachConnection(
+    Connection *connection
+) {
+	LOG_I("Detaching NQ connection...");
+
+	for (connectionIterator_t iterator = peerConnections.begin();
+			iterator != peerConnections.end();
+			++iterator)
+	{
+		Connection *tmpConnection = (*iterator);
+		if (tmpConnection == connection)
+		{
+			peerConnections.erase(iterator);
+			LOG_I("NQ connection detached");
+			break;
+		}
+	}
+}
+
+
+//------------------------------------------------------------------------------
+Server::~Server(
+	void
+) {
+	// Shut down the server socket
+	close(serverSock);
+
+	// Destroy all client connections
+	connectionIterator_t iterator = peerConnections.begin();
+	while (iterator != peerConnections.end())
+	{
+		Connection *tmpConnection = (*iterator);
+		delete tmpConnection;
+		iterator = peerConnections.erase(iterator);
+	}
+}
+
+/** @} */
diff --git a/mobicore/daemon/Daemon/Server/public/ConnectionHandler.h b/mobicore/daemon/Daemon/Server/public/ConnectionHandler.h
new file mode 100644
index 0000000..3d9a002
--- /dev/null
+++ b/mobicore/daemon/Daemon/Server/public/ConnectionHandler.h
@@ -0,0 +1,68 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_SRV
+ * @{
+ * @file
+ *
+ * Interface for connection handlers used by Server.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef CONNECTIONHANDLER_H_
+#define CONNECTIONHANDLER_H_
+
+#include "Connection.h"
+
+
+class ConnectionHandler {
+
+public:
+    virtual ~ConnectionHandler() {};
+
+    /**
+     * Handle connection activities.
+     * The connection handler shall process pending connection activities.
+     *
+     * @param [in] connection Reference to the connection which has data to process.
+     */
+    virtual bool handleConnection(
+        Connection *connection
+    ) = 0;
+
+    /**
+     * Connection has been closed.
+     * The connection handler shall clean up all resources associated with the given connection.
+     * After the method has been executed the connection object will be deleted.
+     *
+     * @param [in] connection Reference to the connection which will be deleted.
+     */
+	virtual void dropConnection(
+	    Connection *connection
+	) = 0;
+};
+
+#endif /* CONNECTIONHANDLER_H_ */
+
+/** @} */
diff --git a/mobicore/daemon/Daemon/Server/public/NetlinkServer.h b/mobicore/daemon/Daemon/Server/public/NetlinkServer.h
new file mode 100644
index 0000000..48d51a2
--- /dev/null
+++ b/mobicore/daemon/Daemon/Server/public/NetlinkServer.h
@@ -0,0 +1,156 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_SRV
+ * @{
+ * @file
+ *
+ * Connection server.
+ *
+ * Handles incoming socket connections from clients using the MobiCore driver.
+ *
+ * Iterative socket server using Netlink dgram protocol.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef NETLINKSERVER_H_
+#define NETLINKSERVER_H_
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <linux/netlink.h>
+#include <cstdio>
+#include <map>
+
+#include "NetlinkConnection.h"
+#include "ConnectionHandler.h"
+#include "Server.h"
+
+class NetlinkServer: public Server, public NetlinkConnectionManager {
+public:
+	/**
+	 * Server contructor.
+	 *
+	 * @param connectionHanler Connection handler to pass incoming connections to.
+	 */
+    NetlinkServer(
+		ConnectionHandler * connectionHandler
+	);
+
+	/**
+	 * Server destructor.
+	 * All available connections will be terminated. Resources will be freed.
+	 */
+    virtual ~NetlinkServer(
+		void
+	);
+
+	/**
+	 * Start server and listen for incoming connections.
+	 * Implements the central socket server loop. Incoming connections will be stored.
+	 */
+	virtual void run(
+		void
+	);
+
+	/**
+	 * Remove a connection object from the list of available connections.
+	 * Detaching is required for notification connections wich are never used to transfer command
+	 * data from TLCs to the driver. If the function succeeds, freeing the connection will no longer
+     * be the server's responsability.
+	 *
+	 * @param connection The connection object to remove.
+	 */
+	virtual void detachConnection(
+		Connection *connection
+	);
+
+private:
+    /**
+     * Handle incomming Netlink message.
+     * It routes the incomming packet to the apropriate connection based on the packet's
+     * session magic.
+     *
+     * @param nlh The netlink message's header + payload
+     */   
+    void handleMessage(
+        struct nlmsghdr *nlh
+    );
+    
+    /**
+	 * Retreive connection based on hash.
+	 * Search the peer connections hashmap for a hash and return 
+	 * the associated Connection object
+     *
+	 * @param seq The seq to search
+     * @return The NetlinkConnection object if found or NULL if not found
+     */
+    NetlinkConnection* findConnection(
+		uint64_t hash
+    );
+    
+    /**
+     * Insert a connection in the peer connection hashmap
+     * Insert a new connection in the peer connections hashmap. If there is 
+	 * already such a connection it will be overriden!
+     *
+	 * @param seq The seq to use
+     * @param connection The connection object to insert
+     */
+    void insertConnection(
+		uint64_t hash,
+        NetlinkConnection *connection
+    );
+    
+    /**
+     * Remove a connection from the peer connections
+     * Remove the connection associated with seq from the peer list. 
+	 * This doesn't actually free the connection object!
+     * If the seq is invalid nothing happens.
+     *
+     * @param seq The seq to use
+     */
+    void removeConnection(
+		uint64_t hash
+    );
+	
+	
+	/**
+	 * Check for sessions started by applications that died(exited)
+	 * Remove the connections to applications that are not active anymore
+	 * If the application has died then all the sessions associated with it
+	 * should be closed!
+	 *
+	 */
+	void cleanupConnections(
+		void
+	);
+
+	connectionMap_t peerConnections; /**< Hashmap with connections to clients */
+};
+
+#endif /* SERVER_H_ */
+
+/** @} */
diff --git a/mobicore/daemon/Daemon/Server/public/Server.h b/mobicore/daemon/Daemon/Server/public/Server.h
new file mode 100644
index 0000000..c14d22c
--- /dev/null
+++ b/mobicore/daemon/Daemon/Server/public/Server.h
@@ -0,0 +1,107 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_SRV
+ * @{
+ * @file
+ *
+ * Connection server.
+ *
+ * Handles incoming socket connections from clients using the MobiCore driver.
+ *
+ * Iterative socket server using UNIX domain stream protocol.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef SERVER_H_
+#define SERVER_H_
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <string>
+#include <cstdio>
+#include <vector>
+#include "CThread.h"
+#include "ConnectionHandler.h"
+
+/** Number of incoming connections that can be queued.
+ * Additional clients will generate the error ECONNREFUSED. */
+#define LISTEN_QUEUE_LEN	(16)
+
+
+class Server: public CThread {
+
+public:
+	/**
+	 * Server contructor.
+	 *
+	 * @param connectionHanler Connection handler to pass incoming connections to.
+	 * @param localAdrerss Pointer to a zero terminated string containing the file to listen to.
+	 */
+	Server(
+		ConnectionHandler * connectionHandler,
+		const char *localAddr
+	);
+
+	/**
+	 * Server destructor.
+	 * All available connections will be terminated. Resources will be freed.
+	 */
+    virtual ~Server(
+		void
+	);
+
+	/**
+	 * Start server and listen for incoming connections.
+	 * Implements the central socket server loop. Incoming connections will be stored.
+	 */
+	virtual void run(
+	);
+
+	/**
+	 * Remove a connection object from the list of available connections.
+	 * Detaching is required for notification connections wich are never used to transfer command
+	 * data from TLCs to the driver. If the function succeeds, the connection object will no longer
+	 * be handled by the server.
+	 *
+	 * @param connection The connection object to remove.
+	 */
+    virtual void detachConnection(
+		Connection *connection
+	);
+
+protected:
+	int serverSock;
+	string socketAddr;
+	ConnectionHandler   *connectionHandler;	/**< Connection handler registered to the server */
+	
+private:
+	connectionList_t    peerConnections; /**< Connections to devices */
+
+};
+
+#endif /* SERVER_H_ */
+
+/** @} */
diff --git a/mobicore/daemon/Daemon/public/MobiCoreDriverCmd.h b/mobicore/daemon/Daemon/public/MobiCoreDriverCmd.h
new file mode 100644
index 0000000..15be3a6
--- /dev/null
+++ b/mobicore/daemon/Daemon/public/MobiCoreDriverCmd.h
@@ -0,0 +1,335 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON
+ * @{
+ * @file
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef MCDAEMON_H_
+#define MCDAEMON_H_
+
+#include <inttypes.h>      // ANSI C99
+
+
+#define SOCK_PATH "#mcdaemon"
+#include "mcUuid.h"
+#include "mcVersionInfo.h"
+
+typedef enum {
+    MC_DRV_CMD_PING                 = 0,
+    MC_DRV_CMD_GET_INFO             = 1,
+    MC_DRV_CMD_OPEN_DEVICE          = 2,
+    MC_DRV_CMD_CLOSE_DEVICE         = 3,
+    MC_DRV_CMD_NQ_CONNECT           = 4,
+	MC_DRV_CMD_OPEN_SESSION         = 5,
+	MC_DRV_CMD_CLOSE_SESSION        = 6,
+    MC_DRV_CMD_NOTIFY               = 7,
+	MC_DRV_CMD_MAP_BULK_BUF         = 8,
+	MC_DRV_CMD_UNMAP_BULK_BUF       = 9,
+    MC_DRV_CMD_GET_VERSION          = 10,
+    MC_DRV_CMD_GET_MOBICORE_VERSION = 11,
+} mcDrvCmd_t;
+
+
+typedef enum {
+	MC_DRV_RSP_OK                                   = 0,
+	MC_DRV_RSP_FAILED                               = 1,
+    MC_DRV_RSP_DEVICE_NOT_OPENED                    = 2,
+    MC_DRV_RSP_DEVICE_ALREADY_OPENED                = 3,
+	MC_DRV_RSP_COMMAND_NOT_ALLOWED                  = 4,
+	MC_DRV_INVALID_DEVICE_NAME                      = 5,
+	MC_DRV_RSP_MAP_BULK_ERRO                        = 6,
+	MC_DRV_RSP_TRUSTLET_NOT_FOUND                   = 7,
+	MC_DRV_RSP_PAYLOAD_LENGTH_ERROR	                = 8,
+    MC_DRV_RSP_WRONG_PUBLIC_KEY                     = 9,  /**< System Trustlet public key is wrong. */
+    MC_DRV_RSP_CONTAINER_TYPE_MISMATCH              = 10, /**< Wrong containter type(s). */
+    MC_DRV_RSP_CONTAINER_LOCKED                     = 11, /**< Container is locked (or not activated). */
+    MC_DRV_RSP_SP_NO_CHILD                          = 12, /**< SPID is not registered with root container. */
+    MC_DRV_RSP_TL_NO_CHILD                          = 13, /**< UUID is not registered with sp container. */
+    MC_DRV_RSP_UNWRAP_ROOT_FAILED                   = 14, /**< Unwrapping of root container failed. */
+    MC_DRV_RSP_UNWRAP_SP_FAILED                     = 15, /**< Unwrapping of service provider container failed. */
+    MC_DRV_RSP_UNWRAP_TRUSTLET_FAILED               = 16, /**< Unwrapping of Trustlet container failed. */
+} mcDrvRsp_t;
+
+
+typedef struct {
+    uint32_t  commandId;
+} mcDrvCommandHeader_t, *mcDrvCommandHeader_ptr;
+
+typedef struct {
+    uint32_t  responseId;
+} mcDrvResponseHeader_t, *mcDrvResponseHeader_ptr;
+
+#define MC_DEVICE_ID_DEFAULT    0 /**< The default device ID */
+
+
+//--------------------------------------------------------------
+typedef struct{
+	uint32_t  deviceId;
+} mcDrvCmdOpenDevicePayload_t, *mcDrvCmdOpenDevicePayload_ptr;
+
+typedef struct{
+    mcDrvCommandHeader_t         header;
+    mcDrvCmdOpenDevicePayload_t  payload;
+} mcDrvCmdOpenDevice_t, *mcDrvCmdOpenDevice_ptr;
+
+
+typedef struct{
+    // empty
+} mcDrvRspOpenDevicePayload_t, *mcDrvRspOpenDevicePayload_ptr;
+
+typedef struct{
+    mcDrvResponseHeader_t        header;
+    mcDrvRspOpenDevicePayload_t  payload;
+} mcDrvRspOpenDevice_t, *mcDrvRspOpenDevice_ptr;
+
+
+//--------------------------------------------------------------
+typedef struct{
+    mcDrvCommandHeader_t          header;
+    // no payload here because close has none.
+    // If we use an empty struct, C++ will count it as 4 bytes.
+    // This will write too much into the socket at write(cmd,sizeof(cmd))
+} mcDrvCmdCloseDevice_t, *mcDrvCmdCloseDevice_ptr;
+
+
+typedef struct{
+    // empty
+} mcDrvRspCloseDevicePayload_t, *mcDrvRspCloseDevicePayload_ptr;
+
+typedef struct{
+    mcDrvResponseHeader_t         header;
+    mcDrvRspCloseDevicePayload_t  payload;
+} mcDrvRspCloseDevice_t, *mcDrvRspCloseDevice_ptr;
+
+
+//--------------------------------------------------------------
+typedef struct{
+	uint32_t  deviceId;
+	mcUuid_t    uuid;
+	uint32_t  tci;
+	uint32_t  len;
+} mcDrvCmdOpenSessionPayload_t, *mcDrvCmdOpenSessionPayload_ptr;
+
+typedef struct{
+    mcDrvCommandHeader_t          header;
+    mcDrvCmdOpenSessionPayload_t  payload;
+} mcDrvCmdOpenSession_t, *mcDrvCmdOpenSession_ptr;
+
+
+typedef struct{
+	uint32_t  deviceId;
+	uint32_t  sessionId;
+	uint32_t  deviceSessionId;
+	uint32_t  mcResult;
+	uint32_t  sessionMagic;
+} mcDrvRspOpenSessionPayload_t, *mcDrvRspOpenSessionPayload_ptr;
+
+typedef struct{
+    mcDrvResponseHeader_t         header;
+    mcDrvRspOpenSessionPayload_t  payload;
+} mcDrvRspOpenSession_t, *mcDrvRspOpenSession_ptr;
+
+
+//--------------------------------------------------------------
+typedef struct{
+	uint32_t  sessionId;
+} mcDrvCmdCloseSessionPayload_t, *mcDrvCmdCloseSessionPayload_ptr;
+
+typedef struct{
+    mcDrvCommandHeader_t           header;
+    mcDrvCmdCloseSessionPayload_t  payload;
+} mcDrvCmdCloseSession_t, *mcDrvCmdCloseSession_ptr;
+
+
+typedef struct{
+    // empty
+} mcDrvRspCloseSessionPayload_t, *mcDrvRspCloseSessionPayload_ptr;
+
+typedef struct{
+    mcDrvResponseHeader_t         header;
+    mcDrvRspCloseSessionPayload_t  payload;
+} mcDrvRspCloseSession_t, *mcDrvRspCloseSession_ptr;
+
+
+//--------------------------------------------------------------
+typedef struct{
+	uint32_t sessionId;
+} mcDrvCmdNotifyPayload_t, *mcDrvCmdNotifyPayload_ptr;
+
+typedef struct{
+    mcDrvCommandHeader_t     header;
+    mcDrvCmdNotifyPayload_t  payload;
+} mcDrvCmdNotify_t, *mcDrvCmdNotify_ptr;
+
+
+typedef struct{
+    // empty
+} mcDrvRspNotifyPayload_t, *mcDrvRspNotifyPayload_ptr;
+
+typedef struct{
+    mcDrvResponseHeader_t    header;
+    mcDrvRspNotifyPayload_t  payload;
+} mcDrvRspNotify_t, *mcDrvRspNotify_ptr;
+
+
+//--------------------------------------------------------------
+typedef struct{
+	uint32_t  sessionId;
+	uint32_t  pAddrL2;
+	uint32_t  offsetPayload;
+	uint32_t  lenBulkMem;
+} mcDrvCmdMapBulkMemPayload_t, *mcDrvCmdMapBulkMemPayload_ptr;
+
+typedef struct{
+    mcDrvCommandHeader_t         header;
+    mcDrvCmdMapBulkMemPayload_t  payload;
+} mcDrvCmdMapBulkMem_t, *mcDrvCmdMapBulkMem_ptr;
+
+
+typedef struct{
+	uint32_t  sessionId;
+	uint32_t  secureVirtualAdr;
+	uint32_t  mcResult;
+} mcDrvRspMapBulkMemPayload_t, *mcDrvRspMapBulkMemPayload_ptr;
+
+typedef struct{
+    mcDrvResponseHeader_t        header;
+    mcDrvRspMapBulkMemPayload_t  payload;
+} mcDrvRspMapBulkMem_t, *mcDrvRspMapBulkMem_ptr;
+
+
+//--------------------------------------------------------------
+typedef struct{
+	uint32_t  sessionId;
+	uint32_t  secureVirtualAdr;
+	uint32_t  lenBulkMem;
+} mcDrvCmdUnmapBulkMemPayload_t, *mcDrvCmdUnmapBulkMemPayload_ptr;
+
+typedef struct{
+    mcDrvCommandHeader_t           header;
+    mcDrvCmdUnmapBulkMemPayload_t  payload;
+} mcDrvCmdUnmapBulkMem_t, *mcDrvCmdUnmapBulkMem_ptr;
+
+
+typedef struct{
+    uint32_t  responseId;
+	uint32_t  sessionId;
+	uint32_t  mcResult;
+} mcDrvRspUnmapBulkMemPayload_t, *mcDrvRspUnmapBulkMemPayload_ptr;
+
+typedef struct{
+    mcDrvResponseHeader_t          header;
+    mcDrvRspUnmapBulkMemPayload_t  payload;
+} mcDrvRspUnmapBulkMem_t, *mcDrvRspUnmapBulkMem_ptr;
+
+
+//--------------------------------------------------------------
+typedef struct {
+    uint32_t  deviceId;
+    uint32_t  sessionId;
+    uint32_t  deviceSessionId;
+    uint32_t  sessionMagic; //Random data
+} mcDrvCmdNqConnectPayload_t, *mcDrvCmdNqConnectPayload_ptr;
+
+typedef struct {
+    mcDrvCommandHeader_t        header;
+    mcDrvCmdNqConnectPayload_t  payload;
+} mcDrvCmdNqConnect_t, *mcDrvCmdNqConnect_ptr;
+
+
+typedef struct {
+    // empty;
+} mcDrvRspNqConnectPayload_t, *mcDrvRspNqConnectPayload_ptr;
+
+typedef struct{
+    mcDrvResponseHeader_t       header;
+    mcDrvRspNqConnectPayload_t  payload;
+} mcDrvRspNqConnect_t, *mcDrvRspNqConnect_ptr;
+
+//--------------------------------------------------------------
+typedef struct {
+    mcDrvCommandHeader_t        header;
+} mcDrvCmdGetVersion_t, *mcDrvCmdGetVersion_ptr;
+
+
+typedef struct {
+    uint32_t version;
+} mcDrvRspGetVersionPayload_t, *mcDrvRspGetVersionPayload_ptr;
+
+typedef struct{
+    mcDrvResponseHeader_t       header;
+    mcDrvRspGetVersionPayload_t payload;
+} mcDrvRspGetVersion_t, mcDrvRspGetVersion_ptr;
+
+//--------------------------------------------------------------
+typedef struct {
+    mcDrvCommandHeader_t        header;
+} mcDrvCmdGetMobiCoreVersion_t, *mcDrvCmdGetMobiCoreVersion_ptr;
+
+
+typedef struct {
+    uint32_t        mcResult;
+    mcVersionInfo_t versionInfo;
+} mcDrvRspGetMobiCoreVersionPayload_t, *mcDrvRspGetMobiCoreVersionPayload_ptr;
+
+typedef struct{
+    mcDrvResponseHeader_t       header;
+    mcDrvRspGetMobiCoreVersionPayload_t payload;
+} mcDrvRspGetMobiCoreVersion_t, mcDrvRspGetMobiCoreVersion_ptr;
+
+//--------------------------------------------------------------
+typedef union {
+    mcDrvCommandHeader_t         header;
+    mcDrvCmdOpenDevice_t         mcDrvCmdOpenDevice;
+    mcDrvCmdCloseDevice_t        mcDrvCmdCloseDevice;
+    mcDrvCmdOpenSession_t        mcDrvCmdOpenSession;
+    mcDrvCmdCloseSession_t       mcDrvCmdCloseSession;
+    mcDrvCmdNqConnect_t          mcDrvCmdNqConnect;
+    mcDrvCmdNotify_t             mcDrvCmdNotify;
+    mcDrvCmdMapBulkMem_t         mcDrvCmdMapBulkMem;
+    mcDrvCmdUnmapBulkMem_t       mcDrvCmdUnmapBulkMem;
+    mcDrvCmdGetVersion_t         mcDrvCmdGetVersion;
+    mcDrvCmdGetMobiCoreVersion_t mcDrvCmdGetMobiCoreVersion;
+} mcDrvCommand_t, *mcDrvCommand_ptr;
+
+typedef union {
+    mcDrvResponseHeader_t        header;
+    mcDrvRspOpenDevice_t         mcDrvRspOpenDevice;
+    mcDrvRspCloseDevice_t        mcDrvRspCloseDevice;
+    mcDrvRspOpenSession_t        mcDrvRspOpenSession;
+    mcDrvRspCloseSession_t       mcDrvRspCloseSession;
+    mcDrvRspNqConnect_t          mcDrvRspNqConnect;
+    mcDrvRspNotify_t             mcDrvRspNotify;
+    mcDrvRspMapBulkMem_t         mcDrvRspMapBulkMem;
+    mcDrvRspUnmapBulkMem_t       mcDrvRspUnmapBulkMem;
+    mcDrvRspGetVersion_t         mcDrvRspGetVersion;
+    mcDrvRspGetMobiCoreVersion_t mcDrvRspGetMobiCoreVersion;
+} mcDrvResponse_t, *mcDrvResponse_ptr;
+
+#endif /* MCDAEMON_H_ */
+
+/** @} */
diff --git a/mobicore/daemon/Daemon/public/mcVersion.h b/mobicore/daemon/Daemon/public/mcVersion.h
new file mode 100644
index 0000000..e019562
--- /dev/null
+++ b/mobicore/daemon/Daemon/public/mcVersion.h
@@ -0,0 +1,35 @@
+/**
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef DAEMON_VERSION_H_
+#define DAEMON_VERSION_H_
+
+#define DAEMON_VERSION_MAJOR 0
+#define DAEMON_VERSION_MINOR 2
+
+#endif /** DAEMON_VERSION_H_ */
+
diff --git a/mobicore/daemon/Kernel/Android.mk b/mobicore/daemon/Kernel/Android.mk
new file mode 100644
index 0000000..9caae0e
--- /dev/null
+++ b/mobicore/daemon/Kernel/Android.mk
@@ -0,0 +1,38 @@
+# =============================================================================
+#
+# Module: libKernel.a - Kernel module access classes
+#
+# =============================================================================
+
+LOCAL_PATH	:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE	:= libMcKernel
+
+# Include platform specific sub-makefiles
+ifdef PLATFORM
+  include $(LOCAL_PATH)/Platforms/Generic/Android.mk
+  include $(LOCAL_PATH)/Platforms/$(PLATFORM)/Android.mk
+else 
+  include $(LOCAL_PATH)/Platforms/Generic/Android.mk
+endif
+
+# Add new folders with header files here
+LOCAL_C_INCLUDES +=\
+	$(COMP_PATH_MobiCoreDriverMod)/Public \
+	$(APP_PROJECT_PATH)/Common \
+	$(LOCAL_PATH) 
+
+# Add new source files here
+LOCAL_SRC_FILES +=\
+	CKMod.cpp
+
+# Header files for components including this module
+LOCAL_EXPORT_C_INCLUDES	+=\
+	$(LOCAL_PATH)
+
+LOCAL_CPPFLAGS += -fno-rtti -fno-exceptions
+
+include $(COMP_PATH_Logwrapper)/Android.mk
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/mobicore/daemon/Kernel/CKMod.cpp b/mobicore/daemon/Kernel/CKMod.cpp
new file mode 100644
index 0000000..a78b87d
--- /dev/null
+++ b/mobicore/daemon/Kernel/CKMod.cpp
@@ -0,0 +1,122 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_KERNEL
+ * @{
+ * @file
+ *
+ * Kernel Module Interface.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <cstdlib>
+
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <errno.h>
+
+#include "CKMod.h"
+
+#define LOG_TAG	"McDaemon"
+#include "log.h"
+
+
+//------------------------------------------------------------------------------
+CKMod::CKMod(
+    void
+) {
+	fdKMod = ERROR_KMOD_NOT_OPEN;
+}
+
+
+//------------------------------------------------------------------------------
+CKMod::~CKMod(
+    void
+) {
+	close();
+}
+
+
+//------------------------------------------------------------------------------
+bool CKMod::isOpen(
+    void
+) {
+	return (ERROR_KMOD_NOT_OPEN == fdKMod) ? false : true;
+}
+
+
+//------------------------------------------------------------------------------
+bool CKMod::open(
+    const char *deviceName
+) {
+	bool ret = true;
+
+	do
+	{
+		if (isOpen())
+		{
+			LOG_W("already open");
+			ret = false;
+			break;
+		}
+
+		// open return -1 on error, "errno" is set with details
+		int openRet = ::open(deviceName, O_RDWR);
+		if (-1 == openRet)
+		{
+			LOG_E("open failed with errno: %d", errno);
+			ret = false;
+			break;
+		}
+
+		fdKMod = openRet;
+
+	} while(0);
+
+	return ret;
+}
+
+
+//------------------------------------------------------------------------------
+void CKMod::close(
+    void
+) {
+	if (isOpen())
+	{
+		if (0 != ::close(fdKMod))
+		{
+			LOG_E("close failed with errno: %d", errno);
+		}
+		else
+		{
+			fdKMod = ERROR_KMOD_NOT_OPEN;
+		}
+	}
+	else
+	{
+		LOG_W("not open");
+	}
+}
+
+/** @} */
diff --git a/mobicore/daemon/Kernel/CKMod.h b/mobicore/daemon/Kernel/CKMod.h
new file mode 100644
index 0000000..bb1d54d
--- /dev/null
+++ b/mobicore/daemon/Kernel/CKMod.h
@@ -0,0 +1,77 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_KERNEL
+ * @{
+ * @file
+ *
+ * Kernel Module Interface.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef CKMOD_H_
+#define CKMOD_H_
+
+#include <stdint.h>
+
+
+#define ERROR_KMOD_NOT_OPEN          ((int)(-1))
+
+/**
+ * Base class for accessing a kernel module.
+ */
+class CKMod {
+
+protected:
+
+    int  fdKMod;
+
+    /**
+     * Helper function to check if connected to kernel module.
+     */
+    bool isOpen(
+    	void
+	);
+
+public:
+
+    CKMod(
+        void
+    );
+
+    virtual ~CKMod(
+        void
+    );
+
+    bool open(
+        const char *deviceName
+    );
+
+    void close(
+        void
+    );
+
+};
+
+#endif // CKMOD_H_
diff --git a/mobicore/daemon/Kernel/Platforms/Generic/Android.mk b/mobicore/daemon/Kernel/Platforms/Generic/Android.mk
new file mode 100644
index 0000000..ac816f1
--- /dev/null
+++ b/mobicore/daemon/Kernel/Platforms/Generic/Android.mk
@@ -0,0 +1,27 @@
+# =============================================================================
+#
+# Generic  TrustZone device includes
+#
+# =============================================================================
+
+# This is not a separate module.
+# Only for inclusion by other modules.
+
+GENERIC_MODULE_PATH		:= $(call my-dir)
+GENERIC_MODULE_PATH_REL	:= Platforms/Generic
+
+# Add new source files here
+LOCAL_SRC_FILES +=\
+	$(GENERIC_MODULE_PATH_REL)/CMcKMod.cpp
+
+# Add new folders with header files here
+LOCAL_C_INCLUDES +=\
+	$(GENERIC_MODULE_PATH)\
+	$(COMP_PATH_MobiCore)/inc\
+	$(COMP_PATH_MobiCoreDriverMod)/Public
+
+# Header files for components including this module
+LOCAL_EXPORT_C_INCLUDES	+=\
+	$(GENERIC_MODULE_PATH)\
+	$(COMP_PATH_MobiCoreDriverMod)/Public
+	
\ No newline at end of file
diff --git a/mobicore/daemon/Kernel/Platforms/Generic/CMcKMod.cpp b/mobicore/daemon/Kernel/Platforms/Generic/CMcKMod.cpp
new file mode 100644
index 0000000..1973ac1
--- /dev/null
+++ b/mobicore/daemon/Kernel/Platforms/Generic/CMcKMod.cpp
@@ -0,0 +1,566 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_KERNEL
+ * @{
+ * @file
+ *
+ * MobiCore Driver Kernel Module Interface.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <cstdlib>
+
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <cstring>
+
+#include "McTypes.h"
+#include "mc_drv_module_api.h"
+#include "mcVersionHelper.h"
+
+#include "CMcKMod.h"
+
+#define LOG_TAG	"McDaemon"
+#include "log.h"
+
+//------------------------------------------------------------------------------
+MC_CHECK_VERSION(MCDRVMODULEAPI,0,1);
+
+// TODO: rename this to mapWsm
+//------------------------------------------------------------------------------
+int CMcKMod::mmap(
+	uint32_t	len,
+	uint32_t	*pHandle,
+	addr_t		*pVirtAddr,
+	addr_t		*pPhysAddr,
+	bool		*pMciReuse
+) {
+	int ret = 0;
+	do
+	{
+		LOG_I("mmap(): len=%d, mci_reuse=%x", len, *pMciReuse);
+
+		if (!isOpen())
+		{
+	        LOG_E("no connection to kmod");
+	        ret = ERROR_KMOD_NOT_OPEN;
+			break;
+		}
+
+		// TODO: add type parameter to distinguish between non-freeing TCI, MCI and others
+		addr_t virtAddr = ::mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED,
+				fdKMod, *pMciReuse ? MC_DRV_KMOD_MMAP_MCI
+						: MC_DRV_KMOD_MMAP_WSM);
+		if (MAP_FAILED == virtAddr)
+		{
+			LOG_E("mmap() failed with errno: %d", errno);
+			ret = ERROR_MAPPING_FAILED;
+			break;
+		}
+
+		// mapping response data is in the buffer
+		struct mc_mmap_resp *pMmapResp = (struct mc_mmap_resp *) virtAddr;
+
+		*pMciReuse = pMmapResp->is_reused;
+
+		LOG_I("mmap(): virtAddr=%p, handle=%d, phys_addr=%p, is_reused=%s",
+				virtAddr, pMmapResp->handle, (addr_t) (pMmapResp->phys_addr),
+				pMmapResp->is_reused ? "true" : "false");
+
+		if (NULL != pVirtAddr)
+		{
+			*pVirtAddr = virtAddr;
+		}
+
+		if (NULL != pHandle)
+		{
+			*pHandle = pMmapResp->handle;
+		}
+
+		if (NULL != pPhysAddr)
+		{
+			*pPhysAddr = (addr_t) (pMmapResp->phys_addr);
+		}
+
+		// clean memory
+		memset(pMmapResp, 0, sizeof(*pMmapResp));
+
+	} while (0);
+
+	return ret;
+}
+
+
+//------------------------------------------------------------------------------
+int CMcKMod::mapPersistent(
+	uint32_t	len,
+	uint32_t	*pHandle,
+	addr_t		*pVirtAddr,
+	addr_t		*pPhysAddr
+) {
+	int ret = 0;
+	do
+	{
+		LOG_I("mapPersistent(): len=%d", len);
+
+		if (!isOpen())
+		{
+	        LOG_E("no connection to kmod");
+			ret = ERROR_KMOD_NOT_OPEN;
+			break;
+		}
+
+		addr_t virtAddr = ::mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED,
+				fdKMod, MC_DRV_KMOD_MMAP_PERSISTENTWSM);
+
+		if (MAP_FAILED == virtAddr)
+		{
+			LOG_E("mmap() failed with errno: %d", errno);
+			ret = ERROR_MAPPING_FAILED;
+			break;
+		}
+
+		// mapping response data is in the buffer
+		struct mc_mmap_resp *pMmapResp = (struct mc_mmap_resp *) virtAddr;
+
+		LOG_I("mapPersistent(): virtAddr=%p, handle=%d, phys_addr=%p, is_reused=%s",
+				virtAddr, pMmapResp->handle,
+				(addr_t) (pMmapResp->phys_addr),
+				pMmapResp->is_reused ? "true" : "false");
+
+		if (NULL != pVirtAddr)
+		{
+			*pVirtAddr = virtAddr;
+		}
+
+		if (NULL != pHandle)
+		{
+			*pHandle = pMmapResp->handle;
+		}
+
+		if (NULL != pPhysAddr)
+		{
+			*pPhysAddr = (addr_t) (pMmapResp->phys_addr);
+		}
+
+		// clean memory
+		memset(pMmapResp, 0, sizeof(*pMmapResp));
+
+	} while (0);
+
+	return ret;
+}
+
+
+//------------------------------------------------------------------------------
+int CMcKMod::read(
+	addr_t		buffer,
+	uint32_t	len
+) {
+	int ret = 0;
+
+	do
+	{
+		if (!isOpen())
+		{
+	        LOG_E("no connection to kmod");
+			ret = ERROR_KMOD_NOT_OPEN;
+			break;
+		}
+
+		ret = ::read(fdKMod, buffer, len);
+		if(-1 == ret)
+		{
+			LOG_E("read() failed with errno: %d", errno);
+		}
+
+	} while (0);
+
+	return ret;
+}
+
+
+//------------------------------------------------------------------------------
+bool CMcKMod::waitSSIQ(
+	uint32_t *pCnt
+) {
+	int ret = true;
+
+	do
+	{
+		uint32_t cnt;
+		int ret = read(&cnt, sizeof(cnt));
+		if (sizeof(cnt) != ret)
+		{
+			ret = false;
+		}
+
+		if (NULL != pCnt)
+		{
+			*pCnt = cnt;
+		}
+
+	} while (0);
+
+	return ret;
+}
+
+
+//------------------------------------------------------------------------------
+int CMcKMod::fcInit(
+	addr_t		mciBuffer,
+	uint32_t	nqOffset,
+	uint32_t	nqLength,
+	uint32_t	mcpOffset,
+	uint32_t	mcpLength
+) {
+	int ret = 0;
+
+	do
+	{
+		if (!isOpen())
+		{
+			ret = ERROR_KMOD_NOT_OPEN;
+			break;
+		}
+
+		// Init MC with NQ and MCP buffer addresses
+		union mc_ioctl_init_params fcInitParams = {
+		// C++ does not support C99 designated initializers
+				/* .in = */{
+				/* .base = */(uint32_t) mciBuffer,
+				/* .nq_offset = */nqOffset,
+				/* .nq_length = */nqLength,
+				/* .mcp_offset = */mcpOffset,
+				/* .mcp_length = */mcpLength } };
+		ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_FC_INIT, &fcInitParams);
+		if (ret != 0)
+		{
+			LOG_E("IOCTL_FC_INIT failed with ret = %d and errno = %d", ret, errno);
+			break;
+		}
+
+	} while (0);
+
+	return ret;
+}
+
+
+//------------------------------------------------------------------------------
+int CMcKMod::fcInfo(
+	uint32_t	extInfoId,
+	uint32_t	*pState,
+	uint32_t	*pExtInfo
+) {
+	int ret = 0;
+
+	do
+	{
+		if (!isOpen())
+		{
+	        LOG_E("no connection to kmod");
+			ret = ERROR_KMOD_NOT_OPEN;
+			break;
+		}
+
+		// Init MC with NQ and MCP buffer addresses
+		union mc_ioctl_info_params fcInfoParams = {
+		// C++ does not support C99 designated initializers
+				/* .in = */{
+				/* .ext_info_id = */extInfoId } };
+		ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_FC_INFO, &fcInfoParams);
+		if (ret != 0)
+		{
+			LOG_E("IOCTL_FC_INFO failed with ret = %d and errno = %d", ret, errno);
+			break;
+		}
+
+		if (NULL != pState)
+		{
+			*pState = fcInfoParams.out.state;
+		}
+
+		if (NULL != pExtInfo)
+		{
+			*pExtInfo = fcInfoParams.out.ext_info;
+		}
+
+	} while (0);
+
+	return ret;
+}
+
+
+//------------------------------------------------------------------------------
+int CMcKMod::fcYield(
+	void
+) {
+	int ret = 0;
+
+	do
+	{
+		if (!isOpen())
+		{
+	        LOG_E("no connection to kmod");
+			ret = ERROR_KMOD_NOT_OPEN;
+			break;
+		}
+
+		ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_FC_YIELD, NULL);
+		if (ret != 0)
+		{
+			LOG_E("IOCTL_FC_YIELD failed with ret = %d and errno = %d", ret, errno);
+			break;
+		}
+
+	} while (0);
+
+	return ret;
+}
+
+
+//------------------------------------------------------------------------------
+int CMcKMod::fcNSIQ(
+	void
+) {
+	int ret = 0;
+
+	do
+	{
+		if (!isOpen())
+		{
+	        LOG_E("no connection to kmod");
+			ret = ERROR_KMOD_NOT_OPEN;
+			break;
+		}
+
+		ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_FC_NSIQ, NULL);
+		if (ret != 0)
+		{
+			LOG_E("IOCTL_FC_NSIQ failed with ret = %d and errno = %d", ret, errno);
+			break;
+		}
+
+	} while (0);
+
+	return ret;
+}
+
+
+//------------------------------------------------------------------------------
+int CMcKMod::free(
+	uint32_t handle
+) {
+	int ret = 0;
+
+	do
+	{
+		LOG_I("free(): handle=%d", handle);
+
+		if (!isOpen())
+		{
+	        LOG_E("no connection to kmod");
+			ret = ERROR_KMOD_NOT_OPEN;
+			break;
+		}
+
+		union mc_ioctl_free_params freeParams = {
+		// C++ does not support c99 designated initializers
+				/* .in = */{
+				/* .handle = */(uint32_t) handle } };
+
+		ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_FREE, &freeParams);
+		if (0 != ret)
+		{
+			LOG_E("IOCTL_FREE failed with ret = %d and errno = %d", ret, errno);
+			break;
+		}
+
+	} while (0);
+
+	return ret;
+}
+
+
+//------------------------------------------------------------------------------
+int CMcKMod::registerWsmL2(
+	addr_t		buffer,
+	uint32_t	len,
+	uint32_t	pid,
+	uint32_t	*pHandle,
+	addr_t		*pPhysWsmL2
+) {
+	int ret = 0;
+
+	do
+	{
+		LOG_I("registerWsmL2(): buffer=%p, len=%d, pid=%d", buffer, len, pid);
+
+		if (!isOpen())
+		{
+	        LOG_E("no connection to kmod");
+			ret = ERROR_KMOD_NOT_OPEN;
+			break;
+		}
+
+		union mc_ioctl_app_reg_wsm_l2_params params = {
+		// C++ does not support C99 designated initializers
+				/* .in = */{
+				/* .buffer = */(uint32_t) buffer,
+				/* .len = */len,
+				/* .pid = */pid } };
+
+		ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_APP_REGISTER_WSM_L2, &params);
+		if (0 != ret)
+		{
+			LOG_E("IOCTL_APP_REGISTER_WSM_L2 failed with ret = %d and errno = %d", ret, errno);
+			break;
+		}
+
+		LOG_I("WSM L2 phys=%x, handle=%d", params.out.phys_wsm_l2_table,
+				params.out.handle);
+
+		if (NULL != pHandle)
+		{
+			*pHandle = params.out.handle;
+		}
+
+		if (NULL != pPhysWsmL2)
+		{
+			*pPhysWsmL2 = (addr_t) params.out.phys_wsm_l2_table;
+		}
+
+	} while (0);
+
+	return ret;
+}
+
+
+//------------------------------------------------------------------------------
+int CMcKMod::unregisterWsmL2(
+	uint32_t handle
+) {
+	int ret = 0;
+
+	do
+	{
+		LOG_I("unregisterWsmL2(): handle=%d", handle);
+
+		if (!isOpen())
+		{
+	        LOG_E("no connection to kmod");
+			ret = ERROR_KMOD_NOT_OPEN;
+			break;
+		}
+
+		struct mc_ioctl_app_unreg_wsm_l2_params params = {
+		// C++ does not support c99 designated initializers
+				/* .in = */{
+				/* .handle = */handle } };
+
+		int ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_APP_UNREGISTER_WSM_L2, &params);
+		if (0 != ret)
+		{
+			LOG_E("IOCTL_APP_UNREGISTER_WSM_L2 failed with ret = %d and errno = %d", ret, errno);
+			break;
+		}
+
+	} while (0);
+
+	return ret;
+}
+
+//------------------------------------------------------------------------------
+int CMcKMod::fcExecute(
+    addr_t    startAddr,
+    uint32_t  areaLength
+) {
+    int ret = 0;
+    union mc_ioctl_fc_execute_params params = {
+        /*.in =*/ {
+            /*.phys_start_addr = */ (uint32_t)startAddr,
+            /*.length = */ areaLength
+        }
+    };
+    do
+    {
+        if (!isOpen())
+        {
+            LOG_E("no connection to kmod");
+            break;
+        }
+
+        ret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_FC_EXECUTE, &params);
+        if (ret != 0)
+        {
+            LOG_E("IOCTL_FC_EXECUTE failed with ret = %d and errno = %d", ret, errno);
+            break;
+        }
+
+    } while(0);
+
+    return ret;
+}
+//------------------------------------------------------------------------------
+bool CMcKMod::checkKmodVersionOk(
+    void
+) {
+    bool ret = false;
+
+    do
+    {
+        if (!isOpen())
+        {
+            LOG_E("no connection to kmod");
+            break;
+        }
+
+        struct mc_ioctl_get_version_params params;
+
+        int ioret = ioctl(fdKMod, MC_DRV_KMOD_IOCTL_GET_VERSION, &params);
+        if (0 != ioret)
+        {
+            LOG_E("IOCTL_GET_VERSION failed with ret = %d and errno = %d", ret, errno);
+            break;
+        }
+
+        // Run-time check.
+        char* errmsg;
+        if (!checkVersionOkMCDRVMODULEAPI(params.out.kernel_module_version, &errmsg)) {
+            LOG_E("%s", errmsg);
+            break;
+        }
+        LOG_I("%s", errmsg);
+
+        ret = true;
+
+    } while (0);
+
+    return ret;
+}
+
+/** @} */
diff --git a/mobicore/daemon/Kernel/Platforms/Generic/CMcKMod.h b/mobicore/daemon/Kernel/Platforms/Generic/CMcKMod.h
new file mode 100644
index 0000000..fa04bf2
--- /dev/null
+++ b/mobicore/daemon/Kernel/Platforms/Generic/CMcKMod.h
@@ -0,0 +1,145 @@
+/** @addtogroup MCD_MCDIMPL_DAEMON_KERNEL
+ * @{
+ * @file
+ *
+ * MobiCore Driver Kernel Module Interface.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef CMCKMOD_H_
+#define CMCKMOD_H_
+
+#include <stdint.h>
+
+#include "McTypes.h"
+#include "CKMod.h"
+
+
+#define ERROR_MAPPING_FAILED         ((int)(-2))
+
+/**
+ * As this is also used by the ClientLib, we do not use exceptions.
+ */
+class CMcKMod : public CKMod {
+
+public:
+
+    /**
+     * Map data.
+     *
+     * @param len
+     * @param pHandle
+     * @param pVirtAddr
+     * @param pPhysAddr
+     * @param pMciReuse [in|out] set to true [in] for reusing MCI buffer
+     *                 is set to true [out] if MCI buffer has been reused
+     * @return 0 if all went fine
+     * @return ERROR_KMOD_NOT_OPEN
+     * @return ERROR_MAPPING_FAILED
+     */
+    int mmap(
+        uint32_t  len,
+        uint32_t  *pHandle,
+        addr_t    *pVirtAddr,
+        addr_t    *pPhysAddr,
+        bool      *pMciReuse
+    );
+
+    /**
+     * Map persistent WSM which will not be freed up once the calling process dies.
+     */
+    int mapPersistent(
+        uint32_t  		len,
+        uint32_t  		*pHandle,
+        addr_t    		*pVirtAddr,
+        addr_t    		*pPhysAddr
+    );
+
+    int read(
+        addr_t    buffer,
+        uint32_t  len
+    );
+
+    bool waitSSIQ(
+        uint32_t  *pCnt
+    );
+
+    int fcInit(
+        addr_t    mciBuffer,
+        uint32_t  nqOffset,
+        uint32_t  nqLength,
+        uint32_t  mcpOffset,
+        uint32_t  mcpLength
+    );
+
+    int fcInfo(
+        uint32_t  extInfoId,
+        uint32_t  *pState,
+        uint32_t  *pExtInfo
+    );
+
+    int fcYield(
+        void
+    );
+
+    int fcNSIQ(
+        void
+    );
+
+    int free(
+        uint32_t  handle
+    );
+
+    int registerWsmL2(
+        addr_t    buffer,
+        uint32_t  len,
+        uint32_t  pid,
+        uint32_t  *pHandle,
+        addr_t    *pPhysWsmL2
+    );
+
+    int unregisterWsmL2(
+        uint32_t  handle
+    );
+
+    /**
+     * Tell stub to start MobiCore from given physical address
+     */
+    int fcExecute(
+        addr_t    startAddr,
+        uint32_t  areaLength
+    );
+
+    bool checkKmodVersionOk(
+        void
+    );
+
+};
+
+typedef CMcKMod  *CMcKMod_ptr;
+
+#endif // CMCKMOD_H_
diff --git a/mobicore/daemon/PaApi/Android.mk b/mobicore/daemon/PaApi/Android.mk
new file mode 100644
index 0000000..4630bbe
--- /dev/null
+++ b/mobicore/daemon/PaApi/Android.mk
@@ -0,0 +1,35 @@
+# =============================================================================
+#
+# Module: libPaApi(Static and Shared variant)
+#
+# =============================================================================
+
+LOCAL_PATH	:= $(call my-dir)
+
+#Now the Shared Object
+include $(CLEAR_VARS)
+
+LOCAL_MODULE	:= libPaApi
+LOCAL_MODULE_TAGS := eng
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_C_INCLUDES += bionic \
+    external/stlport/stlport
+
+# Add your folders with header files here (absolute paths)
+LOCAL_C_INCLUDES += \
+	$(LOCAL_PATH)/Public \
+	$(COMP_PATH_MobiCore)/inc \
+	$(COMP_PATH_MobiCore)/inc/TlCm \
+	$(APP_PROJECT_PATH)/ClientLib/public
+
+# Add your source files here (relative paths)
+LOCAL_SRC_FILES	+= tlcCmApi.cpp
+
+LOCAL_SHARED_LIBRARIES	+= libMcRegistry libMcClient
+LOCAL_STATIC_LIBRARIES =  libstlport_static
+LOCAL_CPPFLAGS += -fno-rtti -fno-exceptions
+
+include $(COMP_PATH_Logwrapper)/Android.mk
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/mobicore/daemon/PaApi/Public/paApi.h b/mobicore/daemon/PaApi/Public/paApi.h
new file mode 100644
index 0000000..6c30026
--- /dev/null
+++ b/mobicore/daemon/PaApi/Public/paApi.h
@@ -0,0 +1,44 @@
+/**
+ * @file
+ * Proivisioning Agent API.
+ *
+ * This header file describes the Provisioning Agent API.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @defgroup PA_API Provisioning Agent API
+ * @defgroup TLC_CONTENT_MANAGER Content Manager API
+ * @ingroup PA_API
+ *
+ * @defgroup MCD_MCDIMPL_DAEMON_REG Registry API
+ * @ingroup PA_API
+ */
+
+#include "tlcCmApi.h"
+#include "MobiCoreRegistry.h"
+
+
diff --git a/mobicore/daemon/PaApi/Public/tlcCmApi.h b/mobicore/daemon/PaApi/Public/tlcCmApi.h
new file mode 100644
index 0000000..a9ea100
--- /dev/null
+++ b/mobicore/daemon/PaApi/Public/tlcCmApi.h
@@ -0,0 +1,84 @@
+/** @addtogroup TLC_CONTENT_MANAGER
+ * @{
+ * @file
+ * Content Manager API.
+ *
+ * This header file describes the interface to the content management trustlet
+ * connector (Content Manager).
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "MobiCoreDriverApi.h"
+#include "mcUuid.h"
+#include "tlCmApi.h"
+#include "tlCmError.h"
+
+#ifdef __cplusplus
+extern "C" { 
+#endif 
+
+/** Opens a content management session.
+ *
+ * After opening a content management session the content manager is ready to
+ * accecpt content management requests. Upon successful execution, this function
+ * sets the cmp pointer to a content management protocol object that is to be
+ * used for subsequent content management operations.
+ *
+ * @param [out] cmp Content management protocol object.
+ *
+ * @return MC_DRV_OK or error code.
+ */
+mcResult_t cmOpen(cmp_t** cmp);
+
+/** Closes a content management session.
+ *
+ * @return MC_DRV_OK or error code.
+ */
+mcResult_t cmClose(void);
+
+/** Performs a content management operation.
+ *
+ * Executes the command contained in the content management protocol object
+ *
+ * returned from cmOpen. The result of the content management operation is also
+ * conveyed within the CMP object returned from cmOpen, unless the overall
+ * operation was aborted due to a low-level driver error, in which case the
+ * return value of this routine is different to MC_DRV_OK.
+ *
+ * @return Indication as to whether the content management operation was executed.
+ * MC_DRV_OK denotes that the operation was executed (see response contents of
+ * the cmp_t object for details about the result of the operation).
+ */
+mcResult_t cmManage(void);
+
+#ifdef __cplusplus
+}
+#endif 
+
+/** @} */
+
diff --git a/mobicore/daemon/PaApi/tlcCmApi.cpp b/mobicore/daemon/PaApi/tlcCmApi.cpp
new file mode 100644
index 0000000..86f213c
--- /dev/null
+++ b/mobicore/daemon/PaApi/tlcCmApi.cpp
@@ -0,0 +1,122 @@
+/** @addtogroup TLC_CONTENT_MANAGER
+ * @{
+ * @file
+ * Content Manager API (implementation).
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "tlcCmApi.h"
+#include "tlCmUuid.h"
+
+#define LOG_TAG "TlcCmApi"
+#include "log.h"
+
+#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)
+{
+    const mcUuid_t UUID = TL_CM_UUID;
+    mcResult_t result;
+
+    if (NULL == cmp) {
+        LOG_E("Parameter cmp is NULL");
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+
+    result = mcOpenDevice(DEVICE_ID);
+    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);
+    if (MC_DRV_OK != result) {
+        LOG_E("Allocation of CMP WSM failed: %d", result);
+        return result;
+    }
+
+    result = mcOpenSession(&m_sessionHandle, &UUID, (uint8_t *)*cmp, (uint32_t) sizeof(cmp_t));
+    if (MC_DRV_OK != result) {
+        LOG_E("Open session failed: %d", result);
+    }
+
+    return result;
+}
+
+mcResult_t cmClose(void)
+{
+    mcResult_t result;
+
+    if (0 == m_sessionHandle.sessionId) {
+        LOG_E("No session to close!");
+    }
+    result = mcCloseSession(&m_sessionHandle);
+    if (MC_DRV_OK != result) {
+        LOG_E("Closing session failed: %d", result);
+    }
+    result = mcCloseDevice(DEVICE_ID);
+    if (MC_DRV_OK != result) {
+        LOG_E("Closing MobiCore device failed: %d", result);
+    }
+
+    return result;
+}
+
+mcResult_t cmManage(void)
+{
+    mcResult_t result;
+
+    if (0 == m_sessionHandle.sessionId) {
+        LOG_E("No session.");
+        return MC_DRV_ERR_INIT;
+    }
+
+    // Send CMP message to content management trustlet.
+    result = mcNotify(&m_sessionHandle);
+
+    if (MC_DRV_OK != result) {
+        LOG_E("Notify failed: %d", result);
+        return result;
+    }
+
+    // Wait for trustlet response.
+    result = mcWaitNotification(&m_sessionHandle, MC_INFINITE_TIMEOUT);
+
+    if (MC_DRV_OK != result) {
+        LOG_E("Wait for response notification failed: %d", result);
+        return result;
+    }
+
+    return MC_DRV_OK;
+}
+
+/** @} */
diff --git a/mobicore/daemon/Registry/Android.mk b/mobicore/daemon/Registry/Android.mk
new file mode 100644
index 0000000..af396f7
--- /dev/null
+++ b/mobicore/daemon/Registry/Android.mk
@@ -0,0 +1,72 @@
+# =============================================================================
+#
+# Module: libMcRegistry.a - MobiCore driver registry
+#
+# =============================================================================
+
+LOCAL_PATH	:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE	:= libMcRegistry
+
+# Prevent not-yet-used functions of being ignored by linker
+LOCAL_LDLIBS	:= -Wl,-whole-archive
+
+LOCAL_C_INCLUDES += bionic \
+    external/stlport/stlport
+
+# Add new folders with header files here
+LOCAL_C_INCLUDES	+=\
+	$(LOCAL_PATH)/Public\
+	$(MY_CLIENTLIB_PATH)/public\
+	$(COMP_PATH_MobiCore)/inc
+
+# Add new source files here
+LOCAL_SRC_FILES		+= Registry.cpp
+
+# Header files for components including this module
+LOCAL_EXPORT_C_INCLUDES	+=\
+	$(LOCAL_PATH)/Public\
+	$(MY_CLIENTLIB_PATH)/public
+
+LOCAL_CPPFLAGS += -fno-rtti -fno-exceptions
+include $(COMP_PATH_Logwrapper)/Android.mk
+
+include $(BUILD_STATIC_LIBRARY)
+
+##################################################
+## Shared Object
+##################################################
+include $(CLEAR_VARS)
+
+LOCAL_MODULE	:= libMcRegistry
+LOCAL_MODULE_TAGS := eng
+LOCAL_PRELINK_MODULE := false
+
+# Prevent not-yet-used functions of being ignored by linker
+LOCAL_LDLIBS	:= -Wl,-whole-archive
+
+LOCAL_C_INCLUDES += bionic \
+    external/stlport/stlport
+
+# Add new folders with header files here
+LOCAL_C_INCLUDES	+=\
+	$(LOCAL_PATH)/Public\
+	$(MY_CLIENTLIB_PATH)/public\
+	$(COMP_PATH_MobiCore)/inc
+
+# Add new source files here
+LOCAL_SRC_FILES		+= Registry.cpp
+
+# Header files for components including this module
+LOCAL_EXPORT_C_INCLUDES	+=\
+	$(LOCAL_PATH)/Public\
+	$(MY_CLIENTLIB_PATH)/public
+
+LOCAL_STATIC_LIBRARIES = libstlport_static
+LOCAL_CPPFLAGS += -fno-rtti -fno-exceptions
+
+include $(COMP_PATH_Logwrapper)/Android.mk
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/mobicore/daemon/Registry/Public/MobiCoreRegistry.h b/mobicore/daemon/Registry/Public/MobiCoreRegistry.h
new file mode 100644
index 0000000..96ca810
--- /dev/null
+++ b/mobicore/daemon/Registry/Public/MobiCoreRegistry.h
@@ -0,0 +1,178 @@
+/**
+ * @addtogroup MCD_MCDIMPL_DAEMON_REG
+ * @{
+ * G&D MobiCore Registry
+ *
+ * @file
+ * Mobicore Driver Registry.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef MOBICORE_REGISTRY_H_
+#define MOBICORE_REGISTRY_H_
+
+#include "MobiCoreDriverApi.h"
+#include "mcContainer.h"
+
+#ifdef __cplusplus
+extern "C" { 
+#endif 
+
+/**
+ * Registry object.
+ */
+typedef struct {
+    uint32_t len;
+    uint8_t value[];
+} regObject_t;
+
+/** Maximum size of a trustlet in bytes. */
+#define MAX_TL_SIZE     (1 * 1024 * 1024)   
+
+//-----------------------------------------------------------------
+
+/** Stores an authentication token in registry.
+ * @param  so Authentication token secure object.
+ * @return MC_DRV_OK if successful, otherwise error code.
+ */
+mcResult_t mcRegistryStoreAuthToken(const mcSoAuthTokenCont_t *so);
+
+/** Reads an authentication token from registry.
+ * @param[out] so Authentication token secure object.
+ * @return MC_DRV_OK if successful, otherwise error code.
+ */
+mcResult_t mcRegistryReadAuthToken(mcSoAuthTokenCont_t *so);
+
+/** Deletes the authentication token secure object from the registry.
+ * @return MC_DRV_OK if successful, otherwise error code.
+ */
+mcResult_t mcRegistryDeleteAuthToken(void);
+
+/** Stores a root container secure object in the registry.
+ * @param so Root container secure object.
+ * @return MC_DRV_OK if successful, otherwise error code.
+ */
+mcResult_t mcRegistryStoreRoot(const mcSoRootCont_t *so);
+
+/** Reads a root container secure object from the registry.
+ * @param[out] so Root container secure object.
+ * @return MC_DRV_OK if successful, otherwise error code.
+ */
+mcResult_t mcRegistryReadRoot(mcSoRootCont_t *so);
+
+/** Stores a service provider container secure object in the registry.
+ * @param spid Service provider ID.
+ * @param so Service provider container secure object.
+ * @return MC_DRV_OK if successful, otherwise error code.
+ */
+mcResult_t mcRegistryStoreSp(mcSpid_t spid, const mcSoSpCont_t *so);
+
+/** Reads a service provider container secure object from the registry.
+ * @param spid Service provider ID.
+ * @param[out] so Service provider container secure object.
+ * @return MC_DRV_OK if successful, otherwise error code.
+ */
+mcResult_t mcRegistryReadSp(mcSpid_t spid, mcSoSpCont_t *so);
+
+/** Deletes a service provider recursively, including all trustlets and
+ * data.
+ * @param spid Service provider ID.
+ * @return MC_DRV_OK if successful, otherwise error code.
+ */
+mcResult_t mcRegistryCleanupSp(mcSpid_t spid);
+
+/** Stores a trustlet container secure object in the registry.
+ * @param uuid Trustlet UUID.
+ * @param so Trustlet container secure object.
+ * @return MC_DRV_OK if successful, otherwise error code.
+ */
+mcResult_t mcRegistryStoreTrustletCon(const mcUuid_t *uuid, const mcSoTltCont_t *so);
+
+/** Reads a trustlet container secure object from the registry.
+ * @param uuid Trustlet UUID.
+ * @param[out] so Trustlet container secure object.
+ * @return MC_DRV_OK if successful, otherwise error code.
+ */
+mcResult_t mcRegistryReadTrustletCon(const mcUuid_t *uuid, mcSoTltCont_t *so);
+
+/** Deletes a trustlet container secure object and all of its associated data.
+ * @param uuid Trustlet UUID.
+ * @return MC_DRV_OK if successful, otherwise error code.
+ */
+mcResult_t mcRegistryCleanupTrustlet(const mcUuid_t *uuid);
+
+/** Stores a data container secure object in the registry.
+ * @param so Data container secure object.
+ * @return MC_DRV_OK if successful, otherwise error code.
+ */
+mcResult_t mcRegistryStoreData(const mcSoDataCont_t *so);
+
+/** Reads a data container secure object from the registry.
+ * @param context (service provider = 0; trustlet = 1).
+ * @param cid Service provider or UUID.
+ * @param pid Personalization data identifier.
+ * @param[out] so Data container secure object.
+ * @param maxLen Maximum size (in bytes) of the destination buffer (so).
+ * @return MC_DRV_OK if successful, otherwise error code.
+ */
+mcResult_t mcRegistryReadData(
+    uint32_t context,
+    const mcCid_t *cid,
+    mcPid_t pid,
+    mcSoDataCont_t *so,
+    uint32_t maxLen
+);
+
+/** Deletes the root container and all of its associated service provider
+ * containers.
+ * @return MC_DRV_OK if successful, otherwise error code.
+ */
+mcResult_t mcRegistryCleanupRoot(void);
+
+/** Returns a registry object for a given service.
+ * @param uuid service UUID
+ * @return Registry object.
+ * @note It is the responsibility of the caller to free the registry object
+ * allocated by this function.
+ */
+regObject_t *mcRegistryGetServiceBlob(const mcUuid_t  *uuid);
+
+/** Returns a registry object for a given service.
+ * @param driverFilename driver filename
+ * @return Registry object.
+ * @note It is the responsibility of the caller to free the registry object
+ * allocated by this function.
+ */
+regObject_t *mcRegistryGetDriverBlob(const char *driverFilename);
+
+#ifdef __cplusplus
+}
+#endif 
+
+#endif // MOBICORE_REGISTRY_H_
+
+/** @} */
diff --git a/mobicore/daemon/Registry/Registry.cpp b/mobicore/daemon/Registry/Registry.cpp
new file mode 100644
index 0000000..4d7fb8d
--- /dev/null
+++ b/mobicore/daemon/Registry/Registry.cpp
@@ -0,0 +1,898 @@
+/** Mobicore Driver Registry.
+ *
+ * Implements the MobiCore driver registry which maintains trustlets.
+ *
+ * @file
+ * @ingroup MCD_MCDIMPL_DAEMON_REG
+ * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "MobiCoreRegistry.h"
+#include <stdlib.h>
+#include <dirent.h>
+#include <fstream>
+#include <sys/stat.h>
+#include <assert.h>
+#include <string>
+#include <cstring>
+#include <cstddef>
+#include "mcLoadFormat.h"
+#include "mcSpid.h"
+#include "mcVersionHelper.h"
+
+#define LOG_TAG "McDaemon"
+#include "log.h"
+
+MC_CHECK_DATA_OBJECT_VERSION(MCLF, 2, 0);
+MC_CHECK_DATA_OBJECT_VERSION(CONTAINER, 2, 0);
+
+// Asserts expression at compile-time (to be used within a function body).
+#define ASSERT_STATIC(e) do { enum { assert_static__ = 1 / (e) }; } while (0)
+
+using namespace std;
+
+static const string MC_REGISTRY_DEFAULT_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_REGISTRY_PATH = "MC_REGISTRY_PATH";
+static const string ENV_MC_REGISTRY_FALLBACK_PATH = "MC_REGISTRY_FALLBACK_PATH";
+static const string ENV_MC_AUTH_TOKEN_PATH = "MC_AUTH_TOKEN_PATH";
+
+static const string getRegistryPath();
+static const string getAuthTokenFilePath();
+static const string getRootContFilePath();
+static const string getSpDataPath(mcSpid_t spid);
+static const string getSpContFilePath(mcSpid_t spid);
+static const string getTlContFilePath(const mcUuid_t* uuid);
+static const string getTlDataPath(const mcUuid_t* uuid);
+static const string getTlDataFilePath(const mcUuid_t* uuid, mcPid_t pid);
+static const string getTlBinFilePath(const mcUuid_t* uuid);
+
+static const string uint32ToString(mcSpid_t spid);
+static const string byteArrayToString(const void* bytes, size_t elems);
+static bool doesDirExist(const char* path);
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryStoreAuthToken(
+	const mcSoAuthTokenCont_t *so
+) {
+    if (NULL == so) {
+        LOG_E("mcRegistry store So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    if (CONT_TYPE_SOC != so->coSoc.type) {
+        LOG_E("mcRegistry store So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    const string& authTokenFilePath = getAuthTokenFilePath();
+    LOG_I("store AuthToken: %s", authTokenFilePath.c_str());
+    fstream fs(authTokenFilePath.c_str(), ios_base::out | ios_base::binary);
+    if (!fs) {
+        LOG_E("mcRegistry store So.Soc failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+    fs.seekg(0, ios::beg);
+    fs.write((char *)so, sizeof(mcSoAuthTokenCont_t));
+    fs.flush();
+    fs.close();
+    return MC_DRV_OK;
+}
+
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryReadAuthToken(
+	mcSoAuthTokenCont_t *so
+) {
+    if (NULL == so) {
+        LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    const string& authTokenFilePath = getAuthTokenFilePath();
+    LOG_I("read AuthToken: %s", authTokenFilePath.c_str());
+    fstream fs(authTokenFilePath.c_str(), ios_base::in | ios_base::binary);
+    if (!fs) {
+        LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+    fs.seekg(0, ios::end);
+    int32_t filesize = fs.tellg();
+    if (sizeof(mcSoAuthTokenCont_t) != filesize) {
+        fs.close();
+        LOG_E("mcRegistry read So.Soc failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES);
+        return MC_DRV_ERR_OUT_OF_RESOURCES;
+    }
+    fs.seekg(0, ios::beg);
+    fs.read((char *)so, sizeof(mcSoAuthTokenCont_t));
+    fs.close();
+    return MC_DRV_OK;
+}
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryDeleteAuthToken(
+	void
+) {
+    remove(getAuthTokenFilePath().c_str());
+    // @TODO: is return to check ?
+    return MC_DRV_OK;
+}
+
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryStoreRoot(
+	const mcSoRootCont_t *so
+) {
+    if (NULL == so) {
+        LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    if(CONT_TYPE_ROOT != so->cont.type) {
+        LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    const string& rootContFilePath = getRootContFilePath();
+    LOG_I("store Root: %s", rootContFilePath.c_str());
+    fstream fs(rootContFilePath.c_str(), ios_base::out | ios_base::binary);
+    if (!fs) {
+        LOG_E("mcRegistry store So.Root failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+    fs.seekg(0, ios::beg);
+    fs.write((char *)so, sizeof(mcSoRootCont_t));
+    fs.flush();
+    fs.close();
+    return MC_DRV_OK;
+}
+
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryReadRoot(
+	mcSoRootCont_t *so
+) {
+    if (NULL == so) {
+        LOG_E("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    const string& rootContFilePath = getRootContFilePath();
+    LOG_I("read Root: %s", rootContFilePath.c_str());
+    fstream fs(rootContFilePath.c_str(), ios_base::in | ios_base::binary);
+    if (!fs) {
+        LOG_E("mcRegistry read So.Root failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+    fs.seekg(0, ios::end);
+    int32_t filesize = fs.tellg();
+    if (sizeof(mcSoRootCont_t) != filesize) {
+        fs.close();
+        LOG_E("mcRegistry read So.Root failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES);
+        return MC_DRV_ERR_OUT_OF_RESOURCES;
+    }
+    fs.seekg(0, ios::beg);
+    fs.read((char *)so, sizeof(mcSoRootCont_t));
+    fs.close();
+    return MC_DRV_OK;
+}
+
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryStoreSp(
+	mcSpid_t			spid,
+	const mcSoSpCont_t	*so
+) {
+    if ((0 == spid) || (NULL == so)) {
+        LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    if(CONT_TYPE_SP != so->cont.type) {
+        LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    const string& spContFilePath = getSpContFilePath(spid);
+    LOG_I("store SP: %s", spContFilePath.c_str());
+    fstream fs(spContFilePath.c_str(), ios_base::out | ios_base::binary);
+    if (!fs) {
+        LOG_E("mcRegistry store So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+    fs.seekg(0, ios::beg);
+    fs.write((char *)so, sizeof(mcSoSpCont_t));
+    fs.flush();
+    fs.close();
+    return MC_DRV_OK;
+}
+
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryReadSp(
+	mcSpid_t		spid,
+	mcSoSpCont_t	*so
+) {
+    if ((0 == spid) || (NULL == so)) {
+        LOG_E("mcRegistry read So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    const string& spContFilePath = getSpContFilePath(spid);
+    LOG_I("read SP: %s", spContFilePath.c_str());
+    fstream fs(spContFilePath.c_str(), ios_base::in | ios_base::binary);
+    if (!fs) {
+        LOG_E("mcRegistry read So.Sp(SpId) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+    fs.seekg(0, ios::end);
+    int32_t filesize = fs.tellg();
+    if (sizeof(mcSoSpCont_t) != filesize) {
+        fs.close();
+        LOG_E("mcRegistry read So.Sp(SpId) failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES);
+        return MC_DRV_ERR_OUT_OF_RESOURCES;
+    }
+    fs.seekg(0, ios::beg);
+    fs.read((char *)so, sizeof(mcSoSpCont_t));
+    fs.close();
+    return MC_DRV_OK;
+}
+
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryStoreTrustletCon(
+	const mcUuid_t		*uuid,
+	const mcSoTltCont_t	*so
+) {
+    if ((NULL == uuid) || (NULL == so)) {
+        LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    if(CONT_TYPE_TLCON != so->cont.type) {
+        LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    const string& tlContFilePath = getTlContFilePath(uuid);
+    LOG_I("store TLc: %s", tlContFilePath.c_str());
+    fstream fs(tlContFilePath.c_str(), ios_base::out | ios_base::binary);
+    if (!fs) {
+        LOG_E("mcRegistry store So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+    fs.seekg(0, ios::beg);
+    fs.write((char *)so, sizeof(mcSoTltCont_t));
+    fs.flush();
+    fs.close();
+    return MC_DRV_OK;
+}
+
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryReadTrustletCon(
+	const mcUuid_t	*uuid,
+	mcSoTltCont_t	*so
+) {
+    if ((NULL == uuid) || (NULL == so)) {
+        LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    const string& tlContFilePath = getTlContFilePath(uuid);
+    LOG_I("read TLc: %s", tlContFilePath.c_str());
+    fstream fs(tlContFilePath.c_str(), ios_base::in | ios_base::binary);
+    if (!fs) {
+        LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+    fs.seekg(0, ios::end);
+    int32_t filesize = fs.tellg();
+    if (sizeof(mcSoTltCont_t) != filesize) {
+        fs.close();
+        LOG_E("mcRegistry read So.TrustletCont(uuid) failed: %d. Size=%i, expected=%i", MC_DRV_ERR_OUT_OF_RESOURCES,filesize,sizeof(mcSoTltCont_t));
+        return MC_DRV_ERR_OUT_OF_RESOURCES;
+    }
+    fs.seekg(0, ios::beg);
+    fs.read((char *)so, sizeof(mcSoTltCont_t));
+    fs.close();
+    return MC_DRV_OK;
+}
+
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryStoreData(
+	const mcSoDataCont_t *so
+) {
+    if (NULL == so) {
+        LOG_E("mcRegistry store So.Data failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    string pathname, filename;
+
+    switch (so->cont.type) {
+    case CONT_TYPE_SPDATA:
+        LOG_E("SPDATA not supported");
+        return MC_DRV_ERR_INVALID_PARAMETER;
+        break;
+    case CONT_TYPE_TLDATA:
+        pathname = getTlDataPath(&so->cont.uuid);
+        filename = getTlDataFilePath(&so->cont.uuid, so->cont.pid);
+        break;
+    default:
+        LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    mkdir(pathname.c_str(), 0777);
+
+    LOG_I("store DT: %s", filename.c_str());
+    fstream fs(filename.c_str(), ios_base::out | ios_base::binary);
+    if (!fs) {
+        LOG_E("mcRegistry store So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+    fs.seekg(0, ios::beg);
+    fs.write((char *)so, MC_SO_SIZE(so->soHeader.plainLen, so->soHeader.encryptedLen));
+    fs.flush();
+    fs.close();
+    return MC_DRV_OK;
+}
+
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryReadData(
+	uint32_t		context,
+	const mcCid_t	*cid,
+	mcPid_t 		pid,
+	mcSoDataCont_t	*so,
+	uint32_t		maxLen
+) {
+    if ((NULL == cid) || (NULL == so)) {
+        LOG_E("mcRegistry read So.Data failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    string filename;
+    switch (context) {
+    case 0:
+        LOG_E("SPDATA not supported");
+        return MC_DRV_ERR_INVALID_PARAMETER;
+        break;
+    case 1:
+        filename = getTlDataFilePath(&so->cont.uuid, so->cont.pid);
+        break;
+    default:
+        LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    LOG_I("read DT: %s", filename.c_str());
+    fstream fs(filename.c_str(), ios_base::in | ios_base::binary);
+    if (!fs) {
+        LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_INVALID_DEVICE_FILE);
+        return MC_DRV_ERR_INVALID_DEVICE_FILE;
+    }
+    fs.seekg(0, ios::end);
+    uint32_t filesize = fs.tellg();
+    if (maxLen < filesize) {
+        fs.close();
+        LOG_E("mcRegistry read So.Data(cid/pid) failed: %d", MC_DRV_ERR_OUT_OF_RESOURCES);
+        return MC_DRV_ERR_OUT_OF_RESOURCES;
+    }
+    fs.seekg(0, ios::beg);
+    char* p = (char*) so;
+    fs.read(p, sizeof(mcSoHeader_t));
+    p += sizeof(mcSoHeader_t);
+    fs.read(p, MC_SO_SIZE(so->soHeader.plainLen, so->soHeader.encryptedLen) - sizeof(mcSoHeader_t));
+    fs.close();
+    return MC_DRV_OK;
+}
+
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryCleanupTrustlet(
+	const mcUuid_t *uuid
+) {
+    DIR            *dp;
+    struct dirent  *de;
+    int             e;
+
+    if (NULL == uuid) {
+        LOG_E("mcRegistry cleanupTrustlet(uuid) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    string pathname = getTlDataPath(uuid);
+    if (NULL != (dp = opendir(pathname.c_str()))) {
+        while (NULL != (de = readdir(dp))) {
+            if (de->d_name[0] != '.') {
+                string dname = pathname + "/" + string (de->d_name);
+                LOG_I("delete DT: %s", dname.c_str());
+                if (0 != (e = remove(dname.c_str()))) {
+                    LOG_E("remove UUID-data %s failed! error: %d", dname.c_str(), e);
+                    return MC_DRV_ERR_UNKNOWN;
+                }
+            }
+        }
+        LOG_I("delete dir: %s", pathname.c_str());
+        if (0 != (e = rmdir(pathname.c_str()))) {
+            LOG_E("remove UUID-dir failed! errno: %d", e);
+            return MC_DRV_ERR_UNKNOWN;
+        }
+    }
+    string tlBinFilePath = getTlBinFilePath(uuid);
+    LOG_I("delete Tlb: %s", tlBinFilePath.c_str());
+    if (0 != (e = remove(tlBinFilePath.c_str()))) {
+        LOG_E("remove Tlb failed! errno: %d", e);
+//        return MC_DRV_ERR_UNKNOWN;     // a trustlet-binary must not be present ! (registered but not usable)
+    }
+    string tlContFilePath = getTlContFilePath(uuid);
+    LOG_I("delete Tlc: %s", tlContFilePath.c_str());
+    if (0 != (e = remove(tlContFilePath.c_str()))) {
+        LOG_E("remove Tlc failed! errno: %d", e);
+        return MC_DRV_ERR_UNKNOWN;
+    }
+    return MC_DRV_OK;
+}
+
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryCleanupSp(
+	mcSpid_t spid
+) {
+    mcResult_t      ret;
+    mcSoSpCont_t    data;
+    uint32_t        i;
+    DIR            *dp;
+    struct dirent  *de;
+    int             e;
+
+    if (0 == spid) {
+        LOG_E("mcRegistry cleanupSP(SpId) failed: %d", MC_DRV_ERR_INVALID_PARAMETER);
+        return MC_DRV_ERR_INVALID_PARAMETER;
+    }
+    ret = mcRegistryReadSp(spid, &data);
+    if (MC_DRV_OK != ret) {
+        LOG_E("read SP->UUID aborted! Return code: %d", ret);
+        return ret;
+    }
+    for (i = 0; (i < MC_CONT_CHILDREN_COUNT) && (ret == MC_DRV_OK); i++) {
+        if (0 != strncmp((const char *)&(data.cont.children[i]), (const char *)&MC_UUID_FREE, sizeof(mcUuid_t))) {
+            ret = mcRegistryCleanupTrustlet(&(data.cont.children[i]));
+        }
+    }
+    if (MC_DRV_OK != ret) {
+        LOG_E("delete SP->UUID failed! Return code: %d", ret);
+        return ret;
+    }
+    string pathname = getSpDataPath(spid);
+
+    if (NULL != (dp = opendir(pathname.c_str()))) {
+        while (NULL != (de = readdir(dp))) {
+            if (de->d_name[0] != '.') {
+                string dname = pathname + "/" + string (de->d_name);
+                LOG_I("delete DT: %s", dname.c_str());
+                if (0 != (e = remove(dname.c_str()))) {
+                    LOG_E("remove SPID-data %s failed! error: %d", dname.c_str(), e);
+                    return MC_DRV_ERR_UNKNOWN;
+                }
+            }
+        }
+        LOG_I("delete dir: %s", pathname.c_str());
+        if (0 != (e = rmdir(pathname.c_str()))) {
+            LOG_E("remove SPID-dir failed! error: %d", e);
+            return MC_DRV_ERR_UNKNOWN;
+        }
+    }
+    string spContFilePath = getSpContFilePath(spid);
+    LOG_I("delete Sp: %s", spContFilePath.c_str());
+    if (0 != (e = remove(spContFilePath.c_str()))) {
+        LOG_E("remove SP failed! error: %d", e);
+        return MC_DRV_ERR_UNKNOWN;
+    }
+    return MC_DRV_OK;
+}
+
+
+//------------------------------------------------------------------------------
+mcResult_t mcRegistryCleanupRoot(void) {
+    mcResult_t ret;
+    mcSoRootCont_t data;
+    uint32_t i;
+    int e;
+
+    ret = mcRegistryReadRoot(&data);
+    if (MC_DRV_OK != ret) {
+        LOG_E("read Root aborted! Return code: %d", ret);
+        return ret;
+    }
+    for (i = 0; (i < MC_CONT_CHILDREN_COUNT) && (ret == MC_DRV_OK); i++) {
+        mcSpid_t spid = data.cont.children[i];
+        if (spid != MC_SPID_FREE) {
+            ret = mcRegistryCleanupSp(spid);
+            if (MC_DRV_OK != ret) {
+                LOG_E("Cleanup SP failed! Return code: %d", ret);
+                return ret;
+            }
+        }
+    }
+
+    string rootContFilePath = getRootContFilePath();
+    LOG_I("Delete root: %s", rootContFilePath.c_str());
+    if (0 != (e = remove(rootContFilePath.c_str()))) {
+        LOG_E("Delete root failed! error: %d", e);
+        return MC_DRV_ERR_UNKNOWN;
+    }
+    return MC_DRV_OK;
+}
+
+
+//------------------------------------------------------------------------------
+regObject_t *mcRegistryGetServiceBlob(
+	const mcUuid_t *uuid
+) {
+    regObject_t* regobj = NULL;
+
+    // Ensure that a UUID is provided.
+    if (NULL == uuid) {
+        LOG_E("mcRegistryGetServiceBlob() failed. No UUID given");
+        return NULL;
+    }
+
+    // Open service blob file.
+    string tlBinFilePath = getTlBinFilePath(uuid);
+    LOG_I("mcRegistryGetServiceBlob() Loading service: %s", tlBinFilePath.c_str());
+
+    ifstream fs(tlBinFilePath.c_str(), ios_base::binary);
+    if (!fs) {
+        LOG_E("mcRegistryGetServiceBlob() failed: cannot open %s", tlBinFilePath.c_str());
+        return NULL;
+    }
+
+    // Determine and check service blob size.
+    fs.seekg(0, ios::end);
+    int32_t tlSize = fs.tellg();
+    fs.seekg(0, ios::beg);
+    if (MAX_TL_SIZE < tlSize) {
+        LOG_E("mcRegistryGetServiceBlob() failed: service blob too big: %d", tlSize);
+        return NULL;
+    }
+
+    // Check TL magic value.
+    fs.seekg(offsetof(mclfIntro_t, magic), ios::beg);
+    uint32_t magic;
+    fs.read((char*)&magic, sizeof(magic));
+    if (magic != MC_SERVICE_HEADER_MAGIC_BE) {
+        LOG_E("mcRegistryGetServiceBlob() failed: wrong header magic value: %d", magic);
+        return NULL;
+    }
+
+    // Check header version.
+    fs.seekg(offsetof(mclfIntro_t, version), ios::beg);
+    uint32_t version;
+    fs.read((char*)&version, sizeof(version));
+
+    char* msg;
+    if (!checkVersionOkDataObjectMCLF(version, &msg)) {
+		LOG_E("mcRegistryGetDriverBlob() failed: Trustlet header incompatible with MobiCore interface version. Check your SDK version!");
+		// msg is null for release version
+		LOG_E("%s", msg);
+		return NULL;
+    }
+
+    // Get service type.
+    fs.seekg(offsetof(mclfHeaderV1_t, serviceType), ios::beg);
+    serviceType_t serviceType;
+    fs.read((char*)&serviceType, sizeof(serviceType));
+    fs.seekg(0, ios::beg);
+
+    LOG_I("mcRegistryGetServiceBlob() Service is of type: %d", serviceType);
+
+    // If loadable driver or system trustlet.
+    if (SERVICE_TYPE_DRIVER == serviceType || SERVICE_TYPE_SYSTEM_TRUSTLET == serviceType) {
+        // Take trustlet blob 'as is'.
+        if (NULL == (regobj = (regObject_t*) (malloc(sizeof(regObject_t) + tlSize)))) {
+            LOG_E("mcRegistryGetServiceBlob() failed: Out of memory");
+            return NULL;
+        }
+        regobj->len = tlSize;
+        fs.read((char *)regobj->value, tlSize);
+        fs.close();
+    // If user trustlet.
+    } else if (SERVICE_TYPE_SP_TRUSTLET == serviceType) {
+        // Take trustlet blob and append root, sp, and tl container.
+        size_t regObjValueSize = tlSize + sizeof(mcSoContainerPath_t);
+
+        // Prepare registry object.
+        if (NULL == (regobj = (regObject_t*) malloc(sizeof(regObject_t) + regObjValueSize))) {
+            LOG_E("mcRegistryGetServiceBlob() failed: Out of memory");
+            return NULL;
+        }
+        regobj->len = regObjValueSize;
+
+        // Read and fill in trustlet blob at beginning.
+        fs.read((char*)regobj->value, tlSize);
+        fs.close();
+
+        // Goto end of allocated space and fill in tl container, sp container,
+        // and root container from back to front. Final registry object value
+        // looks like this:
+        // 
+        //    +---------------------------+-----------+---------+---------+
+        //    | TL-Header TL-Code TL-Data | Root Cont | SP Cont | TL Cont |
+        //    +---------------------------+-----------+-------------------+
+        //    /------ Trustlet BLOB ------/
+        //
+        //    /------------------ regobj->header.len ---------------------/
+
+        uint8_t* p = regobj->value + regobj->len;
+        mcResult_t ret;
+        do {
+            char* msg;
+
+            // Fill in TL container.
+            p -= sizeof(mcSoTltCont_t);
+            mcSoTltCont_t* soTlt = (mcSoTltCont_t*)p;
+            if (MC_DRV_OK != (ret = mcRegistryReadTrustletCon(uuid, soTlt))) {
+                break;
+            }
+            mcTltCont_t* tltCont = &soTlt->cont;
+            if (!checkVersionOkDataObjectCONTAINER(tltCont->version, &msg)) {
+                LOG_E("Tlt container %s", msg);
+                ret = MC_DRV_ERR_CONTAINER_VERSION;
+                break;
+            }
+
+            // Fill in SP container.
+            mcSpid_t spid = tltCont->parent;
+            p -= sizeof(mcSoSpCont_t);
+            mcSoSpCont_t* soSp = (mcSoSpCont_t*)p;
+            if (MC_DRV_OK != (ret = mcRegistryReadSp(spid, soSp))) {
+                break;
+            }
+            mcSpCont_t* spCont = &soSp->cont;
+            if (!checkVersionOkDataObjectCONTAINER(spCont->version, &msg)) {
+                LOG_E("SP container %s", msg);
+                ret = MC_DRV_ERR_CONTAINER_VERSION;
+                break;
+            }
+
+            // Fill in root container.
+            p -= sizeof(mcSoRootCont_t);
+            mcSoRootCont_t* soRoot = (mcSoRootCont_t*)p;
+            if (MC_DRV_OK != (ret = mcRegistryReadRoot(soRoot))) {
+                break;
+            }
+            mcRootCont_t* rootCont = &soRoot->cont;
+            if (!checkVersionOkDataObjectCONTAINER(rootCont->version, &msg)) {
+                LOG_E("Root container %s", msg);
+                ret = MC_DRV_ERR_CONTAINER_VERSION;
+                break;
+            }
+
+            // Ensure order of elements in registry object value.
+            assert(p - tlSize - sizeof(regObject_t) == (uint8_t*)regobj);
+        } while (false);
+
+        if (MC_DRV_OK != ret) {
+            LOG_E("mcRegistryGetServiceBlob() failed: Error code: %d", ret);
+            free(regobj);
+            return NULL;
+        }
+    // Any other service type.
+    } else {
+        LOG_E("mcRegistryGetServiceBlob() failed: Unsupported service type %u", serviceType);
+    }
+
+    return regobj;
+}
+
+//------------------------------------------------------------------------------
+regObject_t *mcRegistryGetDriverBlob(
+	const char *driverFilename
+) {
+	regObject_t* regobj = NULL;
+	
+	// Open service blob file.
+	ifstream fs(driverFilename, ios_base::binary);
+	if (!fs) {
+		LOG_E("mcRegistryGetDriverBlob() failed: cannot open %s", driverFilename);
+		return NULL;
+	}
+	
+	// Determine and check service blob size.
+	fs.seekg(0, ios::end);
+	int32_t tlSize = fs.tellg();
+	fs.seekg(0, ios::beg);
+	if (MAX_TL_SIZE < tlSize) {
+		LOG_E("mcRegistryGetDriverBlob() failed: service blob too big: %d", tlSize);
+		return NULL;
+	}
+	
+	// Check TL magic value.
+	fs.seekg(offsetof(mclfIntro_t, magic), ios::beg);
+	uint32_t magic;
+	fs.read((char*)&magic, sizeof(magic));
+	if (magic != MC_SERVICE_HEADER_MAGIC_BE) {
+		LOG_E("mcRegistryGetDriverBlob() failed: wrong header magic value: %d", magic);
+		return NULL;
+	}
+	
+	// Check header version.
+	fs.seekg(offsetof(mclfIntro_t, version), ios::beg);
+	uint32_t version;
+	fs.read((char*)&version, sizeof(version));
+
+    char* msg;
+    if (!checkVersionOkDataObjectMCLF(version, &msg)) {
+		LOG_E("mcRegistryGetDriverBlob() failed: Driver header incompatible with MobiCore interface version. Check your SDK version!");
+		// msg is null for release version
+		LOG_E("%s", msg);
+		return NULL;
+    }
+	
+	// Get service type.
+	fs.seekg(offsetof(mclfHeaderV1_t, serviceType), ios::beg);
+	serviceType_t serviceType;
+	fs.read((char*)&serviceType, sizeof(serviceType));
+	fs.seekg(0, ios::beg);
+	
+	LOG_I("mcRegistryGetDriverBlob() Service is of type: %d", serviceType);
+	
+	// If loadable driver or system trustlet.
+	if (SERVICE_TYPE_DRIVER == serviceType) {
+		// Take trustlet blob 'as is'.
+		if (NULL == (regobj = (regObject_t*) (malloc(sizeof(regObject_t) + tlSize)))) {
+			LOG_E("mcRegistryGetDriverBlob() failed: Out of memory");
+			return NULL;
+		}
+		regobj->len = tlSize;
+		fs.read((char *)regobj->value, tlSize);
+		fs.close();
+		// Otherwise we are not interested
+	} else {
+		LOG_E("mcRegistryGetServiceBlob() failed: Unsupported service type %u", serviceType);
+	}
+	
+	return regobj;
+}
+
+//------------------------------------------------------------------------------
+static const string getRegistryPath() {
+    const char* path;
+    string registryPath;
+
+    // First, attempt to use regular registry environment variable.
+    path = getenv(ENV_MC_REGISTRY_PATH.c_str());
+    if (doesDirExist(path)) {
+        LOG_I("getRegistryPath(): Using MC_REGISTRY_PATH %s", path);
+        registryPath = path;
+    } else {
+        // Second, attempt to use fallback registry environment variable.
+        path = getenv(ENV_MC_REGISTRY_FALLBACK_PATH.c_str());
+        if (doesDirExist(path)) {
+            LOG_I("getRegistryPath(): Using MC_REGISTRY_FALLBACK_PATH %s", path);
+            registryPath = path;
+        }
+    }
+
+    // As a last resort, use the default registry path.
+    if (registryPath.length() == 0) {
+        registryPath = MC_REGISTRY_DEFAULT_PATH;
+        LOG_I("getRegistryPath(): Using default registry path %s", registryPath.c_str());
+    }
+
+    assert(registryPath.length() != 0);
+    
+    return registryPath;
+}
+
+//------------------------------------------------------------------------------
+static const string getAuthTokenFilePath() {
+    const char* path;
+    string authTokenPath;
+
+    // First, attempt to use regular auth token path environment variable.
+    path = getenv(ENV_MC_AUTH_TOKEN_PATH.c_str());
+    if (doesDirExist(path)) {
+        LOG_I("getAuthTokenFilePath(): Using MC_AUTH_TOKEN_PATH %s", path);
+        authTokenPath = path;
+    } else {
+        authTokenPath = getRegistryPath();
+        LOG_I("getAuthTokenFilePath(): Using path %s", authTokenPath.c_str());
+    }
+
+    return authTokenPath + "/" + AUTH_TOKEN_FILE_NAME;
+}
+
+//------------------------------------------------------------------------------
+static const string getRootContFilePath() {
+    return getRegistryPath() + "/" + ROOT_FILE_NAME;
+}
+
+//------------------------------------------------------------------------------
+static const string getSpDataPath(mcSpid_t spid) {
+    return getRegistryPath() + "/" + uint32ToString(spid);
+}
+
+//------------------------------------------------------------------------------
+static const string getSpContFilePath(mcSpid_t spid) {
+    return getRegistryPath() + "/" + uint32ToString(spid) + SP_CONT_FILE_EXT;
+}
+
+//------------------------------------------------------------------------------
+static const string getTlContFilePath(const mcUuid_t* uuid) {
+    return getRegistryPath() + "/" + byteArrayToString(uuid, sizeof(*uuid)) + TL_CONT_FILE_EXT;
+}
+
+//------------------------------------------------------------------------------
+static const string getTlDataPath(const mcUuid_t* uuid) {
+    return getRegistryPath() + "/" + byteArrayToString(uuid, sizeof(*uuid));
+}
+
+//------------------------------------------------------------------------------
+static const string getTlDataFilePath(const mcUuid_t* uuid, mcPid_t pid) {
+    return getTlDataPath(uuid) + "/" + uint32ToString(pid.data) + DATA_CONT_FILE_EXT;
+}
+
+//------------------------------------------------------------------------------
+static const string getTlBinFilePath(const mcUuid_t* uuid) {
+    return getRegistryPath() + "/" + byteArrayToString(uuid, sizeof(*uuid)) + TL_BIN_FILE_EXT;
+}
+
+//------------------------------------------------------------------------------
+static const string byteArrayToString(const void* bytes, size_t elems) {
+    char hx[elems * 2 + 1];
+
+    for (size_t i = 0; i < elems; i++) {
+		sprintf(&hx[i * 2], "%02x", ((uint8_t*)bytes)[i]);
+	}
+    return string(hx);
+}
+
+//------------------------------------------------------------------------------
+static const string uint32ToString(
+	uint32_t value
+) {
+    char hx[sizeof(uint32_t) * 2 + 1];
+    uint32_t i;
+
+    for (i = 0; i < (2 * sizeof(value)); i++) {
+		hx[i] = (value >> (28 - (i * 4))) & 0x0F;
+		if (hx[i] > 9) {
+			hx[i] = (hx[i] - 9) | 0x40;
+		} else {
+			hx[i] |= 0x30;
+		}
+	}
+    hx[i] = '\0';
+    return string(hx);
+}
+
+//------------------------------------------------------------------------------
+static bool doesDirExist(const char* path) {
+    struct stat ss;
+    if (path != NULL && stat(path, &ss) == 0 && S_ISDIR(ss.st_mode)) {
+        return true;
+    }
+    return false;
+}
+
+
+/** @} */
diff --git a/mobicore/daemon/buildTag.h b/mobicore/daemon/buildTag.h
new file mode 100644
index 0000000..dc1d4b9
--- /dev/null
+++ b/mobicore/daemon/buildTag.h
@@ -0,0 +1 @@
+#define MOBICORE_COMPONENT_BUILD_TAG "*** SAMSUNG Exynos 5250 MC1.2 V002 release ###"
diff --git a/mobicore/include/Public/mc_drv_module_api.h b/mobicore/include/Public/mc_drv_module_api.h
new file mode 100644
index 0000000..8c52ed5
--- /dev/null
+++ b/mobicore/include/Public/mc_drv_module_api.h
@@ -0,0 +1,315 @@
+/** @addtogroup MCD_MCDIMPL_KMOD_API Mobicore Driver Module API
+ * @ingroup  MCD_MCDIMPL_KMOD
+ * @{
+ * Interface to Mobicore Driver Kernel Module.
+ * @file
+ *
+ * <h2>Introduction</h2>
+ * The MobiCore Driver Kernel Module is a Linux device driver, which represents
+ * the command proxy on the lowest layer to the secure world (Swd). Additional
+ * services like memory allocation via mmap and generation of a L2 tables for
+ * given virtual memory are also supported. IRQ functionallity receives
+ * information from the SWd in the non secure world (NWd).
+ * As customary the driver is handled as linux device driver with "open",
+ * "close" and "ioctl" commands. Access to the driver is possible after the
+ * device "/dev/mobicore" has been opened.
+ * The MobiCore Driver Kernel Module must be installed via
+ * "insmod mcDrvModule.ko".
+ *
+ *
+ * <h2>Version history</h2>
+ * <table class="customtab">
+ * <tr><td width="100px"><b>Date</b></td><td width="80px"><b>Version</b></td>
+ * <td><b>Changes</b></td></tr>
+ * <tr><td>2010-05-25</td><td>0.1</td><td>Initial Release</td></tr>
+ * </table>
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2010-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *	notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *	notice, this list of conditions and the following disclaimer in the
+ *	documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *	products derived from this software without specific prior
+ *	written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MC_DRV_MODULEAPI_H_
+#define _MC_DRV_MODULEAPI_H_
+
+#include "version.h"
+
+#define MC_DRV_MOD_DEVNODE		   "mobicore"
+#define MC_DRV_MOD_DEVNODE_FULLPATH  "/dev/" MC_DRV_MOD_DEVNODE
+
+/**
+ * Data exchange structure of the MC_DRV_MODULE_INIT ioctl command.
+ * INIT request data to SWD
+ */
+union mc_ioctl_init_params {
+	struct {
+		/** base address of mci buffer 4KB align */
+		uint32_t  base;
+		/** notification buffer start/length [16:16] [start, length] */
+		uint32_t  nq_offset;
+		/** length of notification queue */
+		uint32_t  nq_length;
+		/** mcp buffer start/length [16:16] [start, length] */
+		uint32_t  mcp_offset;
+		/** length of mcp buffer */
+		uint32_t  mcp_length;
+	} in;
+	struct {
+		/* nothing */
+	} out;
+};
+
+
+/**
+ * Data exchange structure of the MC_DRV_MODULE_INFO ioctl command.
+ * INFO request data to the SWD
+ */
+union mc_ioctl_info_params {
+	struct {
+		uint32_t  ext_info_id; /**< extended info ID */
+	} in;
+	struct {
+		uint32_t  state; /**< state */
+		uint32_t  ext_info; /**< extended info */
+	} out;
+};
+
+/**
+ * Mmap allocates and maps contiguous memory into a process.
+ * We use the third parameter, void *offset, to distinguish between some cases
+ * offset = MC_DRV_KMOD_MMAP_WSM	usual operation, pages are registered in
+ *					device structure and freed later.
+ * offset = MC_DRV_KMOD_MMAP_MCI	get Instance of MCI, allocates or mmaps
+ *					the MCI to daemon
+ * offset = MC_DRV_KMOD_MMAP_PERSISTENTWSM	special operation, without
+ *						registration of pages
+ *
+ * In mmap(), the offset specifies which of several device I/O pages is
+ *  requested. Linux only transfers the page number, i.e. the upper 20 bits to
+ *  kernel module. Therefore we define our special offsets as multiples of page
+ *  size.
+ */
+enum mc_mmap_memtype {
+	MC_DRV_KMOD_MMAP_WSM		= 0,
+	MC_DRV_KMOD_MMAP_MCI		= 4096,
+	MC_DRV_KMOD_MMAP_PERSISTENTWSM	= 8192
+};
+
+struct mc_mmap_resp {
+	uint32_t  handle; /**< WSN handle */
+	uint32_t  phys_addr; /**< physical address of WSM (or NULL) */
+	bool	  is_reused; /**< if WSM memory was reused, or new allocated */
+};
+
+/**
+ * Data exchange structure of the MC_DRV_KMOD_IOCTL_FREE ioctl command.
+ */
+union mc_ioctl_free_params {
+	struct {
+		uint32_t  handle; /**< driver handle */
+		uint32_t  pid; /**< process id */
+	} in;
+	struct {
+		/* nothing */
+	} out;
+};
+
+
+/**
+ * Data exchange structure of the MC_DRV_KMOD_IOCTL_APP_REGISTER_WSM_L2 command.
+ *
+ * Allocates a physical L2 table and maps the buffer into this page.
+ * Returns the physical address of the L2 table.
+ * The page alignment will be created and the appropriated pSize and pOffsetL2
+ * will be modified to the used values.
+ */
+union mc_ioctl_app_reg_wsm_l2_params {
+	struct {
+		uint32_t  buffer; /**< base address of the virtual address  */
+		uint32_t  len; /**< size of the virtual address space */
+		uint32_t  pid; /**< process id */
+	} in;
+	struct {
+		uint32_t  handle; /**< driver handle for locked memory */
+		uint32_t  phys_wsm_l2_table; /* physical address of the L2 table */
+	} out;
+};
+
+
+/**
+ * Data exchange structure of the MC_DRV_KMOD_IOCTL_APP_UNREGISTER_WSM_L2
+ * command.
+ */
+struct mc_ioctl_app_unreg_wsm_l2_params {
+	struct {
+		uint32_t  handle; /**< driver handle for locked memory */
+		uint32_t  pid; /**< process id */
+	} in;
+	struct {
+		/* nothing */
+	} out;
+};
+
+
+/**
+ * Data exchange structure of the MC_DRV_KMOD_IOCTL_DAEMON_LOCK_WSM_L2 command.
+ */
+struct mc_ioctl_daemon_lock_wsm_l2_params {
+	struct {
+		uint32_t  handle; /**< driver handle for locked memory */
+	} in;
+	struct {
+		uint32_t phys_wsm_l2_table;
+	} out;
+};
+
+
+/**
+ * Data exchange structure of the MC_DRV_KMOD_IOCTL_DAEMON_UNLOCK_WSM_L2
+ * command.
+ */
+struct mc_ioctl_daemon_unlock_wsm_l2_params {
+	struct {
+		uint32_t  handle; /**< driver handle for locked memory */
+	} in;
+	struct {
+		/* nothing */
+	} out;
+};
+
+/**
+ * Data exchange structure of the MC_DRV_MODULE_FC_EXECUTE ioctl command.
+ * internal, unsupported
+ */
+union mc_ioctl_fc_execute_params {
+	struct {
+		/**< base address of mobicore binary */
+		uint32_t  phys_start_addr;
+		/**< length of DDR area */
+		uint32_t  length;
+	} in;
+	struct {
+		/* nothing */
+	} out;
+};
+
+/**
+ * Data exchange structure of the MC_DRV_MODULE_GET_VERSION ioctl command.
+ */
+struct mc_ioctl_get_version_params {
+	struct {
+		uint32_t	kernel_module_version;
+	} out;
+};
+
+/* @defgroup Mobicore_Driver_Kernel_Module_Interface IOCTL */
+
+
+
+
+/* TODO: use IOCTL macros like _IOWR.
+ * See Documentation/ioctl/ioctl-number.txt,
+ * Documentation/ioctl/ioctl-decoding.txt */
+/**
+ * defines for the ioctl mobicore driver module function call from user space.
+ */
+enum mc_kmod_ioctl {
+
+	/*
+	 * get detailed MobiCore Status
+	 * internal, unsupported
+	 */
+	MC_DRV_KMOD_IOCTL_DUMP_STATUS  = 200,
+
+	/*
+	 * initialize MobiCore
+	 */
+	MC_DRV_KMOD_IOCTL_FC_INIT  = 201,
+
+	/*
+	 * get MobiCore status
+	 */
+	MC_DRV_KMOD_IOCTL_FC_INFO  = 202,
+
+	/**
+	 * ioctl parameter to send the YIELD command to the SWD.
+	 * Only possible in Privileged Mode.
+	 * ioctl(fd, MC_DRV_MODULE_YIELD)
+	 */
+	MC_DRV_KMOD_IOCTL_FC_YIELD =  203,
+	/**
+	 * ioctl parameter to send the NSIQ signal to the SWD.
+	 * Only possible in Privileged Mode
+	 * ioctl(fd, MC_DRV_MODULE_NSIQ)
+	 */
+	MC_DRV_KMOD_IOCTL_FC_NSIQ   =  204,
+	/**
+	 * ioctl parameter to tzbsp to start Mobicore binary from DDR.
+	 * Only possible in Privileged Mode
+	 * ioctl(fd, MC_DRV_KMOD_IOCTL_FC_EXECUTE)
+	 * internal, unsupported
+	 */
+	MC_DRV_KMOD_IOCTL_FC_EXECUTE =  205,
+
+	/**
+	 * Free's memory which is formerly allocated by the driver's mmap
+	 * command. The parameter must be this mmaped address.
+	 * The internal instance data regarding to this address are deleted as
+	 * well as each according memory page and its appropriated reserved bit
+	 * is cleared (ClearPageReserved).
+	 * Usage: ioctl(fd, MC_DRV_MODULE_FREE, &address) with address beeing of
+	 * type long address
+	 */
+	MC_DRV_KMOD_IOCTL_FREE = 218,
+
+	/**
+	 * Creates a L2 Table of the given base address and the size of the
+	 * data.
+	 * Parameter: mc_ioctl_app_reg_wsm_l2_params
+	 */
+	MC_DRV_KMOD_IOCTL_APP_REGISTER_WSM_L2 = 220,
+
+	/**
+	 * Frees the L2 table created by a MC_DRV_KMOD_IOCTL_APP_REGISTER_WSM_L2
+	 * ioctl.
+	 * Parameter: mc_ioctl_app_unreg_wsm_l2_params
+	 */
+	MC_DRV_KMOD_IOCTL_APP_UNREGISTER_WSM_L2 = 221,
+
+
+	/* TODO: comment this. */
+	MC_DRV_KMOD_IOCTL_DAEMON_LOCK_WSM_L2 = 222,
+	MC_DRV_KMOD_IOCTL_DAEMON_UNLOCK_WSM_L2 = 223,
+
+	/**
+	 * Return kernel driver version.
+	 * Parameter: mc_ioctl_get_version_params
+	 */
+	MC_DRV_KMOD_IOCTL_GET_VERSION = 224,
+};
+
+
+#endif /* _MC_DRV_MODULEAPI_H_ */
+/** @} */
diff --git a/mobicore/include/Public/mc_kernel_api.h b/mobicore/include/Public/mc_kernel_api.h
new file mode 100644
index 0000000..fdfc618
--- /dev/null
+++ b/mobicore/include/Public/mc_kernel_api.h
@@ -0,0 +1,100 @@
+/** @addtogroup MCD_MCDIMPL_KMOD_KAPI Mobicore Driver Module API inside Kernel.
+ * @ingroup  MCD_MCDIMPL_KMOD
+ * @{
+ * Interface to Mobicore Driver Kernel Module inside Kernel.
+ * @file
+ *
+ * Interface to be used by module MobiCoreKernelAPI.
+ *
+ * <!-- Copyright Giesecke & Devrient GmbH 2010-2012 -->
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _MOBICORE_KERNELMODULE_API_H_
+#define _MOBICORE_KERNELMODULE_API_H_
+
+struct mc_instance;
+
+/**
+ * Initialize a new mobicore API instance object
+ *
+ * @return Instance or NULL if no allocation was possible.
+ */
+struct mc_instance *mobicore_open(
+	void
+);
+
+/**
+ * Release a mobicore instance object and all objects related to it
+ * @param instance instance
+ * @return 0 if Ok or -E ERROR
+ */
+int mobicore_release(
+	struct mc_instance	*instance
+);
+
+/**
+ * Free a WSM buffer allocated with mobicore_allocate_wsm
+ * @param instance
+ * @param handle		handle of the buffer
+ *
+ * @return 0 if no error
+ *
+ */
+int mobicore_allocate_wsm(
+	struct mc_instance	*instance,
+	unsigned long		requested_size,
+	uint32_t		*handle,
+	void			**kernel_virt_addr,
+	void			**phys_addr
+);
+
+/**
+ * Free a WSM buffer allocated with mobicore_allocate_wsm
+ * @param instance
+ * @param handle		handle of the buffer
+ *
+ * @return 0 if no error
+ *
+ */
+int mobicore_free(
+	struct mc_instance	*instance,
+	uint32_t		handle
+);
+
+/**
+ * Map a virtual memory buffer structure to Mobicore
+ * @param instance
+ * @param addr		address of the buffer(NB it must be kernel virtual!)
+ * @param len		buffer length
+ * @param handle	pointer to handle
+ * @param phys_wsm_l2_table	pointer to physical L2 table(?)
+ *
+ * @return 0 if no error
+ *
+ */
+int mobicore_map_vmem(
+	struct mc_instance	*instance,
+	void			*addr,
+	uint32_t		len,
+	uint32_t		*handle,
+	void			**phys_wsm_l2_table
+);
+
+/**
+ * Unmap a virtual memory buffer from mobicore
+ * @param instance
+ * @param handle
+ *
+ * @return 0 if no error
+ *
+ */
+int mobicore_unmap_vmem(
+	struct mc_instance	*instance,
+	uint32_t		handle
+);
+#endif /* _MOBICORE_KERNELMODULE_API_H_ */
+/** @} */
diff --git a/mobicore/include/Public/version.h b/mobicore/include/Public/version.h
new file mode 100644
index 0000000..9b2dbca
--- /dev/null
+++ b/mobicore/include/Public/version.h
@@ -0,0 +1,36 @@
+/** @addtogroup MCD_MCDIMPL_KMOD
+ * @{
+ * <!-- Copyright Giesecke & Devrient GmbH 2010-2012 -->
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MC_DRV_VERSION_H_
+#define _MC_DRV_VERSION_H_
+
+#define MCDRVMODULEAPI_VERSION_MAJOR 0
+#define MCDRVMODULEAPI_VERSION_MINOR 1
+
+#endif /* _MC_DRV_VERSION_H_ */
diff --git a/mobicore/provlib/Android.mk b/mobicore/provlib/Android.mk
new file mode 100644
index 0000000..f66549c
--- /dev/null
+++ b/mobicore/provlib/Android.mk
@@ -0,0 +1,12 @@
+# =============================================================================
+#
+# Makefile pointing to all makefiles within the project.
+#
+# =============================================================================
+
+PROJECT_PATH := $(call my-dir)
+
+$(call import-module,$(COMP_PATH_MobiCoreDriverLib))
+
+# Include the Scripts
+include $(PROJECT_PATH)/jni/Android.mk
\ No newline at end of file
diff --git a/mobicore/provlib/Application.mk b/mobicore/provlib/Application.mk
new file mode 100644
index 0000000..91ea85c
--- /dev/null
+++ b/mobicore/provlib/Application.mk
@@ -0,0 +1,21 @@
+# =============================================================================
+#
+# Main build file defining the project modules and their global variables.
+#
+# =============================================================================
+
+# Don't remove this - mandatory
+APP_PROJECT_PATH := $(call my-dir)
+
+# Don't optimize for better debugging
+APP_OPTIM := debug
+
+# Show all warnings
+#APP_CFLAGS := -Wall
+
+MC_INCLUDE_DIR := $(COMP_PATH_MobiCore)/inc \
+    $(COMP_PATH_MobiCore)/inc/TlCm \
+    $(COMP_PATH_MobiCoreDriverLib)/Public
+MC_DEBUG := _DEBUG
+SYSTEM_LIB_DIR=/system/lib
+GDM_PROVLIB_SHARED_LIBS=MobiCoreDriver
\ No newline at end of file
diff --git a/mobicore/provlib/buildTag.h b/mobicore/provlib/buildTag.h
new file mode 100644
index 0000000..dc1d4b9
--- /dev/null
+++ b/mobicore/provlib/buildTag.h
@@ -0,0 +1 @@
+#define MOBICORE_COMPONENT_BUILD_TAG "*** SAMSUNG Exynos 5250 MC1.2 V002 release ###"
diff --git a/mobicore/provlib/inc_private/gdmcdevicebinding.h b/mobicore/provlib/inc_private/gdmcdevicebinding.h
new file mode 100644
index 0000000..c466a18
--- /dev/null
+++ b/mobicore/provlib/inc_private/gdmcdevicebinding.h
@@ -0,0 +1,70 @@
+#ifndef _INC_GDMCDEVICEBINDING_H
+#define _INC_GDMCDEVICEBINDING_H
+
+#include <gdmcprovlib.h>
+#include <gdmcprovprotocol.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _KSoCAuthSNTS  KSoCAuthSNTS;
+
+struct _KSoCAuthSNTS
+{
+  mcSymmetricKey_t  kSoCAuth;
+  _u64              serialNumber;
+  _u64              timeStamp;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+gderror GDMCComposeErrorMessage ( gdmcinst   *inst, 
+                                  gderror     error, 
+                                  _u8        *msgout, 
+                                  _u32       *msgout_size, 
+                                  _u32        initial_msgout_size, 
+                                  const char *pszmsg, ... );
+
+gderror GDPROVAPI GDMCValidateProvMessage ( const _u8        *msg, 
+                                            _u32              msgsize,
+                                            gdmc_msgheader  **ppheader,
+                                            _u8             **ppbody,
+                                            gdmc_msgtrailer **pptrailer );
+
+gderror GDPROVAPI GDMCHandleGetSUID ( gdmcinst *inst,
+                                      _u8      *msgout,
+                                      _u32     *msgout_size,
+                                      _u32      initial_msgout_size );
+
+gderror GDPROVAPI GDMCHandleGenAuthToken ( gdmcinst          *inst,
+                                           gdmc_actmsg_req   *req,
+                                          _u8                *msgout,
+                                          _u32               *msgout_size,
+                                          _u32                initial_msgout_size );
+
+gderror GDPROVAPI GDMCHandleValidateAuthToken ( gdmcinst         *inst,
+                                                gdmc_so_authtok  *validateSoAuthTok,
+                                                _u8              *msgout,
+                                                _u32             *msgout_size,
+                                                _u32              initial_msgout_size );
+
+#define ERRMSG_0001       "Unable to access memory region at %p (size: %u byte(s)) for READ."
+#define ERRMSG_0002       "Unable to access memory region at %p (size: %u byte(s)) for WRITE."
+#define ERRMSG_0003       "First in-message must be empty."
+#define ERRMSG_0004       "Insufficient memory available."
+#define ERRMSG_0005       "Message output buffer too small (%u but %u required to store message)."
+#define ERRMSG_0006       "Message validation failed."
+#define ERRMSG_0007       "Unexpected message received. Cannot evaluate message (ignored)."
+#define ERRMSG_0008       "SUID of returned SO.AuthToken mismatches (my) internal SUID. SO.AuthToken discarded."
+#define ERRMSG_0009       "Unable to generate SD.Receipt."
+#define ERRMSG_000A       "Expecting MC_GETSUID_REQ message from Production Station."
+#define ERRMSG_000B       "Unable to retrieve SUID from SoC (MobiCore)."
+#define ERRMSG_000C       "Unable to dump SO.AuthToken (MobiCore)."
+#define ERRMSG_000D       "Unable to retrieve SUID from SoC."
+#define ERRMSG_000E       "Unable to generate SO.AuthToken."
+#define ERRMSG_000F       "Validation of SO.AuthToken failed because no SO.AuthToken available."
+
+#endif // _INC_GDMCDEVICEBINDING_H
diff --git a/mobicore/provlib/inc_private/gdmcinstance.h b/mobicore/provlib/inc_private/gdmcinstance.h
new file mode 100644
index 0000000..0369f62
--- /dev/null
+++ b/mobicore/provlib/inc_private/gdmcinstance.h
@@ -0,0 +1,28 @@
+#ifndef _INC_GDMCINSTANCE_H
+#define _INC_GDMCINSTANCE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _gdmcinst            gdmcinst;
+
+#define GDMC_STATE_INITIAL          ((_u32)0)         ///< initial state
+#define GDMC_STATE_HAVE_SUID        ((_u32)1)         ///< SUID retrieved from MobiCore
+#define GDMC_STATE_HAVE_AUTHTOK     ((_u32)2)         ///< SO.AuthToken generated by MobiCore
+
+#define MAX_RESEND_TRIES            64
+
+struct _gdmcinst
+{
+  _u32                  state;                        ///< internal state of this instance
+  _u8                   suid[SUID_LENGTH];            ///< SUID as retrieved from MobiCore
+  _u8                   kSoCAuth[K_SOC_AUTH_LENGTH];  ///< the K.SoC.Auth delivered by KPH
+  gdmc_so_authtok       authTok;                      ///< generated SO.AuthToken
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _INC_GDMCINSTANCE_H
diff --git a/mobicore/provlib/inc_private/gdmcprovprotocol.h b/mobicore/provlib/inc_private/gdmcprovprotocol.h
new file mode 100644
index 0000000..bd2686d
--- /dev/null
+++ b/mobicore/provlib/inc_private/gdmcprovprotocol.h
@@ -0,0 +1,127 @@
+#ifndef _INC_GDMCPROVPROTOCOL_H_
+#define _INC_GDMCPROVPROTOCOL_H_
+
+#include <gdmcprovlib.h>
+#include <mobicore.h>
+
+#ifdef WIN32
+
+#pragma warning ( disable : 4200 )
+
+#pragma pack(push,1)
+
+#ifndef PACK_ATTR
+#define PACK_ATTR
+#endif // PACK_ATTR
+
+#else
+
+#ifndef PACK_ATTR
+#define PACK_ATTR   __attribute__((packed))
+#endif // PACK_ATTR
+
+#define IsBadReadPtr(p,c)       (NULL==p)
+#define IsBadWritePtr(p,c)      (NULL==p)
+
+#endif
+
+#define AUTHENTICATION_TOKEN            MC_SO_TYPE_REGULAR    
+#define CONTEXT_SYSTEM                  MC_SO_CONTEXT_TLT     
+#define SUID_LENGTH                     MC_SUID_LEN                 // 16
+#define K_SOC_AUTH_LENGTH               MC_CONT_SYMMETRIC_KEY_SIZE  // 32
+#define SHA256_HASH_LENGTH              MC_SO_HASH_SIZE             // 32
+
+#undef AES_BLOCK_SIZE
+
+#define AES_BLOCK_SIZE                  MC_SO_ENCRYPT_BLOCK_SIZE    // 16
+
+typedef struct _gdmc_actmsg_req         gdmc_actmsg_req;
+typedef struct _gdmc_actmsg_resp        gdmc_actmsg_resp;
+typedef struct _gdmc_so_authtok         gdmc_so_authtok;
+typedef struct _gdmc_error_msg          gdmc_error_msg;
+
+#define MC_GETSUID_REQ            ((_u32)0x0100434D)
+#define MC_GETSUID_RESP           ((_u32)0x0200434D)
+#define MC_GENAUTHTOKEN_REQ       ((_u32)0x0300434D)
+#define MC_GENAUTHTOKEN_RESP      ((_u32)0x0400434D)
+#define MC_VALIDATEAUTHTOKEN_REQ  ((_u32)0x0500434D)
+#define MC_ERROR                  ((_u32)0x0600434D)
+
+#ifndef CMP_GEN_AUTH_TOKEN_PSS_SIZE
+#define CMP_GEN_AUTH_TOKEN_PSS_SIZE 256
+#endif
+
+/// G&D MobiCore error message
+struct _gdmc_error_msg
+{
+  _u32              errorcode;              ///< error code; you can safely cast this to gderror.
+  _u32              errmsg_length;          ///< length of error message, may be 0
+  _u8               errmsg[];               ///< error message (variable)
+} PACK_ATTR;
+
+/// G&D MobiCore SO.AuthToken (authentication token)
+struct _gdmc_so_authtok
+{
+  // Header
+
+  _u32              type;
+  _u32              version;
+  _u32              context;
+  _u32              lifetime;             // NEW2 -> ignore
+  _u32              producer_spid;        // NEW2 -> ignore
+  _u8               producer_uuid[16];    // NEW2 -> ignore
+  _u32              plain_length;         // OLD: 16 (SUID_LENGTH), NEW: 24 (two additional ints)
+                                          // NEW2: 28 (version is new)
+  _u32              encrypted_length;     // here: K_SOC_AUTH_LENGTH
+
+  // Plaintext Data
+
+  _u32              contType;             // NEW: contType_t         = CONT_TYPE_SOC
+  _u32              contVersion;          // NEW2: version
+  _u32              contState;            // NEW: mcContainerState_t = MC_CONT_STATE_UNREGISTERED
+  _u8               suid[SUID_LENGTH];
+  
+  // Encrypted Data (encrypted with K.Device.Ctxt)
+
+  _u8               kSoCAuth[K_SOC_AUTH_LENGTH];
+  _u8               md[SHA256_HASH_LENGTH];
+  _u8               padding[AES_BLOCK_SIZE];
+
+} PACK_ATTR;
+
+/// MobiCore activation message (request)
+struct _gdmc_actmsg_req
+{
+  _u32        msg_type;                     ///< type of message = MC_CMP_CMD_GENERATE_AUTH_TOKEN
+  _u8         suid[SUID_LENGTH];            ///< SoC SUID
+  _u8         kSoCAuth[K_SOC_AUTH_LENGTH];  ///< K.SoC.Auth (AES-256bit key)
+  _u32        kid;                          ///< NEW: key id (currently: 1)
+  //_u8         md[SHA256_HASH_LENGTH];       ///< SHA-256 hash
+  _u8         dsig[CMP_GEN_AUTH_TOKEN_PSS_SIZE];  ///< new: hash substituted by PSS-SIG
+} PACK_ATTR;
+
+/// MobiCore activation response
+struct _gdmc_actmsg_resp
+{
+  _u32              msg_type;               ///< type of message = MC_CMP_CMD_GENERATE_AUTH_TOKEN | 0x80000000
+  _u32              retcode;                ///< NEW: return code (status of operation)
+  gdmc_so_authtok   authtok;                ///< SO.AuthToken (124 bytes)
+} PACK_ATTR;
+
+#ifdef WIN32
+#pragma pack(pop)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_u32 GDPROVAPI CalcCRC32 ( const _u8 *data, _u32 length );
+
+void GDPROVAPI InitCRCTable ( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _INC_GDMCPROVPROTOCOL_H_
diff --git a/mobicore/provlib/inc_private/mobicore.h b/mobicore/provlib/inc_private/mobicore.h
new file mode 100644
index 0000000..1806f2b
--- /dev/null
+++ b/mobicore/provlib/inc_private/mobicore.h
@@ -0,0 +1,174 @@
+/// @file mobicore.h
+/// @author secunet AG (IKU)
+///
+/// This file is a convenience header file (top-level) including
+/// all MobiCore-related and platform-specific stuff.
+
+#ifndef _INC_MOBICORE_H_
+#define _INC_MOBICORE_H_
+
+#if !defined(LINUX) && !defined(ANDROID_ARM) && !defined(WIN32)
+#error "You MUST define either LINUX or ANDROID_ARM or WIN32"
+#endif
+
+// standard C stuff...
+
+#if defined(__cplusplus) && !defined(ANDROID_ARM)
+#include <string>
+#include <vector>
+#include <map>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef LINUX
+#include <safemem.h>
+#endif
+
+#if defined(WIN32) && defined(_DEBUG) // enable memory leak detection
+#define _CRTDBG_MAP_ALLOC
+#define _CRTDBG_MAP_ALLOC_NEW
+#include <windows.h>
+#include <crtdbg.h>
+#define MYDEBUG_NEW   new( _NORMAL_BLOCK, __FILE__, __LINE__)
+#define new MYDEBUG_NEW
+#endif
+
+#ifndef _NO_OPENSSL_INCLUDES
+
+// OpenSSL stuff...
+
+#include <openssl/rand.h>
+#include <openssl/sha.h>
+#include <openssl/aes.h>
+#include <openssl/rsa.h>
+#include <openssl/bn.h>
+#include <openssl/objects.h>
+#include <openssl/err.h>
+
+#endif
+
+#ifdef WIN32
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#pragma pack(push,4)
+
+#pragma warning ( disable : 4200 4996 )
+
+#define GDPUBLIC
+#define GDAPI                 __fastcall
+#define PACK_ATTR
+#define likely(cond)          cond
+#define unlikely(cond)        cond
+
+#define bad_read_ptr(_p,_c)   IsBadReadPtr((const void *)(_p),(UINT_PTR)(_c))
+#define bad_write_ptr(_p,_c)  IsBadWritePtr((void *)(_p),(UINT_PTR)(_c))
+
+#define PATH_SEPARATOR        "\\"
+#define PATH_SEP_CHAR         '\\'
+#define DYNLIB_PREFIX         ""
+#define DYNLIB_EXTENSION      ".dll"
+
+#else
+
+#define GDPUBLIC              __attribute__((visibility("default")))
+#define GDAPI
+#define PACK_ATTR             __attribute__((packed))
+#define likely(x)             __builtin_expect((x),1)
+#define unlikely(x)           __builtin_expect((x),0)
+
+#define bad_read_ptr(_p,_c)   (NULL==(_p))
+#define bad_write_ptr(_p,_c)  (NULL==(_p))
+
+#define PATH_SEPARATOR        "/"
+#define PATH_SEP_CHAR         '/'
+#define DYNLIB_PREFIX         "lib"
+#define DYNLIB_EXTENSION      ".so"
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <sched.h>
+#include <dlfcn.h>
+#include <signal.h>
+#include <ctype.h>
+#ifndef LINUX
+#include <android/log.h>
+#else
+#include <syslog.h>
+#endif
+
+#endif
+
+#include <stdbool.h>
+#include <stdint.h>
+
+// MobiCore stuff...
+
+#ifdef WIN32
+#undef UUID
+#undef uuid_t
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <MobiCoreDriverApi.h>
+#include <mcContainer.h>
+#include <tlCmApi.h>
+#include <tlCmUuid.h>
+#include <mcVersionHelper.h>
+#include <mcVersionInfo.h>
+
+enum _mcAuthState
+{
+  AUTH_NONE     = 0,
+  AUTH_SOC,
+  AUTH_ROOT,
+  AUTH_SP
+};
+
+typedef enum _mcAuthState mcAuthState;
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef WIN32
+#pragma pack(pop)
+#endif
+
+#include <MobiCoreRegistry.h>
+
+#define IS_VALID_SPID(_x)     ((0xFFFFFFFF!=(_x)) && (0xFFFFFFFE!=(_x)))
+#define IS_VALID_ROOTID(_x)   IS_VALID_SPID(_x)
+#define IS_VALID_UUID(_x)     ( ((_x).value[ 0]!=0xFF) && ((_x).value[ 1]!=0xFF) &&\
+                                ((_x).value[ 2]!=0xFF) && ((_x).value[ 3]!=0xFF) &&\
+                                ((_x).value[ 4]!=0xFF) && ((_x).value[ 5]!=0xFF) &&\
+                                ((_x).value[ 6]!=0xFF) && ((_x).value[ 7]!=0xFF) &&\
+                                ((_x).value[ 8]!=0xFF) && ((_x).value[ 9]!=0xFF) &&\
+                                ((_x).value[10]!=0xFF) && ((_x).value[11]!=0xFF) &&\
+                                ((_x).value[12]!=0xFF) && ((_x).value[13]!=0xFF) &&\
+                                ((_x).value[14]!=0xFF) && ((_x).value[15]!=0xFF) && ((_x).value[15]!=0xFE) )
+
+#define MC_SO_PLAIN_SIZE(_struct)   offsetof(_struct,co)
+#define MC_SO_ENC_SIZE(_struct)     sizeof(_struct.co)
+
+#endif // _INC_MOBICORE_H_
+
diff --git a/mobicore/provlib/inc_public/gdmcprovlib.h b/mobicore/provlib/inc_public/gdmcprovlib.h
new file mode 100644
index 0000000..71196ca
--- /dev/null
+++ b/mobicore/provlib/inc_public/gdmcprovlib.h
@@ -0,0 +1,424 @@
+///
+/// @file       gdmcprovlib.h
+/// @author     Giesecke & Devrient GmbH, Munich, Germany
+///
+/// This header file declares simple data types and functions
+/// comprising the G&D Provisioning API.
+///
+
+#ifndef _INC_GDPROVLIB_H_
+#define _INC_GDPROVLIB_H_
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Check defines (macros)...
+
+#if !defined(WIN32) && !defined(LINUX) && !defined(ARM)
+#error "You MUST define one of WIN32, LINUX, and ARM (platform)."
+#endif
+
+#if !defined(_32BIT) && !defined(_64BIT)
+#error "You MUST define either _32BIT or _64BIT."
+#endif
+
+#if !defined(_LENDIAN) && !defined(_BENDIAN)
+#error "You MUST define either _LENDIAN or _BENDIAN."
+#endif
+
+// Declare simple signed and unsigned integer types
+
+/// a byte (octet), unsigned, 0..255
+typedef unsigned char             _u8;
+
+/// a signed byte, -128..+127
+typedef signed char               _i8;
+
+/// an unsigned 16bit integer, 0..65.535
+typedef unsigned short            _u16;
+
+/// a signed 16bit integer, -32.768..+32.767
+typedef signed short              _i16;
+
+/// an unsigned 32bit integer, 0..4.294.967.295
+typedef unsigned int              _u32;
+
+/// a signed 32bit integer, -2.147.483.648..+2.147.483.647
+typedef signed int                _i32;
+
+#ifdef WIN32
+
+#define GDPUBLIC
+#define GDPROVAPI         __fastcall
+
+/// an unsigned 64bit integer, 0..18.446.744.073.709.551.615
+typedef unsigned __int64          _u64;
+
+/// a signed 64bit integer, -9.223.372.036.854.775.808..+9.223.372.036.854.775.807
+typedef signed __int64            _i64;
+
+#else
+
+#define GDPUBLIC          __attribute__((visibility("default")))
+#define GDPROVAPI
+
+#ifdef _32BIT
+
+/// an unsigned 64bit integer, 0..18.446.744.073.709.551.615
+typedef unsigned long long        _u64;
+
+/// a signed 64bit integer, -9.223.372.036.854.775.808..+9.223.372.036.854.775.807
+typedef signed long long          _i64;
+
+#else // 64bit
+
+/// an unsigned 64bit integer, 0..18.446.744.073.709.551.615
+typedef unsigned long             _u64;
+
+/// a signed 64bit integer, -9.223.372.036.854.775.808..+9.223.372.036.854.775.807
+typedef signed long               _i64;
+
+#endif // _32BIT
+
+#endif // WIN32
+
+//////////////////////////////////////////////////////////////////////////////
+
+/// G&D error codes, which are unsigned 32bit integers
+typedef _u32                          gderror;
+
+/// everything okay, operation successful
+#define GDERROR_OK                    ((gderror)0x00000000)
+
+/// one or more of the input parameters to a function is/are invalid
+#define GDERROR_PARAMETER             ((gderror)0x00000001)
+
+/// connection problem occured, unable to establish a connection to the
+/// Key Provisioning Host (KPH)
+#define GDERROR_CONNECTION            ((gderror)0x00000002)
+
+/// communication problem occured, unable to communicate with the
+/// Key Provisioning Host (KPH)
+#define GDERROR_COMMUNICATION         ((gderror)0x00000003)
+
+/// GDMCProvShutdownLibrary was called without calling GDMCProvInitializeLibrary
+#define GDERROR_NOT_INITIALIZED       ((gderror)0x00000004)
+
+/// GDMCProvBeginProvisioning called but no more handles available
+#define GDERROR_NO_MORE_HANDLES       ((gderror)0x00000005)
+
+/// An unknown or invalid gdhandle was passed to a function
+#define GDERROR_INVALID_HANDLE        ((gderror)0x00000006)
+
+/// A so called structured exception occured, which is a severe error
+/// (MS Windows only)
+#define GDERROR_CPU_EXCEPTION         ((gderror)0x00000007)
+
+/// Unable to retrieve the SUID of the SoC
+#define GDERROR_CANT_GET_SUID         ((gderror)0x00000008)
+
+/// Unable to generate the authentication token SO.AuthToken
+#define GDERROR_CANT_BUILD_AUTHTOKEN  ((gderror)0x00000009)
+
+/// Unable to dump the authentication token SO.AuthToken
+#define GDERROR_CANT_DUMP_AUTHTOKEN   ((gderror)0x0000000A)
+
+/// Unable to generate the receipt SD.Receipt
+#define GDERROR_CANT_BUILD_RECEIPT    ((gderror)0x0000000B)
+
+/// (only product version): Authentication KPH Connector <-> Key Provisioning Host (KPH) failed
+#define GDERROR_AUTH_FAILED           ((gderror)0x0000000C)
+
+/// validation of the device binding failed
+#define GDERROR_VALIDATION_FAILURE    ((gderror)0x0000000D)
+
+/// insufficient memory available
+#define GDERROR_INSUFFICIENT_MEMORY   ((gderror)0x0000000E)
+
+/// synchronization error occurred (thread concurrency)
+#define GDERROR_SYNCHRONIZATION       ((gderror)0x0000000F)
+
+/// the Key Provisioning Host (KPH) was not able to generate a random key (TRNG)
+#define GDERROR_CANT_GENERATE_KEY     ((gderror)0x00000010)
+
+/// the received cryptographic message format is erroneous
+#define GDERROR_MESSAGE_FORMAT        ((gderror)0x00000011)
+
+/// CRC32 checksum error
+#define GDERROR_CRC32                 ((gderror)0x00000012)
+
+/// Hash value (message digest) validation error
+#define GDERROR_MESSAGE_DIGEST        ((gderror)0x00000013)
+
+/// SUID comparison failed
+#define GDERROR_SUID_MISMATCH         ((gderror)0x00000014)
+
+/// the Device could not generate the authentication token SO.AuthToken for any reason
+#define GDERROR_GENAUTHTOK_FAILED     ((gderror)0x00000015)
+
+/// the Device could not wrap the authentication token in a secure object (SO)
+#define GDERROR_WRAPOBJECT_FAILED     ((gderror)0x00000016)
+
+/// the Device could not store SO.AuthToken for any reason
+#define GDERROR_STORE_SO_FAILED       ((gderror)0x00000017)
+
+/// the Key Provisioning Host (KPH) could not generate the receipt SD.Receipt for any reason
+#define GDERROR_GENRECEIPT_FAILED     ((gderror)0x00000018)
+
+/// the Key Provisioning Host (KPH) triggered a SO.AuthToken validation in the Device but no SO.AuthToken is available
+#define GDERROR_NO_AUTHTOK_AVAILABLE  ((gderror)0x00000019)
+
+/// the Device could not perform a read-back of the recently stored SO.AuthToken
+#define GDERROR_AUTHTOK_RB_FAILED     ((gderror)0x0000001A)
+
+/// the called API function is not implemented
+#define GDERROR_NOT_IMPLEMENTED       ((gderror)0x0000001B)
+
+/// generic (unspecified) error
+#define GDERROR_UNKNOWN               ((gderror)0x0000001C)
+
+/// MobiCore library initialization or cleanup failed
+#define GDERROR_MOBICORE_LIBRARY      ((gderror)0x0000001D)
+
+/// supplied (output) buffer too small
+#define GDERROR_BUFFER_TOO_SMALL      ((gderror)0x0000001E)
+
+/// cryptographic-related error occured, e.g. loading of RSA keys, etc.
+#define GDERROR_CRYPTO_FAILURE        ((gderror)0x0000001F)
+
+/// no error code: device binding completed successfully
+#define GDERROR_PROVISIONING_DONE     ((gderror)0x10000001)
+
+//////////////////////////////////////////////////////////////////////////////
+
+/// G&D handle (to one instance of the Provisioning API)
+typedef _u32                      gdhandle;
+
+/// Returns the current version of the Provisioning API.
+///
+/// @return an unsigned 32bit integer consisting of four bytes aa|bb|cc|dd
+///         with major version (aa), minor version (bb), patch level (cc), and
+///         OEM (dd), which denotes the numeric ID of an OEM.
+GDPUBLIC _u32 GDPROVAPI GDMCProvGetVersion ( void );
+
+/// [PRODUCTION STATION ONLY] Formats an error message for an error code, 
+/// possibly containing more detailed information about the error. This function
+/// is NOT implemented in the ARM version of the library because no diagnostic
+/// messages can be displayed during the production.
+///
+/// @param[in]      provhandle  the handle returned by GDMCProvBeginProvisioning;
+///                             can be null (0) to format a message for a global
+///                             error code (not context-specific)
+/// @param[in]      errorcode   the G&D error code
+/// @param[in/out]  msgbuf      pointer to buffer receiving the UTF-8 encoded
+///                             error message (in), buffer filled with error
+///                             message (out)
+/// @param[in/out]  size        size of buffer pointed to by msgbuf specified
+///                             as wide characters (in), number of wide
+///                             characters copied into msgbuf (out)
+///
+/// @return                     result code (e.g. buffer too small)
+GDPUBLIC gderror GDPROVAPI GDMCProvFormatErrorMessage ( gdhandle provhandle,
+                                                        gderror  errorcode,
+                                                        char    *msgbuf, 
+                                                        _u32    *size );
+
+/// Initializes the G&D Provisioning API (library) globally. If called
+/// by the Production Software Station, then a TLS-secured channel to
+/// the Key Provisioning Host (KPH) is established.
+/// In a multithreaded environment, this function has to be called from
+/// the primary thread (LWP 0).
+///
+/// @return G&D error code
+GDPUBLIC gderror GDPROVAPI GDMCProvInitializeLibrary ( void );
+
+/// Performs a global shutdown of the G&D Provisioning API (library).
+/// After this call, all resources are cleaned up and all handles are
+/// closed. No functions except for GDMCProvInitializeLibrary may be
+/// called anymore.
+/// In a multithread environment, this function has to be called from
+/// the primary thread (LWP 0).
+///
+/// @return G&D error code
+GDPUBLIC gderror GDPROVAPI GDMCProvShutdownLibrary ( void );
+
+/// Creates one instance of the key provisioning (aka "device binding")
+///
+/// @param[in/out]  provhandle  pointer to memory location receiving the
+///                             handle (in), the handle or 0 (out)
+///
+/// @return                     G&D error code
+GDPUBLIC gderror GDPROVAPI GDMCProvBeginProvisioning ( gdhandle *provhandle );
+
+/// Destroys one instance of the key provisioning (aka "device binding")
+///
+/// @param[in]  provhandle      the handle returned by GDMCProvBeginProvisioning
+///
+/// @return                     G&D error code
+GDPUBLIC gderror GDPROVAPI GDMCProvEndProvisioning ( gdhandle provhandle );
+
+/// Executes one provisioning step of the full sequence. The caller has to
+/// call this function in a loop until either an error is reported or the
+/// error code GDERROR_PROVISIONING_DONE is returned (meaning successful
+/// provisioning). Please refer to the MobiCore Provisioning API documentation
+/// for details.
+///
+/// @param[in]      provhandle      the handle returned by 
+///                                 GDMCProvBeginProvisioning
+/// @param[in]      msgin           pointer to buffer containing the 
+///                                 input message; may be NULL if no message 
+///                                 available
+/// @param[in]      msgin_size      size of buffer pointed to by msgin in bytes
+/// @param[in/out]  msgout          pointer to buffer receiving the output
+///                                 message (in); output message (out)
+/// @param[in/out]  msgout_size     size of buffer pointed to by msgout in
+///                                 bytes (in); number of bytes copied to msgout
+///                                 (out)
+///
+/// @return                         G&D error code; GDERROR_PROVISIONING_DONE
+///                                 if provisioning successfully completed.
+GDPUBLIC gderror GDPROVAPI GDMCProvExecuteProvisioningStep ( 
+                  gdhandle    provhandle,
+                  const _u8  *msgin,
+                  _u32        msgin_size,
+                  _u8        *msgout,
+                  _u32       *msgout_size );
+
+/// [PRODUCTION STATION ONLY] Convenience function to format an SD.Receipt
+///
+/// @param[in]      receipt           pointer to buffer containing the 
+///                                   binary SD.Receipt
+/// @param[in]      receipt_size      size of binary data pointed to by 
+///                                   receipt in bytes
+/// @param[in/out]  fmt_receipt       pointer to buffer receiving the receipt as
+///                                   a BASE64-encoded string (in); the string (out)
+/// @param[in/out]  fmt_receipt_size  size of buffer pointed to by fmt_receipt in
+///                                   bytes (in); number of bytes copied to 
+///                                   fmt_receipt (out)
+///
+/// @return                           G&D error code
+GDPUBLIC gderror GDPROVAPI GDMCProvFormatReceipt (
+                  const _u8  *receipt,
+                  _u32        receipt_size,
+                  _u8        *fmt_receipt,
+                  _u32       *fmt_receipt_size );
+
+/// [PRODUCTION STATION ONLY] Convenience function to query the SUID of
+/// the currently provisioned device (e.g. can be used as primary key in
+/// a production database)
+///
+/// @param[in]      provhandle    the handle returned by 
+///                               GDMCProvBeginProvisioning
+/// @param[in/out]  suid          pointer to buffer (16 octets, in) receiving the
+///                               SUID of the current mobile device (out)
+///
+/// @return                       G&D error code
+GDPUBLIC gderror GDPROVAPI GDMCProvGetSUID (
+                  gdhandle    provhandle,
+                  _u8        *suid );
+
+/// [DEVICE ONLY] Callback function called by the Provisioning API when
+/// GDMCProvExecuteProvisioningStep is executed in the Device. This function
+/// shall store the authentication token SO.AuthToken in a secure location.
+///
+/// @param[in]      authtok           pointer to buffer containing SO.AuthToken
+/// @param[in]      authtok_size      size of buffer pointed to be authtok;
+///                                   shall be 124 octets
+///
+/// @return                           G&D error code
+typedef gderror (*authtok_writecb)( const _u8 *authtok, 
+                                    _u32       authtok_size );
+
+/// [DEVICE ONLY] Callback function called by the Provisioning API when
+/// GDMCProvExecuteValidationStep is executed in the Device. This function
+/// shall perform a read-back of the stored authentication token SO.AuthToken
+///
+/// @param[in/out]  authtok           pointer to buffer receiving SO.AuthToken
+///                                   (in); buffer filled with SO.AuthToken (out)
+/// @param[in/out]  authtok_size      size of buffer pointed to be authtok (in);
+///                                   number of bytes copied to authtok (out);
+///                                   shall be 124 octets
+///
+/// @return                           G&D error code
+typedef gderror (*authtok_readcb)( _u8  *authtok, 
+                                   _u32 *authtok_size );
+
+/// [DEVICE ONLY] The OEM must provide two hook functions (callbacks) for the
+/// reading and writing of the authentication token SO.AuthToken in the device.
+/// 
+/// @param[in]  writefunc   callback function called by the Provisioning API
+///                         when an authentication token SO.AuthToken has to be
+///                         stored
+/// @param[in]  readfunc    callback function called by the Provisioning API
+///                         when an authentication token SO.AuthToken has to be
+///                         read back (for validation purposes)
+///
+/// @return                 G&D error code
+GDPUBLIC gderror GDPROVAPI GDMCProvSetAuthTokenCallbacks ( 
+                             authtok_writecb writefunc,
+                             authtok_readcb  readfunc );
+
+/// [PRODUCTION STATION ONLY] The configuration of the provisioning library
+/// can be patched into the library binary file. If the OEM decided to perform
+/// the configuration e.g. by providing the configuration information via the
+/// production database, then this function can be called to configure the
+/// provisioning library.
+///
+/// @param[in] config_string  a zero-terminated configuration string containing 
+///                           the entire configuration information in a format
+///                           that will be defined by G&D; the exact format of 
+///                           this configuration information can be OEM-specific
+///                           and will be specified in a separate document
+///
+/// @return                   G&D error code
+GDPUBLIC gderror GDPROVAPI GDMCProvSetConfigurationString (
+                            const char *config_string );
+
+//////////////////////////////////////////////////////////////////////////////
+// Declaration of message header and trailer
+//////////////////////////////////////////////////////////////////////////////
+
+#ifdef WIN32
+
+#pragma warning ( disable : 4200 )
+
+#pragma pack(push,1)
+
+#define PACK_ATTR
+
+#else // Linux
+
+#define PACK_ATTR   __attribute__((packed))
+
+#endif
+
+typedef struct _gdmc_msgheader          gdmc_msgheader;
+typedef struct _gdmc_msgtrailer         gdmc_msgtrailer;
+
+/// the G&D MobiCore message header
+struct _gdmc_msgheader
+{
+  _u32        msg_type;   ///< message type
+  _u32        body_size;  ///< size of body (may be 0)
+} PACK_ATTR;
+
+/// the G&D MobiCore message trailer
+struct _gdmc_msgtrailer
+{
+  _u32        magic;      /// message type (one's complement)
+  _u32        crc32;      /// CRC32 checksum
+} PACK_ATTR;
+
+#ifdef WIN32
+#pragma pack(pop)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _INC_GDPROVLIB_H_
+
diff --git a/mobicore/provlib/jni/Android.mk b/mobicore/provlib/jni/Android.mk
new file mode 100644
index 0000000..34971ab
--- /dev/null
+++ b/mobicore/provlib/jni/Android.mk
@@ -0,0 +1,36 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE      := gdmcprov
+LOCAL_MODULE_TAGS := eng
+
+LOCAL_C_INCLUDES  := $(LOCAL_PATH)/../inc_private \
+                     $(LOCAL_PATH)/../inc_public \
+                     $(MC_INCLUDE_DIR)
+
+LOCAL_SRC_FILES   := ../src/gdmcprovlib.cpp \
+                     ../src/crc32.c \
+                     ../src/mobicore.c \
+                     ../src/gdmcdevicebinding.cpp
+
+LOCAL_CFLAGS      := -O2 -Wall -fomit-frame-pointer -DANDROID_ARM -DARM -D_LENDIAN -D_32BIT \
+                     -fvisibility=hidden -I$(OPENSSL_INC_DIR) \
+                     -DGDMCPROVLIB_VERSION=0x01000001 -D$(MC_DEBUG) \
+                     -D_NO_OPENSSL_INCLUDES
+
+LOCAL_CXXFLAGS    := -O2 -Wall -fomit-frame-pointer -DANDROID_ARM -DARM -D_LENDIAN -D_32BIT \
+                     -fvisibility-inlines-hidden -fvisibility=hidden \
+                     -DGDMCPROVLIB_VERSION=0x01000001 -D$(MC_DEBUG)
+
+LOCAL_CPPFLAGS    := -O2 -Wall -fomit-frame-pointer -DANDROID_ARM -DARM -D_LENDIAN -D_32BIT \
+                     -fvisibility-inlines-hidden -fvisibility=hidden \
+                     -DGDMCPROVLIB_VERSION=0x01000001 -D$(MC_DEBUG)
+
+LOCAL_LDFLAGS     := -Wl,-rpath-link,$(SYSTEM_LIB_DIR) \
+                     -L$(SYSTEM_LIB_DIR)
+
+LOCAL_SHARED_LIBRARIES  := $(GDM_PROVLIB_SHARED_LIBS)
+
+include $(BUILD_SHARED_LIBRARY)
+   
diff --git a/mobicore/provlib/src/crc32.c b/mobicore/provlib/src/crc32.c
new file mode 100644
index 0000000..37ac0c6
--- /dev/null
+++ b/mobicore/provlib/src/crc32.c
@@ -0,0 +1,49 @@
+#include <gdmcprovlib.h>
+#include <string.h>
+
+static _u32 crctable[256];
+
+_u32 GDPROVAPI CalcCRC32 ( const _u8 *data, _u32 length )
+{
+  _u32 crc = 0xFFFFFFFF;
+
+  while (length--)
+    crc = (crc>>8) ^ crctable[(crc&0xFF) ^ *data++];
+
+  return crc ^ 0xFFFFFFFF;
+}
+
+static _u32 GDPROVAPI reflect ( _u32 refl, _u8 c )
+{
+  int     i;
+  _u32    value = 0;
+
+  // Swap bit 0 for bit 7, bit 1 For bit 6, etc....
+  for (i = 1; i < (c + 1); i++)
+  {
+    if (refl & 1)
+      value |= (1 << (c - i));
+    refl >>= 1;
+  }
+
+  return value;
+}
+
+void GDPROVAPI InitCRCTable ( void )
+{
+  int       i,j;
+
+  memset(crctable,0,sizeof(crctable));
+
+  for (i = 0; i <= 0xFF; i++)
+  {
+    crctable[i] = reflect(i, 8) << 24;
+
+    for (j = 0; j < 8; j++)
+      crctable[i] = (crctable[i] << 1)
+                  ^ ((crctable[i] & (1 << 31)) ? 0x04C11DB7 : 0);
+
+    crctable[i] = reflect(crctable[i], 32);
+  }
+}
+
diff --git a/mobicore/provlib/src/gdmcdevicebinding.cpp b/mobicore/provlib/src/gdmcdevicebinding.cpp
new file mode 100644
index 0000000..27cd667
--- /dev/null
+++ b/mobicore/provlib/src/gdmcdevicebinding.cpp
@@ -0,0 +1,458 @@
+///
+/// @file       gdmcdevicebinding.cpp
+/// @author     Giesecke & Devrient GmbH, Munich, Germany
+///
+/// Implementation of the (internal) device binding
+///
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <gdmcprovlib.h>
+#include <gdmcprovprotocol.h>
+#include <gdmcinstance.h>
+
+extern "C"
+{
+  gderror MCGetSUID ( _u8 *suid );
+
+  gderror MCGenerateAuthToken ( gdmcinst *inst, const gdmc_actmsg_req *req, gdmc_so_authtok *authtok );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// MS Windows-specific includes
+//////////////////////////////////////////////////////////////////////////////
+
+#if defined(WIN32)
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#ifdef _DEBUG
+#include <crtdbg.h>
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// Linux-specific includes
+//////////////////////////////////////////////////////////////////////////////
+
+#elif defined(LINUX)
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <syslog.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+//////////////////////////////////////////////////////////////////////////////
+// ARM-specific includes
+//////////////////////////////////////////////////////////////////////////////
+
+#else // ARM
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#endif
+
+#include <gdmcprovprotocol.h>
+#include <gdmcinstance.h>
+#include <gdmcdevicebinding.h>
+
+#define MAX_MSGSIZE       4096
+
+extern authtok_writecb g_authtok_writecb;
+extern authtok_readcb  g_authtok_readcb;
+
+#ifdef WIN32
+#define vsnprintf _vsnprintf
+
+#pragma warning ( disable : 4996 )
+
+#endif
+
+gderror GDMCComposeErrorMessage ( gdmcinst *inst, gderror error, _u8 *msgout, _u32 *msgout_size, _u32 initial_msgout_size, const char *pszmsg, ... )
+{
+  _u32              msgsize = 0;
+  gdmc_msgheader   *header;
+  gdmc_error_msg   *body;
+  gdmc_msgtrailer  *trailer;
+  va_list           ap;
+  char             *buffer = NULL;
+  _u32              errmsgsize = 0;
+  _u32              errmsgsize_aligned;
+
+  if (NULL!=pszmsg)
+  {
+    buffer = (char*)malloc(MAX_MSGSIZE);
+
+    if (NULL!=buffer)
+    {
+      memset(buffer,0,MAX_MSGSIZE);
+      va_start(ap,pszmsg);
+      vsnprintf(buffer,MAX_MSGSIZE,pszmsg,ap);
+      va_end(ap);
+
+      errmsgsize = ((_u32)strlen(buffer))+1;
+      if (1==errmsgsize)
+        errmsgsize--;     // if empty message, then do not send anything
+    }
+  }
+
+  errmsgsize_aligned = (errmsgsize+3)&(~3);
+    
+  // compose MC_ERROR message
+
+  msgsize = sizeof(gdmc_msgheader)+sizeof(gdmc_error_msg)+errmsgsize_aligned+sizeof(gdmc_msgtrailer);
+
+  if (msgsize>initial_msgout_size)
+  {
+    if (NULL!=buffer)
+      free(buffer);
+    return GDERROR_BUFFER_TOO_SMALL;
+  }
+
+  header  = (gdmc_msgheader*)msgout;
+  body    = (gdmc_error_msg*)(msgout+sizeof(gdmc_msgheader));
+  trailer = (gdmc_msgtrailer*)(msgout+sizeof(gdmc_msgheader)+sizeof(gdmc_error_msg)+errmsgsize_aligned);
+
+  header->msg_type    = MC_ERROR;
+  header->body_size   = sizeof(gdmc_error_msg)+errmsgsize;
+
+  body->errorcode     = error;
+  body->errmsg_length = errmsgsize_aligned;
+
+  if ((NULL!=buffer) && (0!=errmsgsize))
+  {
+    memset(body->errmsg,0,errmsgsize_aligned);
+    memcpy(body->errmsg,buffer,errmsgsize);
+  }
+
+  if (NULL!=buffer)
+    free(buffer);
+
+  trailer->magic = ~MC_ERROR;
+  trailer->crc32 = CalcCRC32(msgout,msgsize-sizeof(_u32));
+
+  *msgout_size = msgsize;
+
+  return GDERROR_OK;
+}
+
+gderror GDPROVAPI GDMCValidateProvMessage ( const _u8        *msg, 
+                                            _u32              msgsize,
+                                            gdmc_msgheader  **ppheader,
+                                            _u8             **ppbody,
+                                            gdmc_msgtrailer **pptrailer )
+{
+  _u32              expected_msgsize, aligned_body_size;
+  _u32              crc32;
+  gdmc_error_msg   *errmsg;
+  gdmc_actmsg_resp *actmsg;
+
+  *ppheader   = NULL;
+  *ppbody     = NULL;
+  *pptrailer  = NULL;
+
+  if (msgsize<(sizeof(gdmc_msgheader)+sizeof(gdmc_msgtrailer)))
+    return GDERROR_MESSAGE_FORMAT;
+
+  if (msgsize&3)
+    return GDERROR_MESSAGE_FORMAT;
+
+  if (IsBadReadPtr(msg,sizeof(gdmc_msgheader)+sizeof(gdmc_msgtrailer)))
+    return GDERROR_PARAMETER;
+
+  *ppheader = (gdmc_msgheader*)msg;
+
+  aligned_body_size = ((*ppheader)->body_size+3)&(~3);
+
+  expected_msgsize = sizeof(gdmc_msgheader)+sizeof(gdmc_msgtrailer)+aligned_body_size;
+
+  if (msgsize!=expected_msgsize)
+    return GDERROR_MESSAGE_FORMAT;
+
+  if (IsBadReadPtr(msg,expected_msgsize))
+    return GDERROR_PARAMETER;
+
+  *ppbody    = (_u8*)(msg+sizeof(gdmc_msgheader));
+  *pptrailer = (gdmc_msgtrailer*)((*ppbody)+aligned_body_size);
+
+  if ( (*ppheader)->msg_type != (~((*pptrailer)->magic)) )
+    return GDERROR_MESSAGE_FORMAT;
+
+  crc32 = CalcCRC32(msg,msgsize-sizeof(_u32));
+
+  if ( crc32 != (*pptrailer)->crc32 )
+    return GDERROR_CRC32;
+
+  switch((*ppheader)->msg_type)
+  {
+    case MC_GETSUID_REQ:
+      if ( 0!=(*ppheader)->body_size)
+        return GDERROR_MESSAGE_FORMAT;
+      break;
+
+    case MC_GETSUID_RESP:
+      if ( SUID_LENGTH!=(*ppheader)->body_size)
+        return GDERROR_MESSAGE_FORMAT;
+      break;
+
+    case MC_GENAUTHTOKEN_REQ:
+      if ( sizeof(gdmc_actmsg_req)!=(*ppheader)->body_size)
+        return GDERROR_MESSAGE_FORMAT;
+      if ( MC_CMP_CMD_GENERATE_AUTH_TOKEN != ((gdmc_actmsg_req*)(*ppbody))->msg_type )
+        return GDERROR_MESSAGE_FORMAT;
+      break;
+
+    case MC_GENAUTHTOKEN_RESP:
+      if ( sizeof(gdmc_actmsg_resp)!=(*ppheader)->body_size)
+        return GDERROR_MESSAGE_FORMAT;
+      actmsg = (gdmc_actmsg_resp*)*ppbody;
+      if ( (MC_CMP_CMD_GENERATE_AUTH_TOKEN|0x80000000) != actmsg->msg_type )
+        return GDERROR_MESSAGE_FORMAT;
+      if ( (SUID_LENGTH+(sizeof(_u32)*3)) != actmsg->authtok.plain_length)
+        return GDERROR_MESSAGE_FORMAT;
+      if ( (K_SOC_AUTH_LENGTH/*+SHA256_HASH_LENGTH+AES_BLOCK_SIZE*/) != actmsg->authtok.encrypted_length )
+        return GDERROR_MESSAGE_FORMAT;
+      if ( AUTHENTICATION_TOKEN != actmsg->authtok.type )
+        return GDERROR_MESSAGE_FORMAT;
+      if ( CONTEXT_SYSTEM != actmsg->authtok.context )
+        return GDERROR_MESSAGE_FORMAT;
+      if ( CONT_TYPE_SOC != actmsg->authtok.contType )
+        return GDERROR_MESSAGE_FORMAT;
+      if ( MC_CONT_STATE_ACTIVATED != actmsg->authtok.contState )
+        return GDERROR_MESSAGE_FORMAT;
+      break;
+
+    case MC_VALIDATEAUTHTOKEN_REQ:
+      if ( sizeof(gdmc_so_authtok)!=(*ppheader)->body_size)
+        return GDERROR_MESSAGE_FORMAT;
+      break;
+
+    case MC_ERROR:
+      if ( (*ppheader)->body_size<sizeof(gdmc_error_msg))
+        return GDERROR_MESSAGE_FORMAT;
+      errmsg = (gdmc_error_msg*)*ppbody;
+      if ( (*ppheader)->body_size!=(errmsg->errmsg_length+sizeof(gdmc_error_msg)) )
+        return GDERROR_MESSAGE_FORMAT;
+      break;
+
+    default:
+      return GDERROR_MESSAGE_FORMAT;
+  }
+
+  return GDERROR_OK;
+}
+
+gderror GDPROVAPI GDMCHandleGetSUID ( gdmcinst *inst,
+                                      _u8      *msgout,
+                                      _u32     *msgout_size,
+                                      _u32      initial_msgout_size )
+{
+  _u32              msgsize = sizeof(gdmc_msgheader)+SUID_LENGTH+sizeof(gdmc_msgtrailer);
+  gdmc_msgheader   *header  = (gdmc_msgheader*)msgout;
+  _u8              *body    = msgout+sizeof(gdmc_msgheader);
+  gdmc_msgtrailer  *trailer = (gdmc_msgtrailer*)(msgout+sizeof(gdmc_msgheader)+SUID_LENGTH);
+  gderror           error;
+
+  if (msgsize>initial_msgout_size)
+    return GDMCComposeErrorMessage(inst,GDERROR_BUFFER_TOO_SMALL,msgout,msgout_size,initial_msgout_size,
+                                   ERRMSG_0005,initial_msgout_size,msgsize);
+
+  if (inst->state<GDMC_STATE_HAVE_SUID) // request SUID from MobiCore
+  {
+    error = MCGetSUID(inst->suid);
+
+    if (GDERROR_OK!=error)
+      return GDMCComposeErrorMessage(inst,error,msgout,msgout_size,initial_msgout_size,
+                                     ERRMSG_000D);
+
+    inst->state = GDMC_STATE_HAVE_SUID;
+  }
+
+  // We have the SUID, so return the message to the caller
+
+  header->msg_type  = MC_GETSUID_RESP;
+  header->body_size = SUID_LENGTH;
+
+  memcpy(body,inst->suid,SUID_LENGTH);
+
+  trailer->magic   = ~MC_GETSUID_RESP;
+  trailer->crc32   = CalcCRC32(msgout,msgsize-sizeof(_u32));
+
+  *msgout_size = msgsize;
+
+  return GDERROR_OK;
+}
+
+gderror GDPROVAPI GDMCHandleGenAuthToken ( gdmcinst          *inst,
+                                           gdmc_actmsg_req   *req,
+                                          _u8                *msgout,
+                                          _u32               *msgout_size,
+                                          _u32                initial_msgout_size )
+{
+  _u32              msgsize = sizeof(gdmc_msgheader)+sizeof(gdmc_actmsg_resp)+sizeof(gdmc_msgtrailer);
+  gdmc_msgheader   *header  = (gdmc_msgheader*)msgout;
+  gdmc_actmsg_resp *body    = (gdmc_actmsg_resp*)(msgout+sizeof(gdmc_msgheader));
+  gdmc_msgtrailer  *trailer = (gdmc_msgtrailer*)(msgout+sizeof(gdmc_msgheader)+sizeof(gdmc_actmsg_resp));
+  gderror           error;
+
+  if (msgsize>initial_msgout_size)
+    return GDMCComposeErrorMessage(inst,GDERROR_BUFFER_TOO_SMALL,msgout,msgout_size,initial_msgout_size,
+                                   ERRMSG_0005,initial_msgout_size,msgsize);
+
+  switch(inst->state)
+  {
+    case GDMC_STATE_INITIAL: // We do not have the SUID, so get it...
+      error = GDMCHandleGetSUID(inst,msgout,msgout_size,initial_msgout_size);
+      if (GDERROR_OK!=error)
+        return error;
+
+      // discard this message...
+
+      memset(msgout,0,initial_msgout_size);
+      *msgout_size = 0;
+
+      // fall through...
+
+    case GDMC_STATE_HAVE_SUID: // We have the SUID but no SO.AuthToken (yet)
+
+      GenerateAuthToken:
+
+      memcpy(inst->kSoCAuth,req->kSoCAuth,sizeof(inst->kSoCAuth)); // save K.SoC.Auth
+
+      error = MCGenerateAuthToken(inst,req,&inst->authTok);
+
+      if (GDERROR_OK!=error)
+        return GDMCComposeErrorMessage(inst,error,msgout,msgout_size,initial_msgout_size,ERRMSG_000E);
+
+      if (NULL!=g_authtok_writecb)
+      {
+        error = g_authtok_writecb((const _u8 *)&inst->authTok,sizeof(gdmc_so_authtok));
+        if (GDERROR_OK!=error)
+          return GDMCComposeErrorMessage(inst,error,msgout,msgout_size,initial_msgout_size,ERRMSG_000C);
+      }
+
+      header->msg_type  = MC_GENAUTHTOKEN_RESP;
+      header->body_size = sizeof(gdmc_actmsg_resp);
+
+      body->msg_type = MC_CMP_CMD_GENERATE_AUTH_TOKEN|0x80000000;
+      memcpy(&body->authtok,&inst->authTok,sizeof(gdmc_so_authtok));
+
+      trailer->magic   = ~MC_GENAUTHTOKEN_RESP;
+      trailer->crc32   = CalcCRC32(msgout,msgsize-sizeof(_u32));
+
+      *msgout_size = msgsize;
+
+      if (inst->state<GDMC_STATE_HAVE_AUTHTOK)
+        inst->state = GDMC_STATE_HAVE_AUTHTOK;
+
+      return GDERROR_OK;
+
+    default: //case GDMC_STATE_HAVE_AUTHTOK: -> We have already the SO.AuthTok, check if K.SoC.Auth still matches!!!
+
+      if (memcmp(inst->kSoCAuth,req->kSoCAuth,sizeof(inst->kSoCAuth)))
+      {
+        // Oh oh... the KPH generated a new K.SoC.Auth and our SO.AuthToken is invalid now... (generate new one)
+
+        memset(&inst->authTok,0,sizeof(inst->authTok));
+        inst->state = GDMC_STATE_HAVE_SUID;
+        goto GenerateAuthToken;
+      }
+
+      // Okay, K.SoC.Auth still matches and we still have the SO.AuthToken
+
+      header->msg_type  = MC_GENAUTHTOKEN_RESP;
+      header->body_size = sizeof(gdmc_actmsg_resp);
+
+      body->msg_type = MC_CMP_CMD_GENERATE_AUTH_TOKEN|0x80000000;
+      memcpy(&body->authtok,&inst->authTok,sizeof(gdmc_so_authtok));
+
+      trailer->magic   = ~MC_GENAUTHTOKEN_RESP;
+      trailer->crc32   = CalcCRC32(msgout,msgsize-sizeof(_u32));
+
+      *msgout_size = msgsize;
+
+      return GDERROR_OK;
+  }
+}
+
+gderror GDPROVAPI GDMCHandleValidateAuthToken ( gdmcinst         *inst,
+                                                gdmc_so_authtok  *validateSoAuthTok,
+                                                _u8              *msgout,
+                                                _u32             *msgout_size,
+                                                _u32              initial_msgout_size )
+{
+  _u32              msgsize = sizeof(gdmc_msgheader)+sizeof(gdmc_error_msg)+sizeof(gdmc_msgtrailer);
+  gdmc_msgheader   *header  = (gdmc_msgheader*)msgout;
+  gdmc_error_msg   *body    = (gdmc_error_msg*)(msgout+sizeof(gdmc_msgheader));
+  gdmc_msgtrailer  *trailer = (gdmc_msgtrailer*)(msgout+sizeof(gdmc_msgheader)+sizeof(gdmc_error_msg));
+  gderror           error;
+  gdmc_so_authtok   rb_authtok;
+  _u32              rb_authtok_size;
+
+  if (msgsize>initial_msgout_size)
+    return GDMCComposeErrorMessage(inst,GDERROR_BUFFER_TOO_SMALL,msgout,msgout_size,initial_msgout_size,
+                                   ERRMSG_0005,initial_msgout_size,msgsize);
+
+  if (GDMC_STATE_HAVE_AUTHTOK!=inst->state) // Too early call: We do not have an SO.AuthToken to be validated!
+    return GDMCComposeErrorMessage(inst,GDERROR_VALIDATION_FAILURE,msgout,msgout_size,initial_msgout_size,
+                                   ERRMSG_000F,initial_msgout_size,msgsize);
+
+  header->msg_type  = MC_ERROR;
+  header->body_size = sizeof(gdmc_error_msg);
+
+  body->errorcode = GDERROR_PROVISIONING_DONE;
+
+  // 1.) First of all, compare the delivered SO.AuthToken with the one we have stored in our instance
+
+  if (memcmp(validateSoAuthTok,&inst->authTok,sizeof(gdmc_so_authtok)))
+  {
+    body->errorcode = GDERROR_VALIDATION_FAILURE;
+  }
+  else
+  {
+    // 2.) Perform readback (if available) and re-check auth token
+
+    if (NULL!=g_authtok_readcb)
+    {
+      rb_authtok_size = sizeof(rb_authtok);
+
+      error = g_authtok_readcb((_u8*)&rb_authtok,&rb_authtok_size);
+
+      if (GDERROR_OK!=error)
+        body->errorcode = error;
+      else
+      {
+        if ( (rb_authtok_size!=sizeof(gdmc_so_authtok)) ||
+             (memcmp(validateSoAuthTok,&rb_authtok,sizeof(gdmc_so_authtok))) )
+          body->errorcode = GDERROR_VALIDATION_FAILURE;
+      }
+    }
+  }
+
+  trailer->magic   = ~MC_ERROR;
+  trailer->crc32   = CalcCRC32(msgout,msgsize-sizeof(_u32));
+
+  *msgout_size = msgsize;
+
+  return GDERROR_PROVISIONING_DONE;
+}
+
diff --git a/mobicore/provlib/src/gdmcprovlib.cpp b/mobicore/provlib/src/gdmcprovlib.cpp
new file mode 100644
index 0000000..9c6dae7
--- /dev/null
+++ b/mobicore/provlib/src/gdmcprovlib.cpp
@@ -0,0 +1,399 @@
+///
+/// @file       gdmcprovlib.cpp
+/// @author     Giesecke & Devrient GmbH, Munich, Germany
+///
+/// Implementation of the API functions (Provisioning
+/// Library)
+///
+
+#include <gdmcprovlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+//////////////////////////////////////////////////////////////////////////////
+// MS Windows-specific includes
+//////////////////////////////////////////////////////////////////////////////
+
+#if defined(WIN32)
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+static HMODULE g_hInstance = NULL;
+
+//////////////////////////////////////////////////////////////////////////////
+// Linux-specific includes
+//////////////////////////////////////////////////////////////////////////////
+
+#elif defined(LINUX)
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <syslog.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+//////////////////////////////////////////////////////////////////////////////
+// ARM-specific includes
+//////////////////////////////////////////////////////////////////////////////
+
+#else // ARM
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#endif
+
+#include <gdmcprovprotocol.h>
+#include <gdmcinstance.h>
+#include <gdmcdevicebinding.h>
+
+extern "C" {
+extern bool mccmOpen ( void );
+extern void mccmClose ( void );
+}
+
+authtok_writecb         g_authtok_writecb = NULL;
+authtok_readcb          g_authtok_readcb  = NULL;
+
+//////////////////////////////////////////////////////////////////////////////
+// API functions (implementation)
+//////////////////////////////////////////////////////////////////////////////
+
+// this API function is not available on ARM
+static gderror GDPROVAPI _GDMCProvFormatErrorMessage ( 
+                              gdhandle provhandle,
+                              gderror  errorcode,
+                              char    *msgbuf, 
+                              _u32    *size )
+{
+  return GDERROR_NOT_IMPLEMENTED;
+}
+
+static gderror GDPROVAPI _GDMCProvInitializeLibrary ( void )
+{
+  if (unlikely( !mccmOpen() ))
+    return GDERROR_MOBICORE_LIBRARY;
+
+  return GDERROR_OK;
+}
+
+static gderror GDPROVAPI _GDMCProvShutdownLibrary ( void )
+{
+  mccmClose();
+  return GDERROR_OK;
+}
+
+static gderror GDPROVAPI _GDMCProvBeginProvisioning ( gdhandle *provhandle )
+{
+  gdmcinst       *inst;
+
+  if (IsBadWritePtr(provhandle,sizeof(gdhandle)))
+    return GDERROR_PARAMETER;
+
+  inst = (gdmcinst*)malloc(sizeof(gdmcinst));
+
+  if (NULL==inst)
+  {
+    *provhandle = 0;
+    return GDERROR_INSUFFICIENT_MEMORY;
+  }
+
+  memset(inst,0,sizeof(gdmcinst));
+
+  *provhandle = (gdhandle)inst;
+
+  return GDERROR_OK;
+}
+
+static gderror GDPROVAPI _GDMCProvEndProvisioning ( gdhandle provhandle )
+{
+  gdmcinst       *inst = (gdmcinst*)provhandle;
+
+  if (IsBadWritePtr(inst,sizeof(gdmcinst)))
+    return GDERROR_PARAMETER;
+
+  free(inst);
+
+  return GDERROR_OK;
+}
+
+static gderror GDPROVAPI _GDMCProvExecuteProvisioningStep ( 
+                  gdhandle    provhandle,
+                  const _u8  *msgin,
+                  _u32        msgin_size,
+                  _u8        *msgout,
+                  _u32       *msgout_size )
+{
+  gderror           error       = GDERROR_OK;
+  gdmcinst         *inst        = (gdmcinst*)provhandle;
+  gdmc_msgheader   *header      = NULL;
+  _u8              *body        = NULL;
+  gdmc_msgtrailer  *trailer     = NULL;
+  _u32              initial_msgout_size;
+
+  // 1.) Prolog: Check parameters...
+
+  if (IsBadWritePtr(inst,sizeof(gdmcinst)))
+    return GDERROR_PARAMETER;
+
+  if ((0!=msgin_size) && (IsBadReadPtr(msgin,msgin_size)))
+    return GDERROR_PARAMETER;
+
+  if (IsBadWritePtr(msgout_size,sizeof(_u32)))
+    return GDERROR_PARAMETER;
+
+  initial_msgout_size = *msgout_size;
+
+  if (0!=*msgout_size)
+  {
+    if (IsBadWritePtr(msgout,*msgout_size))
+      return GDERROR_PARAMETER;
+    memset(msgout,0,*msgout_size);
+  }
+
+  *msgout_size = 0;
+
+  // 2.) Evaluate the message that has been received
+
+  error = GDMCValidateProvMessage(msgin,msgin_size,&header,&body,&trailer);
+  
+  if (GDERROR_OK!=error) // something is wrong with the received message
+    return GDMCComposeErrorMessage(inst,error,msgout,msgout_size,initial_msgout_size,ERRMSG_0006);
+
+  // 3.) Check which message has been received
+
+  switch(header->msg_type)
+  {
+    case MC_GETSUID_REQ:
+      return GDMCHandleGetSUID(inst,msgout,msgout_size,initial_msgout_size);
+
+    case MC_GENAUTHTOKEN_REQ:
+      return GDMCHandleGenAuthToken(inst,(gdmc_actmsg_req*)body,msgout,msgout_size,initial_msgout_size);
+
+    case MC_VALIDATEAUTHTOKEN_REQ:
+      return GDMCHandleValidateAuthToken(inst,(gdmc_so_authtok*)body,msgout,msgout_size,initial_msgout_size);
+
+    default:
+      return GDMCComposeErrorMessage(inst,GDERROR_UNKNOWN,msgout,msgout_size,initial_msgout_size,ERRMSG_0007);
+  }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Structured Exception Handling (Windows only)
+//////////////////////////////////////////////////////////////////////////////
+
+#if defined(WIN32) && !defined(_NO_STRUCTURED_EXCEPTIONS)
+
+static DWORD GDPROVAPI HandleStructuredException ( DWORD dwExcepCode )
+{
+#ifndef _DEBUG
+  return EXCEPTION_EXECUTE_HANDLER;
+#else // _DEBUG
+  switch(dwExcepCode)
+  {
+    case EXCEPTION_BREAKPOINT:
+    case EXCEPTION_SINGLE_STEP:
+      return EXCEPTION_CONTINUE_SEARCH;
+    default:
+      return EXCEPTION_EXECUTE_HANDLER;
+  }
+#endif
+}
+
+#define SE_TRY          __try {
+#define SE_CATCH        } __except(HandleStructuredException(GetExceptionCode())) { return GDERROR_CPU_EXCEPTION; }
+
+#else // !WIN32 || _NO_STRUCTURED_EXCEPTIONS
+
+#define SE_TRY
+#define SE_CATCH
+
+#endif // WIN32
+
+//////////////////////////////////////////////////////////////////////////////
+// API functions (exported)
+//////////////////////////////////////////////////////////////////////////////
+
+extern "C" _u32 GDPROVAPI GDMCProvGetVersion ( void )
+{
+  return GDMCPROVLIB_VERSION;
+}
+
+extern "C" gderror GDPROVAPI GDMCProvFormatErrorMessage ( 
+                              gdhandle provhandle,
+                              gderror  errorcode,
+                              char    *msgbuf, 
+                              _u32    *size )
+{
+  SE_TRY // MUST BE FIRST INSTRUCTION ////////////////////////////////////////
+
+  return _GDMCProvFormatErrorMessage(provhandle,errorcode,msgbuf,size);
+
+  SE_CATCH // MUST BE LAST INSTRUCTION ///////////////////////////////////////
+}
+
+extern "C" gderror GDPROVAPI GDMCProvInitializeLibrary ( void )
+{
+  SE_TRY // MUST BE FIRST INSTRUCTION ////////////////////////////////////////
+
+  return _GDMCProvInitializeLibrary();
+
+  SE_CATCH // MUST BE LAST INSTRUCTION ///////////////////////////////////////
+}
+
+extern "C" gderror GDPROVAPI GDMCProvShutdownLibrary ( void )
+{
+  SE_TRY // MUST BE FIRST INSTRUCTION ////////////////////////////////////////
+
+  return _GDMCProvShutdownLibrary();
+
+  SE_CATCH // MUST BE LAST INSTRUCTION ///////////////////////////////////////
+}
+
+extern "C" gderror GDPROVAPI GDMCProvBeginProvisioning ( gdhandle *provhandle )
+{
+  SE_TRY // MUST BE FIRST INSTRUCTION ////////////////////////////////////////
+
+  return _GDMCProvBeginProvisioning(provhandle);
+
+  SE_CATCH // MUST BE LAST INSTRUCTION ///////////////////////////////////////
+}
+
+extern "C" gderror GDPROVAPI GDMCProvEndProvisioning ( gdhandle provhandle )
+{
+  SE_TRY // MUST BE FIRST INSTRUCTION ////////////////////////////////////////
+
+  return _GDMCProvEndProvisioning(provhandle);
+
+  SE_CATCH // MUST BE LAST INSTRUCTION ///////////////////////////////////////
+}
+
+extern "C" gderror GDPROVAPI GDMCProvExecuteProvisioningStep ( 
+                  gdhandle    provhandle,
+                  const _u8  *msgin,
+                  _u32        msgin_size,
+                  _u8        *msgout,
+                  _u32       *msgout_size )
+{
+  SE_TRY // MUST BE FIRST INSTRUCTION ////////////////////////////////////////
+
+  return _GDMCProvExecuteProvisioningStep(provhandle,msgin,msgin_size,
+                                          msgout,msgout_size);
+
+  SE_CATCH // MUST BE LAST INSTRUCTION ///////////////////////////////////////
+}
+
+extern "C" gderror GDPROVAPI GDMCProvFormatReceipt (
+                  const _u8  *receipt,
+                  _u32        receipt_size,
+                  _u8        *fmt_receipt,
+                  _u32       *fmt_receipt_size )
+{
+  return GDERROR_NOT_IMPLEMENTED;
+}
+
+extern "C"  gderror GDPROVAPI GDMCProvGetSUID (
+                  gdhandle    provhandle,
+                  _u8        *suid )
+{
+  return GDERROR_NOT_IMPLEMENTED;
+}
+
+extern "C" gderror GDPROVAPI GDMCProvSetAuthTokenCallbacks ( 
+                              authtok_writecb writefunc,
+                              authtok_readcb  readfunc )
+{
+  g_authtok_writecb = writefunc;
+  g_authtok_readcb  = readfunc;
+
+  return GDERROR_OK;
+}
+
+extern "C" gderror GDPROVAPI GDMCProvSetConfigurationString (
+                  const char *config_string )
+{
+#ifdef ARM
+
+  return GDERROR_NOT_IMPLEMENTED;
+
+#else
+
+  SE_TRY // MUST BE FIRST INSTRUCTION ////////////////////////////////////////
+
+  return GDERROR_OK;
+
+  SE_CATCH // MUST BE LAST INSTRUCTION ///////////////////////////////////////
+
+#endif
+}
+
+#ifdef WIN32
+
+/// DLL main function required by MS Windows DLLs
+///
+/// @param[in]  hinstDLL      instance handle (module)
+/// @param[in]  fdwReason     reason for calling (attach, detach, ...)
+/// @param[in]  lpvReserved   reserved
+///
+/// @return     TRUE if DLL loading/unloading successful, FALSE otherwise
+BOOL WINAPI DllMain ( HINSTANCE hinstDLL,
+                      DWORD     fdwReason,
+                      LPVOID    lpvReserved )
+{
+  switch(fdwReason)
+  {
+    case DLL_PROCESS_ATTACH:
+      // We don't need additional calls with DLL_THREAD_ATTACH.
+      g_hInstance = (HMODULE)hinstDLL;
+      DisableThreadLibraryCalls(hinstDLL);
+      InitCRCTable();
+      return TRUE;
+    case DLL_PROCESS_DETACH:  // fall through
+    case DLL_THREAD_ATTACH:   // fall through
+    case DLL_THREAD_DETACH:
+      return TRUE;
+    default:
+      break;
+  }
+  return FALSE;
+}
+
+#else // library initialization and cleanup (Linux/ARM)
+
+void gdmcprovlib_init ( void ) __attribute__((constructor));
+void gdmcprovlib_fini ( void ) __attribute__((destructor));
+
+/// shared object global initialization function; gets automatically
+/// called when library is loaded
+void gdmcprovlib_init ( void )
+{
+  InitCRCTable();
+}
+
+/// shared object global cleanup function; gets automatically
+/// called when library is unloaded
+void gdmcprovlib_fini ( void )
+{
+
+}
+
+#endif // WIN32
+
+
diff --git a/mobicore/provlib/src/mobicore.c b/mobicore/provlib/src/mobicore.c
new file mode 100644
index 0000000..2f4e419
--- /dev/null
+++ b/mobicore/provlib/src/mobicore.c
@@ -0,0 +1,587 @@
+#ifndef _SBL_VERSION // SBL = Secondary Bootloader Version
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <gdmcprovlib.h>
+#include <gdmcprovprotocol.h>
+#include <gdmcinstance.h>
+
+typedef struct tagMCCM        MCCM;
+
+struct tagMCCM
+{
+  cmp_t                *cmp;          ///< World Shared Memory (WSM) to the TCI buffer
+  mcSessionHandle_t     sess;         ///< session handle
+  mcResult_t            lasterror;    ///< last MC driver error
+  cmpReturnCode_t       lastcmperr;   ///< last Content Management Protocol error
+  uint32_t              lastmccmerr;  ///< error code from MCCM (MobiCore Content Management) library
+};
+
+static MCCM g_mccm;
+
+// Copied from MCCM library not to have this additional dependency!
+
+// returns 1 if successful, 0 otherwise
+bool mccmOpen ( void )
+{
+  const mcUuid_t      UUID = TL_CM_UUID;
+  mcResult_t          result;
+
+  memset(&g_mccm,0,sizeof(MCCM));
+
+  result = mcOpenDevice(MC_DEVICE_ID_DEFAULT);
+
+  if (MC_DRV_OK != result) 
+    return false;
+
+  result = mcMallocWsm(MC_DEVICE_ID_DEFAULT, 0, sizeof(cmp_t), (uint8_t **)&g_mccm.cmp, 0);
+  if (MC_DRV_OK != result) 
+  {
+    mcCloseDevice(MC_DEVICE_ID_DEFAULT);
+    return false;
+  }
+
+  result = mcOpenSession(&g_mccm.sess,(const mcUuid_t *)&UUID,(uint8_t *)g_mccm.cmp,(uint32_t)sizeof(cmp_t));
+  if (MC_DRV_OK != result)
+  {
+    mcFreeWsm(MC_DEVICE_ID_DEFAULT,(uint8_t*)g_mccm.cmp);
+    mcCloseDevice(MC_DEVICE_ID_DEFAULT);
+    return false;
+  }
+
+  return true;
+}
+
+void mccmClose ( void )
+{
+  mcCloseSession(&g_mccm.sess);
+
+  if (NULL!=g_mccm.cmp)
+    mcFreeWsm(MC_DEVICE_ID_DEFAULT,(uint8_t*)g_mccm.cmp);
+
+  mcCloseDevice(MC_DEVICE_ID_DEFAULT);
+
+  memset(&g_mccm,0,sizeof(MCCM));
+}
+
+static bool mccmTransmit ( int32_t timeout )
+{
+  // Send CMP message to content management trustlet.
+
+  g_mccm.lasterror = mcNotify(&g_mccm.sess);
+
+  if (unlikely( MC_DRV_OK!=g_mccm.lasterror ))
+    return false;
+
+  // Wait for trustlet response.
+
+  g_mccm.lasterror = mcWaitNotification(&g_mccm.sess, timeout);
+
+  if (unlikely( MC_DRV_OK!=g_mccm.lasterror )) 
+    return false;
+
+  return true;
+}
+
+static bool mccmGetSuid ( mcSuid_t *suid )
+{
+  g_mccm.lastcmperr = SUCCESSFUL;
+
+  memset(g_mccm.cmp,0,sizeof(cmp_t));
+  g_mccm.cmp->msg.cmpCmdGetSuid.cmdHeader.commandId = MC_CMP_CMD_GET_SUID;
+
+  if (unlikely( !mccmTransmit(MC_INFINITE_TIMEOUT) ))
+    return false;
+
+  if (unlikely( (MC_CMP_CMD_GET_SUID|RSP_ID_MASK)!=g_mccm.cmp->msg.cmpRspGetSuid.rspHeader.responseId ))
+  {
+    g_mccm.lasterror = MC_DRV_ERR_UNKNOWN;
+    return false;
+  }
+
+  g_mccm.lastcmperr = g_mccm.cmp->msg.cmpRspGetSuid.rspHeader.returnCode;
+  
+  if (unlikely( SUCCESSFUL!=g_mccm.lastcmperr ))
+  {
+    g_mccm.lasterror = MC_DRV_ERR_UNKNOWN;
+    return false;
+  }
+
+  memcpy(suid,&g_mccm.cmp->msg.cmpRspGetSuid.suid,sizeof(mcSuid_t));
+
+  return true;
+}
+
+static bool mccmGenerateAuthToken ( 
+                      const cmpCmdGenAuthToken_t *cmd, 
+                      cmpRspGenAuthToken_t       *rsp )
+{
+  g_mccm.lastcmperr = SUCCESSFUL;
+
+  memset(g_mccm.cmp,0,sizeof(cmp_t));
+  
+  memcpy(g_mccm.cmp,cmd,sizeof(*cmd));
+
+  if (unlikely( !mccmTransmit(MC_INFINITE_TIMEOUT) ))
+    return false;
+
+  if (unlikely( (cmd->cmd.sdata.cmdHeader.commandId|RSP_ID_MASK)!=g_mccm.cmp->msg.cmpRspGenAuthToken.rsp.rspHeader.responseId ))
+  {
+    g_mccm.lasterror = MC_DRV_ERR_UNKNOWN;
+    return false;
+  }
+
+  g_mccm.lastcmperr = g_mccm.cmp->msg.cmpRspGenAuthToken.rsp.rspHeader.returnCode;
+  
+  if (unlikely( SUCCESSFUL!=g_mccm.lastcmperr ))
+  {
+    g_mccm.lasterror = MC_DRV_ERR_UNKNOWN;
+    return false;
+  }
+
+  memcpy(rsp,g_mccm.cmp,sizeof(*rsp));
+
+  return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// Convenience functions
+///////////////////////////////////////////////////////////////////////////////////////////
+
+gderror MCGetSUID ( _u8 *suid )
+{
+  if (unlikely( NULL==suid ))
+    return GDERROR_PARAMETER;
+
+  memset(suid,0,SUID_LENGTH);
+
+  if (!mccmGetSuid((mcSuid_t*)suid))
+    return GDERROR_CANT_GET_SUID;
+
+  return GDERROR_OK;
+}
+
+gderror MCGenerateAuthToken ( gdmcinst *inst, const gdmc_actmsg_req *req, gdmc_so_authtok *authtok )
+{
+  cmpRspGenAuthToken_t    rsp;
+
+  if (unlikely( NULL==inst || NULL==req || NULL==authtok ))
+    return GDERROR_PARAMETER;
+
+  memset(authtok,0,sizeof(gdmc_so_authtok));
+
+  if (MC_CMP_CMD_GENERATE_AUTH_TOKEN!=req->msg_type)
+    return GDERROR_MESSAGE_FORMAT;
+
+  if (!mccmGenerateAuthToken((const cmpCmdGenAuthToken_t *)req,&rsp))
+    return GDERROR_CANT_BUILD_AUTHTOKEN;
+
+  memcpy(authtok,&rsp.soAuthCont,sizeof(*authtok));
+
+  return GDERROR_OK;
+}
+
+#else // Secondary Bootloader Version
+
+#define _NO_OPENSSL_INCLUDES
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <gdmcprovlib.h>
+#include <gdmcprovprotocol.h>
+#include <gdmcinstance.h>
+
+#define SHA256_BLOCK_LENGTH		64
+#define SHA256_DIGEST_LENGTH		32
+#define SHA256_DIGEST_STRING_LENGTH	(SHA256_DIGEST_LENGTH * 2 + 1)
+
+typedef unsigned char u_int8_t;		/* 1-byte  (8-bits)  */
+typedef unsigned int u_int32_t;		/* 4-bytes (32-bits) */
+typedef unsigned long long u_int64_t;	/* 8-bytes (64-bits) */
+
+typedef unsigned char  sha2_byte;	/* Exactly 1 byte */
+typedef unsigned int sha2_word32;	/* Exactly 4 bytes */
+typedef unsigned long long sha2_word64;	/* Exactly 8 bytes */
+
+typedef struct _SHA256_CTX {
+	u_int32_t	state[8];
+	u_int64_t	bitcount;
+	u_int8_t	buffer[SHA256_BLOCK_LENGTH];
+} SHA256_CTX;
+
+static void SHA256(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]);
+
+gderror MCGetSUID ( gdmcinst *inst, _u8 suid[SUID_LENGTH] )
+{
+  inst->suid[ 0] = 0x11;
+  inst->suid[ 1] = 0x22;
+  inst->suid[ 2] = 0x33;
+  inst->suid[ 3] = 0x44;
+  inst->suid[ 4] = 0x55;
+  inst->suid[ 5] = 0x66;
+  inst->suid[ 6] = 0x77;
+  inst->suid[ 7] = 0x88;
+  inst->suid[ 8] = 0x99;
+  inst->suid[ 9] = 0xAA;
+  inst->suid[10] = 0xBB;
+  inst->suid[11] = 0xCC;
+  inst->suid[12] = 0xDD;
+  inst->suid[13] = 0xEE;
+  inst->suid[14] = 0xFF;
+  inst->suid[15] = 0xFE;
+
+  memcpy(suid,inst->suid,SUID_LENGTH);
+
+  return GDERROR_OK;
+}
+
+gderror MCGenerateAuthToken ( gdmcinst *inst, const gdmc_actmsg_req *req, gdmc_so_authtok *authtok )
+{
+  _u8                 md[SHA256_DIGEST_LENGTH];
+  mcSoAuthTokenCont_t tok;
+
+  memset(&tok,0,sizeof(tok));
+  memset(authtok,0,sizeof(gdmc_so_authtok));
+
+  if (MC_CMP_CMD_GENERATE_AUTH_TOKEN!=req->msg_type)
+    return GDERROR_MESSAGE_FORMAT;
+
+  SHA256((const unsigned char *)req,offsetof(gdmc_actmsg_req,md),md);  // hash it...
+
+  if (memcmp(md,req->md,SHA256_DIGEST_LENGTH))
+    return GDERROR_MESSAGE_DIGEST;
+
+  if (memcmp(inst->suid,req->suid,SUID_LENGTH))
+    return GDERROR_SUID_MISMATCH;
+
+  // Header:
+
+  tok.soHeader.type         = MC_SO_TYPE_REGULAR;
+  tok.soHeader.version      = 1;
+  tok.soHeader.context      = MC_SO_CONTEXT_DEVICE;
+  tok.soHeader.plainLen     = sizeof(tok.coSoc.type)+
+                              sizeof(tok.coSoc.attribs)+
+                              sizeof(tok.coSoc.suid);
+  tok.soHeader.encryptedLen = sizeof(tok.coSoc.co);
+
+  // Plain data:
+
+  tok.coSoc.type          = CONT_TYPE_SOC;
+  tok.coSoc.attribs.state = MC_CONT_STATE_ACTIVATED;
+
+  memcpy(&tok.coSoc.suid,inst->suid,sizeof(tok.coSoc.suid));
+
+  // Secret:
+
+  memcpy(&tok.coSoc.co.kSocAuth,&inst->kSoCAuth,sizeof(tok.coSoc.co.kSocAuth));
+
+  SHA256((const unsigned char *)&tok,
+         offsetof(mcSoAuthTokenCont_t,hashAndPad),
+         (char *)&tok.hashAndPad);
+
+  tok.hashAndPad[MC_SO_HASH_SIZE] = 0x80; // ISO-padding
+
+  memcpy(authtok,&tok,sizeof(gdmc_so_authtok));
+  
+  return GDERROR_OK;
+}
+
+#undef SHA2_UNROLL_TRANSFORM
+
+#define LITTLE_ENDIAN 1234
+#define BYTE_ORDER LITTLE_ENDIAN 
+
+#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
+#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
+#endif
+
+#define SHA256_SHORT_BLOCK_LENGTH	(SHA256_BLOCK_LENGTH - 8)
+#define SHA384_SHORT_BLOCK_LENGTH	(SHA384_BLOCK_LENGTH - 16)
+#define SHA512_SHORT_BLOCK_LENGTH	(SHA512_BLOCK_LENGTH - 16)
+
+
+/*** ENDIAN REVERSAL MACROS *******************************************/
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define REVERSE32(w,x)	{ \
+	sha2_word32 tmp = (w); \
+	tmp = (tmp >> 16) | (tmp << 16); \
+	(x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
+}
+#define REVERSE64(w,x)	{ \
+	sha2_word64 tmp = (w); \
+	tmp = (tmp >> 32) | (tmp << 32); \
+	tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \
+	      ((tmp & 0x00ff00ff00ff00ffULL) << 8); \
+	(x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
+	      ((tmp & 0x0000ffff0000ffffULL) << 16); \
+}
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+/*
+ * Macro for incrementally adding the unsigned 64-bit integer n to the
+ * unsigned 128-bit integer (represented using a two-element array of
+ * 64-bit words):
+ */
+#define ADDINC128(w,n)	{ \
+	(w)[0] += (sha2_word64)(n); \
+	if ((w)[0] < (n)) { \
+		(w)[1]++; \
+	} \
+}
+
+#define R(b,x) 		((x) >> (b))
+#define S32(b,x)	(((x) >> (b)) | ((x) << (32 - (b))))
+
+/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
+#define Ch(x,y,z)	(((x) & (y)) ^ ((~(x)) & (z)))
+#define Maj(x,y,z)	(((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+
+/* Four of six logical functions used in SHA-256: */
+#define Sigma0_256(x)	(S32(2,  (x)) ^ S32(13, (x)) ^ S32(22, (x)))
+#define Sigma1_256(x)	(S32(6,  (x)) ^ S32(11, (x)) ^ S32(25, (x)))
+#define sigma0_256(x)	(S32(7,  (x)) ^ S32(18, (x)) ^ R(3 ,   (x)))
+#define sigma1_256(x)	(S32(17, (x)) ^ S32(19, (x)) ^ R(10,   (x)))
+
+void SHA256_Transform(SHA256_CTX*, const sha2_word32*);
+
+const static sha2_word32 K256[64] = {
+	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
+	0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+	0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
+	0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+	0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+	0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
+	0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+	0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
+	0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
+	0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+	0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
+	0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+	0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+/* Initial hash value H for SHA-256: */
+const static sha2_word32 sha256_initial_hash_value[8] = {
+	0x6a09e667UL,
+	0xbb67ae85UL,
+	0x3c6ef372UL,
+	0xa54ff53aUL,
+	0x510e527fUL,
+	0x9b05688cUL,
+	0x1f83d9abUL,
+	0x5be0cd19UL
+};
+
+static void SHA256_Init(SHA256_CTX* context) 
+{
+	if (context == (SHA256_CTX*)0) 
+  {
+		return;
+	}
+	memcpy(context->state,sha256_initial_hash_value, SHA256_DIGEST_LENGTH);
+	memset(context->buffer, 0,SHA256_BLOCK_LENGTH);
+	context->bitcount = 0;
+}
+
+static void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
+	sha2_word32	a, b, c, d, e, f, g, h, s0, s1;
+	sha2_word32	T1, T2, *W256;
+	int		j;
+
+	W256 = (sha2_word32*)context->buffer;
+
+	/* Initialize registers with the prev. intermediate value */
+	a = context->state[0];
+	b = context->state[1];
+	c = context->state[2];
+	d = context->state[3];
+	e = context->state[4];
+	f = context->state[5];
+	g = context->state[6];
+	h = context->state[7];
+
+	j = 0;
+	do {
+#if BYTE_ORDER == LITTLE_ENDIAN
+		/* Copy data while converting to host byte order */
+		REVERSE32(*data++,W256[j]);
+		/* Apply the SHA-256 compression function to update a..h */
+		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+		/* Apply the SHA-256 compression function to update a..h with copy */
+		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+		T2 = Sigma0_256(a) + Maj(a, b, c);
+		h = g;
+		g = f;
+		f = e;
+		e = d + T1;
+		d = c;
+		c = b;
+		b = a;
+		a = T1 + T2;
+
+		j++;
+	} while (j < 16);
+
+	do {
+		/* Part of the message block expansion: */
+		s0 = W256[(j+1)&0x0f];
+		s0 = sigma0_256(s0);
+		s1 = W256[(j+14)&0x0f];	
+		s1 = sigma1_256(s1);
+
+		/* Apply the SHA-256 compression function to update a..h */
+		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + 
+		     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
+		T2 = Sigma0_256(a) + Maj(a, b, c);
+		h = g;
+		g = f;
+		f = e;
+		e = d + T1;
+		d = c;
+		c = b;
+		b = a;
+		a = T1 + T2;
+
+		j++;
+	} while (j < 64);
+
+	/* Compute the current intermediate hash value */
+	context->state[0] += a;
+	context->state[1] += b;
+	context->state[2] += c;
+	context->state[3] += d;
+	context->state[4] += e;
+	context->state[5] += f;
+	context->state[6] += g;
+	context->state[7] += h;
+
+	/* Clean up */
+	a = b = c = d = e = f = g = h = T1 = T2 = 0;
+}
+
+#define bcopy(s,d,len) memcpy(d,s,len)
+#define bzero(d,len) memset(d,0,len)
+
+static void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
+	unsigned int	freespace, usedspace;
+
+	if (len == 0) {
+		/* Calling with no data is valid - we do nothing */
+		return;
+	}
+
+	usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
+	if (usedspace > 0) {
+		/* Calculate how much free space is available in the buffer */
+		freespace = SHA256_BLOCK_LENGTH - usedspace;
+
+		if (len >= freespace) {
+			/* Fill the buffer completely and process it */
+
+			bcopy(data, &context->buffer[usedspace], freespace);
+			context->bitcount += freespace << 3;
+			len -= freespace;
+			data += freespace;
+			SHA256_Transform(context, (sha2_word32*)context->buffer);
+		} else {
+			/* The buffer is not yet full */
+			bcopy(data, &context->buffer[usedspace], len);
+			context->bitcount += len << 3;
+			/* Clean up: */
+			usedspace = freespace = 0;
+			return;
+		}
+	}
+	while (len >= SHA256_BLOCK_LENGTH) {
+		/* Process as many complete blocks as we can */
+		SHA256_Transform(context, (const sha2_word32*)data);
+		context->bitcount += SHA256_BLOCK_LENGTH << 3;
+		len -= SHA256_BLOCK_LENGTH;
+		data += SHA256_BLOCK_LENGTH;
+	}
+	if (len > 0) {
+		/* There's left-overs, so save 'em */
+		bcopy(data, context->buffer, len);
+		context->bitcount += len << 3;
+	}
+	/* Clean up: */
+	usedspace = freespace = 0;
+}
+
+static void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
+	sha2_word32	*d = (sha2_word32*)digest;
+	unsigned int	usedspace;
+
+	/* If no digest buffer is passed, we don't bother doing this: */
+	if (digest != (sha2_byte*)0) {
+		usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
+#if BYTE_ORDER == LITTLE_ENDIAN
+		/* Convert FROM host byte order */
+		REVERSE64(context->bitcount,context->bitcount);
+#endif
+		if (usedspace > 0) {
+			/* Begin padding with a 1 bit: */
+			context->buffer[usedspace++] = 0x80;
+
+			if (usedspace < SHA256_SHORT_BLOCK_LENGTH) {
+				/* Set-up for the last transform: */
+				bzero(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace);
+			} else {
+				if (usedspace < SHA256_BLOCK_LENGTH) {
+					bzero(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace);
+				}
+				/* Do second-to-last transform: */
+				SHA256_Transform(context, (sha2_word32*)context->buffer);
+
+				/* And set-up for the last transform: */
+				bzero(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
+			}
+		} else {
+			/* Set-up for the last transform: */
+			bzero(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
+
+			/* Begin padding with a 1 bit: */
+			*context->buffer = 0x80;
+		}
+		/* Set the bit count: */
+		*(sha2_word64*)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount;
+
+		/* Final transform: */
+		SHA256_Transform(context, (sha2_word32*)context->buffer);
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+		{
+			/* Convert TO host byte order */
+			int	j;
+			for (j = 0; j < 8; j++) {
+				REVERSE32(context->state[j],context->state[j]);
+				*d++ = context->state[j];
+			}
+		}
+#else
+		bcopy(context->state, d, SHA256_DIGEST_LENGTH);
+#endif
+	}
+
+	/* Clean up state data: */
+	bzero(context, sizeof(context));
+	usedspace = 0;
+}
+
+static void SHA256(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) 
+{
+	SHA256_CTX	context;
+
+	SHA256_Init(&context);
+	SHA256_Update(&context, data, len);
+	SHA256_Final(digest,&context);
+}
+
+#endif
\ No newline at end of file