01/31/2018 OVMF Serial port Debugging on QEMU

It is a sunny day and it seems impossible for me to witness snowfall in Beijing this year anyway, even if almost every other place is reporting snow alerts recently... Another thing is that debug recording does improve my working efficiency, so I will insist anyway.

This passage main describes how I have tried to debug the TPM support issue. Here we are mainly focusing on the configuration of the development platform of TPM based Rmt-Attestation.


TPM Based Rmt-Attestation in UEFI System

(1) The DEBUG Macro and Usage of Serial Port Console

Reference from the links followed:

  • UEFI Tips QEMU的Debug Message
  • Ovmf Project README on Soureforge

The debug info of tianocore will be dumped into debug.log by running

../vtpm-support/qemu-tpm/x86_64-softmmu/qemu-system-x86_64 -display sdl \
-m 2048 -serial file:/home/hecmay/debug.log -global isa-debugcon.iobase=0x402 -net none \
-boot c -bios Build/Ovmf3264/DEBUG_GCC5/FV/OVMF.fd -boot menu=on \
-tpmdev cuse-tpm,id=tpm0,path=/dev/vtpm0 -device tpm-tis,tpmdev=tpm0 Build/test.img

Example of the debug.log content:

SecCoreStartupWithStack(0xFFFCC000, 0x820000)
Register PPI Notify: DCD0BE23-9586-40F4-B643-06522CED4EDE
Install PPI: 8C8CE578-8A3D-4F1C-9935-896185C32DD3
Install PPI: 5473C07A-3DCB-4DCA-BD6F-1E9689E7349A
The 0th FV start address is 0x00000820000, size is 0x000E0000, handle is 0x820000
Register PPI Notify: 49EDB1C1-BF21-4761-BB12-EB0031AABB39
Register PPI Notify: EA7CA24B-DED5-4DAD-A389-BF827E8F9B38
Install PPI: B9E0ABFE-5979-4914-977F-6DEE78C278A6
Install PPI: DBE23AA9-A345-4B97-85B6-B226F1617389
Loading PEIM at 0x0000082C100 EntryPoint=0x0000082CB42 PcdPeim.efi
Install PPI: 06E81C58-4AD7-44BC-8390-F10265F72480
Install PPI: 01F34D25-4DE2-23AD-3FF3-36353FF323F1
Install PPI: 4D8B155B-C059-4C8F-8926-06FD4331DB8A
Install PPI: A60C6B59-E459-425D-9C69-0BCC9CB27D81
Register PPI Notify: 605EA650-C65C-42E1-BA80-91A52AB618C6
Loading PEIM at 0x000008308C0 EntryPoint=0x00000831C7F ReportStatusCodeRouterPei.efi
Install PPI: 0065D394-9951-4144-82A3-0AFC8579C251
Install PPI: 229832D3-7A30-4B36-B827-F40CB7D45436
Loading PEIM at 0x00000832940 EntryPoint=0x00000832E48 StatusCodeHandlerPei.efi
Loading PEIM at 0x00000834AC0 EntryPoint=0x00000834D00 PlatformPei.efi
Select Item: 0x0
FW CFG Signature: 0x554D4551
Select Item: 0x1
FW CFG Revision: 0x1
QemuFwCfg interface (IO Port) is supported.
Platform PEIM Loaded
CMOS:
00: 39 00 26 00 06 00 02 29 01 18 26 02 00 80 00 00
10: 40 00 F0 00 07 80 02 FF FF 2F 00 08 02 10 FF FF
20: C8 08 02 3F 00 00 00 00 00 00 00 00 00 00 00 00
30: FF FF 20 00 00 7F 00 20 00 00 00 00 00 02 00 00
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

(2) The TPM support issues not mentioned in Tiano Guidance

From the log we locate the important pieces of info of TPM

Loading driver at 0x0007E913000 EntryPoint=0x0007E913A81 TcgConfigDxe.efi
InstallProtocolInterface: BC62157E-3E33-4FEC-9920-2D3B36D750DF 7F198298
ProtectUefiImageCommon - 0x7F198040
  - 0x000000007E913000 - 0x0000000000004E00
Image type IA32 can't be started on X64 UEFI system.
//
// ........
//
Loading driver at 0x0007FAC7000 EntryPoint=0x0007FAC7240 TcgDxe.efi
InstallProtocolInterface: BC62157E-3E33-4FEC-9920-2D3B36D750DF 7F1BCE98
ProtectUefiImageCommon - 0x7F1BCBC0
  - 0x000000007FAC7000 - 0x0000000000004BC0
