Index: src/platform/tpm_lite/src/tlcl/tlcl.c |
diff --git a/src/platform/tpm_lite/src/tlcl/tlcl.c b/src/platform/tpm_lite/src/tlcl/tlcl.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..916fb9fb200bbdb854a9ee762194f8ee4d6d524d |
--- /dev/null |
+++ b/src/platform/tpm_lite/src/tlcl/tlcl.c |
@@ -0,0 +1,178 @@ |
+/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+/* A lightweight TPM command library. |
+ * |
+ * The general idea is that TPM commands are array of bytes whose fields are |
+ * mostly compile-time constant. The goal is to build much of the commands at |
+ * compile time (or build time) and change some of the fields at run time as |
+ * needed. The code in generator.c builds structures containing the commands, |
+ * as well as the offsets of the fields that need to be set at run time. |
+ */ |
+ |
+#include "tlcl.h" |
+ |
+#include <string.h> |
+#include <tss/tcs.h> |
+ |
+#include "structures.h" |
+#include "tlcl_internal.h" |
+#include "tpmemu.h" |
+#include "tpmextras.h" |
+ |
+/* Gets the tag field of a TPM command. |
+ */ |
+static INLINE int TpmTag(uint8_t* buffer) { |
+ uint16_t tag; |
+ FromTpmUint16(buffer, &tag); |
+ return (int) tag; |
+} |
+ |
+/* Sets the size field of a TPM command. |
+ */ |
+static INLINE void SetTpmCommandSize(uint8_t* buffer, uint32_t size) { |
+ ToTpmUint32(buffer + 2, size); |
+} |
+ |
+/* Gets the size field of a TPM command. |
+ */ |
+static INLINE int TpmCommandSize(const uint8_t* buffer) { |
+ uint32_t size; |
+ FromTpmUint32(buffer + 2, &size); |
+ return (int) size; |
+} |
+ |
+/* Gets the code field of a TPM command. |
+ */ |
+static INLINE int TpmCommandCode(const uint8_t* buffer) { |
+ uint32_t code; |
+ FromTpmUint32(buffer + 6, &code); |
+ return code; |
+} |
+ |
+/* Gets the code field of a TPM result. |
+ */ |
+static INLINE int TpmReturnCode(const uint8_t* buffer) { |
+ return TpmCommandCode(buffer); |
+} |
+ |
+/* Checks for errors in a TPM response. |
+ */ |
+static void CheckResult(uint8_t* request, uint8_t* response, bool warn_only) { |
+ int command = TpmCommandCode(request); |
+ int result = TpmReturnCode(response); |
+ if (result != TPM_SUCCESS) { |
+ (warn_only? warning : error)("command 0x%x failed: 0x%x\n", |
+ command, result); |
+ } |
+} |
+ |
+/* Sends a request and receive a response. |
+ */ |
+static void SendReceive(uint8_t* request, uint8_t* response, int max_length) { |
+ uint32_t response_length = max_length; |
+ int tag, response_tag; |
+ |
+ tpmemu_execute(request, TpmCommandSize(request), response, &response_length); |
+ |
+ /* sanity checks */ |
+ tag = TpmTag(request); |
+ response_tag = TpmTag(response); |
+ assert( |
+ (tag == TPM_TAG_RQU_COMMAND && |
+ response_tag == TPM_TAG_RSP_COMMAND) || |
+ (tag == TPM_TAG_RQU_AUTH1_COMMAND && |
+ response_tag == TPM_TAG_RSP_AUTH1_COMMAND) || |
+ (tag == TPM_TAG_RQU_AUTH2_COMMAND && |
+ response_tag == TPM_TAG_RSP_AUTH2_COMMAND)); |
+ assert(response_length == TpmCommandSize(response)); |
+} |
+ |
+/* Sends a command and checks the result for errors. Note that this error |
+ * checking is only meaningful when running in user mode. TODO: The entire |
+ * error recovery strategy in the firmware needs more work. |
+ */ |
+static void Send(uint8_t* command) { |
+ uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
+ SendReceive(command, response, sizeof(response)); |
+ CheckResult(command, response, false); |
+} |
+ |
+ |
+/* Exported functions. |
+ */ |
+ |
+void TlclLibinit(void) { |
+ tpmemu_init(); |
+} |
+ |
+void TlclStartup(void) { |
+ Send(tpm_startup_cmd.buffer); |
+} |
+ |
+void TlclSelftestfull(void) { |
+ Send(tpm_selftestfull_cmd.buffer); |
+} |
+ |
+void TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size) { |
+ ToTpmUint32(tpm_nv_definespace_cmd.index, index); |
+ ToTpmUint32(tpm_nv_definespace_cmd.perm, perm); |
+ ToTpmUint32(tpm_nv_definespace_cmd.size, size); |
+ Send(tpm_nv_definespace_cmd.buffer); |
+} |
+ |
+uint32_t TlclWrite(uint32_t index, uint8_t* data, uint32_t length) { |
+ uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
+ const int total_length = |
+ kTpmRequestHeaderLength + kWriteInfoLength + length; |
+ |
+ assert(total_length <= TPM_LARGE_ENOUGH_COMMAND_SIZE); |
+ SetTpmCommandSize(tpm_nv_write_cmd.buffer, total_length); |
+ |
+ ToTpmUint32(tpm_nv_write_cmd.index, index); |
+ ToTpmUint32(tpm_nv_write_cmd.length, length); |
+ memcpy(tpm_nv_write_cmd.data, data, length); |
+ |
+ SendReceive(tpm_nv_write_cmd.buffer, response, sizeof(response)); |
+ CheckResult(tpm_nv_write_cmd.buffer, response, true); |
+ |
+ return TpmReturnCode(response); |
+} |
+ |
+uint32_t TlclRead(uint32_t index, uint8_t* data, uint32_t length) { |
+ uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE]; |
+ uint32_t result_length; |
+ uint32_t result; |
+ |
+ ToTpmUint32(tpm_nv_read_cmd.index, index); |
+ ToTpmUint32(tpm_nv_read_cmd.length, length); |
+ |
+ SendReceive(tpm_nv_read_cmd.buffer, response, sizeof(response)); |
+ result = TpmReturnCode(response); |
+ if (result == TPM_SUCCESS && length > 0) { |
+ uint8_t* nv_read_cursor = response + kTpmResponseHeaderLength; |
+ FromTpmUint32(nv_read_cursor, &result_length); |
+ nv_read_cursor += sizeof(uint32_t); |
+ memcpy(data, nv_read_cursor, result_length); |
+ } |
+ |
+ return result; |
+} |
+ |
+void TlclWriteLock(uint32_t index) { |
+ (void) TlclWrite(index, NULL, 0); |
+} |
+ |
+void TlclReadLock(uint32_t index) { |
+ (void) TlclRead(index, NULL, 0); |
+} |
+ |
+void TlclAssertPhysicalPresence(void) { |
+ Send(tpm_physicalpresence_cmd.buffer); |
+} |
+ |
+void TlclSetNvLocked(void) { |
+ TlclDefineSpace(TPM_NV_INDEX_LOCK, 0, 0); |
+} |