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