No TPM12 instance required!
Error: Image at 0007FAC7000 start failed: Unsupported
//
// ..........
//
Found TCG support in Port 0 PortMultiplierPort 0

// Also note that the TcgPeo.efi was not loaded in the PEI phase

1.The TpmPei.efi was not loaded

// SecurityPkg/Tcg/TcgPei/TcgPei.inf
[Depex]
  gEfiPeiMasterBootModePpiGuid AND
  gEfiPeiReadOnlyVariable2PpiGuid AND
  gEfiTpmDeviceSelectedGuid

Check these three dependency expression independently referring to DEBUG log.

//MdePkg/Mdepkg.dec
[Ppis]
  ## Include/Ppi/MasterBootMode.h
  gEfiPeiMasterBootModePpiGuid = { 0x7408d748, 0xfc8c, 0x4ee6, {0x92, 0x88, 0xc4, 0xbe, \
0xc0, 0x92, 0xa4, 0x10 } }
// ..........
  ## Include/Ppi/ReadOnlyVariable2.h
  gEfiPeiReadOnlyVariable2PpiGuid = { 0x2ab86ef5, 0xecb5, 0x4134, { 0xb5, 0x56, 0x38, 0x54, \
0xca, 0x1f, 0xe1, 0xb4 } }
//...........
// SecurityPkg/SecurityPkg.dec
  ## GUID used to select supported TPM instance from UI.
  #  Include/Guid/TpmInstance.h
  gEfiTpmDeviceSelectedGuid          = { 0x7f4158d3, 0x74d, 0x456d, { 0x8c, 0xb2, 0x1, 0xf9, \
0xc8, 0xf7, 0x9d, 0xaa } }

The gEfiPeiMasterBootModePpi has been installed by certain PEIM referring to debug.log. But the gEfiPeiReadOnlyVariable2Ppi is not installed (gEfiTpmDeviceSelectedGuid should only be a GUID used for TPM device selection).

// MdeModulePkg/Universal/Variable/Pei/Variable.c
EFI_STATUS
EFIAPI
PeimInitializeVariableServices (
  IN       EFI_PEI_FILE_HANDLE       FileHandle,
  IN CONST EFI_PEI_SERVICES          **PeiServices
  )
{
  return PeiServicesInstallPpi (&mPpiListVariable);

// MdeModulePkg/Universal/Variable/Pei/PeiVariable.inf
// Implements ReadOnly Variable Services required by PEIM and installs PEI ReadOnly Varaiable2 PPI
[Depex]
  gEdkiiFaultTolerantWriteGuid

// MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf
// This module installs gEdkiiFaultTolerantWriteGuid PPI to inform the check 
// for FTW last write data has been done. This PEIM is not loaded.
[Depex]
  TRUE

So the solution is to add FaultTolerantWritePei.inf and PeiVariable.inf to the Components of Ovmf.dsc Also comment the gEfiTpmDeviceSelectedGuid and make some further modification to Flash Non-Volatile Working Base Address. Details of which will be mentioned in Section (4)

With amendments showed above, we will run PEIM of TcgPei successfully:

Loading PEIM at 0x0007FEBE000 EntryPoint=0x0007FEBF18A TcgPei.efi
TPM12Startup: TPM_SUCCESS
Install PPI: E9DB0D58-D48D-47F6-9C6E-6F40E86C7B41
Install PPI: A030D115-54DD-447B-9064-F206883D7CCC

The Tpm12Startup Function in Tpm12CommandLib, which is called in the Entry Point Function of TcgPei:

// SecurityPkg/Library/Tpm12CommandLib/Tpm12Startup.c
EFI_STATUS
EFIAPI
Tpm12Startup (
  IN TPM_STARTUP_TYPE  TpmSt
  )
{
  EFI_STATUS           Status;
  TPM_CMD_START_UP     Command;
  TPM_RSP_COMMAND_HDR  Response;
  UINT32               Length;

  //
  // send Tpm command TPM_ORD_Startup
  //
  Command.Hdr.tag       = SwapBytes16 (TPM_TAG_RQU_COMMAND);
  Command.Hdr.paramSize = SwapBytes32 (sizeof (Command));
  Command.Hdr.ordinal   = SwapBytes32 (TPM_ORD_Startup);
  Command.TpmSt         = SwapBytes16 (TpmSt);
  Length = sizeof (Response);
  Status = Tpm12SubmitCommand (sizeof (Command), (UINT8 *)&Command, &Length, (UINT8 *)&Response);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  switch (SwapBytes32(Response.returnCode)) {
  case TPM_SUCCESS:
    DEBUG ((DEBUG_INFO, "TPM12Startup: TPM_SUCCESS\n"));
    return EFI_SUCCESS;
  case TPM_INVALID_POSTINIT:
    // In warm reset, TPM may response TPM_INVALID_POSTINIT
    DEBUG ((DEBUG_INFO, "TPM12Startup: TPM_INVALID_POSTINIT\n"));
    return EFI_SUCCESS;
  default:
    return EFI_DEVICE_ERROR;
  }
}

2.The TPM 1.2 is not required
And in the SecurityPkg/Tcg/TcgDxe/TcgDxe.c driver:

  if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){
    DEBUG ((EFI_D_ERROR, "No TPM12 instance required!\n"));
    return EFI_UNSUPPORTED;
  }

