Command-line utility to execute TPM commands bypassing the TSS stack.

Review URL: http://codereview.chromium.org/3149001
diff --git a/utility/tpmc.c b/utility/tpmc.c
new file mode 100644
index 0000000..d664ffb
--- /dev/null
+++ b/utility/tpmc.c
@@ -0,0 +1,114 @@
+/* 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.
+ *
+ * TPM command utility.  Runs simple TPM commands.  Mostly useful when physical
+ * presence has not been locked.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+
+#include "tlcl.h"
+#include "tpm_error_messages.h"
+
+typedef struct command_record {
+  const char* name;
+  const char* abbr;
+  const char* description;
+  uint32_t (*handler)(void);
+} command_record;
+
+/* Handler functions.  These wouldn't exist if C had closures.
+ */
+
+static uint32_t HandlerGetFlags(void) {
+  uint8_t disabled;
+  uint8_t deactivated;
+  uint8_t nvlocked;
+  uint32_t result = TlclGetFlags(&disabled, &deactivated, &nvlocked);
+  if (result == 0) {
+    printf("disabled: %d\ndeactivated: %d\nnvlocked: %d\n",
+           disabled, deactivated, nvlocked);
+  }
+  return result;
+}
+
+static uint32_t HandlerActivate(void) {
+  return TlclSetDeactivated(0);
+}
+
+static uint32_t HandlerDeactivate(void) {
+  return TlclSetDeactivated(1);
+}
+
+/* Table of TPM commands.
+ */
+command_record command_table[] = {
+  { "getflags", "getf", "read and print the value of selected flags",
+    HandlerGetFlags },
+  { "startup", "sta", "issue a Startup command", TlclStartup },
+  { "selftestfull", "test", "issue a SelfTestFull command", TlclSelfTestFull },
+  { "continueselftest", "ctest", "issue a ContinueSelfTest command",
+    TlclContinueSelfTest },
+  { "assertphysicalpresence", "ppon", "assert Physical Presence",
+    TlclAssertPhysicalPresence },
+  { "enable", "ena", "enable the TPM (needs PP)", TlclSetEnable },
+  { "disable", "dis", "disable the TPM (needs PP)", TlclClearEnable },
+  { "activate", "act", "activate the TPM (needs PP, maybe reboot)",
+    HandlerActivate },
+  { "deactivate", "deact", "deactivate the TPM (needs PP, maybe reboot)",
+    HandlerDeactivate },
+};
+
+static int n_commands = sizeof(command_table) / sizeof(command_table[0]);
+
+int main(int argc, char* argv[]) {
+  if (argc < 2) {
+    fprintf(stderr, "usage: %s <TPM command>\n   or: %s help\n",
+            argv[0], argv[0]);
+    exit(1);
+  } else {
+    command_record* c;
+    const char* cmd = argv[1];
+
+    if (strcmp(cmd, "help") == 0) {
+      printf("%23s %7s  %s\n\n", "command", "abbr.", "description");
+      for (c = command_table; c < command_table + n_commands; c++) {
+        printf("%23s %7s  %s\n", c->name, c->abbr, c->description);
+      }
+      return 0;
+    }
+
+    TlclLibInit();
+
+    for (c = command_table; c < command_table + n_commands; c++) {
+      if (strcmp(cmd, c->name) == 0 || strcmp(cmd, c->abbr) == 0) {
+        uint32_t result;
+        result = c->handler();
+        if (result == 0) {
+          return 0;
+        } else {
+          int i;
+          int n = sizeof(tpm_error_table) / sizeof(tpm_error_table[0]);
+          fprintf(stderr, "command \"%s\" failed with code 0x%x\n",
+                  cmd, result);
+          for (i = 0; i < n; i++) {
+             if (tpm_error_table[i].code == result) {
+               fprintf(stderr, "%s\n%s\n", tpm_error_table[i].name,
+                       tpm_error_table[i].description);
+               return 1;
+             }
+          }
+          fprintf(stderr, "the error code is unknown to this program\n");
+          return 1;
+        }
+      }
+    }
+
+    /* No command matched. */
+    fprintf(stderr, "%s: unknown command: %s\n", argv[0], cmd);
+    return 1;
+  }
+}