[SLOF] [PATCH 02/16] Add TPM initialization support

Nikunj A Dadhania nikunj at linux.vnet.ibm.com
Mon Nov 9 19:29:46 AEDT 2015


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

> 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 |  74 +++++++
>  board-qemu/slof/vtpm-sml.fs         |  56 ++++++
>  lib/Makefile                        |   2 +-
>  lib/libtpm/Makefile                 |   2 +-
>  lib/libtpm/tcgbios.c                | 371 ++++++++++++++++++++++++++++++++++++
>  lib/libtpm/tcgbios.h                |  21 ++
>  lib/libtpm/tcgbios_int.h            | 162 ++++++++++++++++
>  lib/libtpm/tpm.code                 |  37 ++++
>  lib/libtpm/tpm.in                   |  17 ++
>  slof/fs/tpm/tpm-static.fs           |  34 ++++
>  14 files changed, 791 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..bd9495e 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-pp
> +
>  \ 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..2fc1657
> --- /dev/null
> +++ b/board-qemu/slof/vio-vtpm-cdriver.fs
> @@ -0,0 +1,74 @@
> +\ *****************************************************************************
> +\ * 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                              ( -- errcode )
> +    vtpm-debug? IF
> +        ." VTPM: Error code from tpm-start: " dup . cr
> +    THEN
> +
> +    \ check errorcode
> +    0= IF
> +        \ tpm-start had no error: Setup an alias
> +        setup-alias
> +    THEN

Why dont you print an error when the TPM start fails ? Something like
below ?


    tpm-start dup 0= IF
        vtpm-debug? IF ." VTPM: Success code: " dup . cr THEN
        setup-alias drop
    ELSE
         ." VTPM: Init Error, code: " . 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..72edac0
> --- /dev/null
> +++ b/board-qemu/slof/vtpm-sml.fs
> @@ -0,0 +1,56 @@
> +\ *****************************************************************************
> +\ * 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

Why is it there in root, is this documented in PAPR?

We generally push such changes in /openprom.

Thomas do you have some suggestions here?

> +
> +" /" 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-get-handover-size ( -- size )
> +    vtpm-debug? IF
> +        ." Call to sml-get-handover-size; size = " LOG-SIZE . cr
> +    THEN
> +    LOG-SIZE
> +;

What is the difference between the above two ?

: sml-get-handover-size sml-get-allocated-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..efa4cdf
> --- /dev/null
> +++ b/lib/libtpm/tcgbios.c
> @@ -0,0 +1,371 @@
> +/*****************************************************************************
> + * 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"
> +
> +#define DEBUG 0
> +#define dprintf(_x ...) do { \
> +	if (DEBUG) { \
> +		printf("TCGBIOS: " _x); \
> +	} \
> +} while (0);

This will be do { if (0)  { printf (); } } while(0);

which i assume compiler can optimize, but as suggested in earlier patch
can we make it more explicit ?

Variable names look foreign in the SLOF code !

> +
> +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 PhysicalPresence_CMD_ENABLE[]  = { 0x00, 0x20 };
> +static const uint8_t PhysicalPresence_CMD_DISABLE[] = { 0x01, 0x00 };
> +static const uint8_t PhysicalPresence_PRESENT[]     = { 0x00, 0x08 };
> +static const uint8_t PhysicalPresence_NOT_PRESENT_LOCK[] = { 0x00, 0x14 };
> +
> +static const uint8_t CommandFlag_FALSE[] = { 0x00 };
> +static const uint8_t CommandFlag_TRUE[]  = { 0x01 };
> +
> +static const uint8_t GetCapability_Permanent_Flags[] = {
> +	0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04,
> +	0x00, 0x00, 0x01, 0x08
> +};
> +
> +static const uint8_t GetCapability_OwnerAuth[] = {
> +	0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04,
> +	0x00, 0x00, 0x01, 0x11
> +};
> +
> +static const uint8_t GetCapability_Timeouts[] = {
> +	0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04,
> +	0x00, 0x00, 0x01, 0x15
> +};
> +
> +static const uint8_t GetCapability_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_driver_to_use;

	struct tpm_driver *tpm_drv;

> +};
> +
> +static struct tpm_state tpm_state = {
> +	.tpm_driver_to_use = NULL,
> +};
> +
> +extern struct tpm_driver tpm_drivers[];
> +
> +/********************************************************
> +  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_driver_to_use = td;
> +			rc = true;
> +			break;
> +		}
> +	}
> +
> +	return rc;
> +}
> +
> +static void probe_tpm(void)
> +{
> +	if (!tpm_state.tpm_probed) {
> +		tpm_state.tpm_probed = 1;
> +		tpm_state.tpm_found = (is_tpm_present() != 0);

		tpm_state.tpm_found = is_tpm_present();

> +		tpm_state.tpm_working = tpm_state.tpm_found;
> +	}
> +}
> +
> +static bool has_working_tpm(void)
> +{
> +	probe_tpm();

	if (!tpm_state.tpm_probed) {
           probe_tpm(); /* get rid of condition in probe_tpm() */
        }

