summaryrefslogtreecommitdiff
path: root/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmStm.c
diff options
context:
space:
mode:
Diffstat (limited to 'UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmStm.c')
-rw-r--r--UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmStm.c1299
1 files changed, 0 insertions, 1299 deletions
diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmStm.c b/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmStm.c
deleted file mode 100644
index 03937dcbe2..0000000000
--- a/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmStm.c
+++ /dev/null
@@ -1,1299 +0,0 @@
-/** @file
- SMM STM support functions
-
- Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php.
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include <PiSmm.h>
-#include <Library/BaseLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/HobLib.h>
-#include <Library/DebugLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/SmmServicesTableLib.h>
-#include <Library/TpmMeasurementLib.h>
-#include <Register/Cpuid.h>
-#include <Register/ArchitecturalMsr.h>
-#include <Register/SmramSaveStateMap.h>
-
-#include <Protocol/MpService.h>
-
-#include "SmmStm.h"
-
-#define TXT_EVTYPE_BASE 0x400
-#define TXT_EVTYPE_STM_HASH (TXT_EVTYPE_BASE + 14)
-
-#define RDWR_ACCS 3
-#define FULL_ACCS 7
-
-/**
- The constructor function
-
- @param[in] ImageHandle The firmware allocated handle for the EFI image.
- @param[in] SystemTable A pointer to the EFI System Table.
-
- @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
-
-**/
-EFI_STATUS
-EFIAPI
-SmmCpuFeaturesLibConstructor (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- );
-
-EFI_HANDLE mStmSmmCpuHandle = NULL;
-
-BOOLEAN mLockLoadMonitor = FALSE;
-
-//
-// Template of STM_RSC_END structure for copying.
-//
-GLOBAL_REMOVE_IF_UNREFERENCED STM_RSC_END mRscEndNode = {
- {END_OF_RESOURCES, sizeof (STM_RSC_END)},
-};
-
-GLOBAL_REMOVE_IF_UNREFERENCED UINT8 *mStmResourcesPtr = NULL;
-GLOBAL_REMOVE_IF_UNREFERENCED UINTN mStmResourceTotalSize = 0x0;
-GLOBAL_REMOVE_IF_UNREFERENCED UINTN mStmResourceSizeUsed = 0x0;
-GLOBAL_REMOVE_IF_UNREFERENCED UINTN mStmResourceSizeAvailable = 0x0;
-
-GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mStmState = 0;
-
-//
-// System Configuration Table pointing to STM Configuration Table
-//
-GLOBAL_REMOVE_IF_UNREFERENCED
-EFI_SM_MONITOR_INIT_PROTOCOL mSmMonitorInitProtocol = {
- LoadMonitor,
- AddPiResource,
- DeletePiResource,
- GetPiResource,
- GetMonitorState,
-};
-
-
-
-
-#define CPUID1_EDX_XD_SUPPORT 0x100000
-
-//
-// External global variables associated with SMI Handler Template
-//
-extern CONST TXT_PROCESSOR_SMM_DESCRIPTOR gcStmPsd;
-extern UINT32 gStmSmbase;
-extern volatile UINT32 gStmSmiStack;
-extern UINT32 gStmSmiCr3;
-extern volatile UINT8 gcStmSmiHandlerTemplate[];
-extern CONST UINT16 gcStmSmiHandlerSize;
-extern UINT16 gcStmSmiHandlerOffset;
-extern BOOLEAN gStmXdSupported;
-
-//
-// Variables used by SMI Handler
-//
-IA32_DESCRIPTOR gStmSmiHandlerIdtr;
-
-//
-// MP Services Protocol
-//
-EFI_MP_SERVICES_PROTOCOL *mSmmCpuFeaturesLibMpService = NULL;
-
-//
-// MSEG Base and Length in SMRAM
-//
-UINTN mMsegBase = 0;
-UINTN mMsegSize = 0;
-
-BOOLEAN mStmConfigurationTableInitialized = FALSE;
-
-
-/**
- The constructor function
-
- @param[in] ImageHandle The firmware allocated handle for the EFI image.
- @param[in] SystemTable A pointer to the EFI System Table.
-
- @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
-
-**/
-EFI_STATUS
-EFIAPI
-SmmCpuFeaturesLibStmConstructor (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_STATUS Status;
- CPUID_VERSION_INFO_ECX RegEcx;
- EFI_HOB_GUID_TYPE *GuidHob;
- EFI_SMRAM_DESCRIPTOR *SmramDescriptor;
-
- //
- // Call the common constructor function
- //
- Status = SmmCpuFeaturesLibConstructor (ImageHandle, SystemTable);
- ASSERT_EFI_ERROR (Status);
-
- //
- // Lookup the MP Services Protocol
- //
- Status = gBS->LocateProtocol (
- &gEfiMpServiceProtocolGuid,
- NULL,
- (VOID **)&mSmmCpuFeaturesLibMpService
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // If CPU supports VMX, then determine SMRAM range for MSEG.
- //
- AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &RegEcx.Uint32, NULL);
- if (RegEcx.Bits.VMX == 1) {
- GuidHob = GetFirstGuidHob (&gMsegSmramGuid);
- if (GuidHob != NULL) {
- //
- // Retrieve MSEG location from MSEG SRAM HOB
- //
- SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *) GET_GUID_HOB_DATA (GuidHob);
- if (SmramDescriptor->PhysicalSize > 0) {
- mMsegBase = (UINTN)SmramDescriptor->CpuStart;
- mMsegSize = (UINTN)SmramDescriptor->PhysicalSize;
- }
- } else if (PcdGet32 (PcdCpuMsegSize) > 0) {
- //
- // Allocate MSEG from SMRAM memory
- //
- mMsegBase = (UINTN)AllocatePages (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuMsegSize)));
- if (mMsegBase > 0) {
- mMsegSize = ALIGN_VALUE (PcdGet32 (PcdCpuMsegSize), EFI_PAGE_SIZE);
- } else {
- DEBUG ((DEBUG_ERROR, "Not enough SMRAM resource to allocate MSEG size %08x\n", PcdGet32 (PcdCpuMsegSize)));
- }
- }
- if (mMsegBase > 0) {
- DEBUG ((DEBUG_INFO, "MsegBase: 0x%08x, MsegSize: 0x%08x\n", mMsegBase, mMsegSize));
- }
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Internal worker function that is called to complete CPU initialization at the
- end of SmmCpuFeaturesInitializeProcessor().
-
-**/
-VOID
-FinishSmmCpuFeaturesInitializeProcessor (
- VOID
- )
-{
- MSR_IA32_SMM_MONITOR_CTL_REGISTER SmmMonitorCtl;
-
- //
- // Set MSEG Base Address in SMM Monitor Control MSR.
- //
- if (mMsegBase > 0) {
- SmmMonitorCtl.Uint64 = 0;
- SmmMonitorCtl.Bits.MsegBase = (UINT32)mMsegBase >> 12;
- SmmMonitorCtl.Bits.Valid = 1;
- AsmWriteMsr64 (MSR_IA32_SMM_MONITOR_CTL, SmmMonitorCtl.Uint64);
- }
-}
-
-/**
- Return the size, in bytes, of a custom SMI Handler in bytes. If 0 is
- returned, then a custom SMI handler is not provided by this library,
- and the default SMI handler must be used.
-
- @retval 0 Use the default SMI handler.
- @retval > 0 Use the SMI handler installed by SmmCpuFeaturesInstallSmiHandler()
- The caller is required to allocate enough SMRAM for each CPU to
- support the size of the custom SMI handler.
-**/
-UINTN
-EFIAPI
-SmmCpuFeaturesGetSmiHandlerSize (
- VOID
- )
-{
- return gcStmSmiHandlerSize;
-}
-
-/**
- Install a custom SMI handler for the CPU specified by CpuIndex. This function
- is only called if SmmCpuFeaturesGetSmiHandlerSize() returns a size is greater
- than zero and is called by the CPU that was elected as monarch during System
- Management Mode initialization.
-
- @param[in] CpuIndex The index of the CPU to install the custom SMI handler.
- The value must be between 0 and the NumberOfCpus field
- in the System Management System Table (SMST).
- @param[in] SmBase The SMBASE address for the CPU specified by CpuIndex.
- @param[in] SmiStack The stack to use when an SMI is processed by the
- the CPU specified by CpuIndex.
- @param[in] StackSize The size, in bytes, if the stack used when an SMI is
- processed by the CPU specified by CpuIndex.
- @param[in] GdtBase The base address of the GDT to use when an SMI is
- processed by the CPU specified by CpuIndex.
- @param[in] GdtSize The size, in bytes, of the GDT used when an SMI is
- processed by the CPU specified by CpuIndex.
- @param[in] IdtBase The base address of the IDT to use when an SMI is
- processed by the CPU specified by CpuIndex.
- @param[in] IdtSize The size, in bytes, of the IDT used when an SMI is
- processed by the CPU specified by CpuIndex.
- @param[in] Cr3 The base address of the page tables to use when an SMI
- is processed by the CPU specified by CpuIndex.
-**/
-VOID
-EFIAPI
-SmmCpuFeaturesInstallSmiHandler (
- IN UINTN CpuIndex,
- IN UINT32 SmBase,
- IN VOID *SmiStack,
- IN UINTN StackSize,
- IN UINTN GdtBase,
- IN UINTN GdtSize,
- IN UINTN IdtBase,
- IN UINTN IdtSize,
- IN UINT32 Cr3
- )
-{
- EFI_STATUS Status;
- TXT_PROCESSOR_SMM_DESCRIPTOR *Psd;
- VOID *Hob;
- UINT32 RegEax;
- UINT32 RegEdx;
- EFI_PROCESSOR_INFORMATION ProcessorInfo;
-
- CopyMem ((VOID *)((UINTN)SmBase + TXT_SMM_PSD_OFFSET), &gcStmPsd, sizeof (gcStmPsd));
- Psd = (TXT_PROCESSOR_SMM_DESCRIPTOR *)(VOID *)((UINTN)SmBase + TXT_SMM_PSD_OFFSET);
- Psd->SmmGdtPtr = GdtBase;
- Psd->SmmGdtSize = (UINT32)GdtSize;
-
- //
- // Initialize values in template before copy
- //
- gStmSmiStack = (UINT32)((UINTN)SmiStack + StackSize - sizeof (UINTN));
- gStmSmiCr3 = Cr3;
- gStmSmbase = SmBase;
- gStmSmiHandlerIdtr.Base = IdtBase;
- gStmSmiHandlerIdtr.Limit = (UINT16)(IdtSize - 1);
-
- if (gStmXdSupported) {
- AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
- if (RegEax <= CPUID_EXTENDED_FUNCTION) {
- //
- // Extended CPUID functions are not supported on this processor.
- //
- gStmXdSupported = FALSE;
- }
-
- AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);
- if ((RegEdx & CPUID1_EDX_XD_SUPPORT) == 0) {
- //
- // Execute Disable Bit feature is not supported on this processor.
- //
- gStmXdSupported = FALSE;
- }
- }
-
- //
- // Set the value at the top of the CPU stack to the CPU Index
- //
- *(UINTN*)(UINTN)gStmSmiStack = CpuIndex;
-
- //
- // Copy template to CPU specific SMI handler location
- //
- CopyMem (
- (VOID*)((UINTN)SmBase + SMM_HANDLER_OFFSET),
- (VOID*)gcStmSmiHandlerTemplate,
- gcStmSmiHandlerSize
- );
-
- Psd->SmmSmiHandlerRip = SmBase + SMM_HANDLER_OFFSET + gcStmSmiHandlerOffset;
- Psd->SmmSmiHandlerRsp = (UINTN)SmiStack + StackSize - sizeof(UINTN);
- Psd->SmmCr3 = Cr3;
-
- DEBUG((DEBUG_ERROR, "CpuSmmStmExceptionStackSize - %x\n", PcdGet32(PcdCpuSmmStmExceptionStackSize)));
- DEBUG((DEBUG_ERROR, "Pages - %x\n", EFI_SIZE_TO_PAGES(PcdGet32(PcdCpuSmmStmExceptionStackSize))));
- Psd->StmProtectionExceptionHandler.SpeRsp = (UINT64)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmStmExceptionStackSize)));
- Psd->StmProtectionExceptionHandler.SpeRsp += EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmStmExceptionStackSize)));
-
- Psd->BiosHwResourceRequirementsPtr = (UINT64)(UINTN)GetStmResource ();
-
- //
- // Get the APIC ID for the CPU specified by CpuIndex
- //
- Status = mSmmCpuFeaturesLibMpService->GetProcessorInfo (
- mSmmCpuFeaturesLibMpService,
- CpuIndex,
- &ProcessorInfo
- );
- ASSERT_EFI_ERROR (Status);
-
- Psd->LocalApicId = (UINT32)ProcessorInfo.ProcessorId;
- Psd->AcpiRsdp = 0;
-
- Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
- if (Hob != NULL) {
- Psd->PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;
- } else {
- AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
- if (RegEax >= 0x80000008) {
- AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
- Psd->PhysicalAddressBits = (UINT8) RegEax;
- } else {
- Psd->PhysicalAddressBits = 36;
- }
- }
-
- if (!mStmConfigurationTableInitialized) {
- StmSmmConfigurationTableInit ();
- mStmConfigurationTableInitialized = TRUE;
- }
-}
-
-/**
- SMM End Of Dxe event notification handler.
-
- STM support need patch AcpiRsdp in TXT_PROCESSOR_SMM_DESCRIPTOR.
-
- @param[in] Protocol Points to the protocol's unique identifier.
- @param[in] Interface Points to the interface instance.
- @param[in] Handle The handle on which the interface was installed.
-
- @retval EFI_SUCCESS Notification handler runs successfully.
-**/
-EFI_STATUS
-EFIAPI
-SmmEndOfDxeEventNotify (
- IN CONST EFI_GUID *Protocol,
- IN VOID *Interface,
- IN EFI_HANDLE Handle
- )
-{
- VOID *Rsdp;
- UINTN Index;
- TXT_PROCESSOR_SMM_DESCRIPTOR *Psd;
-
- DEBUG ((DEBUG_INFO, "SmmEndOfDxeEventNotify\n"));
-
- //
- // found ACPI table RSD_PTR from system table
- //
- Rsdp = NULL;
- for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
- if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi20TableGuid)) {
- //
- // A match was found.
- //
- Rsdp = gST->ConfigurationTable[Index].VendorTable;
- break;
- }
- }
- if (Rsdp == NULL) {
- for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
- if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi10TableGuid)) {
- //
- // A match was found.
- //
- Rsdp = gST->ConfigurationTable[Index].VendorTable;
- break;
- }
- }
- }
-
- for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {
- Psd = (TXT_PROCESSOR_SMM_DESCRIPTOR *)((UINTN)gSmst->CpuSaveState[Index] - SMRAM_SAVE_STATE_MAP_OFFSET + TXT_SMM_PSD_OFFSET);
- DEBUG ((DEBUG_INFO, "Index=%d Psd=%p Rsdp=%p\n", Index, Psd, Rsdp));
- Psd->AcpiRsdp = (UINT64)(UINTN)Rsdp;
- }
-
- mLockLoadMonitor = TRUE;
-
- return EFI_SUCCESS;
-}
-
-/**
- This function initializes the STM configuration table.
-**/
-VOID
-StmSmmConfigurationTableInit (
- VOID
- )
-{
- EFI_STATUS Status;
- VOID *Registration;
-
- Status = gSmst->SmmInstallProtocolInterface (
- &mStmSmmCpuHandle,
- &gEfiSmMonitorInitProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &mSmMonitorInitProtocol
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- //
- // Register SMM End of DXE Event
- //
- Status = gSmst->SmmRegisterProtocolNotify (
- &gEfiSmmEndOfDxeProtocolGuid,
- SmmEndOfDxeEventNotify,
- &Registration
- );
- ASSERT_EFI_ERROR (Status);
-}
-
-/**
-
- Get STM state.
-
- @return STM state
-
-**/
-EFI_SM_MONITOR_STATE
-EFIAPI
-GetMonitorState (
- VOID
- )
-{
- return mStmState;
-}
-
-/**
-
- Handle single Resource to see if it can be merged into Record.
-
- @param Resource A pointer to resource node to be added
- @param Record A pointer to record node to be merged
-
- @retval TRUE resource handled
- @retval FALSE resource is not handled
-
-**/
-BOOLEAN
-HandleSingleResource (
- IN STM_RSC *Resource,
- IN STM_RSC *Record
- )
-{
- UINT64 ResourceLo;
- UINT64 ResourceHi;
- UINT64 RecordLo;
- UINT64 RecordHi;
-
- ResourceLo = 0;
- ResourceHi = 0;
- RecordLo = 0;
- RecordHi = 0;
-
- //
- // Calling code is responsible for making sure that
- // Resource->Header.RscType == (*Record)->Header.RscType
- // thus we use just one of them as switch variable.
- //
- switch (Resource->Header.RscType) {
- case MEM_RANGE:
- case MMIO_RANGE:
- ResourceLo = Resource->Mem.Base;
- ResourceHi = Resource->Mem.Base + Resource->Mem.Length;
- RecordLo = Record->Mem.Base;
- RecordHi = Record->Mem.Base + Record->Mem.Length;
- if (Resource->Mem.RWXAttributes != Record->Mem.RWXAttributes) {
- if ((ResourceLo == RecordLo) && (ResourceHi == RecordHi)) {
- Record->Mem.RWXAttributes = Resource->Mem.RWXAttributes | Record->Mem.RWXAttributes;
- return TRUE;
- } else {
- return FALSE;
- }
- }
- break;
- case IO_RANGE:
- case TRAPPED_IO_RANGE:
- ResourceLo = (UINT64) Resource->Io.Base;
- ResourceHi = (UINT64) Resource->Io.Base + (UINT64) Resource->Io.Length;
- RecordLo = (UINT64) Record->Io.Base;
- RecordHi = (UINT64) Record->Io.Base + (UINT64) Record->Io.Length;
- break;
- case PCI_CFG_RANGE:
- if ((Resource->PciCfg.OriginatingBusNumber != Record->PciCfg.OriginatingBusNumber) ||
- (Resource->PciCfg.LastNodeIndex != Record->PciCfg.LastNodeIndex)) {
- return FALSE;
- }
- if (CompareMem (Resource->PciCfg.PciDevicePath, Record->PciCfg.PciDevicePath, sizeof(STM_PCI_DEVICE_PATH_NODE) * (Resource->PciCfg.LastNodeIndex + 1)) != 0) {
- return FALSE;
- }
- ResourceLo = (UINT64) Resource->PciCfg.Base;
- ResourceHi = (UINT64) Resource->PciCfg.Base + (UINT64) Resource->PciCfg.Length;
- RecordLo = (UINT64) Record->PciCfg.Base;
- RecordHi = (UINT64) Record->PciCfg.Base + (UINT64) Record->PciCfg.Length;
- if (Resource->PciCfg.RWAttributes != Record->PciCfg.RWAttributes) {
- if ((ResourceLo == RecordLo) && (ResourceHi == RecordHi)) {
- Record->PciCfg.RWAttributes = Resource->PciCfg.RWAttributes | Record->PciCfg.RWAttributes;
- return TRUE;
- } else {
- return FALSE;
- }
- }
- break;
- case MACHINE_SPECIFIC_REG:
- //
- // Special case - merge MSR masks in place.
- //
- if (Resource->Msr.MsrIndex != Record->Msr.MsrIndex) {
- return FALSE;
- }
- Record->Msr.ReadMask |= Resource->Msr.ReadMask;
- Record->Msr.WriteMask |= Resource->Msr.WriteMask;
- return TRUE;
- default:
- return FALSE;
- }
- //
- // If resources are disjoint
- //
- if ((ResourceHi < RecordLo) || (ResourceLo > RecordHi)) {
- return FALSE;
- }
-
- //
- // If resource is consumed by record.
- //
- if ((ResourceLo >= RecordLo) && (ResourceHi <= RecordHi)) {
- return TRUE;
- }
- //
- // Resources are overlapping.
- // Resource and record are merged.
- //
- ResourceLo = (ResourceLo < RecordLo) ? ResourceLo : RecordLo;
- ResourceHi = (ResourceHi > RecordHi) ? ResourceHi : RecordHi;
-
- switch (Resource->Header.RscType) {
- case MEM_RANGE:
- case MMIO_RANGE:
- Record->Mem.Base = ResourceLo;
- Record->Mem.Length = ResourceHi - ResourceLo;
- break;
- case IO_RANGE:
- case TRAPPED_IO_RANGE:
- Record->Io.Base = (UINT16) ResourceLo;
- Record->Io.Length = (UINT16) (ResourceHi - ResourceLo);
- break;
- case PCI_CFG_RANGE:
- Record->PciCfg.Base = (UINT16) ResourceLo;
- Record->PciCfg.Length = (UINT16) (ResourceHi - ResourceLo);
- break;
- default:
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
-
- Add resource node.
-
- @param Resource A pointer to resource node to be added
-
-**/
-VOID
-AddSingleResource (
- IN STM_RSC *Resource
- )
-{
- STM_RSC *Record;
-
- Record = (STM_RSC *)mStmResourcesPtr;
-
- while (TRUE) {
- if (Record->Header.RscType == END_OF_RESOURCES) {
- break;
- }
- //
- // Go to next record if resource and record types don't match.
- //
- if (Resource->Header.RscType != Record->Header.RscType) {
- Record = (STM_RSC *)((UINTN)Record + Record->Header.Length);
- continue;
- }
- //
- // Record is handled inside of procedure - don't adjust.
- //
- if (HandleSingleResource (Resource, Record)) {
- return ;
- }
- Record = (STM_RSC *)((UINTN)Record + Record->Header.Length);
- }
-
- //
- // Add resource to the end of area.
- //
- CopyMem (
- mStmResourcesPtr + mStmResourceSizeUsed - sizeof(mRscEndNode),
- Resource,
- Resource->Header.Length
- );
- CopyMem (
- mStmResourcesPtr + mStmResourceSizeUsed - sizeof(mRscEndNode) + Resource->Header.Length,
- &mRscEndNode,
- sizeof(mRscEndNode)
- );
- mStmResourceSizeUsed += Resource->Header.Length;
- mStmResourceSizeAvailable = mStmResourceTotalSize - mStmResourceSizeUsed;
-
- return ;
-}
-
-/**
-
- Add resource list.
-
- @param ResourceList A pointer to resource list to be added
- @param NumEntries Optional number of entries.
- If 0, list must be terminated by END_OF_RESOURCES.
-
-**/
-VOID
-AddResource (
- IN STM_RSC *ResourceList,
- IN UINT32 NumEntries OPTIONAL
- )
-{
- UINT32 Count;
- UINTN Index;
- STM_RSC *Resource;
-
- if (NumEntries == 0) {
- Count = 0xFFFFFFFF;
- } else {
- Count = NumEntries;
- }
-
- Resource = ResourceList;
-
- for (Index = 0; Index < Count; Index++) {
- if (Resource->Header.RscType == END_OF_RESOURCES) {
- return ;
- }
- AddSingleResource (Resource);
- Resource = (STM_RSC *)((UINTN)Resource + Resource->Header.Length);
- }
- return ;
-}
-
-/**
-
- Validate resource list.
-
- @param ResourceList A pointer to resource list to be added
- @param NumEntries Optional number of entries.
- If 0, list must be terminated by END_OF_RESOURCES.
-
- @retval TRUE resource valid
- @retval FALSE resource invalid
-
-**/
-BOOLEAN
-ValidateResource (
- IN STM_RSC *ResourceList,
- IN UINT32 NumEntries OPTIONAL
- )
-{
- UINT32 Count;
- UINTN Index;
- STM_RSC *Resource;
- UINTN SubIndex;
-
- //
- // If NumEntries == 0 make it very big. Scan will be terminated by
- // END_OF_RESOURCES.
- //
- if (NumEntries == 0) {
- Count = 0xFFFFFFFF;
- } else {
- Count = NumEntries;
- }
-
- //
- // Start from beginning of resource list.
- //
- Resource = ResourceList;
-
- for (Index = 0; Index < Count; Index++) {
- DEBUG ((DEBUG_ERROR, "ValidateResource (%d) - RscType(%x)\n", Index, Resource->Header.RscType));
- //
- // Validate resource.
- //
- switch (Resource->Header.RscType) {
- case END_OF_RESOURCES:
- if (Resource->Header.Length != sizeof (STM_RSC_END)) {
- return FALSE;
- }
- //
- // If we are passed actual number of resources to add,
- // END_OF_RESOURCES structure between them is considered an
- // error. If NumEntries == 0 END_OF_RESOURCES is a termination.
- //
- if (NumEntries != 0) {
- return FALSE;
- } else {
- //
- // If NumEntries == 0 and list reached end - return success.
- //
- return TRUE;
- }
- break;
-
- case MEM_RANGE:
- case MMIO_RANGE:
- if (Resource->Header.Length != sizeof (STM_RSC_MEM_DESC)) {
- return FALSE;
- }
-
- if (Resource->Mem.RWXAttributes > FULL_ACCS) {
- return FALSE;
- }
- break;
-
- case IO_RANGE:
- case TRAPPED_IO_RANGE:
- if (Resource->Header.Length != sizeof (STM_RSC_IO_DESC)) {
- return FALSE;
- }
-
- if ((Resource->Io.Base + Resource->Io.Length) > 0xFFFF) {
- return FALSE;
- }
- break;
-
- case PCI_CFG_RANGE:
- DEBUG ((DEBUG_ERROR, "ValidateResource - PCI (0x%02x, 0x%08x, 0x%02x, 0x%02x)\n", Resource->PciCfg.OriginatingBusNumber, Resource->PciCfg.LastNodeIndex, Resource->PciCfg.PciDevicePath[0].PciDevice, Resource->PciCfg.PciDevicePath[0].PciFunction));
- if (Resource->Header.Length != sizeof (STM_RSC_PCI_CFG_DESC) + (sizeof(STM_PCI_DEVICE_PATH_NODE) * Resource->PciCfg.LastNodeIndex)) {
- return FALSE;
- }
- for (SubIndex = 0; SubIndex <= Resource->PciCfg.LastNodeIndex; SubIndex++) {
- if ((Resource->PciCfg.PciDevicePath[SubIndex].PciDevice > 0x1F) || (Resource->PciCfg.PciDevicePath[SubIndex].PciFunction > 7)) {
- return FALSE;
- }
- }
- if ((Resource->PciCfg.Base + Resource->PciCfg.Length) > 0x1000) {
- return FALSE;
- }
- break;
-
- case MACHINE_SPECIFIC_REG:
- if (Resource->Header.Length != sizeof (STM_RSC_MSR_DESC)) {
- return FALSE;
- }
- break;
-
- default :
- DEBUG ((DEBUG_ERROR, "ValidateResource - Unknown RscType(%x)\n", Resource->Header.RscType));
- return FALSE;
- }
- Resource = (STM_RSC *)((UINTN)Resource + Resource->Header.Length);
- }
- return TRUE;
-}
-
-/**
-
- Get resource list.
- EndResource is excluded.
-
- @param ResourceList A pointer to resource list to be added
- @param NumEntries Optional number of entries.
- If 0, list must be terminated by END_OF_RESOURCES.
-
- @retval TRUE resource valid
- @retval FALSE resource invalid
-
-**/
-UINTN
-GetResourceSize (
- IN STM_RSC *ResourceList,
- IN UINT32 NumEntries OPTIONAL
- )
-{
- UINT32 Count;
- UINTN Index;
- STM_RSC *Resource;
-
- Resource = ResourceList;
-
- //
- // If NumEntries == 0 make it very big. Scan will be terminated by
- // END_OF_RESOURCES.
- //
- if (NumEntries == 0) {
- Count = 0xFFFFFFFF;
- } else {
- Count = NumEntries;
- }
-
- //
- // Start from beginning of resource list.
- //
- Resource = ResourceList;
-
- for (Index = 0; Index < Count; Index++) {
- if (Resource->Header.RscType == END_OF_RESOURCES) {
- break;
- }
- Resource = (STM_RSC *)((UINTN)Resource + Resource->Header.Length);
- }
-
- return (UINTN)Resource - (UINTN)ResourceList;
-}
-
-/**
-
- Add resources in list to database. Allocate new memory areas as needed.
-
- @param ResourceList A pointer to resource list to be added
- @param NumEntries Optional number of entries.
- If 0, list must be terminated by END_OF_RESOURCES.
-
- @retval EFI_SUCCESS If resources are added
- @retval EFI_INVALID_PARAMETER If nested procedure detected resource failer
- @retval EFI_OUT_OF_RESOURCES If nested procedure returned it and we cannot allocate more areas.
-
-**/
-EFI_STATUS
-EFIAPI
-AddPiResource (
- IN STM_RSC *ResourceList,
- IN UINT32 NumEntries OPTIONAL
- )
-{
- EFI_STATUS Status;
- UINTN ResourceSize;
- EFI_PHYSICAL_ADDRESS NewResource;
- UINTN NewResourceSize;
-
- DEBUG ((DEBUG_INFO, "AddPiResource - Enter\n"));
-
- if (!ValidateResource (ResourceList, NumEntries)) {
- return EFI_INVALID_PARAMETER;
- }
-
- ResourceSize = GetResourceSize (ResourceList, NumEntries);
- DEBUG ((DEBUG_INFO, "ResourceSize - 0x%08x\n", ResourceSize));
- if (ResourceSize == 0) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (mStmResourcesPtr == NULL) {
- //
- // First time allocation
- //
- NewResourceSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (ResourceSize + sizeof(mRscEndNode)));
- DEBUG ((DEBUG_INFO, "Allocate - 0x%08x\n", NewResourceSize));
- Status = gSmst->SmmAllocatePages (
- AllocateAnyPages,
- EfiRuntimeServicesData,
- EFI_SIZE_TO_PAGES (NewResourceSize),
- &NewResource
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Copy EndResource for intialization
- //
- mStmResourcesPtr = (UINT8 *)(UINTN)NewResource;
- mStmResourceTotalSize = NewResourceSize;
- CopyMem (mStmResourcesPtr, &mRscEndNode, sizeof(mRscEndNode));
- mStmResourceSizeUsed = sizeof(mRscEndNode);
- mStmResourceSizeAvailable = mStmResourceTotalSize - sizeof(mRscEndNode);
-
- //
- // Let SmmCore change resource ptr
- //
- NotifyStmResourceChange (mStmResourcesPtr);
- } else if (mStmResourceSizeAvailable < ResourceSize) {
- //
- // Need enlarge
- //
- NewResourceSize = mStmResourceTotalSize + (ResourceSize - mStmResourceSizeAvailable);
- NewResourceSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (NewResourceSize));
- DEBUG ((DEBUG_INFO, "ReAllocate - 0x%08x\n", NewResourceSize));
- Status = gSmst->SmmAllocatePages (
- AllocateAnyPages,
- EfiRuntimeServicesData,
- EFI_SIZE_TO_PAGES (NewResourceSize),
- &NewResource
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- CopyMem ((VOID *)(UINTN)NewResource, mStmResourcesPtr, mStmResourceSizeUsed);
- mStmResourceSizeAvailable = NewResourceSize - mStmResourceSizeUsed;
-
- gSmst->SmmFreePages (
- (EFI_PHYSICAL_ADDRESS)(UINTN)mStmResourcesPtr,
- EFI_SIZE_TO_PAGES (mStmResourceTotalSize)
- );
-
- mStmResourceTotalSize = NewResourceSize;
- mStmResourcesPtr = (UINT8 *)(UINTN)NewResource;
-
- //
- // Let SmmCore change resource ptr
- //
- NotifyStmResourceChange (mStmResourcesPtr);
- }
-
- //
- // Check duplication
- //
- AddResource (ResourceList, NumEntries);
-
- return EFI_SUCCESS;
-}
-
-/**
-
- Delete resources in list to database.
-
- @param ResourceList A pointer to resource list to be deleted
- NULL means delete all resources.
- @param NumEntries Optional number of entries.
- If 0, list must be terminated by END_OF_RESOURCES.
-
- @retval EFI_SUCCESS If resources are deleted
- @retval EFI_INVALID_PARAMETER If nested procedure detected resource failer
-
-**/
-EFI_STATUS
-EFIAPI
-DeletePiResource (
- IN STM_RSC *ResourceList,
- IN UINT32 NumEntries OPTIONAL
- )
-{
- if (ResourceList != NULL) {
- // TBD
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
- }
- //
- // Delete all
- //
- CopyMem (mStmResourcesPtr, &mRscEndNode, sizeof(mRscEndNode));
- mStmResourceSizeUsed = sizeof(mRscEndNode);
- mStmResourceSizeAvailable = mStmResourceTotalSize - sizeof(mRscEndNode);
- return EFI_SUCCESS;
-}
-
-/**
-
- Get BIOS resources.
-
- @param ResourceList A pointer to resource list to be filled
- @param ResourceSize On input it means size of resource list input.
- On output it means size of resource list filled,
- or the size of resource list to be filled if size of too small.
-
- @retval EFI_SUCCESS If resources are returned.
- @retval EFI_BUFFER_TOO_SMALL If resource list buffer is too small to hold the whole resources.
-
-**/
-EFI_STATUS
-EFIAPI
-GetPiResource (
- OUT STM_RSC *ResourceList,
- IN OUT UINT32 *ResourceSize
- )
-{
- if (*ResourceSize < mStmResourceSizeUsed) {
- *ResourceSize = (UINT32)mStmResourceSizeUsed;
- return EFI_BUFFER_TOO_SMALL;
- }
-
- CopyMem (ResourceList, mStmResourcesPtr, mStmResourceSizeUsed);
- *ResourceSize = (UINT32)mStmResourceSizeUsed;
- return EFI_SUCCESS;
-}
-
-/**
-
- Set valid bit for MSEG MSR.
-
- @param Buffer Ap function buffer. (not used)
-
-**/
-VOID
-EFIAPI
-EnableMsegMsr (
- IN VOID *Buffer
- )
-{
- MSR_IA32_SMM_MONITOR_CTL_REGISTER SmmMonitorCtl;
-
- SmmMonitorCtl.Uint64 = AsmReadMsr64 (MSR_IA32_SMM_MONITOR_CTL);
- SmmMonitorCtl.Bits.Valid = 1;
- AsmWriteMsr64 (MSR_IA32_SMM_MONITOR_CTL, SmmMonitorCtl.Uint64);
-}
-
-/**
-
- Get 4K page aligned VMCS size.
-
- @return 4K page aligned VMCS size
-
-**/
-UINT32
-GetVmcsSize (
- VOID
- )
-{
- MSR_IA32_VMX_BASIC_REGISTER VmxBasic;
-
- //
- // Read VMCS size and and align to 4KB
- //
- VmxBasic.Uint64 = AsmReadMsr64 (MSR_IA32_VMX_BASIC);
- return ALIGN_VALUE (VmxBasic.Bits.VmcsSize, SIZE_4KB);
-}
-
-/**
-
- Check STM image size.
-
- @param StmImage STM image
- @param StmImageSize STM image size
-
- @retval TRUE check pass
- @retval FALSE check fail
-**/
-BOOLEAN
-StmCheckStmImage (
- IN EFI_PHYSICAL_ADDRESS StmImage,
- IN UINTN StmImageSize
- )
-{
- UINTN MinMsegSize;
- STM_HEADER *StmHeader;
- IA32_VMX_MISC_REGISTER VmxMiscMsr;
-
- //
- // Check to see if STM image is compatible with CPU
- //
- StmHeader = (STM_HEADER *)(UINTN)StmImage;
- VmxMiscMsr.Uint64 = AsmReadMsr64 (MSR_IA32_VMX_MISC);
- if (StmHeader->HwStmHdr.MsegHeaderRevision != VmxMiscMsr.Bits.MsegRevisionIdentifier) {
- DEBUG ((DEBUG_ERROR, "STM Image not compatible with CPU\n"));
- DEBUG ((DEBUG_ERROR, " StmHeader->HwStmHdr.MsegHeaderRevision = %08x\n", StmHeader->HwStmHdr.MsegHeaderRevision));
- DEBUG ((DEBUG_ERROR, " VmxMiscMsr.Bits.MsegRevisionIdentifier = %08x\n", VmxMiscMsr.Bits.MsegRevisionIdentifier));
- return FALSE;
- }
-
- //
- // Get Minimal required Mseg size
- //
- MinMsegSize = (EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (StmHeader->SwStmHdr.StaticImageSize)) +
- StmHeader->SwStmHdr.AdditionalDynamicMemorySize +
- (StmHeader->SwStmHdr.PerProcDynamicMemorySize + GetVmcsSize () * 2) * gSmst->NumberOfCpus);
- if (MinMsegSize < StmImageSize) {
- MinMsegSize = StmImageSize;
- }
-
- if (StmHeader->HwStmHdr.Cr3Offset >= StmHeader->SwStmHdr.StaticImageSize) {
- //
- // We will create page table, just in case that SINIT does not create it.
- //
- if (MinMsegSize < StmHeader->HwStmHdr.Cr3Offset + EFI_PAGES_TO_SIZE(6)) {
- MinMsegSize = StmHeader->HwStmHdr.Cr3Offset + EFI_PAGES_TO_SIZE(6);
- }
- }
-
- //
- // Check if it exceeds MSEG size
- //
- if (MinMsegSize > mMsegSize) {
- DEBUG ((DEBUG_ERROR, "MSEG too small. Min MSEG Size = %08x Current MSEG Size = %08x\n", MinMsegSize, mMsegSize));
- DEBUG ((DEBUG_ERROR, " StmHeader->SwStmHdr.StaticImageSize = %08x\n", StmHeader->SwStmHdr.StaticImageSize));
- DEBUG ((DEBUG_ERROR, " StmHeader->SwStmHdr.AdditionalDynamicMemorySize = %08x\n", StmHeader->SwStmHdr.AdditionalDynamicMemorySize));
- DEBUG ((DEBUG_ERROR, " StmHeader->SwStmHdr.PerProcDynamicMemorySize = %08x\n", StmHeader->SwStmHdr.PerProcDynamicMemorySize));
- DEBUG ((DEBUG_ERROR, " VMCS Size = %08x\n", GetVmcsSize ()));
- DEBUG ((DEBUG_ERROR, " Max CPUs = %08x\n", gSmst->NumberOfCpus));
- DEBUG ((DEBUG_ERROR, " StmHeader->HwStmHdr.Cr3Offset = %08x\n", StmHeader->HwStmHdr.Cr3Offset));
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
-
- Load STM image to MSEG.
-
- @param StmImage STM image
- @param StmImageSize STM image size
-
-**/
-VOID
-StmLoadStmImage (
- IN EFI_PHYSICAL_ADDRESS StmImage,
- IN UINTN StmImageSize
- )
-{
- MSR_IA32_SMM_MONITOR_CTL_REGISTER SmmMonitorCtl;
- UINT32 MsegBase;
- STM_HEADER *StmHeader;
-
- //
- // Get MSEG base address from MSR_IA32_SMM_MONITOR_CTL
- //
- SmmMonitorCtl.Uint64 = AsmReadMsr64 (MSR_IA32_SMM_MONITOR_CTL);
- MsegBase = SmmMonitorCtl.Bits.MsegBase << 12;
-
- //
- // Zero all of MSEG base address
- //
- ZeroMem ((VOID *)(UINTN)MsegBase, mMsegSize);
-
- //
- // Copy STM Image into MSEG
- //
- CopyMem ((VOID *)(UINTN)MsegBase, (VOID *)(UINTN)StmImage, StmImageSize);
-
- //
- // STM Header is at the beginning of the STM Image
- //
- StmHeader = (STM_HEADER *)(UINTN)StmImage;
-
- StmGen4GPageTable ((UINTN)MsegBase + StmHeader->HwStmHdr.Cr3Offset);
-}
-
-/**
-
- Load STM image to MSEG.
-
- @param StmImage STM image
- @param StmImageSize STM image size
-
- @retval EFI_SUCCESS Load STM to MSEG successfully
- @retval EFI_ALREADY_STARTED STM image is already loaded to MSEG
- @retval EFI_BUFFER_TOO_SMALL MSEG is smaller than minimal requirement of STM image
- @retval EFI_UNSUPPORTED MSEG is not enabled
-
-**/
-EFI_STATUS
-EFIAPI
-LoadMonitor (
- IN EFI_PHYSICAL_ADDRESS StmImage,
- IN UINTN StmImageSize
- )
-{
- MSR_IA32_SMM_MONITOR_CTL_REGISTER SmmMonitorCtl;
-
- if (mLockLoadMonitor) {
- return EFI_ACCESS_DENIED;
- }
-
- SmmMonitorCtl.Uint64 = AsmReadMsr64 (MSR_IA32_SMM_MONITOR_CTL);
- if (SmmMonitorCtl.Bits.MsegBase == 0) {
- return EFI_UNSUPPORTED;
- }
-
- if (!StmCheckStmImage (StmImage, StmImageSize)) {
- return EFI_BUFFER_TOO_SMALL;
- }
-
- // Record STM_HASH to PCR 0, just in case it is NOT TXT launch, we still need provide the evidence.
- TpmMeasureAndLogData(
- 0, // PcrIndex
- TXT_EVTYPE_STM_HASH, // EventType
- NULL, // EventLog
- 0, // LogLen
- (VOID *)(UINTN)StmImage, // HashData
- StmImageSize // HashDataLen
- );
-
- StmLoadStmImage (StmImage, StmImageSize);
-
- mStmState |= EFI_SM_MONITOR_STATE_ENABLED;
-
- return EFI_SUCCESS;
-}
-
-/**
- This function return BIOS STM resource.
- Produced by SmmStm.
- Comsumed by SmmMpService when Init.
-
- @return BIOS STM resource
-
-**/
-VOID *
-GetStmResource(
- VOID
- )
-{
- return mStmResourcesPtr;
-}
-
-/**
- This function notify STM resource change.
-
- @param StmResource BIOS STM resource
-
-**/
-VOID
-NotifyStmResourceChange (
- VOID *StmResource
- )
-{
- UINTN Index;
- TXT_PROCESSOR_SMM_DESCRIPTOR *Psd;
-
- for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {
- Psd = (TXT_PROCESSOR_SMM_DESCRIPTOR *)((UINTN)gSmst->CpuSaveState[Index] - SMRAM_SAVE_STATE_MAP_OFFSET + TXT_SMM_PSD_OFFSET);
- Psd->BiosHwResourceRequirementsPtr = (UINT64)(UINTN)StmResource;
- }
- return ;
-}
-
-
-/**
- This is STM setup BIOS callback.
-**/
-VOID
-EFIAPI
-SmmStmSetup (
- VOID
- )
-{
- mStmState |= EFI_SM_MONITOR_STATE_ACTIVATED;
-}
-
-/**
- This is STM teardown BIOS callback.
-**/
-VOID
-EFIAPI
-SmmStmTeardown (
- VOID
- )
-{
- mStmState &= ~EFI_SM_MONITOR_STATE_ACTIVATED;
-}
-