[SLOF] [PATCH v3 02/17] Add TPM initialization support

Stefan Berger stefanb at us.ibm.com
Tue Dec 1 09:01:45 AEDT 2015


From: Stefan Berger <stefanb at linux.vnet.ibm.com>

This patch implements the main part of the firmware extensions. It provides
the following functionality:

- initialization of the TPM by sending a sequence of commands to it
- proper setup of the TPM before the firmware hands over control to the bootloader

Structures that are needed in subsequent patches are also included in the
private header file tcgbios_int.h at this point.

Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
---
 board-qemu/Makefile                 |   2 +-
 board-qemu/slof/Makefile            |  10 +-
 board-qemu/slof/tree.fs             |   3 +
 board-qemu/slof/vio-vtpm-cdriver.fs |  72 ++++++++
 board-qemu/slof/vtpm-sml.fs         |  62 +++++++
 lib/Makefile                        |   2 +-
 lib/libtpm/Makefile                 |   2 +-
 lib/libtpm/tcgbios.c                | 335 ++++++++++++++++++++++++++++++++++++
 lib/libtpm/tcgbios.h                |  22 +++
 lib/libtpm/tcgbios_int.h            | 136 +++++++++++++++
 lib/libtpm/tpm.code                 |  46 +++++
 lib/libtpm/tpm.in                   |  18 ++
 slof/fs/start-up.fs                 |   7 +
 13 files changed, 711 insertions(+), 6 deletions(-)
 create mode 100644 board-qemu/slof/vio-vtpm-cdriver.fs
 create mode 100644 board-qemu/slof/vtpm-sml.fs
 create mode 100644 lib/libtpm/tcgbios.c
 create mode 100644 lib/libtpm/tcgbios.h
 create mode 100644 lib/libtpm/tcgbios_int.h
 create mode 100644 lib/libtpm/tpm.code
 create mode 100644 lib/libtpm/tpm.in

diff --git a/board-qemu/Makefile b/board-qemu/Makefile
index 29ee016..0c03e54 100644
--- a/board-qemu/Makefile
+++ b/board-qemu/Makefile
@@ -15,7 +15,7 @@ BOARD_TARGETS = tools_build romfs_build clients_build stage1 subdirs
 SUBDIRS = slof
 
 COMMON_LIBS = libc libbootmsg libbases libnvram libelf libhvcall libvirtio libusb \
-              libveth libe1k
+              libveth libe1k libtpm
 
 all: $(BOARD_TARGETS)
 	$(MAKE) boot_rom.bin
diff --git a/board-qemu/slof/Makefile b/board-qemu/slof/Makefile
index 283f77d..be6eec1 100644
--- a/board-qemu/slof/Makefile
+++ b/board-qemu/slof/Makefile
@@ -21,7 +21,7 @@ all: version.o Makefile.dep OF.ffs paflof $(SLOFCMNDIR)/xvect.bin
 CPPFLAGS = -I$(LIBCMNDIR)/libbootmsg -I$(LIBCMNDIR)/libhvcall \
 	   -I$(LIBCMNDIR)/libvirtio -I$(LIBCMNDIR)/libnvram \
 	   -I$(LIBCMNDIR)/libusb -I$(LIBCMNDIR)/libveth \
-	   -I$(LIBCMNDIR)/libe1k
+	   -I$(LIBCMNDIR)/libe1k -I$(LIBCMNDIR)/libtpm
 SLOF_LIBS = \
 	$(LIBCMNDIR)/libbootmsg.a \
 	$(LIBCMNDIR)/libelf.a \
@@ -30,7 +30,8 @@ SLOF_LIBS = \
 	$(LIBCMNDIR)/libusb.a \
 	$(LIBCMNDIR)/libnvram.a \
 	$(LIBCMNDIR)/libveth.a \