> +
> +	return tpm_state.tpm_working;
> +}
> +
> +static uint32_t transmit(uint8_t locty, const struct iovec iovec[],
> +			 uint8_t *respbuffer, uint32_t *respbufferlen,
> +			 enum tpmDurationType to_t)
> +{
> +	struct tpm_driver *td;
> +	unsigned int i;
> +
> +	if (tpm_state.tpm_driver_to_use == NULL)
> +		return TCGBIOS_FATAL_COM_ERROR;
> +
> +	td = tpm_state.tpm_driver_to_use;

can be replaced by:

	struct tpm_driver *td = tpm_state.tpm_driver_to_use;
	unsigned int i;

        if (!td)
               return TCGBIOS_FATAL_COM_ERROR;

> +
> +	if (!td->activate(locty))
> +		return TCGBIOS_FATAL_COM_ERROR;
> +
> +	for (i = 0; iovec[i].length; i++) {
> +		if (!td->senddata(iovec[i].data,
> +				  iovec[i].length))
> +			return TCGBIOS_FATAL_COM_ERROR;
> +	}
> +
> +	if (!td->transfer())
> +		return TCGBIOS_FATAL_COM_ERROR;
> +
> +	if (!td->waitrespready(to_t))
> +		return TCGBIOS_FATAL_COM_ERROR;
> +
> +	if (!td->readresp(respbuffer, respbufferlen))
> +		return TCGBIOS_FATAL_COM_ERROR;
> +
> +	td->ready();
> +
> +	return 0;
> +}
> +
> +/*
> + * 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 *returnCode,
> +				      const uint8_t *otherdata,
> +				      uint32_t otherdata_size,
> +				      enum tpmDurationType to_t)
> +{
> +#define MAX_APPEND_SIZE   sizeof(GetCapability_Timeouts)
> +#define MAX_RESPONSE_SIZE sizeof(struct tpm_res_getcap_perm_flags)

move these to the headers please where you have GetCapability_Timeouts
and name it appropriately. I do not get how is GetCapability_Timeouts
linked to APPEND_SIZE.

> +	uint32_t rc;
> +	uint8_t ibuffer[TPM_REQ_HEADER_SIZE + MAX_APPEND_SIZE];

This is very ugly code for TPM_REQ_HEADER_SIZE:

 +#define TPM_REQ_HEADER \
 +    uint16_t tag; \
 +    uint32_t totlen; \
 +    uint32_t ordinal;
 +
 +#define TPM_REQ_HEADER_SIZE  (sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint32_t))

Its just some repitition of variable in different structure that you are
saving. Nothing much. IMHO, you can repeat them in all the structure and
get rid of this define. ditto for TPM_RSP_HEADER_SIZE.

> +	uint8_t obuffer[MAX_RESPONSE_SIZE];
> +	struct tpm_req_header *trqh = (struct tpm_req_header *)ibuffer;
> +	struct tpm_rsp_header *trsh = (struct tpm_rsp_header *)obuffer;
> +	uint8_t locty = 0;
> +	struct iovec iovec[3] = {{ 0 }};
> +	uint32_t obuffer_len = sizeof(obuffer);
> +
> +	if (append_size > MAX_APPEND_SIZE || return_size > MAX_RESPONSE_SIZE) {
> +		dprintf("size of requested buffers too big.");
> +		return TCGBIOS_FIRMWARE_ERROR;
> +	}
> +
> +	iovec[0].data = trqh;
> +	iovec[0].length = TPM_REQ_HEADER_SIZE + append_size;
> +
> +	if (otherdata) {
> +		iovec[1].data = (void *)otherdata;
> +		iovec[1].length = otherdata_size;
> +	}
> +
> +	memset(ibuffer, 0, sizeof(ibuffer));
> +	memset(obuffer, 0, sizeof(obuffer));
> +
> +	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);
> +
> +	if (append_size)
> +		memcpy((char *)trqh + sizeof(*trqh),
> +		       append, append_size);
> +
> +	rc = transmit(locty, iovec, obuffer, &obuffer_len, to_t);
> +	if (rc)
> +		return rc;
> +
> +	*returnCode = 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 *returnCode,
> +				   enum tpmDurationType to_t)
> +{
> +	return build_and_send_cmd_od(ordinal, append, append_size,
> +				     resbuffer, return_size, returnCode,
> +				     NULL, 0, to_t);
> +}
> +
> +static uint32_t determine_timeouts(void)
> +{
> +	uint32_t rc;
> +	uint32_t returnCode;
> +	struct tpm_res_getcap_durations durations;
> +	struct tpm_driver *td = tpm_state.tpm_driver_to_use;
> +	unsigned int i;
> +
> +	rc = build_and_send_cmd(TPM_ORD_GetCapability,
> +				GetCapability_Durations,
> +				sizeof(GetCapability_Durations),
> +				(uint8_t *)&durations, sizeof(durations),
> +				&returnCode, TPM_DURATION_TYPE_SHORT);
> +
> +	dprintf("Return code from TPM_GetCapability(Durations) = 0x%08x\n",
> +		returnCode);
> +
> +	if (rc || returnCode)
> +		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_state.tpm_working = 0;
> +	if (rc)
> +		return rc;
> +	return TCGBIOS_COMMAND_ERROR;
> +}
> +
> +static uint32_t tpm_startup(void)
> +{
> +	uint32_t rc;
> +	uint32_t returnCode;
> +
> +	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, &returnCode,
> +				TPM_DURATION_TYPE_SHORT);
> +
> +	dprintf("Return code from TPM_Startup = 0x%08x\n",
> +		returnCode);
> +
> +	if (rc || returnCode)
> +		goto err_exit;
> +
> +	rc = build_and_send_cmd(TPM_ORD_SelfTestFull, NULL, 0,
> +				NULL, 0, &returnCode,
> +				TPM_DURATION_TYPE_LONG);
> +
> +	dprintf("Return code from TPM_SelfTestFull = 0x%08x\n",
> +		returnCode);
> +
> +	if (rc || returnCode)
> +		goto err_exit;
> +
> +	rc = determine_timeouts();
> +	if (rc)
> +		goto err_exit;
> +
> +	return 0;
> +
> +err_exit:
> +	dprintf("TPM malfunctioning (line %d).\n", __LINE__);
> +
> +	tpm_state.tpm_working = 0;
> +	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_pp(void)

What does unassert_pp mean ?

> +{
> +	uint32_t rc;
> +	uint32_t returnCode;
> +
> +	if (!has_working_tpm())
> +		return TCGBIOS_GENERAL_ERROR;
> +
> +	rc = build_and_send_cmd(TPM_ORD_PhysicalPresence,
> +				PhysicalPresence_CMD_ENABLE,
> +				sizeof(PhysicalPresence_CMD_ENABLE),
> +				NULL, 0, &returnCode,
> +				TPM_DURATION_TYPE_SHORT);
> +
> +	dprintf("Return code from TPM_PhysicalPresence(CMD_ENABLE) = 0x%08x\n",
> +		returnCode);
> +
> +	if (rc || returnCode)
> +		goto err_exit;
> +
> +	rc = build_and_send_cmd(TPM_ORD_PhysicalPresence,
> +				PhysicalPresence_NOT_PRESENT_LOCK,
> +				sizeof(PhysicalPresence_NOT_PRESENT_LOCK),
> +				NULL, 0, &returnCode,
> +				TPM_DURATION_TYPE_SHORT);
> +
> +	dprintf("Return code from TPM_PhysicalPresence(NOT_PRESENT_LOCK) = 0x%08x\n",
> +		returnCode);
> +
> +	if (rc || returnCode)
> +		goto err_exit;
> +
> +	return 0;
> +
> +err_exit:
> +	dprintf("TPM malfunctioning (line %d).\n", __LINE__);
> +
> +	tpm_state.tpm_working = 0;
> +	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..c4c462e
> --- /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_pp(void);
> +
> +#endif /* TCGBIOS_H */
> diff --git a/lib/libtpm/tcgbios_int.h b/lib/libtpm/tcgbios_int.h
> new file mode 100644
> index 0000000..c8caf3b
> --- /dev/null
> +++ b/lib/libtpm/tcgbios_int.h
> @@ -0,0 +1,162 @@
> +/*****************************************************************************
> + * 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_SelfTestFull             0x00000050
> +#define TPM_ORD_ForceClear               0x0000005d
> +#define TPM_ORD_GetCapability            0x00000065
> +#define TPM_ORD_PhysicalEnable           0x0000006f
> +#define TPM_ORD_PhysicalDisable          0x00000070
> +#define TPM_ORD_SetOwnerInstall          0x00000071
> +#define TPM_ORD_PhysicalSetDeactivated   0x00000072
> +#define TPM_ORD_Startup                  0x00000099
> +#define TPM_ORD_PhysicalPresence         0x4000000a
> +#define TPM_ORD_Extend                   0x00000014
> +#define TPM_ORD_SHA1Start                0x000000a0
> +#define TPM_ORD_SHA1Update               0x000000a1
> +#define TPM_ORD_SHA1Complete             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;
> +    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));
> +
> +#define TPM_REQ_HEADER \
> +    uint16_t tag; \
> +    uint32_t totlen; \
> +    uint32_t ordinal;
> +
> +#define TPM_REQ_HEADER_SIZE  (sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint32_t))
> +
> +#define TPM_RSP_HEADER \
> +    uint16_t tag; \
> +    uint32_t totlen; \
> +    uint32_t errcode;
> +
> +#define TPM_RSP_HEADER_SIZE  (sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint32_t))
> +
> +struct tpm_req_header {
> +    TPM_REQ_HEADER;
> +} __attribute__((packed));
> +
> +struct tpm_rsp_header {
> +    TPM_RSP_HEADER;
> +} __attribute__((packed));
> +
> +struct tpm_req_extend {
> +    TPM_REQ_HEADER
> +    uint32_t pcrindex;
> +    uint8_t digest[SHA1_BUFSIZE];
> +} __attribute__((packed));
> +
> +struct tpm_rsp_extend {
> +    TPM_RSP_HEADER
> +    uint8_t digest[SHA1_BUFSIZE];
> +} __attribute__((packed));
> +
> +struct tpm_req_getcap_perm_flags {
> +    TPM_REQ_HEADER
> +    uint32_t capArea;
> +    uint32_t subCapSize;
> +    uint32_t subCap;
> +} __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 {
> +    TPM_RSP_HEADER
> +    uint32_t    size;
> +    struct tpm_permanent_flags perm_flags;
> +} __attribute__((packed));
> +
> +struct tpm_res_getcap_ownerauth {
> +    TPM_RSP_HEADER
> +    uint32_t    size;
> +    uint8_t     flag;
> +} __attribute__((packed));
> +
> +struct tpm_res_getcap_durations {
> +    TPM_RSP_HEADER
> +    uint32_t    size;
> +    uint32_t    durations[TPM_NUM_DURATIONS];
> +} __attribute__((packed));
> +
> +struct tpm_res_sha1start {
> +    TPM_RSP_HEADER
> +    uint32_t    max_num_bytes;
> +} __attribute__((packed));
> +
> +struct tpm_res_sha1complete {
> +    TPM_RSP_HEADER
> +    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..567b384
> --- /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-pp ( -- errcode )       */
> +/* LIBNEWUSB: tpm_unassert_pp(void)             */
> +/************************************************/
> +PRIM(tpm_X2d_unassert_X2d_pp)
> +	PUSH;
> +	TOS.n = tpm_unassert_pp();
> +MIRP
> diff --git a/lib/libtpm/tpm.in b/lib/libtpm/tpm.in
> new file mode 100644
> index 0000000..266439e
> --- /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-pp)
> diff --git a/slof/fs/tpm/tpm-static.fs b/slof/fs/tpm/tpm-static.fs
> new file mode 100644
> index 0000000..11e4ad5
> --- /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-pp
> +    vtpm-available? IF
> +        tpm-unassert-pp                              ( -- errcode )

ignoring the error code here ? why?

> +        vtpm-debug? IF
> +            ." VTPM: Error code from tpm-unassert-pp: " . cr
> +        ELSE
> +            drop
> +        THEN
> +    THEN
> +;
> -- 
> 1.9.3

Regards
Nikunj



More information about the SLOF mailing list