@@ -15,7 +15,7 @@ BOARD_TARGETS = tools_build romfs_build stage1 subdirs
SUBDIRS = slof
COMMON_LIBS = libc libbootmsg libbases libnvram libelf libhvcall libvirtio \
- libusb libveth libe1k libnet libbootmenu
+ libusb libveth libe1k libnet libbootmenu libtpm
all: $(BOARD_TARGETS)
$(MAKE) boot_rom.bin
@@ -22,7 +22,8 @@ CPPFLAGS = -I$(LIBCMNDIR)/libbootmsg -I$(LIBCMNDIR)/libhvcall \
-I$(LIBCMNDIR)/libvirtio -I$(LIBCMNDIR)/libnvram \
-I$(LIBCMNDIR)/libusb -I$(LIBCMNDIR)/libveth \
-I$(LIBCMNDIR)/libe1k -I$(LIBCMNDIR)/libnet \
- -I$(LIBCMNDIR)/libbootmenu
+ -I$(LIBCMNDIR)/libbootmenu -I$(LIBCMNDIR)/libtpm
+
SLOF_LIBS = \
$(LIBCMNDIR)/libbootmsg.a \
$(LIBCMNDIR)/libelf.a \
@@ -33,7 +34,9 @@ SLOF_LIBS = \
$(LIBCMNDIR)/libveth.a \
$(LIBCMNDIR)/libe1k.a \
$(LIBCMNDIR)/libnet.a \
- $(LIBCMNDIR)/libbootmenu.a
+ $(LIBCMNDIR)/libbootmenu.a \
+ $(LIBCMNDIR)/libtpm.a
+
BOARD_SLOF_IN = \
$(LIBCMNDIR)/libhvcall/hvcall.in \
$(LIBCMNDIR)/libvirtio/virtio.in \
@@ -45,7 +48,9 @@ BOARD_SLOF_IN = \
$(LIBCMNDIR)/libveth/veth.in \
$(LIBCMNDIR)/libe1k/e1k.in \
$(LIBCMNDIR)/libnet/libnet.in \
- $(LIBCMNDIR)/libbootmenu/bootmenu.in
+ $(LIBCMNDIR)/libbootmenu/bootmenu.in \
+ $(LIBCMNDIR)/libtpm/tpm.in
+
BOARD_SLOF_CODE = $(BOARD_SLOF_IN:%.in=%.code)
include $(SLOFCMNDIR)/Makefile.inc
@@ -83,6 +88,7 @@ VIO_FFS_FILES = \
$(SLOFBRDDIR)/pci-device_1af4_1050.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 \
@@ -114,6 +120,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 \
@@ -87,6 +87,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
new file mode 100644
@@ -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
new file mode 100644
@@ -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
@@ -11,7 +11,7 @@
# ****************************************************************************/
SUBDIRS = libc libipmi libbootmsg libbases libnvram libelf libhvcall libvirtio \
- libusb libveth libe1k libbcm libnet libbootmenu
+ libusb libveth libe1k libbcm libnet libbootmenu libtpm
all: subdirs
@@ -23,7 +23,7 @@ TARGET = ../libtpm.a
all: $(TARGET)
-SRCS = tpm_drivers.c
+SRCS = tpm_drivers.c tcgbios.c
OBJS = $(SRCS:%.c=%.o)
new file mode 100644
@@ -0,0 +1,271 @@
+
+/*****************************************************************************
+ * 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
+
+struct tpm_state {
+ unsigned tpm_probed:1;
+ unsigned tpm_found:1;
+ unsigned tpm_working:1;
+ unsigned has_physical_presence: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;
+}
+
+/****************************************************************
+ * TPM hardware command wrappers
+ ****************************************************************/
+
+/* Helper function for sending TPM commands that take a single
+ * optional parameter (0, 1, or 2 bytes) and have no special response.
+ */
+static int
+tpm_simple_cmd(uint8_t locty, uint32_t ordinal, int param_size, uint16_t param,
+ enum tpm_duration_type to_t)
+{
+ struct {
+ struct tpm_req_header trqh;
+ uint16_t param;
+ } __attribute__((packed)) req = {
+ .trqh.totlen = cpu_to_be32(sizeof(req.trqh) + param_size),
+ .trqh.tag = cpu_to_be16(TPM_TAG_RQU_CMD),
+ .trqh.ordinal = cpu_to_be32(ordinal),
+ };
+ uint8_t obuffer[64];
+ struct tpm_rsp_header *trsh = (void *)obuffer;
+ uint32_t obuffer_len = sizeof(obuffer);
+ int ret;
+
+ switch (param_size) {
+ case 2:
+ req.param = cpu_to_be16(param);
+ break;
+ case 1:
+ *(uint8_t *)&req.param = param;
+ break;
+ }
+
+ memset(obuffer, 0, sizeof(obuffer));
+ ret = tpmhw_transmit(locty, &req.trqh, obuffer, &obuffer_len, to_t);
+ ret = ret ? -1 : be32_to_cpu(trsh->errcode);
+ dprintf("Return from tpm_simple_cmd(%x, %x) = %x\n",
+ ordinal, param, ret);
+
+ return ret;
+}
+
+static int tpm12_get_capability(uint32_t cap, uint32_t subcap,
+ struct tpm_rsp_header *rsp, uint32_t rsize)
+{
+ struct tpm_req_getcap trgc = {
+ .hdr.tag = cpu_to_be16(TPM_TAG_RQU_CMD),
+ .hdr.totlen = cpu_to_be32(sizeof(trgc)),
+ .hdr.ordinal = cpu_to_be32(TPM_ORD_GET_CAPABILITY),
+ .capArea = cpu_to_be32(cap),
+ .subCapSize = cpu_to_be32(sizeof(trgc.subCap)),
+ .subCap = cpu_to_be32(subcap)
+ };
+ uint32_t resp_size = rsize;
+ int ret = tpmhw_transmit(0, &trgc.hdr, rsp, &resp_size,
+ TPM_DURATION_TYPE_SHORT);
+ ret = (ret || resp_size != rsize) ? -1 : be32_to_cpu(rsp->errcode);
+ dprintf("TCGBIOS: Return code from TPM_GetCapability(%d, %d) = %x\n",
+ cap, subcap, ret);
+ return ret;
+}
+
+static int tpm12_read_permanent_flags(char *buf, size_t buf_len)
+{
+ struct tpm_rsp_getcap_perm_flags pf;
+ int ret;
+
+ memset(buf, 0, buf_len);
+ ret = tpm12_get_capability(TPM_CAP_FLAG, TPM_CAP_FLAG_PERMANENT,
+ &pf.hdr, sizeof(pf));
+ if (ret)
+ return -1;
+
+ memcpy(buf, &pf.perm_flags, buf_len);
+
+ return 0;
+}
+
+static int tpm12_determine_timeouts(void)
+{
+ struct tpm_rsp_getcap_durations durations;
+ int i;
+ int ret = tpm12_get_capability(TPM_CAP_PROPERTY, TPM_CAP_PROP_DURATION,
+ &durations.hdr, sizeof(durations));
+
+ if (ret)
+ return ret;
+
+ 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;
+}
+
+/****************************************************************
+ * Setup and Measurements
+ ****************************************************************/
+
+static bool tpm_is_working(void)
+{
+ if (!tpm_state.tpm_probed)
+ probe_tpm();
+
+ return tpm_state.tpm_working;
+}
+
+static void tpm_set_failure(void)
+{
+ /* we will try to deactivate the TPM now - ignoring all errors */
+ tpm_simple_cmd(0, TPM_ORD_SET_TEMP_DEACTIVATED,
+ 0, 0, TPM_DURATION_TYPE_SHORT);
+
+ tpm_state.tpm_working = false;
+}
+
+static int tpm12_assert_physical_presence(void)
+{
+ struct tpm_permanent_flags pf;
+ int ret = tpm_simple_cmd(0, TPM_ORD_PHYSICAL_PRESENCE,
+ 2, TPM_PP_PRESENT, TPM_DURATION_TYPE_SHORT);
+ if (!ret)
+ return 0;
+
+ ret = tpm12_read_permanent_flags((char *)&pf, sizeof(pf));
+ if (ret)
+ return -1;
+
+ /* check if hardware physical presence is supported */
+ if (pf.flags[PERM_FLAG_IDX_PHYSICAL_PRESENCE_HW_ENABLE]) {
+ /* HW. phys. presence may not be asserted ... */
+ return 0;
+ }
+
+ if (!pf.flags[PERM_FLAG_IDX_PHYSICAL_PRESENCE_LIFETIME_LOCK]
+ && !pf.flags[PERM_FLAG_IDX_PHYSICAL_PRESENCE_CMD_ENABLE]) {
+ tpm_simple_cmd(0, TPM_ORD_PHYSICAL_PRESENCE,
+ 2, TPM_PP_CMD_ENABLE, TPM_DURATION_TYPE_SHORT);
+ return tpm_simple_cmd(0, TPM_ORD_PHYSICAL_PRESENCE,
+ 2, TPM_PP_PRESENT,
+ TPM_DURATION_TYPE_SHORT);
+ }
+ return -1;
+}
+
+static int tpm12_startup(void)
+{
+ dprintf("Starting with TPM_Startup(ST_CLEAR)\n");
+ int ret = tpm_simple_cmd(0, TPM_ORD_STARTUP,
+ 2, TPM_ST_CLEAR, TPM_DURATION_TYPE_SHORT);
+ if (ret)
+ goto err_exit;
+
+ /* asssertion of physical presence is only possible after startup */
+ ret = tpm12_assert_physical_presence();
+ if (!ret)
+ tpm_state.has_physical_presence = true;
+
+ ret = tpm12_determine_timeouts();
+ if (ret)
+ goto err_exit;
+
+ ret = tpm_simple_cmd(0, TPM_ORD_SELF_TEST_FULL,
+ 0, 0, TPM_DURATION_TYPE_LONG);
+ if (ret)
+ goto err_exit;
+
+ return 0;
+
+err_exit:
+ dprintf("TPM malfunctioning (line %d).\n", __LINE__);
+
+ tpm_set_failure();
+ return -1;
+}
+
+uint32_t tpm_start(void)
+{
+ tpm_state.has_physical_presence = false;
+
+ probe_tpm();
+
+ if (!tpm_is_working()) {
+ dprintf("%s: Machine does not have a working TPM\n",
+ __func__);
+ return TCGBIOS_FATAL_COM_ERROR;
+ }
+
+ return tpm12_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)
+{
+ if (tpm_state.has_physical_presence)
+ tpm_simple_cmd(0, TPM_ORD_PHYSICAL_PRESENCE,
+ 2, TPM_PP_NOT_PRESENT_LOCK,
+ TPM_DURATION_TYPE_SHORT);
+
+ return 0;
+}
new file mode 100644
@@ -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 */
new file mode 100644
@@ -0,0 +1,153 @@
+/*****************************************************************************
+ * 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_PP_CMD_ENABLE 0x0020
+#define TPM_PP_PRESENT 0x0008
+#define TPM_PP_NOT_PRESENT_LOCK 0x0014
+
+#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 {
+ struct tpm_req_header hdr;
+ uint32_t capArea;
+ uint32_t subCapSize;
+ uint32_t subCap;
+} __attribute__((packed));
+
+#define TPM_CAP_FLAG 0x04
+#define TPM_CAP_PROPERTY 0x05
+#define TPM_CAP_FLAG_PERMANENT 0x108
+#define TPM_CAP_PROP_DURATION 0x120
+
+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
+#define PERM_FLAG_IDX_PHYSICAL_PRESENCE_CMD_ENABLE 8
+
+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 */
new file mode 100644
@@ -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
new file mode 100644
@@ -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)
@@ -20,6 +20,7 @@
#include "tpm_drivers.h"
#include "libhvcall.h"
#include "paflof.h"
+#include "tcgbios_int.h"
#undef PAPR_VTPM_DEBUG
//#define PAPR_VTPM_DEBUG
@@ -476,3 +477,15 @@ bool spapr_is_vtpm_present(void)
return rc;
}
+
+int tpmhw_transmit(uint8_t locty, struct tpm_req_header *req,
+ void *respbuffer, uint32_t *respbufferlen,
+ enum tpm_duration_type to_t)
+{
+ if (!spapr_vtpm_senddata((uint8_t *)req, be32_to_cpu(req->totlen)) ||
+ !spapr_vtpm_waitresponseready(to_t) ||
+ !spapr_vtpm_readresponse(respbuffer, respbufferlen) ||
+ *respbufferlen < sizeof(struct tpm_rsp_header))
+ return -1;
+ return 0;
+}
@@ -78,4 +78,9 @@ uint32_t spapr_vtpm_get_buffersize(void);
vtpm_drv_state spapr_vtpm_get_state(void);
vtpm_drv_error spapr_vtpm_get_error(void);
+struct tpm_req_header;
+int tpmhw_transmit(uint8_t locty, struct tpm_req_header *req,
+ void *respbuffer, uint32_t *respbufferlen,
+ enum tpm_duration_type to_t);
+
#endif /* TPM_DRIVERS_H */
@@ -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
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@linux.vnet.ibm.com> --- board-qemu/Makefile | 2 +- board-qemu/slof/Makefile | 13 +- 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 | 271 ++++++++++++++++++++++++++++ lib/libtpm/tcgbios.h | 22 +++ lib/libtpm/tcgbios_int.h | 153 ++++++++++++++++ lib/libtpm/tpm.code | 46 +++++ lib/libtpm/tpm.in | 18 ++ lib/libtpm/tpm_drivers.c | 13 ++ lib/libtpm/tpm_drivers.h | 5 + slof/fs/start-up.fs | 7 + 15 files changed, 685 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