-	$(LIBCMNDIR)/libe1k.a
+	$(LIBCMNDIR)/libe1k.a \
+	$(LIBCMNDIR)/libtpm.a
 BOARD_SLOF_IN = \
 	$(LIBCMNDIR)/libhvcall/hvcall.in \
 	$(LIBCMNDIR)/libvirtio/virtio.in \
@@ -40,7 +41,8 @@ BOARD_SLOF_IN = \
 	$(LIBCMNDIR)/libnvram/libnvram.in \
 	$(LIBCMNDIR)/libbases/libbases.in \
 	$(LIBCMNDIR)/libveth/veth.in \
-	$(LIBCMNDIR)/libe1k/e1k.in
+	$(LIBCMNDIR)/libe1k/e1k.in \
+	$(LIBCMNDIR)/libtpm/tpm.in
 BOARD_SLOF_CODE = $(BOARD_SLOF_IN:%.in=%.code)
 
 include $(SLOFCMNDIR)/Makefile.inc
@@ -71,6 +73,7 @@ VIO_FFS_FILES = \
 	$(SLOFBRDDIR)/pci-device_1af4_1009.fs \
 	$(SLOFBRDDIR)/vio-hvterm.fs \
 	$(SLOFBRDDIR)/vio-vscsi.fs \
+	$(SLOFBRDDIR)/vio-vtpm-cdriver.fs \
 	$(SLOFBRDDIR)/vio-veth.fs \
 	$(SLOFBRDDIR)/rtas-nvram.fs \
 	$(SLOFBRDDIR)/virtio-net.fs \
@@ -99,6 +102,7 @@ OF_FFS_FILES = \
 	$(SLOFBRDDIR)/default-font.bin \
 	$(SLOFBRDDIR)/pci-phb.fs \
 	$(SLOFBRDDIR)/rtas.fs \
+	$(SLOFBRDDIR)/vtpm-sml.fs \
 	$(SLOFBRDDIR)/pci-device_1234_1111.fs \
 	$(SLOFBRDDIR)/pci-device_1013_00b8.fs \
 	$(SLOFBRDDIR)/pci-device_8086_100e.fs \
diff --git a/board-qemu/slof/tree.fs b/board-qemu/slof/tree.fs
index 4aba4c5..b71009d 100644
--- a/board-qemu/slof/tree.fs
+++ b/board-qemu/slof/tree.fs
@@ -83,6 +83,9 @@ include fbuffer.fs
 	    2dup " qemu,spapr-nvram" strequal IF
 	    	" rtas-nvram.fs" included
 	    THEN
+	    2dup " IBM,vtpm" strequal IF
+                " vio-vtpm-cdriver.fs" included
+	    THEN
             2drop
        THEN
        peer
