summaryrefslogtreecommitdiff
path: root/security/tf_driver/scxlnx_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/tf_driver/scxlnx_util.c')
-rw-r--r--security/tf_driver/scxlnx_util.c1141
1 files changed, 1141 insertions, 0 deletions
diff --git a/security/tf_driver/scxlnx_util.c b/security/tf_driver/scxlnx_util.c
new file mode 100644
index 000000000000..df928a4ec2c5
--- /dev/null
+++ b/security/tf_driver/scxlnx_util.c
@@ -0,0 +1,1141 @@
+/*
+ * Copyright (c) 2006-2010 Trusted Logic S.A.
+ * All Rights Reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#include <linux/mman.h>
+#include "scxlnx_util.h"
+
+/*----------------------------------------------------------------------------
+ * Debug printing routines
+ *----------------------------------------------------------------------------*/
+#ifdef CONFIG_TF_DRIVER_DEBUG_SUPPORT
+
+void addressCacheProperty(unsigned long va)
+{
+ unsigned long pa;
+ unsigned long inner;
+ unsigned long outer;
+
+ asm volatile ("mcr p15, 0, %0, c7, c8, 0" : : "r" (va));
+ asm volatile ("mrc p15, 0, %0, c7, c4, 0" : "=r" (pa));
+
+ dprintk(KERN_INFO "VA:%x, PA:%x\n",
+ (unsigned int) va,
+ (unsigned int) pa);
+
+ if (pa & 1) {
+ dprintk(KERN_INFO "Prop Error\n");
+ return;
+ }
+
+ outer = (pa >> 2) & 3;
+ dprintk(KERN_INFO "\touter : %x", (unsigned int) outer);
+
+ switch (outer) {
+ case 3:
+ dprintk(KERN_INFO "Write-Back, no Write-Allocate\n");
+ break;
+ case 2:
+ dprintk(KERN_INFO "Write-Through, no Write-Allocate.\n");
+ break;
+ case 1:
+ dprintk(KERN_INFO "Write-Back, Write-Allocate.\n");
+ break;
+ case 0:
+ dprintk(KERN_INFO "Non-cacheable.\n");
+ break;
+ }
+
+ inner = (pa >> 4) & 7;
+ dprintk(KERN_INFO "\tinner : %x", (unsigned int)inner);
+
+ switch (inner) {
+ case 7:
+ dprintk(KERN_INFO "Write-Back, no Write-Allocate\n");
+ break;
+ case 6:
+ dprintk(KERN_INFO "Write-Through.\n");
+ break;
+ case 5:
+ dprintk(KERN_INFO "Write-Back, Write-Allocate.\n");
+ break;
+ case 3:
+ dprintk(KERN_INFO "Device.\n");
+ break;
+ case 1:
+ dprintk(KERN_INFO "Strongly-ordered.\n");
+ break;
+ case 0:
+ dprintk(KERN_INFO "Non-cacheable.\n");
+ break;
+ }
+
+ if (pa & 0x00000002)
+ dprintk(KERN_INFO "SuperSection.\n");
+ if (pa & 0x00000080)
+ dprintk(KERN_INFO "Memory is shareable.\n");
+ else
+ dprintk(KERN_INFO "Memory is non-shareable.\n");
+
+ if (pa & 0x00000200)
+ dprintk(KERN_INFO "Non-secure.\n");
+}
+
+#ifdef CONFIG_BENCH_SECURE_CYCLE
+
+#define LOOP_SIZE (100000)
+
+void runBogoMIPS(void)
+{
+ uint32_t nCycles;
+ void *pAddress = &runBogoMIPS;
+
+ dprintk(KERN_INFO "BogoMIPS:\n");
+
+ setupCounters();
+ nCycles = runCodeSpeed(LOOP_SIZE);
+ dprintk(KERN_INFO "%u cycles with code access\n", nCycles);
+ nCycles = runDataSpeed(LOOP_SIZE, (unsigned long)pAddress);
+ dprintk(KERN_INFO "%u cycles to access %x\n", nCycles,
+ (unsigned int) pAddress);
+}
+
+#endif /* CONFIG_BENCH_SECURE_CYCLE */
+
+/*
+ * Dump the L1 shared buffer.
+ */
+void SCXLNXDumpL1SharedBuffer(struct SCHANNEL_C1S_BUFFER *pBuf)
+{
+ dprintk(KERN_INFO
+ "buffer@%p:\n"
+ " nConfigFlags_S=%08X\n"
+ " sVersionDescription=%64s\n"
+ " nStatus_S=%08X\n"
+ " nSyncSerial_N=%08X\n"
+ " nSyncSerial_S=%08X\n"
+ " sTime_N[0]=%016llX\n"
+ " sTime_N[1]=%016llX\n"
+ " sTimeout_S[0]=%016llX\n"
+ " sTimeout_S[1]=%016llX\n"
+ " nFirstCommand=%08X\n"
+ " nFirstFreeCommand=%08X\n"
+ " nFirstAnswer=%08X\n"
+ " nFirstFreeAnswer=%08X\n\n",
+ pBuf,
+ pBuf->nConfigFlags_S,
+ pBuf->sVersionDescription,
+ pBuf->nStatus_S,
+ pBuf->nSyncSerial_N,
+ pBuf->nSyncSerial_S,
+ pBuf->sTime_N[0],
+ pBuf->sTime_N[1],
+ pBuf->sTimeout_S[0],
+ pBuf->sTimeout_S[1],
+ pBuf->nFirstCommand,
+ pBuf->nFirstFreeCommand,
+ pBuf->nFirstAnswer,
+ pBuf->nFirstFreeAnswer);
+}
+
+
+/*
+ * Dump the specified SChannel message using dprintk.
+ */
+void SCXLNXDumpMessage(union SCX_COMMAND_MESSAGE *pMessage)
+{
+ u32 i;
+
+ dprintk(KERN_INFO "message@%p:\n", pMessage);
+
+ switch (pMessage->sHeader.nMessageType) {
+ case SCX_MESSAGE_TYPE_CREATE_DEVICE_CONTEXT:
+ dprintk(KERN_INFO
+ " nMessageSize = 0x%02X\n"
+ " nMessageType = 0x%02X "
+ "SCX_MESSAGE_TYPE_CREATE_DEVICE_CONTEXT\n"
+ " nOperationID = 0x%08X\n"
+ " nDeviceContextID = 0x%08X\n",
+ pMessage->sHeader.nMessageSize,
+ pMessage->sHeader.nMessageType,
+ pMessage->sHeader.nOperationID,
+ pMessage->sCreateDeviceContextMessage.nDeviceContextID
+ );
+ break;
+
+ case SCX_MESSAGE_TYPE_DESTROY_DEVICE_CONTEXT:
+ dprintk(KERN_INFO
+ " nMessageSize = 0x%02X\n"
+ " nMessageType = 0x%02X "
+ "SCX_MESSAGE_TYPE_DESTROY_DEVICE_CONTEXT\n"
+ " nOperationID = 0x%08X\n"
+ " hDeviceContext = 0x%08X\n",
+ pMessage->sHeader.nMessageSize,
+ pMessage->sHeader.nMessageType,
+ pMessage->sHeader.nOperationID,
+ pMessage->sDestroyDeviceContextMessage.hDeviceContext);
+ break;
+
+ case SCX_MESSAGE_TYPE_OPEN_CLIENT_SESSION:
+ dprintk(KERN_INFO
+ " nMessageSize = 0x%02X\n"
+ " nMessageType = 0x%02X "
+ "SCX_MESSAGE_TYPE_OPEN_CLIENT_SESSION\n"
+ " nParamTypes = 0x%04X\n"
+ " nOperationID = 0x%08X\n"
+ " hDeviceContext = 0x%08X\n"
+ " nCancellationID = 0x%08X\n"
+ " sTimeout = 0x%016llX\n"
+ " sDestinationUUID = "
+ "%08X-%04X-%04X-%02X%02X-"
+ "%02X%02X%02X%02X%02X%02X\n",
+ pMessage->sHeader.nMessageSize,
+ pMessage->sHeader.nMessageType,
+ pMessage->sOpenClientSessionMessage.nParamTypes,
+ pMessage->sHeader.nOperationID,
+ pMessage->sOpenClientSessionMessage.hDeviceContext,
+ pMessage->sOpenClientSessionMessage.nCancellationID,
+ pMessage->sOpenClientSessionMessage.sTimeout,
+ pMessage->sOpenClientSessionMessage.sDestinationUUID.
+ time_low,
+ pMessage->sOpenClientSessionMessage.sDestinationUUID.
+ time_mid,
+ pMessage->sOpenClientSessionMessage.sDestinationUUID.
+ time_hi_and_version,
+ pMessage->sOpenClientSessionMessage.sDestinationUUID.
+ clock_seq_and_node[0],
+ pMessage->sOpenClientSessionMessage.sDestinationUUID.
+ clock_seq_and_node[1],
+ pMessage->sOpenClientSessionMessage.sDestinationUUID.
+ clock_seq_and_node[2],
+ pMessage->sOpenClientSessionMessage.sDestinationUUID.
+ clock_seq_and_node[3],
+ pMessage->sOpenClientSessionMessage.sDestinationUUID.
+ clock_seq_and_node[4],
+ pMessage->sOpenClientSessionMessage.sDestinationUUID.
+ clock_seq_and_node[5],
+ pMessage->sOpenClientSessionMessage.sDestinationUUID.
+ clock_seq_and_node[6],
+ pMessage->sOpenClientSessionMessage.sDestinationUUID.
+ clock_seq_and_node[7]
+ );
+
+ for (i = 0; i < 4; i++) {
+ uint32_t *pParam = (uint32_t *) &pMessage->
+ sOpenClientSessionMessage.sParams[i];
+ dprintk(KERN_INFO " sParams[%d] = "
+ "0x%08X:0x%08X:0x%08X\n",
+ i, pParam[0], pParam[1], pParam[2]);
+ }
+
+ switch (SCX_LOGIN_GET_MAIN_TYPE(
+ pMessage->sOpenClientSessionMessage.nLoginType)) {
+ case SCX_LOGIN_PUBLIC:
+ dprintk(
+ KERN_INFO " nLoginType = "
+ "SCX_LOGIN_PUBLIC\n");
+ break;
+ case SCX_LOGIN_USER:
+ dprintk(
+ KERN_INFO " nLoginType = "
+ "SCX_LOGIN_USER\n");
+ break;
+ case SCX_LOGIN_GROUP:
+ dprintk(
+ KERN_INFO " nLoginType = "
+ "SCX_LOGIN_GROUP\n");
+ break;
+ case SCX_LOGIN_APPLICATION:
+ dprintk(
+ KERN_INFO " nLoginType = "
+ "SCX_LOGIN_APPLICATION\n");
+ break;
+ case SCX_LOGIN_APPLICATION_USER:
+ dprintk(
+ KERN_INFO " nLoginType = "
+ "SCX_LOGIN_APPLICATION_USER\n");
+ break;
+ case SCX_LOGIN_APPLICATION_GROUP:
+ dprintk(
+ KERN_INFO " nLoginType = "
+ "SCX_LOGIN_APPLICATION_GROUP\n");
+ break;
+ case SCX_LOGIN_AUTHENTICATION:
+ dprintk(
+ KERN_INFO " nLoginType = "
+ "SCX_LOGIN_AUTHENTICATION\n");
+ break;
+ case SCX_LOGIN_PRIVILEGED:
+ dprintk(
+ KERN_INFO " nLoginType = "
+ "SCX_LOGIN_PRIVILEGED\n");
+ break;
+ default:
+ dprintk(
+ KERN_ERR " nLoginType = "
+ "0x%08X (Unknown login type)\n",
+ pMessage->sOpenClientSessionMessage.nLoginType);
+ break;
+ }
+
+ dprintk(
+ KERN_INFO " sLoginData = ");
+ for (i = 0; i < 20; i++)
+ dprintk(
+ KERN_INFO "%d",
+ pMessage->sOpenClientSessionMessage.
+ sLoginData[i]);
+ dprintk("\n");
+ break;
+
+ case SCX_MESSAGE_TYPE_CLOSE_CLIENT_SESSION:
+ dprintk(KERN_INFO
+ " nMessageSize = 0x%02X\n"
+ " nMessageType = 0x%02X "
+ "SCX_MESSAGE_TYPE_CLOSE_CLIENT_SESSION\n"
+ " nOperationID = 0x%08X\n"
+ " hDeviceContext = 0x%08X\n"
+ " hClientSession = 0x%08X\n",
+ pMessage->sHeader.nMessageSize,
+ pMessage->sHeader.nMessageType,
+ pMessage->sHeader.nOperationID,
+ pMessage->sCloseClientSessionMessage.hDeviceContext,
+ pMessage->sCloseClientSessionMessage.hClientSession
+ );
+ break;
+
+ case SCX_MESSAGE_TYPE_REGISTER_SHARED_MEMORY:
+ dprintk(KERN_INFO
+ " nMessageSize = 0x%02X\n"
+ " nMessageType = 0x%02X "
+ "SCX_MESSAGE_TYPE_REGISTER_SHARED_MEMORY\n"
+ " nMemoryFlags = 0x%04X\n"
+ " nOperationID = 0x%08X\n"
+ " hDeviceContext = 0x%08X\n"
+ " nBlockID = 0x%08X\n"
+ " nSharedMemSize = 0x%08X\n"
+ " nSharedMemStartOffset = 0x%08X\n"
+ " nSharedMemDescriptors[0] = 0x%08X\n"
+ " nSharedMemDescriptors[1] = 0x%08X\n"
+ " nSharedMemDescriptors[2] = 0x%08X\n"
+ " nSharedMemDescriptors[3] = 0x%08X\n"
+ " nSharedMemDescriptors[4] = 0x%08X\n"
+ " nSharedMemDescriptors[5] = 0x%08X\n"
+ " nSharedMemDescriptors[6] = 0x%08X\n"
+ " nSharedMemDescriptors[7] = 0x%08X\n",
+ pMessage->sHeader.nMessageSize,
+ pMessage->sHeader.nMessageType,
+ pMessage->sRegisterSharedMemoryMessage.nMemoryFlags,
+ pMessage->sHeader.nOperationID,
+ pMessage->sRegisterSharedMemoryMessage.hDeviceContext,
+ pMessage->sRegisterSharedMemoryMessage.nBlockID,
+ pMessage->sRegisterSharedMemoryMessage.nSharedMemSize,
+ pMessage->sRegisterSharedMemoryMessage.
+ nSharedMemStartOffset,
+ pMessage->sRegisterSharedMemoryMessage.
+ nSharedMemDescriptors[0],
+ pMessage->sRegisterSharedMemoryMessage.
+ nSharedMemDescriptors[1],
+ pMessage->sRegisterSharedMemoryMessage.
+ nSharedMemDescriptors[2],
+ pMessage->sRegisterSharedMemoryMessage.
+ nSharedMemDescriptors[3],
+ pMessage->sRegisterSharedMemoryMessage.
+ nSharedMemDescriptors[4],
+ pMessage->sRegisterSharedMemoryMessage.
+ nSharedMemDescriptors[5],
+ pMessage->sRegisterSharedMemoryMessage.
+ nSharedMemDescriptors[6],
+ pMessage->sRegisterSharedMemoryMessage.
+ nSharedMemDescriptors[7]);
+ break;
+
+ case SCX_MESSAGE_TYPE_RELEASE_SHARED_MEMORY:
+ dprintk(KERN_INFO
+ " nMessageSize = 0x%02X\n"
+ " nMessageType = 0x%02X "
+ "SCX_MESSAGE_TYPE_RELEASE_SHARED_MEMORY\n"
+ " nOperationID = 0x%08X\n"
+ " hDeviceContext = 0x%08X\n"
+ " hBlock = 0x%08X\n",
+ pMessage->sHeader.nMessageSize,
+ pMessage->sHeader.nMessageType,
+ pMessage->sHeader.nOperationID,
+ pMessage->sReleaseSharedMemoryMessage.hDeviceContext,
+ pMessage->sReleaseSharedMemoryMessage.hBlock);
+ break;
+
+ case SCX_MESSAGE_TYPE_INVOKE_CLIENT_COMMAND:
+ dprintk(KERN_INFO
+ " nMessageSize = 0x%02X\n"
+ " nMessageType = 0x%02X "
+ "SCX_MESSAGE_TYPE_INVOKE_CLIENT_COMMAND\n"
+ " nParamTypes = 0x%04X\n"
+ " nOperationID = 0x%08X\n"
+ " hDeviceContext = 0x%08X\n"
+ " hClientSession = 0x%08X\n"
+ " sTimeout = 0x%016llX\n"
+ " nCancellationID = 0x%08X\n"
+ " nClientCommandIdentifier = 0x%08X\n",
+ pMessage->sHeader.nMessageSize,
+ pMessage->sHeader.nMessageType,
+ pMessage->sInvokeClientCommandMessage.nParamTypes,
+ pMessage->sHeader.nOperationID,
+ pMessage->sInvokeClientCommandMessage.hDeviceContext,
+ pMessage->sInvokeClientCommandMessage.hClientSession,
+ pMessage->sInvokeClientCommandMessage.sTimeout,
+ pMessage->sInvokeClientCommandMessage.nCancellationID,
+ pMessage->sInvokeClientCommandMessage.
+ nClientCommandIdentifier
+ );
+
+ for (i = 0; i < 4; i++) {
+ uint32_t *pParam = (uint32_t *) &pMessage->
+ sOpenClientSessionMessage.sParams[i];
+ dprintk(KERN_INFO " sParams[%d] = "
+ "0x%08X:0x%08X:0x%08X\n", i,
+ pParam[0], pParam[1], pParam[2]);
+ }
+ break;
+
+ case SCX_MESSAGE_TYPE_CANCEL_CLIENT_COMMAND:
+ dprintk(KERN_INFO
+ " nMessageSize = 0x%02X\n"
+ " nMessageType = 0x%02X "
+ "SCX_MESSAGE_TYPE_CANCEL_CLIENT_COMMAND\n"
+ " nOperationID = 0x%08X\n"
+ " hDeviceContext = 0x%08X\n"
+ " hClientSession = 0x%08X\n",
+ pMessage->sHeader.nMessageSize,
+ pMessage->sHeader.nMessageType,
+ pMessage->sHeader.nOperationID,
+ pMessage->sCancelClientOperationMessage.hDeviceContext,
+ pMessage->sCancelClientOperationMessage.hClientSession);
+ break;
+
+ case SCX_MESSAGE_TYPE_MANAGEMENT:
+ dprintk(KERN_INFO
+ " nMessageSize = 0x%02X\n"
+ " nMessageType = 0x%02X "
+ "SCX_MESSAGE_TYPE_MANAGEMENT\n"
+ " nOperationID = 0x%08X\n"
+ " nCommand = 0x%08X\n"
+ " nW3BSize = 0x%08X\n"
+ " nW3BStartOffset = 0x%08X\n",
+ pMessage->sHeader.nMessageSize,
+ pMessage->sHeader.nMessageType,
+ pMessage->sHeader.nOperationID,
+ pMessage->sManagementMessage.nCommand,
+ pMessage->sManagementMessage.nW3BSize,
+ pMessage->sManagementMessage.nW3BStartOffset);
+ break;
+
+ default:
+ dprintk(
+ KERN_ERR " nMessageType = 0x%08X "
+ "(Unknown message type)\n",
+ pMessage->sHeader.nMessageType);
+ break;
+ }
+}
+
+
+/*
+ * Dump the specified SChannel answer using dprintk.
+ */
+void SCXLNXDumpAnswer(union SCX_ANSWER_MESSAGE *pAnswer)
+{
+ u32 i;
+ dprintk(
+ KERN_INFO "answer@%p:\n",
+ pAnswer);
+
+ switch (pAnswer->sHeader.nMessageType) {
+ case SCX_MESSAGE_TYPE_CREATE_DEVICE_CONTEXT:
+ dprintk(KERN_INFO
+ " nMessageSize = 0x%02X\n"
+ " nMessageType = 0x%02X "
+ "SCX_ANSWER_CREATE_DEVICE_CONTEXT\n"
+ " nOperationID = 0x%08X\n"
+ " nErrorCode = 0x%08X\n"
+ " hDeviceContext = 0x%08X\n",
+ pAnswer->sHeader.nMessageSize,
+ pAnswer->sHeader.nMessageType,
+ pAnswer->sHeader.nOperationID,
+ pAnswer->sCreateDeviceContextAnswer.nErrorCode,
+ pAnswer->sCreateDeviceContextAnswer.hDeviceContext);
+ break;
+
+ case SCX_MESSAGE_TYPE_DESTROY_DEVICE_CONTEXT:
+ dprintk(KERN_INFO
+ " nMessageSize = 0x%02X\n"
+ " nMessageType = 0x%02X "
+ "ANSWER_DESTROY_DEVICE_CONTEXT\n"
+ " nOperationID = 0x%08X\n"
+ " nErrorCode = 0x%08X\n"
+ " nDeviceContextID = 0x%08X\n",
+ pAnswer->sHeader.nMessageSize,
+ pAnswer->sHeader.nMessageType,
+ pAnswer->sHeader.nOperationID,
+ pAnswer->sDestroyDeviceContextAnswer.nErrorCode,
+ pAnswer->sDestroyDeviceContextAnswer.nDeviceContextID);
+ break;
+
+
+ case SCX_MESSAGE_TYPE_OPEN_CLIENT_SESSION:
+ dprintk(KERN_INFO
+ " nMessageSize = 0x%02X\n"
+ " nMessageType = 0x%02X "
+ "SCX_ANSWER_OPEN_CLIENT_SESSION\n"
+ " nReturnOrigin = 0x%02X\n"
+ " nOperationID = 0x%08X\n"
+ " nErrorCode = 0x%08X\n"
+ " hClientSession = 0x%08X\n",
+ pAnswer->sHeader.nMessageSize,
+ pAnswer->sHeader.nMessageType,
+ pAnswer->sOpenClientSessionAnswer.nReturnOrigin,
+ pAnswer->sHeader.nOperationID,
+ pAnswer->sOpenClientSessionAnswer.nErrorCode,
+ pAnswer->sOpenClientSessionAnswer.hClientSession);
+ for (i = 0; i < 4; i++) {
+ dprintk(KERN_INFO " sAnswers[%d]=0x%08X:0x%08X\n",
+ i,
+ pAnswer->sOpenClientSessionAnswer.sAnswers[i].
+ sValue.a,
+ pAnswer->sOpenClientSessionAnswer.sAnswers[i].
+ sValue.b);
+ }
+ break;
+
+ case SCX_MESSAGE_TYPE_CLOSE_CLIENT_SESSION:
+ dprintk(KERN_INFO
+ " nMessageSize = 0x%02X\n"
+ " nMessageType = 0x%02X "
+ "ANSWER_CLOSE_CLIENT_SESSION\n"
+ " nOperationID = 0x%08X\n"
+ " nErrorCode = 0x%08X\n",
+ pAnswer->sHeader.nMessageSize,
+ pAnswer->sHeader.nMessageType,
+ pAnswer->sHeader.nOperationID,
+ pAnswer->sCloseClientSessionAnswer.nErrorCode);
+ break;
+
+ case SCX_MESSAGE_TYPE_REGISTER_SHARED_MEMORY:
+ dprintk(KERN_INFO
+ " nMessageSize = 0x%02X\n"
+ " nMessageType = 0x%02X "
+ "SCX_ANSWER_REGISTER_SHARED_MEMORY\n"
+ " nOperationID = 0x%08X\n"
+ " nErrorCode = 0x%08X\n"
+ " hBlock = 0x%08X\n",
+ pAnswer->sHeader.nMessageSize,
+ pAnswer->sHeader.nMessageType,
+ pAnswer->sHeader.nOperationID,
+ pAnswer->sRegisterSharedMemoryAnswer.nErrorCode,
+ pAnswer->sRegisterSharedMemoryAnswer.hBlock);
+ break;
+
+ case SCX_MESSAGE_TYPE_RELEASE_SHARED_MEMORY:
+ dprintk(KERN_INFO
+ " nMessageSize = 0x%02X\n"
+ " nMessageType = 0x%02X "
+ "ANSWER_RELEASE_SHARED_MEMORY\n"
+ " nOperationID = 0x%08X\n"
+ " nErrorCode = 0x%08X\n"
+ " nBlockID = 0x%08X\n",
+ pAnswer->sHeader.nMessageSize,
+ pAnswer->sHeader.nMessageType,
+ pAnswer->sHeader.nOperationID,
+ pAnswer->sReleaseSharedMemoryAnswer.nErrorCode,
+ pAnswer->sReleaseSharedMemoryAnswer.nBlockID);
+ break;
+
+ case SCX_MESSAGE_TYPE_INVOKE_CLIENT_COMMAND:
+ dprintk(KERN_INFO
+ " nMessageSize = 0x%02X\n"
+ " nMessageType = 0x%02X "
+ "SCX_ANSWER_INVOKE_CLIENT_COMMAND\n"
+ " nReturnOrigin = 0x%02X\n"
+ " nOperationID = 0x%08X\n"
+ " nErrorCode = 0x%08X\n",
+ pAnswer->sHeader.nMessageSize,
+ pAnswer->sHeader.nMessageType,
+ pAnswer->sInvokeClientCommandAnswer.nReturnOrigin,
+ pAnswer->sHeader.nOperationID,
+ pAnswer->sInvokeClientCommandAnswer.nErrorCode
+ );
+ for (i = 0; i < 4; i++) {
+ dprintk(KERN_INFO " sAnswers[%d]=0x%08X:0x%08X\n",
+ i,
+ pAnswer->sInvokeClientCommandAnswer.sAnswers[i].
+ sValue.a,
+ pAnswer->sInvokeClientCommandAnswer.sAnswers[i].
+ sValue.b);
+ }
+ break;
+
+ case SCX_MESSAGE_TYPE_CANCEL_CLIENT_COMMAND:
+ dprintk(KERN_INFO
+ " nMessageSize = 0x%02X\n"
+ " nMessageType = 0x%02X "
+ "SCX_ANSWER_CANCEL_CLIENT_COMMAND\n"
+ " nOperationID = 0x%08X\n"
+ " nErrorCode = 0x%08X\n",
+ pAnswer->sHeader.nMessageSize,
+ pAnswer->sHeader.nMessageType,
+ pAnswer->sHeader.nOperationID,
+ pAnswer->sCancelClientOperationAnswer.nErrorCode);
+ break;
+
+ case SCX_MESSAGE_TYPE_MANAGEMENT:
+ dprintk(KERN_INFO
+ " nMessageSize = 0x%02X\n"
+ " nMessageType = 0x%02X "
+ "SCX_MESSAGE_TYPE_MANAGEMENT\n"
+ " nOperationID = 0x%08X\n"
+ " nErrorCode = 0x%08X\n",
+ pAnswer->sHeader.nMessageSize,
+ pAnswer->sHeader.nMessageType,
+ pAnswer->sHeader.nOperationID,
+ pAnswer->sHeader.nErrorCode);
+ break;
+
+ default:
+ dprintk(
+ KERN_ERR " nMessageType = 0x%02X "
+ "(Unknown message type)\n",
+ pAnswer->sHeader.nMessageType);
+ break;
+
+ }
+}
+
+#endif /* defined(TF_DRIVER_DEBUG_SUPPORT) */
+
+/*----------------------------------------------------------------------------
+ * SHA-1 implementation
+ * This is taken from the Linux kernel source crypto/sha1.c
+ *----------------------------------------------------------------------------*/
+
+struct sha1_ctx {
+ u64 count;
+ u32 state[5];
+ u8 buffer[64];
+};
+
+static inline u32 rol(u32 value, u32 bits)
+{
+ return ((value) << (bits)) | ((value) >> (32 - (bits)));
+}
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#define blk0(i) block32[i]
+
+#define blk(i) (block32[i & 15] = rol( \
+ block32[(i + 13) & 15] ^ block32[(i + 8) & 15] ^ \
+ block32[(i + 2) & 15] ^ block32[i & 15], 1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v, w, x, y, z, i) do { \
+ z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
+ w = rol(w, 30); } while (0)
+
+#define R1(v, w, x, y, z, i) do { \
+ z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
+ w = rol(w, 30); } while (0)
+
+#define R2(v, w, x, y, z, i) do { \
+ z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
+ w = rol(w, 30); } while (0)
+
+#define R3(v, w, x, y, z, i) do { \
+ z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
+ w = rol(w, 30); } while (0)
+
+#define R4(v, w, x, y, z, i) do { \
+ z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
+ w = rol(w, 30); } while (0)
+
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+static void sha1_transform(u32 *state, const u8 *in)
+{
+ u32 a, b, c, d, e;
+ u32 block32[16];
+
+ /* convert/copy data to workspace */
+ for (a = 0; a < sizeof(block32)/sizeof(u32); a++)
+ block32[a] = ((u32) in[4 * a]) << 24 |
+ ((u32) in[4 * a + 1]) << 16 |
+ ((u32) in[4 * a + 2]) << 8 |
+ ((u32) in[4 * a + 3]);
+
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a, b, c, d, e, 0); R0(e, a, b, c, d, 1);
+ R0(d, e, a, b, c, 2); R0(c, d, e, a, b, 3);
+ R0(b, c, d, e, a, 4); R0(a, b, c, d, e, 5);
+ R0(e, a, b, c, d, 6); R0(d, e, a, b, c, 7);
+ R0(c, d, e, a, b, 8); R0(b, c, d, e, a, 9);
+ R0(a, b, c, d, e, 10); R0(e, a, b, c, d, 11);
+ R0(d, e, a, b, c, 12); R0(c, d, e, a, b, 13);
+ R0(b, c, d, e, a, 14); R0(a, b, c, d, e, 15);
+
+ R1(e, a, b, c, d, 16); R1(d, e, a, b, c, 17);
+ R1(c, d, e, a, b, 18); R1(b, c, d, e, a, 19);
+
+ R2(a, b, c, d, e, 20); R2(e, a, b, c, d, 21);
+ R2(d, e, a, b, c, 22); R2(c, d, e, a, b, 23);
+ R2(b, c, d, e, a, 24); R2(a, b, c, d, e, 25);
+ R2(e, a, b, c, d, 26); R2(d, e, a, b, c, 27);
+ R2(c, d, e, a, b, 28); R2(b, c, d, e, a, 29);
+ R2(a, b, c, d, e, 30); R2(e, a, b, c, d, 31);
+ R2(d, e, a, b, c, 32); R2(c, d, e, a, b, 33);
+ R2(b, c, d, e, a, 34); R2(a, b, c, d, e, 35);
+ R2(e, a, b, c, d, 36); R2(d, e, a, b, c, 37);
+ R2(c, d, e, a, b, 38); R2(b, c, d, e, a, 39);
+
+ R3(a, b, c, d, e, 40); R3(e, a, b, c, d, 41);
+ R3(d, e, a, b, c, 42); R3(c, d, e, a, b, 43);
+ R3(b, c, d, e, a, 44); R3(a, b, c, d, e, 45);
+ R3(e, a, b, c, d, 46); R3(d, e, a, b, c, 47);
+ R3(c, d, e, a, b, 48); R3(b, c, d, e, a, 49);
+ R3(a, b, c, d, e, 50); R3(e, a, b, c, d, 51);
+ R3(d, e, a, b, c, 52); R3(c, d, e, a, b, 53);
+ R3(b, c, d, e, a, 54); R3(a, b, c, d, e, 55);
+ R3(e, a, b, c, d, 56); R3(d, e, a, b, c, 57);
+ R3(c, d, e, a, b, 58); R3(b, c, d, e, a, 59);
+
+ R4(a, b, c, d, e, 60); R4(e, a, b, c, d, 61);
+ R4(d, e, a, b, c, 62); R4(c, d, e, a, b, 63);
+ R4(b, c, d, e, a, 64); R4(a, b, c, d, e, 65);
+ R4(e, a, b, c, d, 66); R4(d, e, a, b, c, 67);
+ R4(c, d, e, a, b, 68); R4(b, c, d, e, a, 69);
+ R4(a, b, c, d, e, 70); R4(e, a, b, c, d, 71);
+ R4(d, e, a, b, c, 72); R4(c, d, e, a, b, 73);
+ R4(b, c, d, e, a, 74); R4(a, b, c, d, e, 75);
+ R4(e, a, b, c, d, 76); R4(d, e, a, b, c, 77);
+ R4(c, d, e, a, b, 78); R4(b, c, d, e, a, 79);
+
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+ memset(block32, 0x00, sizeof(block32));
+}
+
+
+static void sha1_init(void *ctx)
+{
+ struct sha1_ctx *sctx = ctx;
+ static const struct sha1_ctx initstate = {
+ 0,
+ { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 },
+ { 0, }
+ };
+
+ *sctx = initstate;
+}
+
+
+static void sha1_update(void *ctx, const u8 *data, unsigned int len)
+{
+ struct sha1_ctx *sctx = ctx;
+ unsigned int i, j;
+
+ j = (sctx->count >> 3) & 0x3f;
+ sctx->count += len << 3;
+
+ if ((j + len) > 63) {
+ memcpy(&sctx->buffer[j], data, (i = 64 - j));
+ sha1_transform(sctx->state, sctx->buffer);
+ for ( ; i + 63 < len; i += 64)
+ sha1_transform(sctx->state, &data[i]);
+ j = 0;
+ } else
+ i = 0;
+ memcpy(&sctx->buffer[j], &data[i], len - i);
+}
+
+
+/* Add padding and return the message digest. */
+static void sha1_final(void *ctx, u8 *out)
+{
+ struct sha1_ctx *sctx = ctx;
+ u32 i, j, index, padlen;
+ u64 t;
+ u8 bits[8] = { 0, };
+ static const u8 padding[64] = { 0x80, };
+
+ t = sctx->count;
+ bits[7] = 0xff & t; t >>= 8;
+ bits[6] = 0xff & t; t >>= 8;
+ bits[5] = 0xff & t; t >>= 8;
+ bits[4] = 0xff & t; t >>= 8;
+ bits[3] = 0xff & t; t >>= 8;
+ bits[2] = 0xff & t; t >>= 8;
+ bits[1] = 0xff & t; t >>= 8;
+ bits[0] = 0xff & t;
+
+ /* Pad out to 56 mod 64 */
+ index = (sctx->count >> 3) & 0x3f;
+ padlen = (index < 56) ? (56 - index) : ((64+56) - index);
+ sha1_update(sctx, padding, padlen);
+
+ /* Append length */
+ sha1_update(sctx, bits, sizeof(bits));
+
+ /* Store state in digest */
+ for (i = j = 0; i < 5; i++, j += 4) {
+ u32 t2 = sctx->state[i];
+ out[j+3] = t2 & 0xff; t2 >>= 8;
+ out[j+2] = t2 & 0xff; t2 >>= 8;
+ out[j+1] = t2 & 0xff; t2 >>= 8;
+ out[j] = t2 & 0xff;
+ }
+
+ /* Wipe context */
+ memset(sctx, 0, sizeof(*sctx));
+}
+
+
+
+
+/*----------------------------------------------------------------------------
+ * Process identification
+ *----------------------------------------------------------------------------*/
+
+/* This function generates a processes hash table for authentication */
+int SCXLNXConnGetCurrentProcessHash(void *pHash)
+{
+ int nResult = 0;
+ void *buffer;
+ struct mm_struct *mm;
+ struct vm_area_struct *vma;
+
+ buffer = internal_kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (buffer == NULL) {
+ dprintk(
+ KERN_ERR "SCXLNXConnGetCurrentProcessHash:"
+ KERN_ERR " Out of memory for buffer!\n");
+ return -ENOMEM;
+ }
+
+ mm = current->mm;
+
+ down_read(&(mm->mmap_sem));
+ for (vma = mm->mmap; vma != NULL; vma = vma->vm_next) {
+ if ((vma->vm_flags & VM_EXECUTABLE) != 0 && vma->vm_file
+ != NULL) {
+ struct dentry *dentry;
+ unsigned long start;
+ unsigned long cur;
+ unsigned long end;
+ struct sha1_ctx sha1Context;
+
+ dentry = dget(vma->vm_file->f_dentry);
+
+ dprintk(
+ KERN_DEBUG "SCXLNXConnGetCurrentProcessHash: "
+ "Found executable VMA for inode %lu "
+ "(%lu bytes).\n",
+ dentry->d_inode->i_ino,
+ (unsigned long) (dentry->d_inode->
+ i_size));
+
+ start = do_mmap(vma->vm_file, 0,
+ dentry->d_inode->i_size,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE, 0);
+ if (start < 0) {
+ dprintk(
+ KERN_ERR "SCXLNXConnGetCurrentProcess"
+ "Hash: do_mmap failed (error %d)!\n",
+ (int) start);
+ dput(dentry);
+ nResult = -EFAULT;
+ goto vma_out;
+ }
+
+ end = start + dentry->d_inode->i_size;
+
+ sha1_init(&sha1Context);
+ cur = start;
+ while (cur < end) {
+ unsigned long chunk;
+
+ chunk = end - cur;
+ if (chunk > PAGE_SIZE)
+ chunk = PAGE_SIZE;
+ if (copy_from_user(buffer, (const void *) cur,
+ chunk) != 0) {
+ dprintk(
+ KERN_ERR "SCXLNXConnGetCurrent"
+ "ProcessHash: copy_from_user "
+ "failed!\n");
+ nResult = -EINVAL;
+ (void) do_munmap(mm, start,
+ dentry->d_inode->i_size);
+ dput(dentry);
+ goto vma_out;
+ }
+ sha1_update(&sha1Context, buffer, chunk);
+ cur += chunk;
+ }
+ sha1_final(&sha1Context, pHash);
+ nResult = 0;
+
+ (void) do_munmap(mm, start, dentry->d_inode->i_size);
+ dput(dentry);
+ break;
+ }
+ }
+vma_out:
+ up_read(&(mm->mmap_sem));
+
+ internal_kfree(buffer);
+
+ if (nResult == -ENOENT)
+ dprintk(
+ KERN_ERR "SCXLNXConnGetCurrentProcessHash: "
+ "No executable VMA found for process!\n");
+ return nResult;
+}
+
+
+/* This function hashes the path of the current application.
+ * If pData = NULL ,nothing else is added to the hash
+ else add pData to the hash
+ */
+int SCXLNXConnHashApplicationPathAndData(char *pBuffer, void *pData,
+ u32 nDataLen)
+{
+ int nResult = -ENOENT;
+ char *buffer = NULL;
+ struct mm_struct *mm;
+ struct vm_area_struct *vma;
+
+ buffer = internal_kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (buffer == NULL) {
+ nResult = -ENOMEM;
+ goto end;
+ }
+
+ mm = current->mm;
+
+ down_read(&(mm->mmap_sem));
+ for (vma = mm->mmap; vma != NULL; vma = vma->vm_next) {
+ if ((vma->vm_flags & VM_EXECUTABLE) != 0
+ && vma->vm_file != NULL) {
+ struct path *path;
+ char *endpath;
+ size_t pathlen;
+ struct sha1_ctx sha1Context;
+ u8 pHashData[SHA1_DIGEST_SIZE];
+
+ path = &vma->vm_file->f_path;
+
+ endpath = d_path(path, buffer, PAGE_SIZE);
+ if (IS_ERR(path)) {
+ nResult = PTR_ERR(endpath);
+ up_read(&(mm->mmap_sem));
+ goto end;
+ }
+ pathlen = (buffer + PAGE_SIZE) - endpath;
+
+#ifdef CONFIG_TF_DRIVER_DEBUG_SUPPORT
+ {
+ char *pChar;
+ dprintk(KERN_DEBUG "current process path = ");
+ for (pChar = endpath;
+ pChar < buffer + PAGE_SIZE;
+ pChar++)
+ dprintk("%c", *pChar);
+
+ dprintk(", uid=%d, euid=%d\n", current_uid(),
+ current_euid());
+ }
+#endif /*defined(CONFIG_TF_DRIVER_DEBUG_SUPPORT) */
+
+ sha1_init(&sha1Context);
+ sha1_update(&sha1Context, endpath, pathlen);
+ if (pData != NULL) {
+ dprintk(KERN_INFO "SCXLNXConnHashApplication"
+ "PathAndData: Hashing additional"
+ "data\n");
+ sha1_update(&sha1Context, pData, nDataLen);
+ }
+ sha1_final(&sha1Context, pHashData);
+ memcpy(pBuffer, pHashData, sizeof(pHashData));
+
+ nResult = 0;
+
+ break;
+ }
+ }
+ up_read(&(mm->mmap_sem));
+
+ end:
+ if (buffer != NULL)
+ internal_kfree(buffer);
+
+ return nResult;
+}
+
+void *internal_kmalloc(size_t nSize, int nPriority)
+{
+ void *pResult;
+ struct SCXLNX_DEVICE *pDevice = SCXLNXGetDevice();
+
+ pResult = kmalloc(nSize, nPriority);
+
+ if (pResult != NULL)
+ atomic_inc(
+ &pDevice->sDeviceStats.stat_memories_allocated);
+
+ return pResult;
+}
+
+void internal_kfree(void *pMemory)
+{
+ struct SCXLNX_DEVICE *pDevice = SCXLNXGetDevice();
+
+ if (pMemory != NULL)
+ atomic_dec(
+ &pDevice->sDeviceStats.stat_memories_allocated);
+ return kfree(pMemory);
+}
+
+void internal_vunmap(void *pMemory)
+{
+ struct SCXLNX_DEVICE *pDevice = SCXLNXGetDevice();
+
+ if (pMemory != NULL)
+ atomic_dec(
+ &pDevice->sDeviceStats.stat_memories_allocated);
+
+ vunmap((void *) (((unsigned int)pMemory) & 0xFFFFF000));
+}
+
+void *internal_vmalloc(size_t nSize)
+{
+ void *pResult;
+ struct SCXLNX_DEVICE *pDevice = SCXLNXGetDevice();
+
+ pResult = vmalloc(nSize);
+
+ if (pResult != NULL)
+ atomic_inc(
+ &pDevice->sDeviceStats.stat_memories_allocated);
+
+ return pResult;
+}
+
+void internal_vfree(void *pMemory)
+{
+ struct SCXLNX_DEVICE *pDevice = SCXLNXGetDevice();
+
+ if (pMemory != NULL)
+ atomic_dec(
+ &pDevice->sDeviceStats.stat_memories_allocated);
+ return vfree(pMemory);
+}
+
+unsigned long internal_get_zeroed_page(int nPriority)
+{
+ unsigned long nResult;
+ struct SCXLNX_DEVICE *pDevice = SCXLNXGetDevice();
+
+ nResult = get_zeroed_page(nPriority);
+
+ if (nResult != 0)
+ atomic_inc(&pDevice->sDeviceStats.
+ stat_pages_allocated);
+
+ return nResult;
+}
+
+void internal_free_page(unsigned long pPage)
+{
+ struct SCXLNX_DEVICE *pDevice = SCXLNXGetDevice();
+
+ if (pPage != 0)
+ atomic_dec(
+ &pDevice->sDeviceStats.stat_pages_allocated);
+ return free_page(pPage);
+}
+
+int internal_get_user_pages(
+ struct task_struct *tsk,
+ struct mm_struct *mm,
+ unsigned long start,
+ int len,
+ int write,
+ int force,
+ struct page **pages,
+ struct vm_area_struct **vmas)
+{
+ int nResult;
+ struct SCXLNX_DEVICE *pDevice = SCXLNXGetDevice();
+
+ nResult = get_user_pages(
+ tsk,
+ mm,
+ start,
+ len,
+ write,
+ force,
+ pages,
+ vmas);
+
+ if (nResult > 0)
+ atomic_add(nResult,
+ &pDevice->sDeviceStats.stat_pages_locked);
+
+ return nResult;
+}
+
+void internal_get_page(struct page *page)
+{
+ struct SCXLNX_DEVICE *pDevice = SCXLNXGetDevice();
+
+ atomic_inc(&pDevice->sDeviceStats.stat_pages_locked);
+
+ get_page(page);
+}
+
+void internal_page_cache_release(struct page *page)
+{
+ struct SCXLNX_DEVICE *pDevice = SCXLNXGetDevice();
+
+ atomic_dec(&pDevice->sDeviceStats.stat_pages_locked);
+
+ page_cache_release(page);
+}
+
+