[SLOF] [PATCH v2 02/20] Add TPM initialization support
Stefan Berger
stefanb at us.ibm.com
Wed Nov 18 04:02:18 AEDT 2015
From: Stefan Berger <stefanb at linux.vnet.ibm.com>
This patch implements the main part of the fimrmware 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/OF.fs | 6 +
board-qemu/slof/tree.fs | 3 +
board-qemu/slof/vio-vtpm-cdriver.fs | 71 +++++++
board-qemu/slof/vtpm-sml.fs | 49 +++++
lib/Makefile | 2 +-
lib/libtpm/Makefile | 2 +-
lib/libtpm/tcgbios.c | 406 ++++++++++++++++++++++++++++++++++++
lib/libtpm/tcgbios.h | 21 ++
lib/libtpm/tcgbios_int.h | 173 +++++++++++++++
lib/libtpm/tpm.code | 37 ++++
lib/libtpm/tpm.in | 17 ++
slof/fs/tpm/tpm-static.fs | 34 +++
14 files changed, 827 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
create mode 100644 slof/fs/tpm/tpm-static.fs
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/OF.fs b/board-qemu/slof/OF.fs
index 561d892..80bc011 100644
--- a/board-qemu/slof/OF.fs
+++ b/board-qemu/slof/OF.fs
@@ -113,6 +113,10 @@ d# 512000000 VALUE tb-frequency \ default value - needed for "ms" to work
#include "fdt.fs"
+350 cp
+
+#include <tpm/tpm-static.fs>
+
360 cp
#include <root.fs>
@@ -300,6 +304,8 @@ cr
#include "copyright-oss.fs"
cr cr
+vtpm-unassert-physical-presence
+
\ this CATCH is to ensure the code bellow always executes: boot may ABORT!
' start-it CATCH drop
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..86e8bd6
--- /dev/null
+++ b/board-qemu/slof/vio-vtpm-cdriver.fs
@@ -0,0 +1,71 @@
+\ *****************************************************************************
+\ * 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
+ 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
+ IF ." VTPM: Error code from tpm-start: " . cr THEN
+ 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..40f1b7e
--- /dev/null
+++ b/board-qemu/slof/vtpm-sml.fs
@@ -0,0 +1,49 @@
+\ *****************************************************************************
+\ * 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 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 alloc-mem to 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 = " LOG-SIZE . cr
+ THEN
+ LOG-SIZE
+;
+
+: sml-handover ( dest size -- )
+ vtpm-debug? IF
+ 2dup
+ ." Call to sml-handover; size = " . ." dest = " . cr
+ THEN
+ log-base ( dest size src )
+ -rot ( src dest size )
+ move
+;
+
+: 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 a174815..53d3abb 100644
--- a/lib/libtpm/Makefile
+++ b/lib/libtpm/Makefile
@@ -24,7 +24,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..0dae810
--- /dev/null
+++ b/lib/libtpm/tcgbios.c
@@ -0,0 +1,406 @@
+
+/*****************************************************************************
+ * 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 {
+ uint8_t tpm_probed:1;
+ uint8_t tpm_found:1;
+ uint8_t tpm_working:1;
+ uint8_t if_shutdown:1;
+ struct tpm_driver *tpm_drv;
+};
+
+static struct tpm_state tpm_state = {
+ .tpm_drv = NULL,
+};
+
+extern struct tpm_driver tpm_drivers[];
+
+/* prototypes */
+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);
+
+/********************************************************
+ Extensions for TCG-enabled BIOS
+ *******************************************************/
+
+static bool is_tpm_present(void)
+{
+ bool rc = false;
+ unsigned int i;
+
+ for (i = 0; i < TPM_NUM_DRIVERS; i++) {
+ struct tpm_driver *td = &tpm_drivers[i];
+ if (td->probe()) {
+ td->init();
+ tpm_state.tpm_drv = td;
+ rc = true;
+ break;
+ }
+ }
+
+ return rc;
+}
+
+static void probe_tpm(void)
+{
+ tpm_state.tpm_probed = 1;
+ tpm_state.tpm_found = is_tpm_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 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 = 0;
+}
+
+static uint32_t transmit(uint8_t locty, const struct iovec iovec[],
+ uint8_t *respbuffer, uint32_t *respbufferlen,
+ enum tpm_duration_type to_t)
+{
+ struct tpm_driver *td = tpm_state.tpm_drv;
+ unsigned int i;
+
+ if (td == NULL)
+ goto err_exit;
+
+ if (!td->activate(locty))
+ goto err_exit;
+
+ for (i = 0; iovec[i].length; i++) {
+ if (!td->senddata(iovec[i].data,
+ iovec[i].length))
+ goto err_exit;
+ }
+
+ if (!td->transfer() ||
+ !td->waitresponseready(to_t) ||
+ !td->readresponse(respbuffer, respbufferlen))
+ goto err_exit;
+
+ td->ready();
+
+ return 0;
+
+err_exit:
+ tpm_set_failure();
+
+ 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_od(uint32_t ordinal,
+ const uint8_t *append,
+ uint32_t append_size,
+ uint8_t *resbuffer,
+ uint32_t return_size,
+ uint32_t *return_code,
+ const uint8_t *otherdata,
+ uint32_t otherdata_size,
+ enum tpm_duration_type to_t)
+{
+#define MAX_RESPONSE_SIZE 64 /* max. number of bytes in response */
+ uint32_t rc;
+ uint8_t obuffer[MAX_RESPONSE_SIZE];
+ struct tpm_req_header trqh;
+ struct tpm_rsp_header *trsh = (struct tpm_rsp_header *)obuffer;
+ uint8_t locty = 0;
+ struct iovec iovec[4] = {{ 0 }};
+ unsigned int idx = 1;
+ uint32_t obuffer_len = sizeof(obuffer);
+
+ if (return_size > MAX_RESPONSE_SIZE) {
+ dprintf("size of requested response buffer too big.");
+ return TCGBIOS_FIRMWARE_ERROR;
+ }
+
+ trqh.tag = cpu_to_be16(TPM_TAG_RQU_CMD);
+ trqh.totlen = cpu_to_be32(TPM_REQ_HEADER_SIZE +
+ append_size + otherdata_size);
+ trqh.ordinal = cpu_to_be32(ordinal);
+
+ iovec[0].data = &trqh;
+ iovec[0].length = TPM_REQ_HEADER_SIZE;
+
+ if (append_size) {
+ iovec[idx].data = append;
+ iovec[idx].length = append_size;
+ idx++;
+ }
+
+ if (otherdata) {
+ iovec[idx].data = otherdata;
+ iovec[idx].length = otherdata_size;
+ }
+
+ /*
+ * receive response into own buffer so we can return
+ * return code from here
+ */
+ memset(obuffer, 0, sizeof(obuffer));
+
+ rc = transmit(locty, iovec, 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 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)
+{
+ return build_and_send_cmd_od(ordinal, append, append_size,
+ resbuffer, return_size, return_code,
+ NULL, 0, to_t);
+}
+
+static uint32_t determine_timeouts(void)
+{
+ uint32_t rc;
+ uint32_t return_code;
+ struct tpm_res_getcap_durations durations;
+ struct tpm_driver *td = tpm_state.tpm_drv;
+ 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]);
+
+ td->setdurations(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.if_shutdown = 0;
+ tpm_state.tpm_probed = 0;
+ tpm_state.tpm_found = 0;
+ tpm_state.tpm_working = 0;
+
+ if (!has_working_tpm()) {
+ dprintf("%s: Machine does not have a working TPM\n",
+ __func__);
+ tpm_state.if_shutdown = 1;
+ return TCGBIOS_FATAL_COM_ERROR;
+ }
+
+ return tpm_startup();
+}
+
+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..594a089
--- /dev/null
+++ b/lib/libtpm/tcgbios.h
@@ -0,0 +1,21 @@
+/*****************************************************************************
+ * 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);
+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..a6a0d8f
--- /dev/null
+++ b/lib/libtpm/tcgbios_int.h
@@ -0,0 +1,173 @@
+/*****************************************************************************
+ * 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_ORD_SHA1_START 0x000000a0
+#define TPM_ORD_SHA1_UPDATE 0x000000a1
+#define TPM_ORD_SHA1_COMPLETE 0x000000a2
+
+#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_COMPACT_HASH 12
+#define EV_IPL 13
+#define EV_IPL_PARTITION_DATA 14
+
+#define STATUS_FLAG_SHUTDOWN (1 << 0)
+
+#define SHA1_BUFSIZE 20
+
+struct iovec {
+ size_t length;
+ const void *data;
+};
+
+/* 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 {
+ uint16_t tag;
+ uint32_t totlen;
+ uint32_t ordinal;
+ uint32_t pcrindex;
+ uint8_t digest[SHA1_BUFSIZE];
+} __attribute__((packed));
+
+struct tpm_rsp_extend {
+ uint16_t tag;
+ uint32_t totlen;
+ uint32_t errcode;
+ uint8_t digest[SHA1_BUFSIZE];
+} __attribute__((packed));
+
+struct tpm_req_getcap_perm_flags {
+ uint16_t tag;
+ uint32_t totlen;
+ uint32_t ordinal;
+ 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_res_getcap_perm_flags {
+ uint16_t tag;
+ uint32_t totlen;
+ uint32_t errcode;
+ uint32_t size;
+ struct tpm_permanent_flags perm_flags;
+} __attribute__((packed));
+
+struct tpm_res_getcap_ownerauth {
+ uint16_t tag;
+ uint32_t totlen;
+ uint32_t errcode;
+ uint32_t size;
+ uint8_t flag;
+} __attribute__((packed));
+
+struct tpm_res_getcap_durations {
+ uint16_t tag;
+ uint32_t totlen;
+ uint32_t errcode;
+ uint32_t size;
+ uint32_t durations[TPM_NUM_DURATIONS];
+} __attribute__((packed));
+
+struct tpm_res_sha1start {
+ uint16_t tag;
+ uint32_t totlen;
+ uint32_t errcode;
+ uint32_t max_num_bytes;
+} __attribute__((packed));
+
+struct tpm_res_sha1complete {
+ uint16_t tag;
+ uint32_t totlen;
+ uint32_t errcode;
+ uint8_t hash[SHA1_BUFSIZE];
+} __attribute__((packed));
+
+#endif /* TCGBIOS_INT_H */
diff --git a/lib/libtpm/tpm.code b/lib/libtpm/tpm.code
new file mode 100644
index 0000000..e42fd0b
--- /dev/null
+++ b/lib/libtpm/tpm.code
@@ -0,0 +1,37 @@
+/******************************************************************************
+ * 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 ) */
+/* LIBNEWUSB: tpm_start(void) */
+/************************************************/
+PRIM(tpm_X2d_start)
+ PUSH;
+ TOS.n = tpm_start();
+MIRP
+
+/***************************************************************/
+/* Prepare TPM state for bootloader */
+/* SLOF: tpm-unassert-physical-presence ( -- errcode ) */
+/* LIBNEWUSB: 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..4933af5
--- /dev/null
+++ b/lib/libtpm/tpm.in
@@ -0,0 +1,17 @@
+/******************************************************************************
+ * 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-unassert-physical-presence)
diff --git a/slof/fs/tpm/tpm-static.fs b/slof/fs/tpm/tpm-static.fs
new file mode 100644
index 0000000..504c345
--- /dev/null
+++ b/slof/fs/tpm/tpm-static.fs
@@ -0,0 +1,34 @@
+\ *****************************************************************************
+\ * 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
+\ ****************************************************************************/
+
+false VALUE vtpm-debug?
+
+\ none of the vTPM functions may be called if the alias is not there
+: vtpm-available?
+ " ibm,vtpm" find-alias 0 <> IF
+ drop
+ true
+ ELSE
+ false
+ THEN
+;
+
+: vtpm-unassert-physical-presence
+ vtpm-available? IF
+ tpm-unassert-physical-presence ( -- errcode )
+ dup 0<> IF
+ ." VTPM: Error code from tpm-unassert-physical-presence: " . cr
+ ELSE
+ drop
+ THEN
+ THEN
+;
--
2.4.3
More information about the SLOF
mailing list