diff --git a/board-qemu/slof/vio-vtpm-cdriver.fs b/board-qemu/slof/vio-vtpm-cdriver.fs
new file mode 100644
index 0000000..f873456
--- /dev/null
+++ b/board-qemu/slof/vio-vtpm-cdriver.fs
@@ -0,0 +1,72 @@
+\ *****************************************************************************
+\ * Copyright (c) 2015 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ *     IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+." Populating " pwd
+
+false VALUE vtpm-debug?
+0     VALUE vtpm-unit
+
+: setup-alias
+    " ibm,vtpm" find-alias 0= IF
+        " ibm,vtpm" get-node node>path set-alias
+    ELSE
+        drop
+    THEN
+;
+
+: vtpm-cleanup ( )
+    vtpm-debug? IF ." VTPM: Disabling RTAS bypass" cr THEN
+    tpm-finalize
+    vtpm-unit 0 rtas-set-tce-bypass
+;
+
+: vtpm-init ( -- true | false )
+    0 0 get-node open-node ?dup 0= IF EXIT THEN
+    my-self >r
+    dup to my-self
+
+    vtpm-debug? IF ." VTPM: Initializing for c-driver" cr THEN
+
+    my-unit to vtpm-unit
+
+    \ Enable TCE bypass special qemu feature
+    vtpm-unit 1 rtas-set-tce-bypass
+
+    \ Have TCE bypass cleaned up
+    ['] vtpm-cleanup add-quiesce-xt
+
+    tpm-start dup 0= IF
+        vtpm-debug? IF ." VTPM: Success from tpm-start" cr THEN
+        drop
+        setup-alias
+    ELSE
+        ." VTPM: Error code from tpm-start: " . cr
+    THEN
+
+    close-node
+    r> to my-self
+;
+
+: open ( )
+    vtpm-debug? IF ." VTPM: vTPM open()" cr THEN
+    true
+;
+
+: close ( )
+    vtpm-debug? IF ." VTPM: vTPM close()" cr THEN
+;
+
+\ setup alias and the RTAS bypass
+vtpm-init
+
+\ setup the log
+include vtpm-sml.fs
diff --git a/board-qemu/slof/vtpm-sml.fs b/board-qemu/slof/vtpm-sml.fs
new file mode 100644
index 0000000..4d63b70
--- /dev/null
+++ b/board-qemu/slof/vtpm-sml.fs
@@ -0,0 +1,62 @@
+\ *****************************************************************************
+\ * Copyright (c) 2015 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ *     IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+\ KVM/qemu TPM Stored Measurement Log (SML) entries in /ibm,vtpm
+
+" /" find-device
+
+new-device
+
+false VALUE    vtpm-debug?
+0     VALUE    log-base
+40000 CONSTANT LOG-SIZE   \ 256k per VTPM FW spec.
+
+LOG-SIZE BUFFER: log-base
+
+\ create /ibm,vtpm
+s" ibm,vtpm" 2dup device-name device-type
+
+: sml-get-allocated-size ( -- buffer-size)
+    vtpm-debug? IF
+        ." Call to sml-get-allocated-size; size = 0x" LOG-SIZE . cr
+    THEN
+    LOG-SIZE
+;
+
+: sml-handover ( dest size -- )
+    vtpm-debug? IF
+        2dup
+        ." Call to sml-handover; size = 0x" . ." dest = " . cr
+    THEN
+    log-base        ( dest size src )
+    -rot            ( src dest size )
+    move
+;
+
+\
+\ internal API calls
+\
+
+: unassert-physical-presence ( -- )
+    tpm-unassert-physical-presence                    ( -- errcode )
+    dup 0<> IF
+        ." VTPM: Error code from tpm-unassert-physical-presence: " . cr
+    ELSE
+        drop
+    THEN
+;
+
+: open  true ;
+: close ;
+
+finish-device
+device-end
diff --git a/lib/Makefile b/lib/Makefile
index ed8a359..9c802e2 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -11,7 +11,7 @@
 # ****************************************************************************/
 
 SUBDIRS = libc libipmi libbootmsg libbases libnvram libelf libhvcall libvirtio \
-          libusb libveth libe1k libbcm
+          libusb libveth libe1k libbcm libtpm
 
 all:  subdirs
 
diff --git a/lib/libtpm/Makefile b/lib/libtpm/Makefile
index ff19e1c..012fe37 100644
--- a/lib/libtpm/Makefile
+++ b/lib/libtpm/Makefile
@@ -23,7 +23,7 @@ TARGET = ../libtpm.a
 
 all: $(TARGET)
 
-SRCS = tpm_drivers.c
+SRCS = tpm_drivers.c tcgbios.c
 
 OBJS = $(SRCS:%.c=%.o)
 
diff --git a/lib/libtpm/tcgbios.c b/lib/libtpm/tcgbios.c
new file mode 100644
index 0000000..dd0d801
--- /dev/null
+++ b/lib/libtpm/tcgbios.c
@@ -0,0 +1,335 @@
+
+/*****************************************************************************
+ * Copyright (c) 2015 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ *     IBM Corporation - initial implementation
+ *****************************************************************************/
+
+/*
+ *  Implementation of the TPM BIOS extension according to the specification
+ *  described in the IBM VTPM Firmware document and the TCG Specification
+ *  that can be found here under the following link:
+ *  http://www.trustedcomputinggroup.org/resources/pc_client_work_group_specific_implementation_specification_for_conventional_bios
+ */
+
+#include "types.h"
+#include "byteorder.h"
+#include "tpm_drivers.h"
+#include "string.h"
+#include "tcgbios.h"
+#include "tcgbios_int.h"
+#include "stdio.h"
+
+#undef TCGBIOS_DEBUG
+//#define TCGBIOS_DEBUG
+#ifdef TCGBIOS_DEBUG
+#define dprintf(_x ...) do { printf("TCGBIOS: " _x); } while(0)
+#else
+#define dprintf(_x ...)
+#endif
+
+static const uint8_t startup_st_clear[] = { 0x00, TPM_ST_CLEAR };
+static const uint8_t startup_st_state[] = { 0x00, TPM_ST_STATE };
+
+static const uint8_t physical_presence_cmd_enable[]  = { 0x00, 0x20 };
+static const uint8_t physical_presence_cmd_disable[] = { 0x01, 0x00 };
+static const uint8_t physical_presence_present[]     = { 0x00, 0x08 };
+static const uint8_t physical_presence_not_present_lock[] = { 0x00, 0x14 };
+
+static const uint8_t command_flag_false[] = { 0x00 };
+static const uint8_t command_flag_true[]  = { 0x01 };
+
+static const uint8_t get_capability_permanent_flags[] = {
+	0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04,
+	0x00, 0x00, 0x01, 0x08
+};
+
+static const uint8_t get_capability_owner_auth[] = {
+	0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04,
+	0x00, 0x00, 0x01, 0x11
+};
+
+static const uint8_t get_capability_timeouts[] = {
+	0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04,
+	0x00, 0x00, 0x01, 0x15
+};
+
+static const uint8_t get_capability_durations[] = {
+	0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04,
+	0x00, 0x00, 0x01, 0x20
+};
+
+struct tpm_state {
+	unsigned tpm_probed:1;
+	unsigned tpm_found:1;
+	unsigned tpm_working:1;
+};
+
+static struct tpm_state tpm_state;
+
+/********************************************************
+  Extensions for TCG-enabled BIOS
+ *******************************************************/
+
+static void probe_tpm(void)
+{
+	tpm_state.tpm_probed = true;
+	tpm_state.tpm_found = spapr_is_vtpm_present();
+	tpm_state.tpm_working = tpm_state.tpm_found;
+}
+
+static bool has_working_tpm(void)
+{
+	if (!tpm_state.tpm_probed)
+		probe_tpm();
+
+	return tpm_state.tpm_working;
+}
+
+static uint32_t transmit(struct tpm_req_header *req,
+			 uint8_t *respbuffer, uint32_t *respbufferlen,
+			 enum tpm_duration_type to_t)
+{
+	if (!spapr_vtpm_transmit((uint8_t *)req, be32_to_cpu(req->totlen),
+	                         to_t, respbuffer, respbufferlen))
+		goto err_exit;
+
+	return 0;
+
+err_exit:
+	/* do not send any commands */
+	tpm_state.tpm_working = false;
+
+	return TCGBIOS_FATAL_COM_ERROR;
+}
+
+/*
+ * Send a TPM command with the given ordinal. Append the given buffer
+ * containing all data in network byte order to the command (this is
+ * the custom part per command) and expect a response of the given size.
+ * If a buffer is provided, the response will be copied into it.
+ */
+static uint32_t build_and_send_cmd(uint32_t ordinal,
+				   const uint8_t *append,
+				   uint32_t append_size,
+				   uint8_t *resbuffer,
+				   uint32_t return_size,
+				   uint32_t *return_code,
+				   enum tpm_duration_type to_t)
+{
+	uint32_t rc;
+	struct {
+		struct tpm_req_header trqh;
+		uint8_t cmd[64];
+	} __attribute__((packed)) req = {
+		.trqh.tag = cpu_to_be16(TPM_TAG_RQU_CMD),
+		.trqh.totlen = cpu_to_be32(TPM_REQ_HEADER_SIZE + append_size),
+		.trqh.ordinal = cpu_to_be32(ordinal),
+	};
+	uint8_t obuffer[64];
+	struct tpm_rsp_header *trsh = (struct tpm_rsp_header *)obuffer;
+	uint32_t obuffer_len = sizeof(obuffer);
+
+	if (return_size > sizeof(obuffer) || append_size > sizeof(req.cmd)) {
+		printf("TCGBIOS: Error: size of requested response buffer too big.");
+		return TCGBIOS_FIRMWARE_ERROR;
+	}
+
+	memset(obuffer, 0, sizeof(obuffer));
+
+	if (append_size)
+		memcpy(req.cmd, append, append_size);
+
+	rc = transmit(&req.trqh, obuffer, &obuffer_len, to_t);
+	if (rc)
+		return rc;
+
+	*return_code = be32_to_cpu(trsh->errcode);
+
+	if (resbuffer)
+		memcpy(resbuffer, trsh, return_size);
+
+	return 0;
+}
+
+static void tpm_set_failure(void)
+{
+	uint32_t return_code;
+
+	/* we will try to deactivate the TPM now - ignoring all errors */
+	build_and_send_cmd(TPM_ORD_PHYSICAL_PRESENCE,
+			   physical_presence_cmd_enable,
+			   sizeof(physical_presence_cmd_enable),
+			   NULL, 0, &return_code,
+			   TPM_DURATION_TYPE_SHORT);
+
+	build_and_send_cmd(TPM_ORD_PHYSICAL_PRESENCE,
+			   physical_presence_present,
+			   sizeof(physical_presence_present),
+			   NULL, 0, &return_code,
+			   TPM_DURATION_TYPE_SHORT);
+
+	build_and_send_cmd(TPM_ORD_SET_TEMP_DEACTIVATED,
+			   NULL, 0, NULL, 0, &return_code,
+			   TPM_DURATION_TYPE_SHORT);
+
+	tpm_state.tpm_working = false;
+}
+
+static uint32_t determine_timeouts(void)
+{
+	uint32_t rc;
+	uint32_t return_code;
+	struct tpm_rsp_getcap_durations durations;
+	unsigned int i;
+
+	rc = build_and_send_cmd(TPM_ORD_GET_CAPABILITY,
+				get_capability_durations,
+				sizeof(get_capability_durations),
+				(uint8_t *)&durations, sizeof(durations),
+				&return_code, TPM_DURATION_TYPE_SHORT);
+
+	dprintf("Return code from TPM_GetCapability(Durations) = 0x%08x\n",
+		return_code);
+
+	if (rc || return_code)
+		goto err_exit;
+
+	for (i = 0; i < TPM_NUM_DURATIONS; i++)
+		durations.durations[i] = be32_to_cpu(durations.durations[i]);
+
+	dprintf("durations: %u %u %u\n",
+		durations.durations[0],
+		durations.durations[1],
+		durations.durations[2]);
+
+	spapr_vtpm_set_durations(durations.durations);
+
+	return 0;
+
+err_exit:
+	dprintf("TPM malfunctioning (line %d).\n", __LINE__);
+
+	tpm_set_failure();
+	if (rc)
+		return rc;
+	return TCGBIOS_COMMAND_ERROR;
+}
+
+static uint32_t tpm_startup(void)
+{
+	uint32_t rc;
+	uint32_t return_code;
+
+	if (!has_working_tpm())
+		return TCGBIOS_GENERAL_ERROR;
+
+	dprintf("Starting with TPM_Startup(ST_CLEAR)\n");
+	rc = build_and_send_cmd(TPM_ORD_STARTUP,
+				startup_st_clear, sizeof(startup_st_clear),
+				NULL, 0, &return_code,
+				TPM_DURATION_TYPE_SHORT);
+
+	dprintf("Return code from TPM_Startup = 0x%08x\n",
+		return_code);
+
+	if (rc || return_code)
+		goto err_exit;
+
+	rc = build_and_send_cmd(TPM_ORD_SELF_TEST_FULL, NULL, 0,
+				NULL, 0, &return_code,
+				TPM_DURATION_TYPE_LONG);
+
+	dprintf("Return code from TPM_SelfTestFull = 0x%08x\n",
+		return_code);
+
+	if (rc || return_code)
+		goto err_exit;
+
+	rc = determine_timeouts();
+	if (rc)
+		goto err_exit;
+
+	return 0;
+
+err_exit:
+	dprintf("TPM malfunctioning (line %d).\n", __LINE__);
+
+	tpm_set_failure();
+	if (rc)
+		return rc;
+	return TCGBIOS_COMMAND_ERROR;
+}
+
+uint32_t tpm_start(void)
+{
+	tpm_state.tpm_probed = false;
+	tpm_state.tpm_found = false;
+	tpm_state.tpm_working = false;
+
+	if (!has_working_tpm()) {
+		dprintf("%s: Machine does not have a working TPM\n",
+			__func__);
+		return TCGBIOS_FATAL_COM_ERROR;
+	}
+
+	return tpm_startup();
+}
+
+void tpm_finalize(void)
+{
+	spapr_vtpm_finalize();
+}
+
+/*
+ * Give up physical presence; this function has to be called before
+ * the firmware transitions to the boot loader.
+ */
+uint32_t tpm_unassert_physical_presence(void)
+{
+	uint32_t rc;
+	uint32_t return_code;
+
+	if (!has_working_tpm())
+		return TCGBIOS_GENERAL_ERROR;
+
+	rc = build_and_send_cmd(TPM_ORD_PHYSICAL_PRESENCE,
+				physical_presence_cmd_enable,
+				sizeof(physical_presence_cmd_enable),
+				NULL, 0, &return_code,
+				TPM_DURATION_TYPE_SHORT);
+
+	dprintf("Return code from TPM_PhysicalPresence(CMD_ENABLE) = 0x%08x\n",
+		return_code);
+
+	if (rc || return_code)
+		goto err_exit;
+
+	rc = build_and_send_cmd(TPM_ORD_PHYSICAL_PRESENCE,
+				physical_presence_not_present_lock,
+				sizeof(physical_presence_not_present_lock),
+				NULL, 0, &return_code,
+				TPM_DURATION_TYPE_SHORT);
+
+	dprintf("Return code from TPM_PhysicalPresence(NOT_PRESENT_LOCK) = 0x%08x\n",
+		return_code);
+
+	if (rc || return_code)
+		goto err_exit;
+
+	return 0;
+
+err_exit:
+	dprintf("TPM malfunctioning (line %d).\n", __LINE__);
+
+	tpm_set_failure();
+	if (rc)
+		return rc;
+	return TCGBIOS_COMMAND_ERROR;
+}
diff --git a/lib/libtpm/tcgbios.h b/lib/libtpm/tcgbios.h
new file mode 100644
index 0000000..5b5e481
--- /dev/null
+++ b/lib/libtpm/tcgbios.h
@@ -0,0 +1,22 @@
+/*****************************************************************************
+ * Copyright (c) 2015 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ *     IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef TCGBIOS_H
+#define TCGBIOS_H
+
+#include <stdint.h>
+
+uint32_t tpm_start(void);
+void tpm_finalize(void);
+uint32_t tpm_unassert_physical_presence(void);
+
+#endif /* TCGBIOS_H */
diff --git a/lib/libtpm/tcgbios_int.h b/lib/libtpm/tcgbios_int.h
new file mode 100644
index 0000000..c0cb960
--- /dev/null
+++ b/lib/libtpm/tcgbios_int.h
@@ -0,0 +1,136 @@
+/*****************************************************************************
+ * Copyright (c) 2015 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ *     IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#ifndef TCGBIOS_INT_H
+#define TCGBIOS_INT_H
+
+#include <stdint.h>
+
+#include "tpm_drivers.h"
+
+/* internal error codes */
+#define TCGBIOS_OK                       0x0
+#define TCGBIOS_LOGOVERFLOW              0x1
+#define TCGBIOS_GENERAL_ERROR            0x2
+#define TCGBIOS_FIRMWARE_ERROR           0x3
+#define TCGBIOS_FATAL_COM_ERROR          0x4
+#define TCGBIOS_INVALID_INPUT_PARA       0x5
+#define TCGBIOS_COMMAND_ERROR            0x6
+#define TCGBIOS_INTERFACE_SHUTDOWN       0x7
+
+#define TPM_ORD_SELF_TEST_FULL           0x00000050
+#define TPM_ORD_FORCE_CLEAR              0x0000005d
+#define TPM_ORD_GET_CAPABILITY           0x00000065
+#define TPM_ORD_PHYSICAL_ENABLE          0x0000006f
+#define TPM_ORD_PHYSICAL_DISABLE         0x00000070
+#define TPM_ORD_SET_OWNER_INSTALL        0x00000071
+#define TPM_ORD_PHYSICAL_SET_DEACTIVATED 0x00000072
+#define TPM_ORD_SET_TEMP_DEACTIVATED     0x00000073
+#define TPM_ORD_STARTUP                  0x00000099
+#define TPM_ORD_PHYSICAL_PRESENCE        0x4000000a
+#define TPM_ORD_EXTEND                   0x00000014
+
+#define TPM_ST_CLEAR                     0x1
+#define TPM_ST_STATE                     0x2
+#define TPM_ST_DEACTIVATED               0x3
+
+#define TPM_TAG_RQU_CMD                  0x00c1
+
+/* TPM command error codes */
+#define TPM_INVALID_POSTINIT             0x26
+
+/* event types */
+#define EV_POST_CODE                     1
+#define EV_SEPARATOR                     4
+#define EV_ACTION                        5
+#define EV_EVENT_TAG                     6
+#define EV_IPL                          13
+#define EV_IPL_PARTITION_DATA           14
+
+#define SHA1_BUFSIZE                    20
+
+/* Input and Output blocks for the TCG BIOS commands */
+
+/* PCClient_PCREventStruct -- format of log entries; compatible with x86 */
+struct pcpes {
+	uint32_t pcrindex;
+	uint32_t eventtype;
+	uint8_t digest[SHA1_BUFSIZE];
+	uint32_t eventdatasize;
+	uint32_t event;
+} __attribute__((packed));
+
+struct tpm_req_header {
+	uint16_t tag;
+	uint32_t totlen;
+	uint32_t ordinal;
+} __attribute__((packed));
+
+#define TPM_REQ_HEADER_SIZE (sizeof(struct tpm_req_header))
+
+struct tpm_rsp_header {
+	uint16_t tag;
+	uint32_t totlen;
+	uint32_t errcode;
+} __attribute__((packed));
+
+#define TPM_RSP_HEADER_SIZE (sizeof(struct tpm_rsp_header))
+
+struct tpm_req_extend {
+	struct tpm_req_header hdr;
+	uint32_t pcrindex;
+	uint8_t digest[SHA1_BUFSIZE];
+} __attribute__((packed));
+
+struct tpm_rsp_extend {
+	struct tpm_rsp_header hdr;
+	uint8_t digest[SHA1_BUFSIZE];
+} __attribute__((packed));
+
+struct tpm_req_getcap_perm_flags {
+	struct tpm_req_header hdr;
+	uint32_t cap_area;
+	uint32_t sub_cap_zize;
+	uint32_t sub_cap;
+} __attribute__((packed));
+
+struct tpm_permanent_flags {
+	uint16_t tag;
+	uint8_t flags[20];
+} __attribute__((packed));
+
+#define PERM_FLAG_IDX_DISABLE 0
+#define PERM_FLAG_IDX_OWNERSHIP 1
+#define PERM_FLAG_IDX_DEACTIVATED 2
+#define PERM_FLAG_IDX_DISABLEOWNERCLEAR 4
+#define PERM_FLAG_IDX_PHYSICAL_PRESENCE_LIFETIME_LOCK 6
+#define PERM_FLAG_IDX_PHYSICAL_PRESENCE_HW_ENABLE 7
+
+struct tpm_rsp_getcap_perm_flags {
+	struct tpm_rsp_header hdr;
+	uint32_t size;
+	struct tpm_permanent_flags perm_flags;
+} __attribute__((packed));
+
+struct tpm_rsp_getcap_ownerauth {
+	struct tpm_rsp_header hdr;
+	uint32_t size;
+	uint8_t flag;
+} __attribute__((packed));
+
+struct tpm_rsp_getcap_durations {
+	struct tpm_rsp_header hdr;
+	uint32_t size;
+	uint32_t durations[TPM_NUM_DURATIONS];
+} __attribute__((packed));
+
+#endif /* TCGBIOS_INT_H */
diff --git a/lib/libtpm/tpm.code b/lib/libtpm/tpm.code
new file mode 100644
index 0000000..08f52e9
--- /dev/null
+++ b/lib/libtpm/tpm.code
@@ -0,0 +1,46 @@
+/******************************************************************************
+ * Copyright (c) 2015 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ *     IBM Corporation - initial implementation
+ *****************************************************************************/
+/*
+ * libtpm bindings for SLOF - implementation
+ */
+
+#include <tcgbios.h>
+
+
+/************************************************/
+/* Startup TPM code                             */
+/* SLOF:   tpm-start  ( -- errcode )            */
+/* LIBTPM: tpm_start(void)                      */
+/************************************************/
+PRIM(tpm_X2d_start)
+	PUSH;
+	TOS.n = tpm_start();
+MIRP
+
+/************************************************/
+/* Shutdown TPM layer before OS takes over      */
+/* SLOF:   tpm-finalize  ( -- )                 */
+/* LIBTPM: tpm_finalize(void)                   */
+/************************************************/
+PRIM(tpm_X2d_finalize)
+	tpm_finalize();
+MIRP
+
+/***************************************************************/
+/* Prepare TPM state for bootloader                            */
+/* SLOF:   tpm-unassert-physical-presence ( -- errcode )       */
+/* LIBTPM: tpm_unassert_physical-presence(void)                */
+/***************************************************************/
+PRIM(tpm_X2d_unassert_X2d_physical_X2d_presence)
+	PUSH;
+	TOS.n = tpm_unassert_physical_presence();
+MIRP
diff --git a/lib/libtpm/tpm.in b/lib/libtpm/tpm.in
new file mode 100644
index 0000000..e212483
--- /dev/null
+++ b/lib/libtpm/tpm.in
@@ -0,0 +1,18 @@
+/******************************************************************************
+ * Copyright (c) 2015 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ *     IBM Corporation - initial implementation
+ *****************************************************************************/
+/*
+ * libtpm bindings for SLOF - definitions
+ */
+
+cod(tpm-start)
+cod(tpm-finalize)
+cod(tpm-unassert-physical-presence)
diff --git a/slof/fs/start-up.fs b/slof/fs/start-up.fs
index f1488fa..f115b89 100644
--- a/slof/fs/start-up.fs
+++ b/slof/fs/start-up.fs
@@ -56,6 +56,13 @@
 ;
 
 : (boot?) ( -- )
+   \ last step before we boot we give up physical presence on the TPM
+   s" /ibm,vtpm" find-node dup IF
+      s" unassert-physical-presence" rot $call-static
+   ELSE
+      drop
+   THEN
+
    of-prompt? not auto-boot? and IF
       (boot)
    THEN
-- 
2.4.3



More information about the SLOF mailing list