The PcdGetPtr function will retrieve PCD value with the token passed in from the DEC file of the Pkg.
The PCD value should be set up in advance to pair with the TPM_DEVICE_INTERFACE_TPM12 or other macros.

// SecurityPkg/SecurityPkg.dec   
  ## GUID value used for PcdTpmInstanceGuid to indicate TPM 1.2 device is selected to support.
  #  Include/Guid/TpmInstance.h
  gEfiTpmDeviceInstanceTpm12Guid     = { 0x8b01e5b6, 0x4f19, 0x46e8, { 0xab, 0x93, \
0x1c, 0x53, 0x67, 0x1b, 0x90, 0xcc } }
//
// ........
//
  ## Guid name to identify TPM instance.

# TPM_DEVICE_INTERFACE_NONE means disable.
# TPM_DEVICE_INTERFACE_TPM12 means TPM 1.2 DTPM.
# TPM_DEVICE_INTERFACE_DTPM2 means TPM 2.0 DTPM.
# Other GUID value means other TPM 2.0 device.
# @Prompt TPM device type identifier gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid |{ 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }|VOID*|0x0001000F

So the gEfiTpmDeviceInstanceTpm12Guid is the same GUID with TPM_DEVICE_INTERFACE_TPM12:

//SecurityPkg/Include/Guid/TpmInstance.h
#define TPM_DEVICE_INTERFACE_TPM12  \
  { 0x8b01e5b6, 0x4f19, 0x46e8, { 0xab, 0x93, 0x1c, 0x53, 0x67, 0x1b, 0x90, 0xcc } }

However, simply setting the PcdTpmInstanceGuid to the GUID corresponding to TPM12 does not work
{ 0x8b, 0x01, 0xe5, 0xb6, 0x4f, 0x19, 0x46, 0xe8, 0xab, 0x93, 0x1c, 0x53, 0x67, 0x1b, 0x90, 0xcc }

The Pcd value obtained by PcdGetPtr is up-tail-down in position.

TpmInstanceguid:  B6E5018B-194F-E846-AB93-1C53671B90CC
Tpm12Guid:        8B01E5B6-4F19-46E8-AB93-1C53671B90CC

Even if we set the same GUID manually, there will still be other errors:

Loading driver at 0x0007FAC8000 EntryPoint=0x0007FAC8240 TcgDxe.efi
InstallProtocolInterface: BC62157E-3E33-4FEC-9920-2D3B36D750DF 7F1BCF18
ProtectUefiImageCommon - 0x7F1BCBC0
  - 0x000000007FAC8000 - 0x0000000000004C00
Tpm12RequestUseTpm - TCG - Not Found
TPM not detected!

This can be strange for the Tpm12RequestUseTpm() has been used successfully in TcgPei when locating EFI_TCG_PROTOCOL. The calling convention in Entry Point Function of TcgPei PEIM:

  if (!mImageInMemory) {
    Status = Tpm12RequestUseTpm ();
    if (EFI_ERROR (Status)) {
      DEBUG ((DEBUG_ERROR, "TPM not detected!\n"));
      goto Done;
    }

    if (PcdGet8 (PcdTpmInitializationPolicy) == 1) {
      if (BootMode == BOOT_ON_S3_RESUME) {
        Status = Tpm12Startup (TPM_ST_STATE);
      } else {
        Status = Tpm12Startup (TPM_ST_CLEAR);
      }
      if (EFI_ERROR (Status) ) {
        goto Done;
      }
    }

    //
    // TpmSelfTest is optional on S3 path, skip it to save S3 time
    //
    if (BootMode != BOOT_ON_S3_RESUME) {
      Status = Tpm12ContinueSelfTest ();
      if (EFI_ERROR (Status)) {
        goto Done;
      }
    }

    //
    // Only intall TpmInitializedPpi on success
    //
    Status = PeiServicesInstallPpi (&mTpmInitializedPpiList);
    ASSERT_EFI_ERROR (Status);
  }

