From: Stefan Berger <stefanb@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Cc: mst@redhat.com, kevin@koconnor.net, marcandre.lureau@redhat.com
Subject: Re: [Qemu-devel] [RFC PATCH 3/3] acpi: Build TPM Physical Presence interface
Date: Wed, 10 Jan 2018 13:49:13 -0500 [thread overview]
Message-ID: <1bc0d808-a29e-03de-2a37-e2585c54385f@linux.vnet.ibm.com> (raw)
In-Reply-To: <1515609318-1897-4-git-send-email-stefanb@linux.vnet.ibm.com>
On 01/10/2018 01:35 PM, Stefan Berger wrote:
> The TPM Physical Presence interface consists of an ACPI part, a shared
> memory part, and code in the firmware. Users can send messages to the
> firmware by writing a code into the shared memory through invoking the
> ACPI code. When a reboot happens, the firmware looks for the code and
> acts on it by sending sequences of commands to the TPM.
>
> This patch adds the ACPI code. It is similar to the one in EDK2 but doesn't
> assume that SMIs are necessary to use. Besides that it tests the code
> entered by the user and checks whether it is supported. The range of codes
> supported matches the range of codes supported in SeaBIOS. It uses the same
> datastructure for the shared memory as EDK2 does so that EDK2 and SeaBIOS
> could both make use of the shared memory.
>
> The underlying TCG specification is accessible from the following page.
>
> https://trustedcomputinggroup.org/tcg-physical-presence-interface-specification/
>
> This patch implements version 1.20.
The below ACPI code is partly a translation to C from a previous posted
patch:
https://lists.gnu.org/archive/html/qemu-devel/2015-05/msg05353.html
Stefan
>
> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
> ---
> hw/i386/acpi-build.c | 227 ++++++++++++++++++++++++++++++++++++++++++++++++++
> include/hw/acpi/tpm.h | 15 ++++
> 2 files changed, 242 insertions(+)
>
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 18b939e..e3905a3 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -42,6 +42,7 @@
> #include "hw/acpi/memory_hotplug.h"
> #include "sysemu/tpm.h"
> #include "hw/acpi/tpm.h"
> +#include "hw/tpm/tpm_ppi.h"
> #include "hw/acpi/vmgenid.h"
> #include "sysemu/tpm_backend.h"
> #include "hw/timer/mc146818rtc_regs.h"
> @@ -1860,6 +1861,231 @@ static Aml *build_q35_osc_method(void)
> }
>
> static void
> +build_tpm_ppi(Aml *dev, TPMVersion tpm_version)
> +{
> + Aml *method, *field, *ifctx, *ifctx2, *ifctx3, *pak;
> +
> + aml_append(dev,
> + aml_operation_region("TPPI", AML_SYSTEM_MEMORY,
> + aml_int(TPM_PPI_ADDR_BASE),
> + TPM_PPI_STRUCT_SIZE));
> +
> + field = aml_field("TPPI", AML_ANY_ACC, AML_NOLOCK, AML_PRESERVE);
> + aml_append(field, aml_named_field("PPIN",
> + sizeof(uint8_t) * BITS_PER_BYTE));
> + aml_append(field, aml_named_field("PPIP",
> + sizeof(uint32_t) * BITS_PER_BYTE));
> + aml_append(field, aml_named_field("PPRP",
> + sizeof(uint32_t) * BITS_PER_BYTE));
> + aml_append(field, aml_named_field("PPRQ",
> + sizeof(uint32_t) * BITS_PER_BYTE));
> + aml_append(field, aml_named_field("PPRM",
> + sizeof(uint32_t) * BITS_PER_BYTE));
> + aml_append(field, aml_named_field("LPPR",
> + sizeof(uint32_t) * BITS_PER_BYTE));
> + aml_append(field, aml_named_field("FRET",
> + sizeof(uint32_t) * BITS_PER_BYTE));
> + aml_append(field, aml_named_field("RES1",
> + sizeof(uint8_t) * BITS_PER_BYTE));
> + aml_append(field, aml_named_field("RES2",
> + sizeof(uint32_t) * BITS_PER_BYTE * 4));
> + aml_append(field, aml_named_field("FAIL",
> + sizeof(uint32_t) * BITS_PER_BYTE));
> + aml_append(dev, field);
> +
> + /*
> + * Write the given operations code into 'PPRQ'.
> + */
> + method = aml_method("WRAM", 2, AML_SERIALIZED);
> + {
> + aml_append(method, aml_store(aml_arg(0), aml_name("PPRQ")));
> + aml_append(method, aml_store(aml_arg(1), aml_name("PPRM")));
> + /* 0 = Success */
> + aml_append(method, aml_return(aml_int(0)));
> + }
> + aml_append(dev, method);
> +
> + /*
> + * CKOP: Check whether the opcode is valid
> + */
> + if (tpm_version == TPM_VERSION_1_2) {
> + method = aml_method("CKOP", 1, AML_NOTSERIALIZED);
> + {
> + ifctx = aml_if(
> + aml_or(
> + aml_or(
> + aml_and(
> + aml_lgreater_equal(aml_arg(0), aml_int(0)),
> + aml_lless_equal(aml_arg(0), aml_int(11)),
> + NULL
> + ),
> + aml_equal(aml_arg(0), aml_int(14)),
> + NULL
> + ),
> + aml_and(
> + aml_lgreater_equal(aml_arg(0), aml_int(21)),
> + aml_lless_equal(aml_arg(0), aml_int(22)),
> + NULL
> + ),
> + NULL
> + )
> + );
> + {
> + aml_append(ifctx, aml_return(aml_int(1)));
> + }
> + aml_append(method, ifctx);
> +
> + aml_append(method, aml_return(aml_int(0)));
> + }
> + } else {
> + method = aml_method("CKOP", 1, AML_NOTSERIALIZED);
> + {
> + ifctx = aml_if(
> + aml_equal(aml_arg(0), aml_int(0))
> + );
> + {
> + aml_append(ifctx, aml_return(aml_int(1)));
> + }
> + aml_append(method, ifctx);
> +
> + aml_append(method, aml_return(aml_int(0)));
> + }
> + }
> + aml_append(dev, method);
> +
> + method = aml_method("_DSM", 4, AML_SERIALIZED);
> + {
> + uint8_t zerobyte[1] = { 0 };
> +
> + ifctx = aml_if(
> + aml_equal(aml_arg(0),
> + aml_touuid("3DDDFAA6-361B-4EB4-A424-8D10089D1653"))
> + );
> + {
> + aml_append(ifctx,
> + aml_store(aml_to_integer(aml_arg(2)), aml_local(0)));
> +
> + /* standard DSM query function */
> + ifctx2 = aml_if(aml_equal(aml_local(0), aml_int(0)));
> + {
> + uint8_t byte_list[2] = { 0xff, 0x01 };
> + aml_append(ifctx2, aml_return(aml_buffer(2, byte_list)));
> + }
> + aml_append(ifctx, ifctx2);
> +
> + /* interface version: 1.2 */
> + ifctx2 = aml_if(aml_equal(aml_local(0), aml_int(1)));
> + {
> + aml_append(ifctx2, aml_return(aml_string("1.2")));
> + }
> + aml_append(ifctx, ifctx2);
> +
> + /* submit TPM operation */
> + ifctx2 = aml_if(aml_equal(aml_local(0), aml_int(2)));
> + {
> + aml_append(ifctx2,
> + aml_store(aml_derefof(aml_index(aml_arg(3),
> + aml_int(0))),
> + aml_local(0)));
> + ifctx3 = aml_if(aml_call1("CKOP", aml_local(0)));
> + {
> + aml_append(ifctx3,
> + aml_return(aml_call2("WRAM",
> + aml_local(0),
> + aml_int(0))));
> + }
> + aml_append(ifctx2, ifctx3);
> + aml_append(ifctx2, aml_return(aml_int(1)));
> + }
> + aml_append(ifctx, ifctx2);
> +
> + /* get pending TPM operation */
> + ifctx2 = aml_if(aml_equal(aml_local(0), aml_int(3)));
> + {
> + pak = aml_package(2);
> + aml_append(pak, aml_int(0));
> + aml_append(pak, aml_name("PPRQ"));
> + aml_append(ifctx2, aml_return(pak));
> + }
> + aml_append(ifctx, ifctx2);
> +
> + /* get platform-specific action to transition to pre-OS env. */
> + ifctx2 = aml_if(aml_equal(aml_local(0), aml_int(4)));
> + {
> + /* 2 = reboot */
> + aml_append(ifctx2, aml_return(aml_int(2)));
> + }
> + aml_append(ifctx, ifctx2);
> +
> + /* get TPM operation response */
> + ifctx2 = aml_if(aml_equal(aml_local(0), aml_int(5)));
> + {
> + pak = aml_package(3);
> +
> + aml_append(pak, aml_name("FAIL"));
> + aml_append(pak, aml_name("LPPR"));
> + aml_append(pak, aml_name("PPRP"));
> +
> + aml_append(ifctx2, aml_return(pak));
> + }
> + aml_append(ifctx, ifctx2);
> +
> + /* submit preferred user language */
> + ifctx2 = aml_if(aml_equal(aml_local(0), aml_int(6)));
> + {
> + /* 3 = not implemented */
> + aml_append(ifctx2, aml_return(aml_int(3)));
> + }
> + aml_append(ifctx, ifctx2);
> +
> + /* submit TPM operation v2 */
> + ifctx2 = aml_if(aml_equal(aml_local(0), aml_int(7)));
> + {
> + aml_append(ifctx2,
> + aml_store(aml_derefof(aml_index(aml_arg(3),
> + aml_int(0))),
> + aml_local(0)));
> + ifctx3 = aml_if(aml_call1("CKOP", aml_local(0)));
> + {
> + aml_append(ifctx3,
> + aml_store(aml_call2("WRAM",
> + aml_local(0),
> + aml_int(0)),
> + aml_local(1)));
> + aml_append(ifctx3, aml_return(aml_local(1)));
> + }
> + aml_append(ifctx2, ifctx3);
> + /* 1 = requested operation not implemented */
> + aml_append(ifctx2, aml_return(aml_int(1)));
> + }
> + aml_append(ifctx, ifctx2);
> +
> + /* get user confirmation status for operation */
> + ifctx2 = aml_if(aml_equal(aml_local(0), aml_int(8)));
> + {
> + aml_append(ifctx2,
> + aml_store(aml_derefof(aml_index(aml_arg(3),
> + aml_int(0))),
> + aml_local(0)));
> + ifctx3 = aml_if(aml_call1("CKOP", aml_local(0)));
> + {
> + /* 4 = Allowed and physically present user not required */
> + aml_append(ifctx3, aml_return(aml_int(4)));
> + }
> + aml_append(ifctx2, ifctx3);
> + /* 0 = requested operation not implemented */
> + aml_append(ifctx2, aml_return(aml_int(0)));
> + }
> + aml_append(ifctx, ifctx2);
> +
> + aml_append(ifctx, aml_return(aml_buffer(1, zerobyte)));
> + }
> + aml_append(method, ifctx);
> + }
> + aml_append(dev, method);
> +}
> +
> +static void
> build_dsdt(GArray *table_data, BIOSLinker *linker,
> AcpiPmInfo *pm, AcpiMiscInfo *misc,
> Range *pci_hole, Range *pci_hole64, MachineState *machine)
> @@ -2218,6 +2444,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
> */
> /* aml_append(crs, aml_irq_no_flags(TPM_TIS_IRQ)); */
> aml_append(dev, aml_name_decl("_CRS", crs));
> + build_tpm_ppi(dev, misc->tpm_version);
> aml_append(scope, dev);
> }
>
> diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
> index d9b7452..23f5da1 100644
> --- a/include/hw/acpi/tpm.h
> +++ b/include/hw/acpi/tpm.h
> @@ -37,4 +37,19 @@
> #define TPM_PPI_ADDR_SIZE 0x100
> #define TPM_PPI_ADDR_BASE 0xffff0000
>
> +struct tpm_ppi {
> + uint8_t ppin; /* set by BIOS; currently initialization flag */
> + uint32_t ppip; /* set by ACPI; not used */
> + uint32_t pprp; /* response from TPM; set by BIOS */
> + uint32_t pprq; /* opcode; set by ACPI */
> + uint32_t pprm; /* parameter for opcode; set by ACPI */
> + uint32_t lppr; /* last opcode; set by BIOS */
> + uint32_t fret; /* set by ACPI; not used*/
> + uint32_t res1; /* reserved */
> + uint32_t res2[4]; /* reserved */
> + uint32_t fail; /* set by BIOS (0 = success) */
> +} QEMU_PACKED;
> +
> +#define TPM_PPI_STRUCT_SIZE sizeof(struct tpm_ppi)
> +
> #endif /* HW_ACPI_TPM_H */
next prev parent reply other threads:[~2018-01-10 18:49 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-01-10 18:35 [Qemu-devel] [RFC PATCH 0/3] Implement Pysical Presence Interface for TPM 1.2 and 2 Stefan Berger
2018-01-10 18:35 ` [Qemu-devel] [RFC PATCH 1/3] tpm: Implement virtual memory device for TPM PPI Stefan Berger
2018-01-12 14:55 ` Marc-André Lureau
2018-01-12 16:29 ` Eric Blake
2018-01-12 17:24 ` Stefan Berger
2018-01-12 18:23 ` Stefan Berger
2018-01-15 14:49 ` Stefan Berger
2018-01-10 18:35 ` [Qemu-devel] [RFC PATCH 2/3] acpi: implement aml_lless_equal Stefan Berger
2018-01-12 15:17 ` Marc-André Lureau
2018-01-12 19:42 ` Stefan Berger
2018-01-15 14:31 ` Igor Mammedov
2018-01-10 18:35 ` [Qemu-devel] [RFC PATCH 3/3] acpi: Build TPM Physical Presence interface Stefan Berger
2018-01-10 18:49 ` Stefan Berger [this message]
2018-01-12 16:07 ` Marc-André Lureau
2018-01-12 17:00 ` Stefan Berger
2018-01-12 20:16 ` Stefan Berger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1bc0d808-a29e-03de-2a37-e2585c54385f@linux.vnet.ibm.com \
--to=stefanb@linux.vnet.ibm.com \
--cc=kevin@koconnor.net \
--cc=marcandre.lureau@redhat.com \
--cc=mst@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).