From: "Ard Biesheuvel" <ard.biesheuvel@linaro.org>
To: Laszlo Ersek <lersek@redhat.com>
Cc: edk2-devel-groups-io <devel@edk2.groups.io>
Subject: Re: [PATCH 2/4] ArmVirtPkg/PlatformPeiLib: discover the TPM base address from the DT
Date: Wed, 8 Jan 2020 15:41:13 +0100 [thread overview]
Message-ID: <CAKv+Gu9U3DPKC_L2Hj_tBL3wW9e=H2hjtaV0FSYKqptSEtJszg@mail.gmail.com> (raw)
In-Reply-To: <211c92c6-b4fe-1667-fd26-ae282e303ae8@redhat.com>
On Tue, 7 Jan 2020 at 16:42, Laszlo Ersek <lersek@redhat.com> wrote:
>
> On 01/07/20 10:47, Ard Biesheuvel wrote:
> > Introduce a boolean PCD that tells us whether TPM support is enabled
> > in the build, and if it is, record the TPM base address in the existing
> > routine that traverses the device tree in the platform PEIM.
> >
> > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > ---
> > ArmVirtPkg/ArmVirtPkg.dec | 5 ++
> > ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.inf | 12 ++-
> > ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c | 82 +++++++++++++++++---
> > 3 files changed, 87 insertions(+), 12 deletions(-)
>
> (1) I recommend replacing "boolean PCD" in the commit message with
> "feature PCD", and updating the rest of the patch accordingly. (New
> [PcdsFeatureFlag] section in the DEC file, [FeaturePcd] section in the
> INF file, matching API calls.)
>
OK
> >
> > diff --git a/ArmVirtPkg/ArmVirtPkg.dec b/ArmVirtPkg/ArmVirtPkg.dec
> > index a019cc269d10..ed5114887489 100644
> > --- a/ArmVirtPkg/ArmVirtPkg.dec
> > +++ b/ArmVirtPkg/ArmVirtPkg.dec
> > @@ -58,6 +58,11 @@ [PcdsFixedAtBuild, PcdsPatchableInModule]
> > #
> > gArmVirtTokenSpaceGuid.PcdTerminalTypeGuidBuffer|{0x65, 0x60, 0xA6, 0xDF, 0x19, 0xB4, 0xD3, 0x11, 0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D}|VOID*|0x00000007
> >
> > + #
> > + # Boolean PCD that defines whether TPM2 support is enabled
> > + #
> > + gArmVirtTokenSpaceGuid.PcdTpm2SupportEnabled|FALSE|BOOLEAN|0x00000004
> > +
> > [PcdsDynamic]
> > #
> > # Whether to force disable ACPI, regardless of the fw_cfg settings
> > diff --git a/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.inf b/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.inf
> > index 46db117ac28e..c41ee22c9767 100644
> > --- a/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.inf
> > +++ b/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.inf
> > @@ -21,22 +21,30 @@ [Sources]
> > [Packages]
> > ArmPkg/ArmPkg.dec
> > ArmVirtPkg/ArmVirtPkg.dec
> > - MdePkg/MdePkg.dec
> > - MdeModulePkg/MdeModulePkg.dec
> > EmbeddedPkg/EmbeddedPkg.dec
> > + MdeModulePkg/MdeModulePkg.dec
> > + MdePkg/MdePkg.dec
> > + OvmfPkg/OvmfPkg.dec
> > + SecurityPkg/SecurityPkg.dec
> >
> > [LibraryClasses]
> > DebugLib
> > HobLib
> > FdtLib
> > + PeiServicesLib
> >
> > [FixedPcd]
> > gArmTokenSpaceGuid.PcdFvSize
> > gArmVirtTokenSpaceGuid.PcdDeviceTreeAllocationPadding
> > + gArmVirtTokenSpaceGuid.PcdTpm2SupportEnabled
> >
> > [Pcd]
> > gArmTokenSpaceGuid.PcdFvBaseAddress
> > gArmVirtTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress
> > + gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress ## SOMETIMES_PRODUCES
> > +
>
> This is a dynamic PCD -- we're going to set it below --, and this lib
> instance does not use dynamic PCDs at the moment (I checked the build
> report file, and all PCDs in
> "ArmPlatformPkg/PlatformPei/PlatformPeim.inf", when built for
> ArmVirtQemu, are FIXED, or FLAG (i.e. Feature PCD)).
>
> This gave me pause for a good while. In particular, in commit
> cc667df08ae8 ("ArmVirtualizationPkg: use a HOB to store device tree
> blob", 2015-02-28), we replaced a PcdSet64() in this lib instance with a
> HOB production:
>
> Instead of using a dynamic PCD, store the device tree address in a HOB
> so that we can also run under a configuration that does not support
> dynamic PCDs.
>
> So, this change seemed to conflict with that, at first look.
>
> Then I noticed the new PcdSet64() is protected with the new feature flag
> (PcdTpm2SupportEnabled), which we only set to TRUE in "ArmVirtQemu.dsc".
>
> So things seem safe for ArmVirtQemuKernel and ArmVirtXen (the dynamic
> PCD setting will never be reached). But can we guarantee the PCD PPI
> exists by the time we reach the PcdSet64() in ArmVirtQemu?
>
> Apparently: yes. This lib instance depends on PcdLib, and in the
> ArmVirtQemu build, "ArmPlatformPkg/PlatformPei/PlatformPeim.inf"
> receives a PcdLib resolution to
> "MdePkg/Library/PeiPcdLib/PeiPcdLib.inf". From which the module inherits
> a DEPEX on "gEfiPeiPcdPpiGuid". Therefore, the PcdSet64() call is safe
> here -- but it's hard to see why.
>
> (2) Can you please add a separate patch for this lib instance, for
> spelling out PcdLib under [LibraryClasses] in the INF file? Please
> mention in the commit message that we inherit a dependency on
> gEfiPeiPcdPpiGuid.
>
I tried adding this to [LibraryClasses] but apparently, this syntax is
not supported yet :-(
PcdLib |gArmVirtTokenSpaceGuid.PcdTpm2SupportEnabled
PeiServicesLib |gArmVirtTokenSpaceGuid.PcdTpm2SupportEnabled
>
> > +[Ppis]
> > + gOvmfTpmDiscoveredPpiGuid ## SOMETIMES_PRODUCES
>
> Per commit 6cf1880fb5b6 ("OvmfPkg: add customized Tcg2ConfigPei clone",
> 2018-03-09), we try to make sure that gPeiTpmInitializationDonePpiGuid
> is always installed.
>
> Normally, Tcg2ConfigPei installs gEfiTpmDeviceSelectedGuid, which
> dispatches Tcg2Pei. In turn, Tcg2Pei installs
> gPeiTpmInitializationDonePpiGuid.
>
> However, if Tcg2ConfigPei finds no TPM2 device (at the known base
> address), then gEfiTpmDeviceSelectedGuid is not installed, and so
> Tcg2Pei is not dispatched. Which would prevent the installation of
> gPeiTpmInitializationDonePpiGuid. To make sure the latter PPI gets
> installed nonetheless, in this scenario Tcg2ConfigPei installs
> gPeiTpmInitializationDonePpiGuid (sort of "on behalf of" Tcg2Pei).
>
> With another layer of depex prepended in this patch series, which may
> even prevent the dispatching of Tcg2ConfigPei, I think we might have to
> install gPeiTpmInitializationDonePpiGuid in this module -- to remain
> consistent with the goal "always install
> gPeiTpmInitializationDonePpiGuid in case TPM2 support is included in the
> binary".
>
> The above is an entirely formal (not semantic) argument on my part.
>
> For the semantic argument, I think we should look at the following hunk
> in commit 6cf1880fb5b6:
>
> + DEBUG ((DEBUG_INFO, "%a: no TPM2 detected\n", __FUNCTION__));
> + // If no TPM2 was detected, we still need to install
> + // TpmInitializationDonePpi. Namely, Tcg2Pei will exit early upon
> + // seeing the default (all-bits-zero) contents of
> + // PcdTpmInstanceGuid, thus we have to install the PPI in its place,
> + // in order to unblock any dependent PEIMs.
> + Status = PeiServicesInstallPpi (&mTpmInitializationDonePpiList);
> + ASSERT_EFI_ERROR (Status);
>
> Note that there is no actual consumer of, or dependent module on,
> gPeiTpmInitializationDonePpiGuid, in edk2. Therefore even the "semantic"
> argument boils down to "be a good citizen". Nonetheless, it matches the
> PPIs documentation in SecurityPkg.dec:
>
> ## The PPI GUID for that TPM initialization is done. TPM initialization may be success or fail.
> # Include/Ppi/TpmInitialized.h
> gPeiTpmInitializationDonePpiGuid = { 0xa030d115, 0x54dd, 0x447b, { 0x90, 0x64, 0xf2, 0x6, 0x88, 0x3d, 0x7c, 0xcc }}
>
> (3) Do you agree with installing gPeiTpmInitializationDonePpiGuid in
> this lib instance in case we do *not* install gOvmfTpmDiscoveredPpiGuid,
> but PcdTpm2SupportEnabled is TRUE?
>
Yes, that makes sense.
>
> >
> > [Guids]
> > gEarlyPL011BaseAddressGuid
> > diff --git a/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c b/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c
> > index 0a1469550db0..249e45c04624 100644
> > --- a/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c
> > +++ b/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c
> > @@ -1,7 +1,7 @@
> > /** @file
> > *
> > * Copyright (c) 2011-2014, ARM Limited. All rights reserved.
> > -* Copyright (c) 2014, Linaro Limited. All rights reserved.
> > +* Copyright (c) 2014-2020, Linaro Limited. All rights reserved.
> > *
> > * SPDX-License-Identifier: BSD-2-Clause-Patent
> > *
> > @@ -13,11 +13,18 @@
> > #include <Library/DebugLib.h>
> > #include <Library/HobLib.h>
> > #include <Library/PcdLib.h>
> > +#include <Library/PeiServicesLib.h>
> > #include <libfdt.h>
> >
> > #include <Guid/EarlyPL011BaseAddress.h>
> > #include <Guid/FdtHob.h>
> >
> > +STATIC CONST EFI_PEI_PPI_DESCRIPTOR mTpm2DiscoveredPpi = {
> > + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
> > + &gOvmfTpmDiscoveredPpiGuid,
> > + NULL
> > +};
> > +
> > EFI_STATUS
> > EFIAPI
> > PlatformPeim (
> > @@ -31,13 +38,18 @@ PlatformPeim (
> > UINT64 *FdtHobData;
> > UINT64 *UartHobData;
> > INT32 Node, Prev;
> > + INT32 Parent, Depth;
> > CONST CHAR8 *Compatible;
> > CONST CHAR8 *CompItem;
> > CONST CHAR8 *NodeStatus;
> > INT32 Len;
> > + INT32 RangesLen;
> > INT32 StatusLen;
> > CONST UINT64 *RegProp;
> > + CONST UINT32 *RangesProp;
> > UINT64 UartBase;
> > + UINT64 TpmBase;
> > + EFI_STATUS Status;
> >
> >
> > Base = (VOID*)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
> > @@ -58,18 +70,16 @@ PlatformPeim (
> > ASSERT (UartHobData != NULL);
> > *UartHobData = 0;
> >
> > - //
> > - // Look for a UART node
> > - //
> > - for (Prev = 0;; Prev = Node) {
> > - Node = fdt_next_node (Base, Prev, NULL);
> > + for (Prev = Depth = 0;; Prev = Node) {
> > + Node = fdt_next_node (Base, Prev, &Depth);
> > if (Node < 0) {
> > break;
> > }
> >
> > - //
> > - // Check for UART node
> > - //
> > + if (Depth == 1) {
> > + Parent = Node;
> > + }
> > +
> > Compatible = fdt_getprop (Base, Node, "compatible", &Len);
> >
> > //
> > @@ -89,10 +99,62 @@ PlatformPeim (
> >
> > UartBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
> >
> > - DEBUG ((EFI_D_INFO, "%a: PL011 UART @ 0x%lx\n", __FUNCTION__, UartBase));
> > + DEBUG ((DEBUG_INFO, "%a: PL011 UART @ 0x%lx\n", __FUNCTION__, UartBase));
>
> (4) If we're not touching this line otherwise, then please drop this
> change (or isolate it to another patch).
>
OK
> >
> > *UartHobData = UartBase;
> > break;
> > + } else if (FixedPcdGetBool (PcdTpm2SupportEnabled) &&
> > + AsciiStrCmp (CompItem, "tcg,tpm-tis-mmio") == 0) {
> > +
> > + RegProp = fdt_getprop (Base, Node, "reg", &Len);
> > + ASSERT (Len == 8 || Len == 16);
> > + if (Len == 8) {
> > + TpmBase = fdt32_to_cpu (RegProp[0]);
> > + } else if (Len == 16) {
> > + TpmBase = fdt64_to_cpu (ReadUnaligned64 ((UINT64 *)RegProp));
> > + }
> > +
> > + if (Depth > 1) {
> > + //
> > + // QEMU/mach-virt may put the TPM on the platform bus, in which case
> > + // we have to take its 'ranges' property into account to translate the
> > + // MMIO address. This consists of a <child base, parent base, size>
> > + // tuple, where the child base and the size use the same number of
> > + // cells as the 'reg' property above, and the parent base uses 2 cells
> > + //
> > + RangesProp = fdt_getprop (Base, Parent, "ranges", &RangesLen);
> > + ASSERT (RangesProp != NULL);
> > +
> > + // a plain 'ranges' attribute without a value implies a 1:1 mapping
>
> (5) please use the edk2 coding style for comments (empty "//" lines
> before and after)
>
>
> > + if (RangesLen != 0) {
> > + // assume a single translated range with 2 cells for the parent base
>
> (6) same as (5)
>
> > + if (RangesLen != Len + 2 * sizeof (UINT32)) {
> > + DEBUG ((DEBUG_WARN,
> > + "%a: 'ranges' property has unexpected size %d\n",
> > + __FUNCTION__, RangesLen));
> > + break;
> > + }
> > +
> > + if (Len == 8) {
> > + TpmBase -= fdt32_to_cpu (RangesProp[0]);
> > + } else {
> > + TpmBase -= fdt64_to_cpu (ReadUnaligned64 ((UINT64 *)RangesProp));
> > + }
> > +
> > + // advance RangesProp to the parent bus address
>
> (7) same as (5)
>
> > + RangesProp = (UINT32 *)((UINT8 *)RangesProp + Len / 2);
> > + TpmBase += fdt64_to_cpu (ReadUnaligned64 ((UINT64 *)RangesProp));
> > + }
> > + }
> > +
> > + DEBUG ((DEBUG_INFO, "%a: TPM @ 0x%lx\n", __FUNCTION__, TpmBase));
> > +
> > + Status = PcdSet64S (PcdTpmBaseAddress, TpmBase);
> > + ASSERT_RETURN_ERROR (Status);
> > +
> > + Status = PeiServicesInstallPpi (&mTpm2DiscoveredPpi);
> > + ASSERT_EFI_ERROR (Status);
> > + break;
> > }
> > }
> > }
> >
>
> So I was quite unhappy about adding this bunch of FDT parsing to this
> lib instance. Because, the original reason for this library is (from
> commit 433b31ddeeeb): "it allows us to preserve the device tree blob if
> it was passed to us in system DRAM."
>
> However:
>
> (a) I can also see commit 337d450e2014 ("ArmVirtualizationPkg: move
> early UART discovery to PlatformPeim", 2015-02-28), where we said "this
> is a more suitable place anyway", for parsing the FDT for UART details.
>
> (b) In ArmVirtQemu's PEI phase (unlike in the DXE phase), we have no
> centralized FDT parsing facility. That means we parse the FDT whenever
> and wherever we need something from it. Examples:
>
> - "Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c" -->
> causes basically all SEC, PEI_CORE, and PEIM modules to re-fetch the
> UART details from the FDT. (The HOB that is produced in the above-quoted
> context is only consumed in DXE_CORE and later modules)
>
> - "Library/QemuVirtMemInfoLib/QemuVirtMemInfoPeiLibConstructor.c" -->
> causes PcdSystemMemorySize to be set internally to
> "ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.inf", parsed from the FDT's
> lowest memory node.
>
> (8) Can you please summarize this briefly in the commit message? (I.e.
> that it's OK to parse the FDT in the PEI phase wherever we need it,
> whatever we need it for, because we have no centralized parsing service
> or data collection facility for that, in PEI).
>
>
> Peeking ahead, I can see that in the next patch, we dump yet more
> functionality in this lib instance; I feel that *there* I'm going to
> recommend against doing that. But I'll need to look at that patch in
> more depth first.
>
> Thanks!
> Laszlo
>
next prev parent reply other threads:[~2020-01-08 14:41 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-01-07 9:47 [PATCH 0/4] ArmVirtPkg: implement measured boot for ArmVirtQemu Ard Biesheuvel
2020-01-07 9:47 ` [PATCH 1/4] OvmfPkg/Tcg2ConfigPei: introduce a signalling PPI to depex on Ard Biesheuvel
2020-01-07 11:58 ` Laszlo Ersek
2020-01-07 9:47 ` [PATCH 2/4] ArmVirtPkg/PlatformPeiLib: discover the TPM base address from the DT Ard Biesheuvel
2020-01-07 15:42 ` Laszlo Ersek
2020-01-08 14:41 ` Ard Biesheuvel [this message]
2020-01-09 13:04 ` Laszlo Ersek
2020-01-07 9:47 ` [PATCH 3/4] ArmVirtPkg/PlatformPeiLib: implement Reset2 PPI based on PSCI Ard Biesheuvel
2020-01-07 16:50 ` Laszlo Ersek
2020-01-07 16:55 ` [edk2-devel] " Ard Biesheuvel
2020-01-07 18:47 ` Laszlo Ersek
2020-01-08 9:59 ` Ard Biesheuvel
2020-01-07 9:48 ` [PATCH 4/4] ArmVirtPkg/ArmVirtQemu: add optional support for TPM2 measured boot Ard Biesheuvel
2020-01-07 17:37 ` Laszlo Ersek
2020-01-08 14:13 ` Ard Biesheuvel
2020-01-08 14:45 ` Laszlo Ersek
2020-01-09 0:51 ` Yao, Jiewen
2020-01-09 13:07 ` Laszlo Ersek
2020-01-10 0:32 ` Yao, Jiewen
2020-01-13 1:55 ` [edk2-devel] " Gary Lin
2020-01-13 15:56 ` Laszlo Ersek
2020-01-07 11:55 ` [PATCH 0/4] ArmVirtPkg: implement measured boot for ArmVirtQemu Laszlo Ersek
2020-01-07 12:04 ` Ard Biesheuvel
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-list 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='CAKv+Gu9U3DPKC_L2Hj_tBL3wW9e=H2hjtaV0FSYKqptSEtJszg@mail.gmail.com' \
--to=devel@edk2.groups.io \
/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