So the TPM12 should have been detected and EFI_TCG_PROTOCOL actually existed in PEI phase. The details of Tpm12RequestUseTpm() in Tpm12DeviceLibTcg Library is like:

// SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.c
/**
  This service requests use TPM12.

  @retval EFI_SUCCESS      Get the control of TPM12 chip.
  @retval EFI_NOT_FOUND    TPM12 not found.
  @retval EFI_DEVICE_ERROR Unexpected device behaviour.
**/
EFI_STATUS
EFIAPI
Tpm12RequestUseTpm (
  VOID
  )
{
  EFI_STATUS   Status;

  if (mTcgProtocol == NULL) {
    Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **) &mTcgProtocol);
    if (EFI_ERROR (Status)) {
      //
      // TCG protocol is not installed. So, TPM12 is not present.
      //
      DEBUG ((EFI_D_ERROR, "Tpm12RequestUseTpm - TCG - %r\n", Status));
      return EFI_NOT_FOUND;
    }
  }
  //
  // Assume when TCG Protocol is ready, RequestUseTpm already done.
  //
  return EFI_SUCCESS;
}

3. The Image of TcgConfigDxe.efi type incompatibility
To declare one of my misunderstandings: OvmfIA32X64 is not for a specific architecture but a combination of IA32 and X64 in different phases:

// OvmfPkg/README
                             PEI arch   DXE arch   UEFI interfaces
* OvmfPkg/OvmfPkgIa32.dsc      IA32       IA32           IA32
* OvmfPkg/OvmfPkgIa32X64.dsc   IA32       X64            X64
* OvmfPkg/OvmfPkgX64.dsc       X64        X64            X64

So the TcgConfigDxe.efi can be compiled with IA32 target wrongly somehow. To avoid this, we use X64 Architecture as target for all phases.

(3) Details of Modification to Ovmf.dsc to enable TPM support

in the Vimdiff we can see the difference shown with the original and modified version.
Vimdiff showing modification

With knowledge from the analysis mentioned above, modify the DSC file further. In this part, we will describe explicitly how each part should be modified in OVMF.dsc and OVMF.dec.

Note that '*' means changing and "+" means adding.

1. Secure Boot Setting

  • Make sure the following lib instances exist in OVMF.dsc
    [LibraryClasses] IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
    [LibraryClasses] OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf *
  • Make sure BaseCrptolib instances exist in different [LibraryClasses.common.phase]
    For PEI driver: BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf +
    For DXE driver: BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf +
    For RUNTIME driver: BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
    For SMM driver: BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
  • Replace the Null Platform Security lib instance with
    [LibraryClasses] PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf
  • Ensure DxeImageVerificationLib is added to module SecurityStubDxe in the platform DSC file
    MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf {
       
          NULL|SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
    }
  • Add Authenticated Variable driver INF in OVMF.dsc
    SecurityPkg/VariableAuthenticated/Pei/VariablePei.inf +
    SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf +
    SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf +

Following steps are for OVMF.fdf or VarStore.fdf.inc configuration

  • Remove original variable driver INF from the platform FDF file
    INF MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
    INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf -
  • Add Authenticated Variable Driver INF to the platform FDF file
    INF SecurityPkg/VariableAuthenticated/Pei/VariablePei.inf +
    INF SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf +
    INF SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf +
  • Update Variable GUID value of VARIABLE_STORE_HEADER in VarStore.fdf.inc as
 #Signature: gEfiAuthenticatedVariableGuid =
    # {0xaaf32c78, 0x947b, 0x439a, { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92}}
    0x78, 0x2c, 0xf3, 0xaa, 0x7b, 0x94, 0x9a, 0x43,
    0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92,

Following steps are for PCD configuration in paltform DEC

  • Set gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize for certificate storage purpose
    gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x400|UINT32|0x30000003
  • Set a platform policy of image verification by PCDs in [PcdsFixedAtBuild] of SecurityPkg.dec
    https://github.com/tianocore/tianocore.github.io/wiki/How-to-Enable-Security#How_to_add_Secure_Boot_to_DSC_and_FDF

Optional

  • Enable SMM authenticated variable
    [Components] SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf

2. TPM Support Setting in OVMF

  • Ensure OpensslLib library instance is defined in [LibraryClasses] of the platform DSC*
    [LibraryClasses] IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
    [LibraryClasses] OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
  • Ensure BaseCryptLib library instances in each phase are defined in the platfrom
    DSC

    PEI phase: BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
    DXE phase: BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
  • Add TPM library instance in the platform DSC file
    TPM Command Lib
    SecurityPkg/Library/TpmCommLib/TpmCommLib.inf +
    TCG physical presence library
    SecurityPkg/Library/DxeTcgPhysicalPresenceLib/DxeTcgPhysicalPresenceLib.inf +
    TPM measure boot library
    SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf +
  • ** Add TPM drivers to [Component] section of the platform DSC**
    SecurityPkg/Tcg/TcgPei/TcgPei.inf +
    SecurityPkg/Tcg/TcgDxe/TcgDxe.inf +
    SecurityPkg/Tcg/TcgSmm/TcgSmm.inf +
    SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf +
    SecurityPkg/Tcg/PhysicalPresencePei/PhysicalPresencePei.inf +
    SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.inf +

Configuration for platform FDF and PCD

  • Add TPM drivers to the platform FDF
    INF SecurityPkg/Tcg/TcgPei/TcgPei.inf +
    INF SecurityPkg/Tcg/TcgDxe/TcgDxe.inf +
    INF SecurityPkg/Tcg/TcgSmm/TcgSmm.inf +
    INF SecurityPkg/Tcg/TcgConfigDxe/TcgConfigDxe.inf +
    INF SecurityPkg/Tcg/PhysicalPresencePei/PhysicalPresencePei.inf +
    INF SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.inf +
  • Set the platform policy by PCDs
gEfiSecurityPkgTokenSpaceGuid.PcdTpmPlatformClass|0|UINT8|0x00000006
gEfiSecurityPkgTokenSpaceGuid.PcdHideTpmSupport|FALSE|BOOLEAN|0x00000007

3. Amendments during building OVMF
For the guidance on the Tianocore Wiki is way too old, which is written for UDK2010, the newest EDKII will need further modification to the configuration in order to run Secure Boot and TPM Support.

  • Documnetation Compatibility
1. SecurityPkg/VariableAuthenticated/Pei/VariablePei.inf  not existent ---> MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
2. Add MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf
3. SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf not existent ---> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf (duplicated)
4. Duplicated document: SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
  • Library Issues:
1. Tpm12DeviceLib lib clasee for PEIM not found: SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf
2. Tpm12CommandLib for PEIM not found: SecurityPkg/Library/Tpm12CommandLib/Tpm12CommandLib.inf
3. Tpm12DeviceLib for DXE Driver not found: SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf
4. Tpm12CommandLib for DXE Driver not found: SecurityPkg/Library/Tpm12CommandLib/Tpm12CommandLib.inf
5. TcgPpVendorLib for SMM Driver not found: SecurityPkg/Library/TcgPpVendorLibNull/TcgPpVendorLibNull.inf

(4) Modification to Fault Tolerant Write PEIM

The result demonstrates the correctness of our hypothesis. But some novel bugs emerged.....

Install PPI: EE16160A-E8BE-47A6-820A-C6900DB0250A
Loading PEIM at 0x0007FEC7000 EntryPoint=0x0007FEC8469 FaultTolerantWritePei.efi
ASSERT [FaultTolerantWritePei] /home/hecmay/Desktop/Tiano/edk2/MdeModulePkg/Universal\
/FaultTolerantWritePei/FaultTolerantWritePei.c(241): (WorkSpaceAddress != 0) && (SpareAreaAddress != 0)

OK. Let us have a look where is wrong in the FaultTolerantWritePei.c

// MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.c
EFI_STATUS
EFIAPI
PeimFaultTolerantWriteInitialize (
  IN       EFI_PEI_FILE_HANDLE  FileHandle,
  IN CONST EFI_PEI_SERVICES     **PeiServices
  )
{
  EFI_STATUS                                Status;
  EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER   *FtwWorkingBlockHeader;
  EFI_FAULT_TOLERANT_WRITE_HEADER           *FtwLastWriteHeader;
  EFI_FAULT_TOLERANT_WRITE_RECORD           *FtwLastWriteRecord;
  EFI_PHYSICAL_ADDRESS                      WorkSpaceAddress;
  UINTN                                     WorkSpaceLength;
  EFI_PHYSICAL_ADDRESS                      SpareAreaAddress;
  UINTN                                     SpareAreaLength;
  EFI_PHYSICAL_ADDRESS                      WorkSpaceInSpareArea;
  FAULT_TOLERANT_WRITE_LAST_WRITE_DATA      FtwLastWrite;

  FtwWorkingBlockHeader = NULL;
  FtwLastWriteHeader = NULL;
  FtwLastWriteRecord = NULL;

  WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageFtwWorkingBase64);
  if (WorkSpaceAddress == 0) {
    WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwWorkingBase);
  }
  WorkSpaceLength = (UINTN) PcdGet32 (PcdFlashNvStorageFtwWorkingSize);

  SpareAreaAddress = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageFtwSpareBase64);
  if (SpareAreaAddress == 0) {
    SpareAreaAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwSpareBase);
  }
  SpareAreaLength = (UINTN) PcdGet32 (PcdFlashNvStorageFtwSpareSize);

  //
  // The address of FTW working base and spare base must not be 0.
  //
  ASSERT ((WorkSpaceAddress != 0) && (SpareAreaAddress != 0));

the issue should be relevant to the PCD default setting in the configuration.

  • PcdFlashNvStorageFtwWorkingBase64 || PcdFlashNvStorageFtwWorkingBase
  • PcdFlashNvStorageFtwSpareBase64 || PcdFlashNvStorageFtwSpareBase
  • Size: PcdFlashNvStorageFtwWorkingSize || PcdFlashNvStorageFtwSpareSize

Reference:

  • Default PcdFlashNvStorageVariableSize crashed OVMF
  • FTW spare space alignment with emulated NV storage

I still cannot fully understand why the FTW working space base address should not be 0x0? it seems that the address is required to be aligned. if we comment the ASSERT, similar error will appear:

Loading PEIM at 0x0007FEC7000 EntryPoint=0x0007FEC8469 FaultTolerantWritePei.efi
ASSERT [FaultTolerantWritePei] /home/hecmay/Desktop/Tiano/edk2/MdePkg/Library/BaseLib/Unaligned.c(192): Buffer != ((void *) 0)

The difference between OVMF and physical machine is another possible reason:

// OvmfPkg/OvmfPkg.fdf.inc 
!if $(FD_SIZE_IN_KB) == 4096
DEFINE VARS_LIVE_SIZE    = 0x40000
DEFINE FW_BASE_ADDRESS   = 0xFFC00000

//
// ......
//

SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageVariableBase = $(FW_BASE_ADDRESS)
SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize = $(VARS_LIVE_SIZE)

SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwWorkingBase = \
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase + \
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize
SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize = $(BLOCK_SIZE)

SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwSpareBase = \
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwWorkingBase + \
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize = $(VARS_SPARE_SIZE)

The solution is to replace the PCD Token in the original PcdFlashNvStorageWorkingBase with PcdOvmfFlashNvStorageWorkingBase. Remenber to add OVMF platform DEC to [Packages] part of FTW PEIM INF and include the new PCD token in the [Pcd] part.

in my understanding, the FlashNvStorageWorking Base Address should be dependent to different firmware volume setting, and its value will be set dynamically. The default value is like a reminder, which is set to be 0x0 is to confirm whether the Base Address has been initialized by using ASSERT.

(5) Conclusion and Future Plans

We have demonstrated that TPM can be detected in UEFI PEI Phase. The PEIM named TcgPei.efi will initialize TPM by calling Tpm with Tpm12RequestUseTpm() and Startup TPM

  • Why the TPM DXE Driver failed to locate EFI_TCG_PROTOCOL when calling Tpm12RequestUseTpm() function, which has been successfully called by TPM PEI Driver in its Entry Point function?
  • What is the mechanism in UEFI to detect the type of TPM? Is the EFI_TCGPROTOCOL compatible with EFI_TCG_PROTOCOL? and how are they implemented?

(6) Update for Debugging on 02/02/2018:

The bug is finally resolved. Along with the procedures shown above, we should also be aware of the correctness of the Tpm12DeviceLib we are using.

Change the Tpm12DeviceLibTcg used in OVMF.dsc [LibraryClasses.common.DEX_DRIVER] to Tpm12DeviceLibDTpm should work. The first Lib will not install EFI_TCG_PROTOCOL and can only be used with a EFI_TCG_PROTOCOL installed.

Tpm12 PCR values

OK, we can go to the next stage of testing the Socket model in UEFI environment and build up the Remote-Attestation framework based on it.

你可能感兴趣的:(01/31/2018 OVMF Serial port Debugging on QEMU)