Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ArmPlatformPkg/ArmPlatformPkg.dsc
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibFfa/Tpm2DeviceSecLibFfa.inf
HashLib|SecurityPkg/Library/HashLibTpm2/HashLibTpm2PeilessSecLib.inf
PeilessSecMeasureLib|SecurityPkg/Library/PeilessSecMeasureLib/PeilessSecMeasureLib.inf
Tpm2StartupLib|SecurityPkg/Library/Tpm2StartupLibNull/Tpm2StartupLibNull.inf # MU_CHANGE
Tpm2StartupLib|SecurityPkg/Library/Tpm2StartupLibNull/Tpm2StartupLibNull.inf ## MU_CHANGE

[LibraryClasses.AARCH64.MM_STANDALONE]
HobLib|StandaloneMmPkg/Library/StandaloneMmHobLib/StandaloneMmHobLib.inf
Expand Down
51 changes: 32 additions & 19 deletions ArmPlatformPkg/PeilessSec/PeilessSec.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
**/

#include "PeilessSec.h"
#include <Library/Tpm2StartupLib.h> // MU_CHANGE

#define IS_XIP() (((UINT64)FixedPcdGet64 (PcdFdBaseAddress) > mSystemMemoryEnd) ||\
((FixedPcdGet64 (PcdFdBaseAddress) + FixedPcdGet32 (PcdFdSize)) <= FixedPcdGet64 (PcdSystemMemoryBase)))
Expand Down Expand Up @@ -105,6 +104,7 @@ SecMain (
FIRMWARE_SEC_PERFORMANCE Performance;
VOID *TransferListBase;
UINTN *TransferListHobData;
EFI_PEI_HOB_POINTERS FvHob; // MU_CHANGE

// If ensure the FD is either part of the System Memory or totally outside of the System Memory (XIP)
ASSERT (
Expand Down Expand Up @@ -206,29 +206,42 @@ SecMain (
// SEC phase needs to run library constructors by hand.
ProcessLibraryConstructorList ();

// MU_CHANGE [BEGIN] - Add Tpm2StartupInit call
// Initialize the TPM before loading the DXE core
Status = Tpm2StartupInit ();

/* NOTE: EFI_UNSUPPORTED is treated as a success due to the possibility of there
* not being a TPM on the system and if so, the NULL instance of the startup
* lib should be linked in which returns UNSUPPORTED. Also, even if TPM is
* enabled, Tpm2StartupInit could return UNSUPPORTED depending on the TPM
* instance. */
if ((Status != EFI_SUCCESS) && (Status != EFI_UNSUPPORTED)) {
DEBUG ((DEBUG_ERROR, "Failed to initialize the TPM\n"));
ASSERT_EFI_ERROR (Status);
}

// MU_CHANGE [END]

// MU_CHANGE [BEGIN] - Remove DXE Core FV placement assumption

// Decompress firmware volumes and load the DXE Core
DecompressFvs ();

Status = MeasurePeilessSec ();
ASSERT_EFI_ERROR (Status);
// MU_CHANGE - [BEGIN]
// Status = MeasurePeilessSec ();
// ASSERT_EFI_ERROR (Status);

Status = Tpm2StartupInitializeTpm (FALSE);
if (!EFI_ERROR (Status)) {
Status = Tpm2StartupMeasureCoreEvents ();
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a: Tpm2StartupMeasureCoreEvents failed: %r\n", __func__, Status));
}

// Walk every FV HOB and measure each FV into PCR 0. Excluded FVs and
// pre-hashed FVs are handled inside Tpm2StartupMeasureFvImage via
// gExcludedFvHobGuid / gPrehashedFvHobGuid HOB lookups.
FvHob.Raw = GetNextHob (EFI_HOB_TYPE_FV, GetHobList ());
while (FvHob.Raw != NULL) {
(VOID)Tpm2StartupMeasureFvImage (
FvHob.FirmwareVolume->BaseAddress,
FvHob.FirmwareVolume->Length
);
FvHob.Raw = GET_NEXT_HOB (FvHob);
FvHob.Raw = GetNextHob (EFI_HOB_TYPE_FV, FvHob.Raw);
}

Tpm2StartupPublishMeasuredFvHob ();
} else if (Status != EFI_UNSUPPORTED) {
DEBUG ((DEBUG_ERROR, "%a: Tpm2StartupInitializeTpm failed: %r\n", __func__, Status));
ASSERT_EFI_ERROR (Status);
}

// MU_CHANGE - [END]

// Load the DXE Core and transfer control to it
Status = LoadDxeCoreFromFv (NULL, 0);
Expand Down
3 changes: 2 additions & 1 deletion ArmPlatformPkg/PeilessSec/PeilessSec.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@
#include <Library/DebugLib.h>
#include <Library/HobLib.h>
#include <Library/PerformanceLib.h>
#include <Library/PeilessSecMeasureLib.h>
// #include <Library/PeilessSecMeasureLib.h> // MU_CHANGE
#include <Library/PrePiHobListPointerLib.h>
#include <Library/PrePiLib.h>
#include <Library/PrintLib.h>
#include <Library/SerialPortLib.h>
#include <Library/TimerLib.h>
#include <Library/ArmTransferListLib.h>
#include <Library/Tpm2StartupLib.h> // MU_CHANGE
#include <Guid/TransferListHob.h>

#include <Ppi/ArmMpCoreInfo.h>
Expand Down
33 changes: 33 additions & 0 deletions MdeModulePkg/Library/DeviceStateLib/DeviceStateLibFixed.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/** @file
Read-only DeviceStateLib for platforms that pin PcdDeviceStateBitmask as
FixedAtBuild. GetDeviceState returns the compile-time value; AddDeviceState
is unsupported (Fixed PCDs cannot be updated).

Copyright (C) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#include <Uefi/UefiBaseType.h>
#include <Library/PcdLib.h>
#include <Library/DeviceStateLib.h>
#include <Library/DebugLib.h>

DEVICE_STATE
EFIAPI
GetDeviceState (
VOID
)
{
return (DEVICE_STATE)FixedPcdGet32 (PcdDeviceStateBitmask);
}

RETURN_STATUS
EFIAPI
AddDeviceState (
DEVICE_STATE AdditionalState
)
{
(VOID)AdditionalState;
DEBUG ((DEBUG_WARN, "%a: AddDeviceState is unsupported when PcdDeviceStateBitmask is FixedAtBuild\n", __func__));
return RETURN_UNSUPPORTED;
}
36 changes: 36 additions & 0 deletions MdeModulePkg/Library/DeviceStateLib/DeviceStateLibFixed.inf
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
## @file
# Read-only DeviceStateLib variant for platforms that resolve
# PcdDeviceStateBitmask as FixedAtBuild.
#
# Peiless SEC platforms (e.g. QemuArmVirtPkg) have no dynamic PCD store,
# so the PCD must be Fixed. PcdSet32S is not legal on a Fixed PCD, so this
# variant omits the write path from AddDeviceState. The read path is
# preserved so consumers such as Tpm2StartupLib continue to see the
# platform's build-time device state and emit the appropriate PCR
# measurements.
#
# Copyright (C) Microsoft Corporation.
# SPDX-License-Identifier: BSD-2-Clause-Patent
##

[Defines]
INF_VERSION = 0x00010017
BASE_NAME = DeviceStateLibFixed
FILE_GUID = 6c7b1d1a-9c8e-4c2f-8b3a-1e5f2a7d4c60
VERSION_STRING = 1.0
MODULE_TYPE = BASE
LIBRARY_CLASS = DeviceStateLib

[LibraryClasses]
DebugLib
PcdLib

[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec

[Sources]
DeviceStateLibFixed.c

[FixedPcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdDeviceStateBitmask
9 changes: 8 additions & 1 deletion MdeModulePkg/MdeModulePkg.ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,14 @@

## options defined .pytool/Plugin/DscCompleteCheck
"DscCompleteCheck": {
"IgnoreInf": [],
"IgnoreInf": [
# MU_CHANGE
# DeviceStateLibFixed.inf uses FixedPcd(PcdDeviceStateBitmask) and can
# only be built in a DSC that sets it as FixedAtBuild. MdeModulePkg.dsc
# declares it as DynamicEx to support the writeable DeviceStateLib.inf, so
# the Fixed variant cannot be built here.
"MdeModulePkg/Library/DeviceStateLib/DeviceStateLibFixed.inf"
],
"DscPath": "MdeModulePkg.dsc"
},
## options defined .pytool/Plugin/HostUnitTestDscCompleteCheck
Expand Down
10 changes: 5 additions & 5 deletions MdeModulePkg/MdeModulePkg.dec
Original file line number Diff line number Diff line change
Expand Up @@ -2573,6 +2573,11 @@
# @Prompt Max size to accept in PCIe Resizable BAR Capability register.
gEfiMdeModulePkgTokenSpaceGuid.PcdPcieResizableBarMaxSize|43|UINT8|0x10000030

## MU_CHANGE - Add DeviceStateLib to MdeModulePkg
## This PCD holds the device state bitmap as described in Include/Library/DeviceStateLib.h.
# @Prompt Describes device state
gEfiMdeModulePkgTokenSpaceGuid.PcdDeviceStateBitmask|0x00000000|UINT32|0x00040009

[PcdsPatchableInModule]
## Specify memory size with page number for PEI code when
# Loading Module at Fixed Address feature is enabled.
Expand Down Expand Up @@ -2638,11 +2643,6 @@
# The amount of memory allocated for GHCBs is dependent on the number of APs.
# @Prompt GHCB Pool Size
gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize|0|UINT64|0x00030008

## MU_CHANGE - Add DeviceStateLib to MdeModulePkg
## This dynamic PCD holds the device state bitmap as described in Include/Library/DeviceStateLib.h
# @Prompt Describes device state
gEfiMdeModulePkgTokenSpaceGuid.PcdDeviceStateBitmask|0x00000000|UINT32|0x00040009

[PcdsDynamicEx]
## This dynamic PCD enables the default variable setting.
Expand Down
1 change: 1 addition & 0 deletions MdeModulePkg/MdeModulePkg.dsc
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@

[PcdsDynamicExDefault]
gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryFileName|L"FVMAIN.FV"
gEfiMdeModulePkgTokenSpaceGuid.PcdDeviceStateBitmask|0x00000000 ## MU_CHANGE

[Components]
MdeModulePkg/Application/HelloWorld/HelloWorld.inf
Expand Down
39 changes: 39 additions & 0 deletions SecurityPkg/Include/Guid/PrehashedFvHob.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/** @file
HOB used to declare pre-hashed firmware volumes to Tpm2StartupLib
(or any consumer that needs to know a FV's digests without hashing it).

This is the phase-agnostic equivalent of
gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid. Producers include:
- Tcg2Pei, which translates the PPI to this HOB early in its flow so
the consolidated Tpm2StartupLib can find pre-hashed FVs without
depending on PEI services.
- PEI-less platforms (SEC / early DXE), which can BuildGuidHob directly
when they have pre-computed FV digests (typically obtained from a
prior firmware stage such as TF-A).

One HOB is produced per pre-hashed FV. The HOB payload begins with a
PREHASHED_FV_HOB header identifying the FV, immediately followed by
Count HASH_INFO records; each HASH_INFO is followed inline by its
digest bytes (HashSize bytes). This mirrors the PPI payload layout to
keep any PPI-to-HOB translator trivial.

Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#ifndef PREHASHED_FV_HOB_H_
#define PREHASHED_FV_HOB_H_

#include <Ppi/FirmwareVolumeInfoPrehashedFV.h>

extern EFI_GUID gPrehashedFvHobGuid;

typedef struct {
EFI_PHYSICAL_ADDRESS FvBase;
UINT64 FvLength;
UINT32 Count;
// HASH_INFO HashInfo[]; each followed inline by HashSize bytes of digest
} PREHASHED_FV_HOB;

#endif
97 changes: 87 additions & 10 deletions SecurityPkg/Include/Library/Tpm2StartupLib.h
Original file line number Diff line number Diff line change
@@ -1,26 +1,103 @@
/** @file
Definitions for TPM 2.0 startup and initialization
Declarations for TPM 2.0 startup and initialization.

A single library instance consolidates the TPM startup and pre-DXE
measurement work that previously lived in PEI so it can be driven
from either PEI or from SEC on PEI-less platforms.

Copyright (c), Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#ifndef TPM2_STARTUP_LIB_H_
#define TPM2_STARTUP_LIB_H_
#pragma once

/**
Initialize the TPM 2.0 device. Requests use of the TPM, invokes
the OEM pre-startup hook, runs TPM startup (with S3-state fallback
to SU_CLEAR and PCR 0..7 separator error events on fallback),
runs TPM self test, the OEM post-selftest hook, and a debug PCR read.
On failure, produces an ERROR HOB so later phases exit early.

@param[in] IsS3Resume TRUE when the platform is resuming from S3.
Drives TPM_SU_STATE vs TPM_SU_CLEAR selection,
whether self-test runs, and whether error
separator events are generated on PCRs 0..7.

@retval EFI_SUCCESS Initialization completed.
@retval EFI_UNSUPPORTED TPM2 is not required.
@retval EFI_NOT_FOUND TPM device not detected.
@retval EFI_DEVICE_ERROR A TPM command failed; error HOB was produced,
or a prior error HOB was found.
**/
EFI_STATUS
EFIAPI
Tpm2StartupInitializeTpm (
IN BOOLEAN IsS3Resume
);

/**
This function initializes the TPM if required
Generates the pre-Tcg2 core measurement events. Runs the OEM
pre-measurement hook, seeds the pre-UEFI event log, measures the
firmware debugger state (when enabled), and measures the CRTM version
(when enabled). On failure, produces an ERROR HOB so later phases exit
early.

@retval EFI_SUCCESS TPM successfully initialized
@retval EFI_UNSUPPORTED TPM is not supported
@retval EFI_NOT_FOUND TPM device not found
@retval EFI_DEVICE_ERROR Unexpected device error
@retval EFI_SUCCESS All applicable events measured.
@retval EFI_UNSUPPORTED TPM2 is not required.
@retval EFI_NOT_FOUND TPM device not detected.
@retval EFI_DEVICE_ERROR A TPM command failed; error HOB was produced,
or a prior error HOB was found.
**/
EFI_STATUS
EFIAPI
Tpm2StartupInit (
Tpm2StartupMeasureCoreEvents (
VOID
);

#endif
/**
Measure a single firmware volume image into PCR 0. Handles
excluded FV HOBs, pre-hashed FV HOBs (where digests are provided
to prevent re-hashing), and migrated FV HOBs.

@param[in] FvBase Base address of the FV image.
@param[in] FvLength Length of the FV image.

@retval EFI_SUCCESS FV was measured or was already
measured/excluded.
@retval EFI_INVALID_PARAMETER Malformed data.
@retval EFI_OUT_OF_RESOURCES Allocation failure.
@retval EFI_DEVICE_ERROR A TPM command failed.
**/
EFI_STATUS
EFIAPI
Tpm2StartupMeasureFvImage (
IN EFI_PHYSICAL_ADDRESS FvBase,
IN UINT64 FvLength
);

/**
Record a child FV (an FV embedded inside a file inside its parent) so
that when the same address range is presented again during a later
FV-notify, it is not measured a second time. The child's content was
already covered by the parent measurement.

@param[in] FvBase Base address of the child FV.
@param[in] FvLength Length of the child FV.
**/
VOID
EFIAPI
Tpm2StartupRecordChildFv (
IN EFI_PHYSICAL_ADDRESS FvBase,
IN UINT64 FvLength
);

/**
Publish gMeasuredFvHobGuid containing every base and child FV that
was measured.
**/
VOID
EFIAPI
Tpm2StartupPublishMeasuredFvHob (
VOID
);
Loading
Loading