<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>